向附件页固定链接添加文件扩展名

时间:2016-08-30 作者:Leon Williams

上传文件时的简介(stackexchange.jpg) WordPress站点中的媒体库有两个相关链接。

  1. Direct link to file
    http://example.com/wp-content/uploads/stackexchange.jpg

  2. Attachment page
    http://example.com/stackexchange/

    我的问题涉及第二个问题:附件页。

    我想做的是,我想在附件页面permalink中添加文件扩展名。例如,而不是

    http://example.com/stackexchange/

    我想

    http://example.com/stackexchange-jpg/

    为什么这会有用这会非常有用,有几个原因。首先,它不会hogging permalinks 如果我想将其用于帖子或页面等其他内容,我可以上载另一个名为stackexchange.png. 那么,我会:
    http://example.com/stackexchange-jpg/

    http://example.com/stackexchange-png/

    再说一次,我仍然可以使用http://example.com/stackexchange/ 对于实际页面。

    我确实意识到我可以手动浏览和编辑每个文件的slug,这反过来确实会改变permalink的附件页,但我想如果我想这样做的话,几乎不用说我实际上不需要制作线程。

    问题

    是否有一个我可以编写的函数,以便无论何时上传文件,它都能反映我正在寻找的更改?这可能吗?如果是,我该怎么做?如果您知道如何编辑默认的永久链接,但不知道如何添加文件扩展名部分,我很可能仍然可以使用这些信息。

    我认为如果不篡改核心文件(这可能会破坏交易),这可能是不可能的,但希望如此。

    感谢您的阅读和帮助。

2 个回复
最合适的回答,由SO网友:KenB 整理而成

好问题!我自己也在思考这个问题,你的问题促使我深入研究。

有一个过滤器wp_insert_attachment_data 可用于修复上载文件的段塞名称。在将附件插入到中的数据库之前不久,会调用它以获取附件post.php.

