diff --git a/.travis.yml b/.travis.yml index 7e07b40a6..ca6eb50ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,7 +58,6 @@ matrix: before_script: # Init PHP - pecl channel-update pecl.php.net - - travis_retry printf "\n" | pecl install imagick - phpenv rehash - phpenv config-rm xdebug.ini || true - echo 'memory_limit = 2048M' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini diff --git a/docs/en/00_Getting_Started/02_Composer.md b/docs/en/00_Getting_Started/02_Composer.md index 437399cb3..f24618ce8 100644 --- a/docs/en/00_Getting_Started/02_Composer.md +++ b/docs/en/00_Getting_Started/02_Composer.md @@ -41,7 +41,7 @@ For those that use WAMP as a development environment, [detailed information is a Composer can create a new site for you, using the installer as a template (by default composer will download the latest stable version): ``` -composer create-project silverstripe/installer ./my/website/folder +composer create-project silverstripe/installer ./my/website/folder ^4 ``` If you want to get all additional fixtures for testing, such as behat and phpunit configuration, @@ -282,7 +282,7 @@ the latest unstable silverstripe/installer composer create-project silverstripe/installer ./my/website/folder dev-master ``` -Or for the latest development version in the 3.0.x series +Or for the latest development version in the 4.0.x series ``` composer create-project silverstripe/installer ./my/website/folder 4.0.x-dev diff --git a/docs/en/04_Changelogs/4.0.0.md b/docs/en/04_Changelogs/4.0.0.md index 72c761b7e..12f414bfd 100644 --- a/docs/en/04_Changelogs/4.0.0.md +++ b/docs/en/04_Changelogs/4.0.0.md @@ -1,4 +1,4 @@ -# 4.0.0 (unreleased) +# 4.0.0 ## Introduction @@ -81,7 +81,6 @@ Backup your existing `composer.json` and overwrite it with the following content This composer file uses the new [recipe](https://github.com/silverstripe/recipe-plugin) approach which bundles all core dependencies in a meta package. If you want more granular control over what gets installed, check the `composer.json` files in [recipe-core](https://github.com/silverstripe/recipe-core) and [recipe-cms](https://github.com/silverstripe/recipe-cms). -Since this is a pre-release, you need to allow composer to install unstable dependencies via `minimum-stability: dev`. Now run a `composer update`. This will remove all existing modules from your local codebase since we replaced your project's `composer.json`. Now you can move back your modules @@ -488,6 +487,7 @@ For instance, code which logs errors should be upgraded as below: ```diff -SS_Log::log('My error message', SS_Log::ERR); +use Psr\Log\LoggerInterface; ++use SilverStripe\Core\Injector\Injector; +Injector::inst()->get(LoggerInterface::class)->error('My error message'); ``` diff --git a/src/Control/Email/Email.php b/src/Control/Email/Email.php index ffa0dbfd6..230af870f 100644 --- a/src/Control/Email/Email.php +++ b/src/Control/Email/Email.php @@ -621,6 +621,12 @@ class Email extends ViewableData */ public function setBody($body) { + $plainPart = $this->findPlainPart(); + if ($plainPart) { + $this->getSwiftMessage()->detach($plainPart); + } + unset($plainPart); + $body = HTTP::absoluteURLs($body); $this->getSwiftMessage()->setBody($body); @@ -856,6 +862,12 @@ class Email extends ViewableData */ public function generatePlainPartFromBody() { + $plainPart = $this->findPlainPart(); + if ($plainPart) { + $this->getSwiftMessage()->detach($plainPart); + } + unset($plainPart); + $this->getSwiftMessage()->addPart( Convert::xml2raw($this->getBody()), 'text/plain', diff --git a/src/Dev/SapphireTest.php b/src/Dev/SapphireTest.php index 0c3fec858..8b4cc28cc 100644 --- a/src/Dev/SapphireTest.php +++ b/src/Dev/SapphireTest.php @@ -343,12 +343,18 @@ class SapphireTest extends PHPUnit_Framework_TestCase implements TestOnly * - Custom state helpers * * User code should call parent::setUpBeforeClass() before custom setup code + * + * @throws Exception */ public static function setUpBeforeClass() { // Start tests static::start(); + if (!static::$state) { + throw new Exception('SapphireTest failed to bootstrap!'); + } + // Call state helpers static::$state->setUpOnce(static::class); diff --git a/src/Forms/RequiredFields.php b/src/Forms/RequiredFields.php index 9972f042d..27916f03b 100644 --- a/src/Forms/RequiredFields.php +++ b/src/Forms/RequiredFields.php @@ -44,7 +44,7 @@ class RequiredFields extends Validator /** * Clears all the validation from this object. * - * @return RequiredFields + * @return $this */ public function removeValidation() { @@ -56,6 +56,7 @@ class RequiredFields extends Validator /** * Debug helper + * @return string */ public function debug() { @@ -152,7 +153,7 @@ class RequiredFields extends Validator * * @param string $field * - * @return RequiredFields + * @return $this */ public function addRequiredField($field) { @@ -166,7 +167,7 @@ class RequiredFields extends Validator * * @param string $field * - * @return RequiredFields + * @return $this */ public function removeRequiredField($field) { @@ -179,7 +180,7 @@ class RequiredFields extends Validator * Add {@link RequiredField} objects together * * @param RequiredFields $requiredFields - * @return RequiredFields + * @return $this */ public function appendRequiredFields($requiredFields) { diff --git a/src/ORM/FieldType/DBText.php b/src/ORM/FieldType/DBText.php index 1e6066727..494d21986 100644 --- a/src/ORM/FieldType/DBText.php +++ b/src/ORM/FieldType/DBText.php @@ -198,7 +198,7 @@ class DBText extends DBString $keywords = Convert::raw2xml($keywords); // Find the search string - $position = (int) stripos($text, $keywords); + $position = (int) mb_stripos($text, $keywords); // We want to search string to be in the middle of our block to give it some context $position = max(0, $position - ($characters / 2)); @@ -206,19 +206,19 @@ class DBText extends DBString if ($position > 0) { // We don't want to start mid-word $position = max( - (int) strrpos(substr($text, 0, $position), ' '), - (int) strrpos(substr($text, 0, $position), "\n") + (int) mb_strrpos(substr($text, 0, $position), ' '), + (int) mb_strrpos(substr($text, 0, $position), "\n") ); } - $summary = substr($text, $position, $characters); + $summary = mb_substr($text, $position, $characters); $stringPieces = explode(' ', $keywords); if ($highlight) { // Add a span around all key words from the search term as well if ($stringPieces) { foreach ($stringPieces as $stringPiece) { - if (strlen($stringPiece) > 2) { + if (mb_strlen($stringPiece) > 2) { // Maintain case of original string $summary = preg_replace( '/' . preg_quote($stringPiece, '/') . '/i', diff --git a/tests/php/ORM/DBTextTest.php b/tests/php/ORM/DBTextTest.php index e5985cc33..2fde108a0 100644 --- a/tests/php/ORM/DBTextTest.php +++ b/tests/php/ORM/DBTextTest.php @@ -41,6 +41,7 @@ class DBTextTest extends SapphireTest ['The little brown fox jumped over the lazy cow.', 'The little brown fox...'], ['
Short & Sweet
', '<p>Short & Sweet</p>'], ['This text contains & in it', 'This text contains &...'], + ['Is an umault in schön?', 'Is an umault in schö...'], ]; } @@ -80,7 +81,10 @@ class DBTextTest extends SapphireTest ['Lorem ipsum dolor sit amet
', 24, '<p>Lorem ipsum dolor...'], ['Lorem ipsum dolor sit amet
', 24, '<p><span>Lorem ipsum...'], ['Lorem ipsum
', 24, '<p>Lorem ipsum</p>'], - ['Lorem & ipsum dolor sit amet', 24, 'Lorem & ipsum dolor...'] + ['Lorem & ipsum dolor sit amet', 24, 'Lorem & ipsum dolor...'], + + ['Is an umault in schön or not?', 22, 'Is an umault in schön...'], + ]; } @@ -124,6 +128,9 @@ class DBTextTest extends SapphireTest // If storing HTML you should use DBHTMLText instead ['Text inside a paragraph tag should also work
', 3, '<p>Text inside a...'], ['Two words
', 3, '<p>Two words</p>'], + + // Check UTF8 + ['Is an umault in schön or not?', 5, 'Is an umault in schön...'], ]; } @@ -156,6 +163,9 @@ class DBTextTest extends SapphireTest // If storing HTML you should use DBHTMLText instead ['First sentence.
', 2, '<p>First sentence.</p>'], ['First sentence. Second sentence. Third sentence
', 2, '<p>First sentence. Second sentence.'], + + // Check UTF8 + ['Is schön. Isn\'t schön.', 1, 'Is schön.'], ]; } @@ -187,6 +197,9 @@ class DBTextTest extends SapphireTest // If storing HTML you should use DBHTMLText instead ['First sentence. Second sentence. Third sentence
', '<p>First sentence.'], + + // Check UTF8 + ['Is schön. Isn\'t schön.', 'Is schön.'], ]; } @@ -243,7 +256,16 @@ class DBTextTest extends SapphireTest 'ate', // it should highlight 3 letters or more. 'A dog ate a cat while looking at a Foobar', + ], + [ + 'both schön and können have umlauts', + 21, + 'schön', + // check UTF8 support + 'both schön and können...', ] + + ]; }