Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make date display consistently across manager components #16604

Open
wants to merge 15 commits into
base: 3.x
Choose a base branch
from
Open
18 changes: 18 additions & 0 deletions _build/data/transport.core.system_settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,24 @@
'area' => 'manager',
'editedon' => null,
], '', true, true);
$settings['manager_datetime_separator'] = $xpdo->newObject(modSystemSetting::class);
$settings['manager_datetime_separator']->fromArray([
'key' => 'manager_datetime_separator',
'value' => ', ',
'xtype' => 'textfield',
'namespace' => 'core',
'area' => 'manager',
'editedon' => null,
], '', true, true);
$settings['manager_datetime_empty_value'] = $xpdo->newObject(modSystemSetting::class);
$settings['manager_datetime_empty_value']->fromArray([
'key' => 'manager_datetime_empty_value',
'value' => '—',
'xtype' => 'textfield',
'namespace' => 'core',
'area' => 'manager',
'editedon' => null,
], '', true, true);
$settings['manager_direction'] = $xpdo->newObject(modSystemSetting::class);
$settings['manager_direction']->fromArray([
'key' => 'manager_direction',
Expand Down
2 changes: 2 additions & 0 deletions core/lexicon/en/default.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
$_lang['data_err_load'] = 'Error loading data.';
$_lang['date'] = 'Date';
$_lang['datechanged'] = 'Date changed';
$_lang['datetime_conversion_err_invalid_mysql_format'] = 'Attempted to convert the value “[[+value]]” to a timestamp, but the the value is not in the required mysql format (Y-m-d H:i:s).';
$_lang['db_header'] = 'Database tables';
$_lang['db_info_mysql'] = 'If a table has an overhead, you may optimize it by clicking on the link in the Overhead column.';
$_lang['delete'] = 'Delete';
Expand Down Expand Up @@ -510,6 +511,7 @@
$_lang['untitled_tv'] = 'Untitled tv';
$_lang['untitled_weblink'] = 'Untitled weblink';
$_lang['untitled_symlink'] = 'Untitled symlink';
$_lang['unedited'] = 'Unedited';
$_lang['unknown'] = 'Unknown';
$_lang['unsaved_changes'] = 'There are unsaved changes. Are you sure you want to leave this page?';
$_lang['update'] = 'Update';
Expand Down
6 changes: 6 additions & 0 deletions core/lexicon/en/setting.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,12 @@
$_lang['setting_date_timezone'] = 'Default Time Zone';
$_lang['setting_date_timezone_desc'] = 'Controls the default timezone setting for PHP date functions, if not empty. If empty and the PHP date.timezone ini setting is not set in your environment, UTC will be assumed.';

$_lang['manager_datetime_empty_value'] = 'Datetime Empty Value';
$_lang['manager_datetime_empty_value_desc'] = 'The text (if any) that will show in grids and forms when a datetime field’s value has not been set. (Default: “–” [a single en dash])';

$_lang['manager_datetime_separator'] = 'Datetime Separator';
$_lang['manager_datetime_separator_desc'] = 'When the date and time are shown as a combined element, these characters will be used to visually seapate them. (Default: “, ” [comma and space])';

$_lang['setting_debug'] = 'Debug';
$_lang['setting_debug_desc'] = 'Controls turning debugging on/off in MODX and/or sets the PHP error_reporting level. \'\' = use current error_reporting, \'0\' = false (error_reporting = 0), \'1\' = true (error_reporting = -1), or any valid error_reporting value (as an integer).';

Expand Down
1 change: 1 addition & 0 deletions core/lexicon/en/workspace.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
$_lang['newest_additions'] = 'Newest Additions';
$_lang['no_preview'] = 'No Preview';
$_lang['not_installed'] = 'Not Installed';
$_lang['not_updated'] = 'Not Updated';
$_lang['package'] = 'Package';
$_lang['package_add'] = 'New Package';
$_lang['package_already_downloaded'] = 'Package already downloaded';
Expand Down
244 changes: 244 additions & 0 deletions core/src/Revolution/Formatter/modManagerDateFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
<?php

/*
* This file is part of the MODX Revolution package.
*
* Copyright (c) MODX, LLC
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace MODX\Revolution\Formatter;

use MODX\Revolution\modX;

/**
* Provides utility methods for processors and controllers
*
* @package MODX\Revolution
*/
class modManagerDateFormatter
{
/**
* A reference to the modX object.
* @var modX $modx
*/
protected ?modX $modx = null;

// DATE FORMATTER PROPERTIES

/**
* @var string $managerDateFormat The php datetime format for dates, as defined in the system settings
*/
protected string $managerDateFormat = '';

/**
* @var string $managerTimeFormat The php datetime format for times, as defined in the system settings
*/
protected string $managerTimeFormat = '';

/**
* @var string $managerDateHiddenFormat Standard mysql format required for date transformations
*/
protected string $managerDateHiddenFormat = 'Y-m-d H:i:s';

/**
* @var array $managerDateEmptyValues A list of possible values representing an empty date
*/
protected array $managerDateEmptyValues = [
'',
'-001-11-30 00:00:00',
'-1-11-30 00:00:00',
'1969-12-31 00:00:00',
'0000-00-00 00:00:00',
0,
'0',
null
];

/**
* @var string $managerDateEmptyDisplay The text (if any) to show for empty dates
*/
private string $managerDateEmptyDisplay = '';


public function __construct(modX $modx)
{
$this->modx =& $modx;
$this->managerDateFormat = $this->modx->getOption('manager_date_format', null, 'Y-m-d', true);
$this->managerTimeFormat = $this->modx->getOption('manager_time_format', null, 'H:i', true);
$this->managerDateEmptyDisplay = $this->modx->getOption('manager_datetime_empty_value', null, '–', true);
}

public function isEmpty($value): bool
{
return in_array($value, $this->managerDateEmptyValues);
}

/**
* Calculates the Unix timestamp for a valid date/time-related value,
* applying the system-specified server offset if applicable
* @param string|int $value The value to transform (a Unix timestamp or mysql-format string)
* @param bool $useOffset Whether to use the offset time (system setting) in the date calculation
* @return int|null The calculated timestamp
*/
protected function parseValue($value, bool $useOffset = false): ?int
{
if ($this->isEmpty($value)) {
return null;
}

if (!modX::isValidTimestamp($value)) {
// If not a timestamp integer, expecting mysql-formatted value
$dateTime = \DateTimeImmutable::createFromFormat($this->managerDateHiddenFormat, $value);
if ($dateTime === false) {
$msg = $this->modx->lexicon('datetime_conversion_err_invalid_mysql_format', ['value' => $value]);
$this->modx->log(modX::LOG_LEVEL_WARN, $msg);
return 0;
}
$value = $dateTime->getTimestamp();
}

$value = (int)$value;

if (!$useOffset) {
return $value;
}

$offset = floatval($this->modx->getOption('server_offset_time', null, 0)) * 3600;

return $value + $offset;
}

/**
* Transforms a date/time-related value using the specified DateTime format
* @param string|int $value The value to transform (a Unix timestamp or mysql-format string)
* @param string $format The custom format to use when formatting the $value
* @param bool $useOffset Whether to use the offset time (system setting) in the date calculation
* @param string|null $emptyValue The text to show when the $value passed is empty
* @return string The formatted date
*/
public function format($value, string $format, bool $useOffset = false, ?string $emptyValue = null): string
{
$value = $this->parseValue($value, $useOffset);

if ($value === null) {
return $emptyValue === null ? $this->managerDateEmptyDisplay : $emptyValue;
}

return date($format, $value);
}

/**
* Transforms a date/time-related value according to the DateTime system format used for hidden values
* @param string|int $value The value to transform (a Unix timestamp or mysql-format string)
* @return string The formatted date
*/
public function formatHidden($value): string
{
return $this->format($value, $this->managerDateHiddenFormat, false, '');
}

/**
* Transforms a date/time-related value into the specified date-only DateTime format
* @param string|int $value The value to transform (a Unix timestamp or mysql-format string)
* @param bool $useOffset Whether to use the offset time (system setting) in the date calculation
* @param string|null $emptyValue The text to show when the $value passed is empty
* @return string The formatted date
*/
public function formatDate($value, bool $useOffset = false, ?string $emptyValue = null): string
{
return $this->format($value, $this->managerDateFormat, $useOffset, $emptyValue);
}

/**
* Transforms a date/time-related value into the specified time-only DateTime format
* @param string|int $value The value to transform (a Unix timestamp or mysql-format string)
* @param bool $useOffset Whether to use the offset time (system setting) in the date calculation
* @param string|null $emptyValue The text to show when the $value passed is empty
* @return string The formatted date
*/
public function formatTime($value, bool $useOffset = false, ?string $emptyValue = null): string
{
return $this->format($value, $this->managerTimeFormat, $useOffset, $emptyValue);
}

/**
* Transforms a date/time-related value into the specified DateTime format showing
* both date and time, including an optional system-specified separator
* @param string|int $value The value to transform (a Unix timestamp or mysql-format string)
* @param bool $useOffset Whether to use the offset time (system setting) in the date calculation
* @param string|null $emptyValue The text to show when the $value passed is empty
* @return string The formatted date
*/
public function formatDateTime($value, bool $useOffset = false, ?string $emptyValue = null): string
{
$managerDateTimeSeparator = $this->modx->getOption('manager_datetime_separator', null, ', ', true);
$format = $this->managerDateFormat . $managerDateTimeSeparator . $this->managerTimeFormat;

return $this->format($value, $format, $useOffset, $emptyValue);
}

/**
* Formats a Resource-related date when applicable and includes localized default text to
* represent conditions where a date is not present or applicable
*
* @param string|int $value The source date value to format
* @param string $whichDate An identifier specifying the type of date being formatted
* @param bool $useStandardEmptyValue Whether to use the default empty value defined in the system settings
* @return string The formatted date or relevant text indicating an empty date value
*/
public function formatResourceDate($value, string $whichDate = 'created', bool $useStandardEmptyValue = true): string

Check warning on line 192 in core/src/Revolution/Formatter/modManagerDateFormatter.php

View workflow job for this annotation

GitHub Actions / phpcs

Line exceeds 120 characters; contains 121 characters
{
if ($useStandardEmptyValue) {
return $this->formatDateTime($value, true, null);
}
switch ($whichDate) {
case 'edited':
$emptyValue = $this->modx->lexicon('unedited');
break;
case 'publish':
case 'unpublish':
$emptyValue = $this->modx->lexicon('notset');
break;
case 'published':
$emptyValue = $this->modx->lexicon('unpublished');
break;
default:
$emptyValue = $this->modx->lexicon('unknown');
}
$emptyValue = '(' . $emptyValue . ')';

return $this->formatDateTime($value, true, $emptyValue);
}

/**
* Formats a Package-related date when applicable and includes localized default text to
* represent conditions where a date is not present or applicable
*
* @param string|int $value The source date value to format
* @param string $whichDate An identifier specifying the type of date being formatted
* @param bool $useStandardEmptyValue Whether to use the default empty value defined in the system settings
* @return string The formatted date or relevant text indicating an empty date value
*/
public function formatPackageDate($value, string $whichDate = 'created', bool $useStandardEmptyValue = true): string
{
if ($useStandardEmptyValue) {
return $this->formatDateTime($value, true, null);
}
switch ($whichDate) {
case 'installed':
$emptyValue = $this->modx->lexicon('not_installed');
break;
case 'updated':
$emptyValue = $this->modx->lexicon('not_updated');
break;
default:
$emptyValue = $this->modx->lexicon('unknown');
}
$emptyValue = '(' . $emptyValue . ')';

return $this->formatDateTime($value, true, $emptyValue);
}
}
17 changes: 13 additions & 4 deletions core/src/Revolution/Processors/Browser/Directory/GetFiles.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/*
* This file is part of the MODX Revolution package.
*
Expand All @@ -10,7 +11,7 @@

namespace MODX\Revolution\Processors\Browser\Directory;


use MODX\Revolution\Formatter\modManagerDateFormatter;
use MODX\Revolution\Processors\Browser\Browser;

/**
Expand Down Expand Up @@ -45,8 +46,16 @@ public function process()
}
$list = $this->source->getObjectsInContainer($dir);

return $this->source->hasErrors()
? $this->failure($this->source->getErrors(), [])
: $this->outputArray($list);
if ($this->source->hasErrors()) {
return $this->failure($this->source->getErrors(), []);
}

/** @var modManagerDateFormatter $formatter */
$formatter = $this->modx->services->get(modManagerDateFormatter::class);
foreach ($list as $i => $file) {
$list[$i]['lastmod'] = $formatter->formatDateTime($file['lastmod']);
}

return $this->outputArray($list);
}
}
Loading
Loading