Skip to content

Commit

Permalink
API Substitute Zend_Currency with NumberFormatter based solution
Browse files Browse the repository at this point in the history
API Substitute Zend_Locale with Locale / NumberFormatter
API Substitute Zend_Date with IntlDateFormatter
API Added DBTIme::Nice12, FormatFromSettings
API Added Short() method to DBDate / DBTime / DBDatetime
API Add Date::getTimestamp()
API Added setSubmittedValue api for FormField
API Add second arg to base FormField::setValue()
API Major refactor of i18n into component data parts
API Implement Resettable interface to reset objects between tests
ENHANCEMENT Changed DBField::create_field return type to `static` to support better type hinting
ENHANCEMENT i18nTextCollector supports __CLASS__
  • Loading branch information
Damian Mooyman committed Feb 9, 2017
1 parent 71383b8 commit a9d39d2
Show file tree
Hide file tree
Showing 579 changed files with 6,203 additions and 255,494 deletions.
10 changes: 8 additions & 2 deletions _config/i18n.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
Name: basei18n
Before: '/i18n'
---
SilverStripe\i18n\i18n:
SilverStripe\i18n\Data\Sources:
module_priority:
- admin
- framework
- sapphire
---
Name: defaulti18n
---
SilverStripe\i18n\i18n:
SilverStripe\i18n\Data\Sources:
module_priority:
- other_modules
---
Expand Down Expand Up @@ -58,3 +58,9 @@ SilverStripe\Core\Injector\Injector:
properties:
Reader: %$SilverStripe\i18n\Messages\Reader
Writer: %$SilverStripe\i18n\Messages\Writer
---
Name: i18ndata
---
SilverStripe\Core\Injector\Injector:
SilverStripe\i18n\Data\Locales:
class: SilverStripe\i18n\Data\Intl\IntlLocales
631 changes: 315 additions & 316 deletions admin/client/dist/js/bundle.js

Large diffs are not rendered by default.

61 changes: 34 additions & 27 deletions admin/client/src/legacy/DateField.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,43 @@ import $ from 'jQuery';
require('../../../thirdparty/jquery-ui/jquery-ui.js');

$.fn.extend({
ssDatepicker: function(opts) {
return $(this).each(function() {
// disabled, readonly or already applied
if($(this).prop('disabled') || $(this).prop('readonly') || $(this).data('datepicker')) return;

$(this).siblings("button").addClass("ui-icon ui-icon-calendar");

var holder = $(this).closest('.field.date'),
config = $.extend(opts || {}, $(this).data(), $(this).data('jqueryuiconfig'), {});
if(!config.showcalendar) return;
ssDatepicker: function(opts) {
return $(this).each(function() {

if(config.locale && $.datepicker.regional[config.locale]) {
config = $.extend(config, $.datepicker.regional[config.locale], {});
}

if(config.min) config.minDate = $.datepicker.parseDate('yy-mm-dd', config.min);
if(config.max) config.maxDate = $.datepicker.parseDate('yy-mm-dd', config.max);

// Initialize and open a datepicker
// live() doesn't have "onmatch", and jQuery.entwine is a bit too heavyweight for this, so we need to do this onclick.
config.dateFormat = config.jquerydateformat;
$(this).datepicker(config);
});
}
// disabled, readonly or already applied
if ($(this).prop('disabled') || $(this).prop('readonly') || $(this).hasClass('hasDatepicker')) {
return;
}

$(this).siblings("button").addClass("ui-icon ui-icon-calendar");

let config = $.extend(
{},
opts || {},
$(this).data(),
$(this).data('jqueryuiconfig')
);
if(!config.showcalendar) {
return;
}

if(config.locale && $.datepicker.regional[config.locale]) {
// Note: custom config overrides regional settings
config = $.extend({}, $.datepicker.regional[config.locale], config);
}

// Initialize and open a datepicker
// live() doesn't have "onmatch", and jQuery.entwine is a bit too heavyweight
// for this, so we need to do this onclick.
$(this).datepicker(config);
});
}
});

