Неможливо вибрати стару дату в wordpress


13

Я не можу встановити рік нижче 1899 року на посаду. Якщо я встановити рік нижче 1899 року, він встановлюється автоматично на поточний рік.

знімок екрана

Я придбав тему Timeline і запитав їх на форумі підтримки. Вони відповіли:

Це звучить як обмеження, створене вашим хостинг-провайдером. Ніщо в темі не заважає призначити дату - як ви бачите, демонстрація має публікації з використанням дат у 1400-х. Спробуйте зв’язатися з постачальником послуг хостингу і дізнатись, чи мають вони зрозуміти, як вирішити цю проблему.


2
І ваше питання - що саме? Є тисячі тем там - це довго зйомка припустити, що хтось знатиме тему, яку ви купили. Вам доведеться хоча б надати відповідний код.
Йоганнес Пілль

1
Я сумніваюся, що це вина вини. Мова йде про значення, збережене в базі даних. Увімкніть WP_DEBUGта відредагуйте повідомлення про помилку у своєму запитанні. Можливо, я зробив би це так, але посилання на робочу версію відповідної теми насправді теж не дуже допомагає.
Йоганнес Пілль

1
Це законне питання. Це не пов’язано з темою. Я можу відтворити цю проблему. Дивіться цей анімаційний знімок екрана .
fuxia

1
Ця

1
Я можу це відтворити, до речі, є і проблеми, що перевищують діапазон часових позначок Unix (2038). PHP 5.4 у програмі Win7x64
Рарст,

Відповіді:


10

Це насправді не відповідь, а лише спроба знайти конкретний контекст для цієї проблеми. Установіть наступний плагін на свій сайт, спробуйте встановити три дати та додати свій результат другим <pre>у таблиці нижче.

/* Plugin Name: WPSE Sysinfo */
add_action( 'admin_footer', 'wpse_sysinfo' );
function wpse_sysinfo() {

    $bit         = 4 === PHP_INT_SIZE ? 32 : 64; // PHP version, not OS!
    $php_version = PHP_VERSION;
    $db_version  = $GLOBALS['wpdb']->db_version();

    print "<pre>$bit | $php_version | $db_version</pre>";
}

Історію плагіна можна перевірити тут .

ОС | Біт ОС | PHP | PHP Біт | MySQL | 999 | 1899 | 2020 | 2039 | користувач
WIN7 | 64 | 5.4.4 | ?? | 5.5.25 | ✘ | ✘ | ✔ | ✘ | тошо
Linux | ?? | 5.3.18-нмм1 | ?? | 5.1.70 | ✔ | ✔ | ✔ | ✔ | тошо
CentOS 6 | 64 | 5.5.4 | ?? | 5.0.95 | ✔ | ✔ | ✔ | ✔ | тошо
WIN7 | 64 | 5.4.15 | 32 | 5.5.31 | ✘ | ✘ | ✔ | ✘ | рідкість
Ubuntu 12.04 | 64 | 5.3.10-1 | 64 | 5.5.32 | ✔ | ✔ | ✔ | ✔ | Піл
CloudLinux | 64 | 5.2.17 | 64 | 5.0.96 | ✔ | ✔ | ✔ | ✔ | Піл
Ubuntu 12.10 | 64 | 5.4.6 | 64 | 5.5.32 | ✔ | ✔ | ✔ | ✔ | Майкл Еклунд
CENTOS 5.9 | 32 | 5.3.27 | 32 | 5.5.32 | ✘ | ✘ | ✔ | ✘ | Майкл Еклунд
WIN7 | 64 | 5.4.7 | 64 | 5.5.27 | ✘ | ✘ | ✔ | ✘ | кайзер
OSX 10.7.5 | 64 | 5.3.6 | 64 | 5.5.9 | ✔ | ✔ | ✔ | ✔ | GhostToast
Centos 6.4 | 64 | 5.4.17 | 32 | 5.1.59 | ✘ | ✘ | ✔ | ✘ | birgire
Debian 6 | 64 | 5.4.19 | 64 | 5.1.66 | ✘ | ✘ | ✔ | ✘ | birgire
WIN7 | 64 | 5.5.0 | 64 | 5.5.22 | ✘ | ✘ | ✔ | ✘ | ГМ
OSX 10.7.4 | 64 | 5.3.6 | 64 | 5.5.9 | ✔ | ✔ | ✔ | ✔ | брасофіло
CentOS 5 | 64 | 5.3.22 | 64 | 5.1.68 | ✔ | ✔ | ✔ | ✔ | брасофіло
Mac 10.8.5 | 64 | 5.3.26 | 64 | 5.5.25 | ✔ | ✔ | ✔ | ✔ | flentini
WIN7 | 64 | 5.3.27 | 64 | 5.5.31 | ✔ | ✔ | ✔ | ✔ | Саша Краузе
Win7SP1 | 64 | 5.3.8 | 64 | 5.5.28 | ✔ | ✔ | ✔ | ✔ | Мануель Сіхольд
  1. Створіть нову публікацію. Збережи це.
  2. Встановіть дату на 1 січня 0999, натисніть Оновити . Це збережено чи змінено на поточну дату?
  3. Повторіть ці дії для налаштування дати для 1899, 2020і 2039.
  4. Візьміть інформацію з виводу плагіна у нижньому колонтитулі адміністратора та оновіть таблицю.

