WordPress как на ладони
rgbcode is looking for WordPress developers. Очень Удобный и Быстрый Хостинг для сайтов на WordPress. Пользуюсь сам и вам рекомендую!

Баг с перемещением папки uploads

Похоже напоролся на баг в WordPress, который связан с каталогом загрузок wp-content/uploads. Хотя утверждать что это баг я не буду, но логика точно отсутствует...

Разберемся по порядку, дело было так: есть у меня старый сайт, который работает еще с версии WP 2+. При его создании я переместил папку файлов uploads в корень сайта. Для этого определил константу в wp-config.php:

define( 'UPLOADS', 'uploads'); // значит что папка uploads должна лежать в корне сайта

Также, переименовал папку контента с wp-content на content. Для этого определил константы в том же wp-config.php:

define( 'WP_CONTENT_DIR', $_SERVER['DOCUMENT_ROOT'].'/content' );
define( 'WP_CONTENT_URL', 'http://'. $_SERVER['HTTP_HOST'] .'/content' );

Все работало до недавнего времени...

Недавно я переместил ядро WordPress в отдельную папку wp - это удобно. Теперь, получилось: ядро лежит в папке wp, плагины и т.д. в content и файлы в uploads и все это в корне сайта.

Для тех кто не знает, в WordPress можно логически разделить файлы содержимого (wp-contents) и файлы движка (wp-includes, wp-admin, ...). При этом в настройках устанавливаются 2 разных УРЛ: адрес сайта и адрес WordPress:

wpurls

После перемещения ядра WordPress, в медиатеке у меня пропали картинки. Посмотрев на УРЛ картинок я увидел что УРЛ изменился с /uploads на /wp/uploads при этом я не менял ранее установленную константу UPLOADS.

Заглянув в код _wp_upload_dir() (эта функцию лежит в основе получения всех ссылок на файлы) увидел, что ссылка (url) строиться из объединения UPLOADS с опцией siteurl, а путь (path) строиться так: ABSPATH . UPLOADS.

if ( defined( 'UPLOADS' ) && ! ( is_multisite() && get_site_option( 'ms_files_rewriting' ) ) ) {
	$dir = ABSPATH . UPLOADS;
	$url = trailingslashit( $siteurl ) . UPLOADS;
}

Это значит что за основу берется не корень сайта, а папка где находится ядро WordPress, и если это вложенный каталог, то UPLOADS будет относится уже к этому каталогу. Это не логично, потому что едва ли можно отнести папку с файлами сайта к понятию движок... Это контент сайта!

OK раз нельзя определить константу UPLOADS так, чтобы файлы «смотрели» на корень сайта, а не корень движка, то будем удалять». И удалил константу UPLOADS из wp-config.php, а затем переместил папку uploads в папку контента - content.

В итоге общая структура получилась такая:

/wp/wp-admin
/wp/wp-includes
/content
/content/uploads

Далее, чтобы проверить все ли работает как надо, я попробовал загрузить картинку в медиатеку, но картинка загрузилась не в ожидаемую папку: /content/uploads/..., а все в туже подпапку движка: /wp/uploads/....

Расследование показало, что в настройках WP установлена опция upload_path, которая с версий 3.0 не является обязательной и по умолчанию не устанавливается. А у меня там было значение uploads тоже самое что я установил когда-то в константе UPLOADS.

Чтобы решить проблему, я просто удалил опцию upload_path. Заменил все старые ссылки в контенте на новые. Для этого я запустил такой SQL запрос:

UPDATE wp_posts SET post_content = REPLACE (post_content, 'http://example.com/uploads/', 'http://example.com/content/uploads/');

И на всякий случай переименовал все поля guid у вложений, для этого я сделал мини-плагин.

К чему это все?

К тому, что если вы вдруг будите на старом сайте перемещать базовые папки WordPress, то зайдите во все опции: http://ВАШСАЙТ/wp-admin/options.php и проверьте не установлены ли у вас опции upload_path и upload_url_path они в 99% случаев не нужны с версии WP 3.0+ и их можно просто удалить. К слову на этом блоге они тоже были и я их удалил...

В тех случаях, когда они нужны, вы скорее все будите знать об этом и эта статья будет вам не интересна smile

Также, не пытайтесь перенести папку uploads за пределы папки контента (по умолчанию wp-contents). Это у вас не получится, если WP вынесен в отдельную папку. Или это вызовет проблемы, если в будущем вы заходите вынести файлы движка в отдельную папку.

Выше упомянул что опции нужны в 99%, но есть 1% когда опция upload_url_path нужна - это когда у нас включен мультисайт и мы переместили папку контента или ядро ВП. В обоих случаях нам придется установить константу WP_CONTENT_URL. Далее, при переключении в одном блоге сети на другой с помощью switch_to_blog(). Мы поймаем баг, потому что во многих функциях, например получение URL картинки (см. wp_get_attachment_url() и _wp_upload_dir()) ВП использует константу WP_CONTENT_URL, а она при переключении будет относится к текущему блогу, а не к тому на который переключились. Вот для таких случаев нужна опция upload_url_path, потому что сначала проверяется её значение и только потом используется константа, если в опции пусто.

Обращу еще внимание на то, что Url на загруженные файлы даже при установленной константе WP_CONTENT_URL, все равно остается рабочим при переключении на другой блог. Только домен этого URL будет основной, а не текущего сайта на который переключились.

5 комментариев
    Войти