$(document).on("click", ".field.date input.text,input.text.date", function() {
$(this).ssDatepicker();
$(this).ssDatepicker();

if($(this).data('datepicker')) {
$(this).datepicker('show');
}
if($(this).data('datepicker')) {
$(this).datepicker('show');
}
});
3 changes: 2 additions & 1 deletion admin/code/CMSMenu.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Manifest\ClassLoader;
use SilverStripe\Core\Object;
use SilverStripe\Control\Controller;
use SilverStripe\i18n\i18n;
Expand Down Expand Up @@ -427,7 +428,7 @@ public function provideI18nEntities()
$entities = array();
foreach ($cmsClasses as $cmsClass) {
$defaultTitle = LeftAndMain::menu_title($cmsClass, false);
$ownerModule = i18n::get_owner_module($cmsClass);
$ownerModule = ClassLoader::instance()->getManifest()->getOwnerModule($cmsClass);
$entities["{$cmsClass}.MENUTITLE"] = [
'default' => $defaultTitle,
'module' => $ownerModule
Expand Down
3 changes: 2 additions & 1 deletion admin/code/LeftAndMain.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use SilverStripe\Dev\Deprecation;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\HiddenField;
use SilverStripe\Forms\HTMLEditor\TinyMCEConfig;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\FormAction;
use SilverStripe\Forms\FieldList;
Expand Down Expand Up @@ -576,7 +577,7 @@ protected function init()
// Set default values in the config if missing. These things can't be defined in the config
// file because insufficient information exists when that is being processed
$htmlEditorConfig = HTMLEditorConfig::get_active();
$htmlEditorConfig->setOption('language', i18n::get_tinymce_lang());
$htmlEditorConfig->setOption('language', TinyMCEConfig::get_tinymce_lang());

Requirements::customScript("
window.ss = window.ss || {};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
$DateField.SmallFieldHolder
$TimeField.SmallFieldHolder
<% if $HasTimezone %>
<% if $TimeZone %>
$TimezoneField.Field
<% end_if %>
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ A custom date format for a [api:DateField] can be provided through `setConfig`.

:::php
// will display a date in the following format: 31-06-2012
DateField::create('MyDate')->setConfig('dateformat', 'dd-MM-yyyy');
DateField::create('MyDate')->setDateFormat('dd-MM-yyyy');

<div class="info" markdown="1">
The formats are based on [Zend_Date constants](http://framework.zend.com/manual/1.12/en/zend.date.constants.html).
Expand Down
85 changes: 83 additions & 2 deletions docs/en/04_Changelogs/4.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,7 @@ specific functions.
service name from the filename. Now the service name will either
by the array key, or the `class` parameter value.
* Uniqueness checks for `File.Name` is performed on write only (not in `setName()`)
* Created `Resettable` interface to better declare objects which should be reset between tests.

#### <a name="overview-general-removed"></a>General and Core Removed API

Expand Down Expand Up @@ -1051,6 +1052,26 @@ A very small number of methods were chosen for deprecation, and will be removed
* `ChangeSet` and `ChangeSetItem` have been added for batch publishing of versioned dataobjects.
* `DataObject.table_name` config can now be used to customise the database table for any record.
* `DataObjectSchema` class added to assist with mapping between classes and tables.
* `DBMoney` values are now treated as empty only Amount is null. Values without Currency
will be formatted in the default locale.

The below methods have been added or had their functionality updated to `DBDate`, `DBTime` and `DBDatetime`
* `getTimestamp()` added to get the respective date / time as unix timestamp (seconds since 1970-01-01)
* `Format()` method now use CLDR format strings, rather than PHP format strings.
See http://userguide.icu-project.org/formatparse/datetime.
* getISOFormat() added which returns the standard date/time ISO 8601 pattern in CLDR format.
* Dates passed in m/d/y format will now raise a notice but will be parsed.
Dates passed to constructors should follow ISO 8601 (y-m-d).
* 2-digit years will raise a notice.
* `FormatFromSettings` will default to `Nice()` format if no member is logged in.
* `Nice`, `Long` and `Full` methods will now follow standard formatting rules for the
current locale, rather than pre-defined formats.
* `Short` added to format concise date/time values, as a shorter version than `Nice`
* `getFormatter` method added, which returns a locale-specific date/time formatter.

`DBTime` specific changes:
* Added `DBTime::FormatFromSettings`
* Added `DBTime::Nice12`

#### <a name="overview-orm-removed"></a>ORM Removed API

Expand Down Expand Up @@ -1085,6 +1106,24 @@ A very small number of methods were chosen for deprecation, and will be removed
* `DataObject::validateModelDefinitions()` has been removed. Validation and parsing of config is now handled
within `DataObjectSchema`.
* `CMSBatchAction_Delete` removed. Use `CMSBatchAction_Archive` instead.
* Removed several DBDate methods:
- `past_date`
- `prior_monday`
- `weekday`
- `next_day`
- `day_before`
- `days_between`
* `nice_format` has been removed from `DBDate` / `DBTime` / `DBDatetime` has been removed in favour of
locale-specific formatting for Nice()
* Removed `DBTime::TwelveHour`
* Removed some `DBMoney` methods due to lack of support in php-intl.
- `NiceWithShortname`
- `NiceWithName`
- `getShortName`
- `getCurrencyName`
* Removed additional arguments from `DBMoney::getSymbol`. The result of this value is
now localised based on the currency code assigned to the `DBMoney` instance
* Removed `DBMoney::getAllowedCurrencies`. Apply validation to `MoneyField` instead.

### <a name="overview-filesystem"></a>Filesystem API

Expand Down Expand Up @@ -1275,6 +1314,28 @@ handle field-level and form-level messages. This has the following properties:

* `$message` second constructor parameter is removed. Constructor only accepts `$result`,
which may be a string, and optional `$code`

New `DatetimeField` methods replace `getConfig()` / `setConfig()`:

* `getTimezone()` / `setTimezone()`
* `getDateTimeOrder()` / `setDateTimeOrder()`
* `getLocale()` / `setLocale()`

New `DateField` methods replace `getConfig()` / `setConfig()`:

* `getShowCalendar()` / `setShowCalendar()`
* `getDateFormat()` / `setShowCalendar()`
* `getMinDate()` / `setMinDate()`
* `getMaxDate()` / `setMaxDate()`
* `getPlaceholders()` / `setPlaceholders()`
* `getSeparateDMYFields()` / `setSeparateDMYFields()`
* `getClientLocale` / `setClientLocale`
* `getLocale()` / `setLocale()`

New `TimeField` methods replace `getConfig()` / `setConfig()`

* `getTimeFormat()` / `setTimeFormat()`
* `getLocale()` / `setLocale()`

#### <a name="overview-template-removed"></a>Template and Form Removed API

Expand Down Expand Up @@ -1307,6 +1368,8 @@ handle field-level and form-level messages. This has the following properties:
* Removed `PermissionCheckboxSetField::getAssignedPermissionCodes()` (never implemented)
* `Requirements::delete_combined_files()` and `Requirements::delete_combined_files()` methods have been removed
as they are obsolete.
* Removed `DatetimeField`, `DateField` and `TimeField` methods `getConfig` and `setConfig`. Individual
getters and setters for individual options are provided instead. See above for list of new methods.

### <a name="overview-i18n"></a>i18n API

Expand All @@ -1320,12 +1383,30 @@ handle field-level and form-level messages. This has the following properties:
for all DataObject subclasses, rather than just the basename without namespace.
* i18n key for locale-respective pluralisation rules added as '.PLURALS'. These can be configured
within yaml in array format as per [ruby i18n pluralization rules](http://guides.rubyonrails.org/i18n.html#pluralization).
* `i18n.all_locales` config moved to `Locales.locales`
* `i18n.common_languages` config moved to `Locales.languages`
* `i18n.likely_subtags` config moved to `Locales.likely_subtags`
* `i18n.tinymce_lang` config moved to `TinyMCEConfig.tinymce_lang`
* `i18n::get_tinymce_lang()` moved to `TinyMCEConfig::get_tinymce_lang()`
* `i18n::get_locale_from_lang()` moved to `Locales::localeFromLang()`
* `i18n::get_lange_from_locale()` moved to `Locales::langFromLocale()`
* `i18n::validate_locale()` moved to `Locales::validate()`
* `i18n::get_common_languages()` moved to `Locales::getLanguages()`
* `i18n::get_locale_name()` moved to `Locales::localeName()`
* `i18n::get_language_name()` moved to `Locales::languageName()`
* `i18n.module_priority` config moved to `Sources.module_priority`
* `i18n::get_owner_module()` moved to `ClassManifest::getOwnerModule()`
* `i18n::get_existing_translations()` moved to `Sources::getKnownLocales()`

#### <a name="overview-i18n-removed"></a>i18n API Removed API

* `Zend_Translate` removed
* `i18n::_t` Support for sprintf-style `%s` arguments deprecated
* `i18n::_t` Using non-associative injection with named parameters is now an error
* `i18n::_t()` Support for sprintf-style `%s` arguments deprecated
* `i18n::_t()` Using non-associative injection with named parameters is now an error
* `i18n::get_language_name()` removed.
* `i18n::get_language_code()` removed.
* `i18n::get_common_locales()` removed.
* `i18n.common_locales` config removed

### <a name="overview-mailer"></a>Email and Mailer

Expand Down
2 changes: 1 addition & 1 deletion src/Control/CookieJar.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public function set($name, $value, $expiry = 90, $path = null, $domain = null, $
//expiry === 0 is a special case where we set a cookie for the current user session
if ($expiry !== 0) {
//don't do the maths if we are clearing
$expiry = $clear ? -1 : DBDatetime::now()->Format('U') + (86400 * $expiry);
$expiry = $clear ? -1 : DBDatetime::now()->getTimestamp() + (86400 * $expiry);
}
//set the path up
$path = $path ? $path : Director::baseURL();
Expand Down
2 changes: 1 addition & 1 deletion src/Control/Director.php
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ public static function setBaseURL($baseURL)
*/
public static function baseFolder()
{
$alternate = Config::inst()->get('SilverStripe\\Control\\Director', 'alternate_base_folder');
$alternate = static::config()->get('alternate_base_folder');
return ($alternate) ? $alternate : BASE_PATH;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Control/Email/Email.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ public function getSwiftMessage()
*/
public function setSwiftMessage($swiftMessage)
{
$swiftMessage->setDate(DBDatetime::now()->Format('U'));
$swiftMessage->setDate(DBDatetime::now()->getTimestamp());
if (!$swiftMessage->getFrom() && ($defaultFrom = $this->config()->admin_email)) {
$swiftMessage->setFrom($defaultFrom);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Control/FlushRequestFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace SilverStripe\Control;

use SilverStripe\Core\Flushable;
use SilverStripe\ORM\DataModel;
use SilverStripe\Core\ClassInfo;

Expand All @@ -23,7 +24,7 @@ class FlushRequestFilter implements RequestFilter
public function preRequest(HTTPRequest $request, Session $session, DataModel $model)
{
if (array_key_exists('flush', $request->getVars())) {
foreach (ClassInfo::implementorsOf('SilverStripe\\Core\\Flushable') as $class) {
foreach (ClassInfo::implementorsOf(Flushable::class) as $class) {
$class::flush();
}
}
Expand Down
27 changes: 27 additions & 0 deletions src/Core/Manifest/ClassManifest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace SilverStripe\Core\Manifest;

use Exception;
use SilverStripe\Control\Director;

/**
* A utility class which builds a manifest of all classes, interfaces and some
Expand Down Expand Up @@ -354,6 +355,32 @@ public function getModules()
return $modules;
}

/**
* Get module that owns this class
*
* @param string $class Class name
* @return string
*/
public function getOwnerModule($class)
{
$path = realpath($this->getItemPath($class));
if (!$path) {
return null;
}

// Find based on loaded modules
foreach ($this->getModules() as $parent => $module) {
if (stripos($path, realpath($parent)) === 0) {
return $module;
}
}

// Assume top level folder is the module name
$relativePath = substr($path, strlen(realpath(Director::baseFolder())));
$parts = explode('/', trim($relativePath, '/'));
return array_shift($parts);
}

/**
* Used to set up files that we want to exclude from parsing for performance reasons.
*/
Expand Down
17 changes: 17 additions & 0 deletions src/Core/Resettable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace SilverStripe\Core;

/**
* Represents a class with a local cache which normally invalidates itself between requests.
*
* Designed so that tests can automatically flush these objects between runs in lieu
* of a real change.
*/
interface Resettable
{
/**
* Reset the local cache of this object
*/
public static function reset();
}
Loading

0 comments on commit a9d39d2

Please sign in to comment.