7

Питання та очікування

Хоча буквальна форма цього питання практична в контексті (рік 1899), в теоретичному сенсі вона є дещо невиразною. Скільки років? Як далеко в минуле ми могли б хотіти піти? Що з майбутнім?

З тих пір, як WordPress почав функціонувати як блог, в цьому контекстному сенсі він перетворився на наступний проміжок часу:

  • дати існування WP (очевидно, щоб мати можливість використовувати його)
  • діапазон можливих історичних публікацій (неявно, до тих пір, як існував Інтернет)
  • якомога далі в майбутнє без особливих зусиль (працюйте, поки вона не зламається)

У міру того, як використання WordPress перетворювалося на додатки, що не блогують, такі проекти (як правило, історія та мистецтво, як я бачив у звітах) почали стикатися з різними проблемами з датами поза цим періодом.

Для мого дослідження я сформулював такі питання:

  1. Які два найдавніші та останні повні календарні роки, які можна використовувати з датами публікації WordPress споконвічно та надійно?
  2. Які низько висячі фрукти (якщо такі є), щоб розширити доступний проміжок за межі рідного асортименту?

Обмеження платформи

Оскільки WordPress є програмою PHP і використовує MySQL для зберігання даних, це обмежується їх обмеженнями.

MySQL

WordPress зберігає дати публікації у post_dateстовпці DATETIMEтипу в MySQL.

Відповідно до документації, цей тип підтримує роки від 1000 до 9999 :

DATETIMEТипу використовуються для значень , які містять як дату і час частина. MySQL отримує та відображає DATETIMEзначення у 'YYYY-MM-DD HH:MM:SS'форматі. Підтримується діапазон '1000-01-01 00:00:00'до '9999-12-31 23:59:59'.

Однак він також говорить про те, що більш ранні значення можуть працювати, не згадуючи про пізніші значення:

Для DATE and DATETIMEописів діапазону "підтримується" означає, що хоча попередні значення можуть працювати, гарантії немає.

Хоча емпірично я спостерігав значення поза межами діапазону, це анекдотично і випадає з нашого стану надійності.

PHP

У програмуванні PHP широко використовується уявлення часових позначок Unix. Відповідно до документації для наших цілей (PHP 5.2+ та загальне 32-бітове середовище), він підтримує роки (у повному обсязі) з 1902 по 2037 рік :

Дійсний діапазон часової позначки, як правило, від Fri, 13 Dec 1901 20:45:54 UTCдо Tue, 19 Jan 2038 03:14:07 UTC. (Це дати, які відповідають мінімальному та максимальному значенню для 32-бітного цілого числа, підписаного.) Крім того, не всі платформи підтримують негативні часові позначки, тому діапазон дат може бути обмежений не раніше епохи Unix. Це означає, що, наприклад, дати до Jan 1, 1970цього не працюватимуть у Windows, деяких дистрибутивах Linux та кількох інших операційних системах. PHP 5.1.0 і новіші версії подолали це обмеження.

Окрім того, що більш нове Date/Timeкерування має 64 біт і має діапазон приблизно від -292 мільярдів до 292 мільярдів років , що, ймовірно, перевищує потреби людства в цей час.

Обмеження WordPress

WordPress вводить і успадковує деякі додаткові обмеження у своїй кодовій базі.

Потік даних

З точки зору базового робочого процесу користувача, є два оброблені, пов'язані з датою:

  • Введення дати у формі редагування публікації має бути правильно оброблено та збережено у базі даних
  • Дата, збережена в базі даних, повинна бути правильно прочитана та показана в інтерфейсі

Зауважте, що це технічно абсолютно різні та незалежні процеси. Як пояснено далі, їхні діапазони не перетинаються, а збереження правильної дати не дорівнює можливості правильного читання в середовищі WordPress.