例如,以下示例将mime类型附加到slug名称image-jpg 将添加到jpeg图像标题。

    /**
     * Filter attachment post data before it is added to the database
     *  - Add mime type to post_name to reduce slug collisions
     *
     * @param array $data    Array of santized attachment post data
     * @param array $postarr Array of unsanitized attachment post data
     * @return $data, array of post data
     */
    function filter_attachment_slug($data, $postarr)
    {
        /**
         * Only work on attachment types
         */
        if ( ! array_key_exists( \'post_type\', $data ) || \'attachment\' != $data[\'post_type\'] )
            return $data;

        /**
         * Add mime type to the post title to build post-name
         */
        $post_title = array_key_exists( \'post_title\', $data ) ? $data[\'post_title\'] : $postarr[\'post_title\'];
        $post_mime_type = array_key_exists( \'post_mime_type\', $data ) ? $data[\'post_mime_type\'] : $postarr[\'post_mime_type\'];
        $post_mime_type = str_replace( \'/\', \'-\', $post_mime_type );
        $post_name = sanitize_title( $post_title . \'-\' . $post_mime_type );

        /**
         * Generate unique slug for post name
         */
        $post_ID = array_key_exists( \'ID\', $data ) ? $data[\'ID\'] : $postarr[\'ID\'];
        $post_status = array_key_exists( \'post_status\', $data ) ? $data[\'post_status\'] : $postarr[\'post_status\'];
        $post_type = array_key_exists( \'post_type\', $data ) ? $data[\'post_type\'] : $postarr[\'post_type\'];
        $post_parent = array_key_exists( \'post_parent\', $data ) ? $data[\'post_parent\'] : $postarr[\'post_parent\'];

        $post_name = wp_unique_post_slug( $post_name, $post_ID, $post_status, $post_type, $post_parent );
        $data[\'post_name\'] = $post_name;

        return $data;
    }

    /**
     * Adjust slug for uploaded files to include mime type
     */
    add_filter( \'wp_insert_attachment_data\', \'filter_attachment_slug\', 10, 2 );

SO网友:Leon Williams

这是对KenB\'s answer; 我刚刚加入了一些小的编辑。

区别在于,让我们考虑一下文件stackexchange.png 正在上载到媒体库。

KenB的原始解决方案结果:http://example.com/stackexchange-image-png/
这将访问数据库以获取帖子并从post_mime_type 列,在本例中image/png.

+这些编辑结果:http://example.com/stackexchange-png/
而不是从post_mime_type, 我们可以从guid (在这种情况下http://example.com/wp-content/uploads/stackexchange.png), 然后,我们可以去掉除文件扩展名以外的所有内容并处理它。

代码

现在,我已经解释了该解决方案和此解决方案之间的区别,下面是如何做到这一点。我已经包括并做了一些编辑DisgruntledGoat and redanimalwar\'s answer to a question on StackOverflow.

我在KenB的解决方案中禁用的所有内容都保留在代码中,但只是将其注释掉了,这样您就可以看到我实际做了什么。

/**
 * This finds the last \'.\' in a URI and returns the string after that.
 * For example, in the case of \'example.com/photo.jpg\', \'jpg\' is returned. 
 *
 * @author DisgruntledGoat
 * @author redanimalwar
 *
 * @link https://stackoverflow.com/a/1361752/5675729
 */
function get_file_extension($uri) {
    $position = strrpos($uri, \'.\');
    $extension = $position === false ? $uri : substr($uri, $position + 1);
    return $extension;
}

/**
 * Filter attachment post data before it is added to the database
 *  - Add mime type to post_name to reduce slug collisions
 *
 * @author KenB
 *
 * @link https://wordpress.stackexchange.com/a/238205/88601 Original solution
 * @link https://wordpress.stackexchange.com/a/238291/88601 This variation
 *
 * @param array $data    Array of santized attachment post data
 * @param array $postarr Array of unsanitized attachment post data
 *
 * @return $data, array of post data
 */
function filter_attachment_slug($data, $postarr) {
    /**
     * Only work on attachment types
     */
    if ( ! array_key_exists( \'post_type\', $data ) || \'attachment\' != $data[\'post_type\'] )
        return $data;

    /**
     * Add mime type to the post title to build post-name
     */
    $post_title = array_key_exists( \'post_title\', $data ) ? $data[\'post_title\'] : $postarr[\'post_title\'];

    /**
     * This was in KenB\'s original solution, but was removed by Leon Williams,
     * as this version does not deal with the MIME type.
     */
    //$post_mime_type = array_key_exists( \'post_mime_type\', $data ) ? $data[\'post_mime_type\'] : $postarr[\'post_mime_type\'];

    /**
     * This this takes the MIME type, for example, \'image/jpg\', into \'image-jpg\'.
     * This was in KenB\'s original solution, but was removed by Leon Williams,
     * as this version does not deal with the MIME type.
     */
    //$post_mime_type = str_replace( \'/\', \'-\', $post_mime_type );

    /**
     * Access the \'guid\' column from the database (which retrieves the link to the file),
     * then send it to get_file_extension().
     *
     * @author Leon Williams
     */
    $post_file_extention = get_file_extension($postarr[\'guid\']);

    // Instead of tacking on the MIME type, tack on the file extension that we just obtained.
    $post_name = sanitize_title( $post_title . \'-\' /*. $post_mime_type*/ . $post_file_extention);

    /**
     * Generate unique slug for post name
     */
    $post_ID = array_key_exists( \'ID\', $data ) ? $data[\'ID\'] : $postarr[\'ID\'];
    $post_status = array_key_exists( \'post_status\', $data ) ? $data[\'post_status\'] : $postarr[\'post_status\'];
    $post_type = array_key_exists( \'post_type\', $data ) ? $data[\'post_type\'] : $postarr[\'post_type\'];
    $post_parent = array_key_exists( \'post_parent\', $data ) ? $data[\'post_parent\'] : $postarr[\'post_parent\'];

    $post_name = wp_unique_post_slug( $post_name, $post_ID, $post_status, $post_type, $post_parent );
    $data[\'post_name\'] = $post_name;

    return $data;
}

/**
 * Adjust slug for uploaded files to include file extension
 */
add_filter( \'wp_insert_attachment_data\', \'filter_attachment_slug\', 10, 2 );
备选方案(使用post_mime_type 而不是guid)你也可以png 关闭(共个)image/png (通过get_file_extension() 寻找/ 而不是.), 这同样有效。只是,有了这个(我的方式),你也可以使用get_file_extension() 对于其他链接也是如此。

值得注意的是,经过一点测试,我发现在原始解决方案和此版本中,this filter also fires anytime you push the "Update" button while editing an attachment.

例如,假设您正在编辑一个名为的附件example.png 它有一个定制的slugexample-file-slug (让我们假设你很久以前就给了它那个定制的鼻涕虫)。今天,您正在编辑描述,当您完成描述并点击“更新”时,此过滤器将启动,并将自动更改slugexample-file-slugexample-png 除了更新描述之外。如果您尝试返回并将slug更改为其他任何内容,那么当您点击“更新”时,过滤器将再次启动,并覆盖您更改slug的尝试。

这对我个人来说没有什么问题,但这可能是其他人需要考虑的问题。

Workarounds
如果要更改slug名称,则必须禁用此筛选器(例如,通过注释将其删除),然后将更改保存到附件,然后再次启用筛选器。或者,您可以直接编辑数据库。

我确信有一种方法可以编写解决方案,但我目前没有。

感谢这些优秀的人: