douchuopiao9002 2014-08-07 16:14
浏览 36
已采纳

WordPress的自定义元框和字段:根据用户编辑页面更改目录上载

I am using the CMB script (Custom Meta Boxes and Fields for WordPress) for uploading files for different users that have the custom role of cliente.

I am able to show the fields and make them work (though they only appear when editing a user, and not when creating it, but this is for another question). What I am trying to achieve now is to upload files to different folders for different users.

Here is the code:

// Here we add a new user role, "cliente"
add_role( 'cliente', 'Cliente' );

add_filter('wp_handle_upload_prefilter', 'my_upload_prefilter');
add_filter('wp_handle_upload', 'my_upload_postfilter');

function my_upload_prefilter( $file ) {
    add_filter('upload_dir', 'custom_upload_dir');
    return $file;
}

function my_upload_postfilter( $fileinfo ) {
    remove_filter('upload_dir', 'custom_upload_dir');
    return $fileinfo;
}

function custom_upload_dir( $path ) {
    global $pagenow;

    // Check if we are on the user-edit.php page
    if ( $pagenow == 'user-edit.php' && isset($_GET['user_id']) ) {
        // Set the role we want to change the path for
        $role_to_check = 'cliente';
        // Get a bunch of user info for later use
        $user_id = filter_var( $_GET['user_id'], FILTER_SANITIZE_NUMBER_INT );
        $meta = get_user_meta($user_id);
        $roles = unserialize($meta['wp_capabilities'][0]);
        // If we are on the chosen role page, set the $customdir to first_name + last_name
        if ( !empty($roles[$role_to_check]) ) {
            $customdir = '/' . $meta['first_name'][0] . $meta['last_name'][0];
        }
    } else {
        // Here we are not on the user-edit.php page. This is just a check to prove that WP is not recognizing the correct page, maybe because we are doing an Ajax call when this function is called. Confusing.
        $customdir = '/did-not-work';
    }

    // If there is any error, just return the $path and abort the rest.
    if ( !empty( $path['error'] ) ) {
        return $path;
    }

    // Here we set the new $path with the $customdir set above
    $path['path']    = str_replace($path['subdir'], '', $path['path']); //remove default subdir (year/month)
    $path['url']     = str_replace($path['subdir'], '', $path['url']);      
    $path['subdir']  = $customdir;
    $path['path']   .= $customdir; 
    $path['url']    .= $customdir; 
    return $path;

}

From a few checks I have run it seems like my code does retrieve the user id and the data stored in the db, but it does not detect it when uploading the images. Might this be related to the fact that we are uploading images via Ajax or something like that?

Just to be clear, I don't want the upload based on the current logged in user, but on the user I, as a super-admin, am editing using the edit-user.php page.

Any help would be much appreciated.

  • 写回答

1条回答 默认 最新

  • douping3860 2014-08-09 11:17
    关注

    I figured it out myself. First the correct code, then an explaination:

    // Here we add a new user role, "cliente".
    add_role( 'cliente', 'Cliente' );
    
    // These are the filters we need to add in order to modify the default upload path.
    add_filter('wp_handle_upload_prefilter', 'my_upload_prefilter');
    add_filter('wp_handle_upload', 'my_upload_postfilter');
    
    function my_upload_prefilter( $file ) {
        add_filter('upload_dir', 'custom_upload_dir');
        return $file;
    }
    function my_upload_postfilter( $fileinfo ) {
        remove_filter('upload_dir', 'custom_upload_dir');
        return $fileinfo;
    }
    
    function custom_upload_dir( $path ) {
        // When uploading, the file gets sent to upload_async.php, so we need to take the referral page in order to be able to get the user_id we need. We then take the query string, pass it through parse_str and store it in a $query_array. Took me a while to figure it out, but now it works like a charm.
        $actual_page = $_SERVER['HTTP_REFERER'];
        parse_str( parse_url($actual_page, PHP_URL_QUERY), $query_array );
    
        // Check if we are uploading from the user-edit.php page.
        if ( strpos($actual_page, 'user-edit.php') ) {
            // Set the role we want to change the path for.
            $role_to_check = 'cliente';
            // Get a bunch of user info for later use
            $user_id = filter_var( $query_array['user_id'], FILTER_SANITIZE_NUMBER_INT );
            $meta = get_user_meta( $user_id );
            $roles = unserialize( $meta['wp_capabilities'][0] );
            // If we are on the chosen role page, set the $customdir to first_name + last_name
            if ( !empty($roles[$role_to_check]) ) {
                $customdir = '/docs/' . $meta['first_name'][0] . $meta['last_name'][0];
    
                // If there is any error, just return the $path and abort the rest.
                if ( !empty( $path['error'] ) ) {
                    return $path;
                }
    
                // Here we set the new $path with the $customdir set above
                $new_subdir = $customdir . $path['subdir'];
                $path['path']    = str_replace( $path['subdir'], $new_subdir, $path['path'] );
                $path['url']     = str_replace( $path['subdir'], $new_subdir, $path['url'] );
                $path['subdir']  = $new_subdir;
                return $path;
            }
        } else {
            // We are not uploading from user-edit.php, so go ahead as per default.
            return $path;
        }
    }
    

    The problem was that when uploading via Ajax, $pagenow correctly stores the async-upload.php page, rather than the url we're in. I simply had to retrieve the referral page via php $_SERVER['HTTP_REFERER'] (please, note that the referer typo is there because of a legacy typo in the http spec, funny stuff).

    Please also note that the PHP specs discourage the use of HTTP_REFERER because it could yield unexpected results based on server configurations, but in this case I should have full control over the server, so it should not be a problem. If you encounter any issue, I would suggest to check that out.

    Once I have the correct url I am able to parse it and check if we are on user-edit.php, if we are, get the user_id from the query string and proceed from there.

    Took me a while to figure it out, but in hindsight it was quite easy.

    Hope it helps somebody else in the future.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 wpf中在模版中寻找元素
  • ¥15 MFC平台生成指定圆
  • ¥15 jmeter出现403
  • ¥500 求华为P30PRO手机硬盘数据恢复
  • ¥15 关于#vscode#的问题:ESP32开发板对接MQTT实现小灯泡的开关
  • ¥15 TMC2209串口模式下读取不到寄存器的值串口助手蓝色字体是发过去的消息,绿色字体是收到的消息,第二行发送读取寄存器的指令但是没有读取到寄存器的值串口助手如下图:接线如下图,如何解决?
  • ¥15 怎样删除 右键菜单里的 剪切(T)和复制(C)
  • ¥15 高通安卓11提取完整线刷包软件,或者优博讯dt50顺丰刷机包
  • ¥20 C,有个译码器,换了信道就跑不出原来数据
  • ¥15 MIMIC数据库安装问题