Явні обмеження

  • WordPress пошта редактор в адміністраторі дозволяє діапазон років, які можуть бути представлені як дата публікації, від 100 до 9999
  • _wp_translate_postdata() рік процесів (подається як окреме число від форми) та:
    • саніфікує його до негативного > 0
    • перевіряє його за допомогою wp_checkdate(), який викликає PHP native checkdate(), що встановлює ліміт від 1 до 32767

Неявні межі

  • strtotime()Функція PHP використовується декілька разів і підпорядковується вищезазначеній часовій позначці Unix, на найнижчому рівні, mysql2date()що впливає на всі читання дат із бази даних, діапазон 1902 - 2037 успадковується
  • WordPress повертається до регулярного вираження для розбору дат у get_gmt_from_date(), який, як очікується, буде роком ([0-9]{1,4}), обмежуючи його від 1 до 9999 , великою можливістю подібної обробки в інших функціях, які потребують більш ретельного аудиту коду для перерахування

Можливість обходу

  • wp_checkdate()має wp_checkdateфільтр, який дозволяє замінити цю перевірку перевірки
  • вихід, спрямований на кінцевого споживача, проходить через date_i18n()який має date_i18nфільтр, теоретично дозволяє повністю перехоплювати та повторно обробляти виведення дат на інтерфейс, однак складним, якщо функція передана вже поза діапазоном ( false) введення часових позначок

Висновки

Для практичних цілей і портативності даних діапазон дат після WordPress, схоже, дорівнює 32-бітовій часовій позначці Unix і складається з 1902 по 2037 роки включно .

Для будь-якої операції після дати поза цим середовищем діапазону необхідно перевірити (64-бітний діапазон часових позначок Unix, фактично функціонуючий MySQL або альтернативне зберігання бази даних для значень). Для подальших діапазонів ( нижче 1000, вище 9999 ), ймовірно, знадобиться значна кількість користувацького коду.

Для будь-якої реалізації довільних дат має сенс:

  • зберігати їх у MySQL у форматі, що не обмежується обмеженнями в базі даних
  • обробляти в PHP, використовуючи повністю користувальницький Date/Timeкод та / або функції WordPress, піддані аудиту, на які не впливають обмеження часових позначок Unix

Код тестового ліжка

Для дослідження та перевірки висновків було використано наступний код та вибраний набір років:

require ABSPATH . '/wp-admin/includes/post.php';

$timestamp_size_info = array(
    'PHP_INT_SIZE'   => PHP_INT_SIZE,
    'PHP_INT_MAX'    => number_format( PHP_INT_MAX ),
    'min timestamp'  => date( DATE_ISO8601, - PHP_INT_MAX ),
    'zero timestamp' => date( DATE_ISO8601, 0 ),
    'max timestamp'  => date( DATE_ISO8601, PHP_INT_MAX ),
);

r( $timestamp_size_info );

// hand picked set of years to test for assorted limits
$years = array(
    'negative'           => - 1,
    'zero'               => 0,
    'one'                => 1,
    'wp min'             => 100,
    'mysql first'        => 1000,
    'before unix'        => 1899,
    'unix first'         => 1902,
    'current'            => 2013,
    'unix last'          => 2037,
    'after unix'         => 2039,
    'mysql last, wp max' => 9999,
    'after checkdate'    => 33000,
);

// simulates form submission data
$post = array(
    'post_type' => 'post', // shut notice
    'edit_date' => 1,
    'aa'        => 1,
    'mm'        => '01',
    'jj'        => '01',
    'hh'        => '00',
    'mn'        => '00',
    'ss'        => '00',
);

// add_filter( 'wp_checkdate', '__return_true' );

foreach ( $years as $name => $year ) {

    $post['aa'] = $year;
    $translated = _wp_translate_postdata( false, $post );

    if ( is_wp_error( $translated ) ) { // wp_checkdate() failed
        r( array( 'year' => $year . " ({$name})", 'translated valid' => false ) );
    }
    else {

        $post_date        = $translated['post_date'];
        $post_date_gmt    = $translated['post_date_gmt'];
        $translated_valid = (string) $year == substr( $post_date, 0, strpos( $post_date, '-' ) );
        $mysql2date       = mysql2date( DATE_ISO8601, $post_date );
        $mysql2date_valid = (string) $year == substr( $mysql2date, 0, strpos( $mysql2date, '-' ) );

        r( array(
            'year'             => $year . " ({$name})",
            'post_date'        => $post_date,
            'translated valid' => $translated_valid,
            'post_date_gmt'    => $post_date_gmt,
            'mysql2date'       => $mysql2date,
            'from sql valid'   => $mysql2date_valid,
        ) );
    }
}

+1 Залишилося лише питання: що таке r()?
кайзер

1
@kaiser php-ref , заміни на дамп функцію за вибором :)
Rarst
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.