Update config / code styles for 4.0

Related https://github.com/silverstripe/silverstripe-framework/issues/7590
This commit is contained in:
Damian Mooyman 2017-11-21 17:35:20 +13:00
parent acaaf95d22
commit 24cf40beaf
No known key found for this signature in database
GPG Key ID: 78B823A10DE27D1A
9 changed files with 176 additions and 84 deletions

View File

@ -1,8 +1,10 @@
language: php language: php
dist: precise dist: trusty
sudo: false cache:
directories:
- $HOME/.composer/cache/files
php: php:
- 5.6 - 5.6
@ -10,25 +12,29 @@ php:
- 7.1 - 7.1
env: env:
- DB=SQLITE CORE_RELEASE=4 PDO=1 global:
- DB=SQLITE
- PDO=1
matrix: matrix:
fast_finish: true fast_finish: true
include: include:
- php: 5.6 - php: 5.6
env: DB=SQLITE CORE_RELEASE=4 PDO=0 env: PDO=0 PHPCS_TEST=1
before_script: before_script:
# Init PHP # Init PHP
- printf "\n" | pecl install imagick
- phpenv rehash - phpenv rehash
- phpenv config-rm xdebug.ini - phpenv config-rm xdebug.ini
- export PATH=~/.composer/vendor/bin:$PATH
- echo 'memory_limit = 2048M' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini - echo 'memory_limit = 2048M' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
# Install composer dependencies # Install composer dependencies
- composer validate - composer validate
- composer require symfony/config:^3.2 silverstripe/framework:4.0.x-dev silverstripe/cms:4.0.x-dev silverstripe/siteconfig:4.0.x-dev silverstripe/config:1.0.x-dev silverstripe/admin:1.0.x-dev silverstripe/assets:1.0.x-dev silverstripe/versioned:1.0.x-dev --no-update - composer require --no-update silverstripe/recipe-cms:1.0.x-dev
- composer install --prefer-dist --no-interaction --no-progress --no-suggest --optimize-autoloader --verbose --profile - composer install --prefer-dist --no-interaction --no-progress --no-suggest --optimize-autoloader --verbose --profile
- if [[ $PHPCS_TEST ]]; then composer global require squizlabs/php_codesniffer:^3 --prefer-dist --no-interaction --no-progress --no-suggest -o; fi
script: script:
- vendor/bin/phpunit vendor/silverstripe/framework/tests - vendor/bin/phpunit vendor/silverstripe/framework/tests
- if [[ $PHPCS_TEST ]]; then composer run-script lint; fi

View File

@ -1,14 +1,25 @@
<?php <?php
// Script called from ConfigureFromEnv.php // Called from DatabaseAdapterRegistry::autoconfigure($config)
global $databaseConfig; use SilverStripe\Core\Environment;
if(strpos($databaseConfig['type'], 'SQLite') === 0) { use SilverStripe\SQLite\SQLite3Database;
if(defined('SS_SQLITE_DATABASE_PATH')) { if (!isset($databaseConfig)) {
$databaseConfig['path'] = SS_SQLITE_DATABASE_PATH; global $databaseConfig;
} }
if(defined('SS_SQLITE_DATABASE_KEY')) { // Get path
$databaseConfig['key'] = SS_SQLITE_DATABASE_KEY; $path = Environment::getEnv(SQLite3Database::ENV_PATH);
} if ($path) {
$databaseConfig['path'] = $path;
} elseif (defined(SQLite3Database::ENV_PATH)) {
$databaseConfig['path'] = constant(SQLite3Database::ENV_PATH);
}
// Get key
$key = Environment::getEnv(SQLite3Database::ENV_KEY);
if ($key) {
$databaseConfig['key'] = $key;
} elseif (defined(SQLite3Database::ENV_KEY)) {
$databaseConfig['key'] = constant(SQLite3Database::ENV_KEY);
} }

View File

@ -4,51 +4,51 @@ use SilverStripe\Dev\Install\DatabaseAdapterRegistry;
use SilverStripe\SQLite\SQLiteDatabaseConfigurationHelper; use SilverStripe\SQLite\SQLiteDatabaseConfigurationHelper;
$sqliteDatabaseAdapterRegistryFields = array( $sqliteDatabaseAdapterRegistryFields = array(
'path' => array( 'path' => array(
'title' => 'Directory path<br /><small>Absolute path to directory, writeable by the webserver user.<br />' 'title' => 'Directory path<br /><small>Absolute path to directory, writeable by the webserver user.<br />'
. 'Recommended to be outside of your webroot</small>', . 'Recommended to be outside of your webroot</small>',
'default' => dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . '.sqlitedb' 'default' => dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'assets' . DIRECTORY_SEPARATOR . '.sqlitedb'
), ),
'database' => array( 'database' => array(
'title' => 'Database filename (extension .sqlite)', 'title' => 'Database filename (extension .sqlite)',
'default' => 'database.sqlite' 'default' => 'database.sqlite'
) )
); );
// Basic SQLLite3 Database // Basic SQLLite3 Database
/** @skipUpgrade */ /** @skipUpgrade */
DatabaseAdapterRegistry::register( DatabaseAdapterRegistry::register(
array( array(
'class' => 'SQLite3Database', 'class' => 'SQLite3Database',
'module' => 'sqlite3', 'module' => 'sqlite3',
'title' => 'SQLite 3.3+ (using SQLite3)', 'title' => 'SQLite 3.3+ (using SQLite3)',
'helperPath' => __DIR__.'/code/SQLiteDatabaseConfigurationHelper.php', 'helperPath' => __DIR__.'/code/SQLiteDatabaseConfigurationHelper.php',
'helperClass' => SQLiteDatabaseConfigurationHelper::class, 'helperClass' => SQLiteDatabaseConfigurationHelper::class,
'supported' => class_exists('SQLite3'), 'supported' => class_exists('SQLite3'),
'missingExtensionText' => 'The <a href="http://php.net/manual/en/book.sqlite3.php">SQLite3</a> 'missingExtensionText' => 'The <a href="http://php.net/manual/en/book.sqlite3.php">SQLite3</a>
PHP Extension is not available. Please install or enable it of them and refresh this page.', PHP Extension is not available. Please install or enable it of them and refresh this page.',
'fields' => array_merge($sqliteDatabaseAdapterRegistryFields, array('key' => array( 'fields' => array_merge($sqliteDatabaseAdapterRegistryFields, array('key' => array(
'title' => 'Encryption key<br><small>This function is experimental and requires configuration of an ' 'title' => 'Encryption key<br><small>This function is experimental and requires configuration of an '
. 'encryption module</small>', . 'encryption module</small>',
'default' => '' 'default' => ''
))) )))
) )
); );
// PDO database // PDO database
/** @skipUpgrade */ /** @skipUpgrade */
DatabaseAdapterRegistry::register( DatabaseAdapterRegistry::register(
array( array(
'class' => 'SQLite3PDODatabase', 'class' => 'SQLite3PDODatabase',
'module' => 'sqlite3', 'module' => 'sqlite3',
'title' => 'SQLite 3.3+ (using PDO)', 'title' => 'SQLite 3.3+ (using PDO)',
'helperPath' => __DIR__.'/code/SQLiteDatabaseConfigurationHelper.php', 'helperPath' => __DIR__.'/code/SQLiteDatabaseConfigurationHelper.php',
'helperClass' => SQLiteDatabaseConfigurationHelper::class, 'helperClass' => SQLiteDatabaseConfigurationHelper::class,
'supported' => (class_exists('PDO') && in_array('sqlite', PDO::getAvailableDrivers())), 'supported' => (class_exists('PDO') && in_array('sqlite', PDO::getAvailableDrivers())),
'missingExtensionText' => 'missingExtensionText' =>
'Either the <a href="http://php.net/manual/en/book.pdo.php">PDO Extension</a> or the 'Either the <a href="http://php.net/manual/en/book.pdo.php">PDO Extension</a> or the
<a href="http://php.net/manual/en/book.sqlite3.php">SQLite3 PDO Driver</a> <a href="http://php.net/manual/en/book.sqlite3.php">SQLite3 PDO Driver</a>
are unavailable. Please install or enable these and refresh this page.', are unavailable. Please install or enable these and refresh this page.',
'fields' => $sqliteDatabaseAdapterRegistryFields 'fields' => $sqliteDatabaseAdapterRegistryFields
) )
); );

View File

@ -111,7 +111,7 @@ class SQLite3Connector extends DBConnector
case 'array': case 'array':
case 'unknown type': case 'unknown type':
default: default:
user_error("Cannot bind parameter \"$value\" as it is an unsupported type ($phpType)", E_USER_ERROR); $this->databaseError("Cannot bind parameter \"$value\" as it is an unsupported type ($phpType)");
break; break;
} }
$values[] = array( $values[] = array(
@ -176,7 +176,7 @@ class SQLite3Connector extends DBConnector
public function selectDatabase($name) public function selectDatabase($name)
{ {
if ($name !== $this->databaseName) { if ($name !== $this->databaseName) {
user_error("SQLite3Connector can't change databases. Please create a new database connection", E_USER_ERROR); $this->databaseError("SQLite3Connector can't change databases. Please create a new database connection");
} }
return true; return true;
} }

View File

@ -20,6 +20,16 @@ class SQLite3Database extends Database
{ {
use Configurable; use Configurable;
/**
* Global environment config for setting 'path'
*/
const ENV_PATH = 'SS_SQLITE_DATABASE_PATH';
/**
* Global environment config for setting 'key'
*/
const ENV_KEY = 'SS_SQLITE_DATABASE_KEY';
/** /**
* Extension added to every database name * Extension added to every database name
* *
@ -178,7 +188,8 @@ class SQLite3Database extends Database
* *
* @return string|null * @return string|null
*/ */
public function getPath() { public function getPath()
{
if ($this->getLivesInMemory()) { if ($this->getLivesInMemory()) {
return null; return null;
} }
@ -278,14 +289,22 @@ class SQLite3Database extends Database
* @param bool $invertedMatch * @param bool $invertedMatch
* @return PaginatedList DataObjectSet of result pages * @return PaginatedList DataObjectSet of result pages
*/ */
public function searchEngine($classesToSearch, $keywords, $start, $pageLength, $sortBy = "Relevance DESC", public function searchEngine(
$extraFilter = "", $booleanSearch = false, $alternativeFileFilter = "", $invertedMatch = false $classesToSearch,
$keywords,
$start,
$pageLength,
$sortBy = "Relevance DESC",
$extraFilter = "",
$booleanSearch = false,
$alternativeFileFilter = "",
$invertedMatch = false
) { ) {
$keywords = $this->escapeString(str_replace(array('*', '+', '-', '"', '\''), '', $keywords)); $keywords = $this->escapeString(str_replace(array('*', '+', '-', '"', '\''), '', $keywords));
$htmlEntityKeywords = htmlentities(utf8_decode($keywords)); $htmlEntityKeywords = htmlentities(utf8_decode($keywords));
$pageClass = 'SilverStripe\\CMS\\Model\\SiteTree'; $pageClass = 'SilverStripe\\CMS\\Model\\SiteTree';
$fileClass = 'SilverStripe\\Assets\\File'; $fileClass = 'SilverStripe\\Assets\\File';
$extraFilters = array($pageClass => '', $fileClass => ''); $extraFilters = array($pageClass => '', $fileClass => '');
@ -311,17 +330,24 @@ class SQLite3Database extends Database
$notMatch = $invertedMatch ? "NOT " : ""; $notMatch = $invertedMatch ? "NOT " : "";
if ($keywords) { if ($keywords) {
$match[$pageClass] = " $match[$pageClass] =
(Title LIKE '%$keywords%' OR MenuTitle LIKE '%$keywords%' OR Content LIKE '%$keywords%' OR MetaDescription LIKE '%$keywords%' OR "(Title LIKE '%$keywords%' OR MenuTitle LIKE '%$keywords%' OR Content LIKE '%$keywords%'"
Title LIKE '%$htmlEntityKeywords%' OR MenuTitle LIKE '%$htmlEntityKeywords%' OR Content LIKE '%$htmlEntityKeywords%' OR MetaDescription LIKE '%$htmlEntityKeywords%') . " OR MetaDescription LIKE '%$keywords%' OR Title LIKE '%$htmlEntityKeywords%'"
"; . " OR MenuTitle LIKE '%$htmlEntityKeywords%' OR Content LIKE '%$htmlEntityKeywords%'"
. " OR MetaDescription LIKE '%$htmlEntityKeywords%')";
$fileClassSQL = Convert::raw2sql($fileClass); $fileClassSQL = Convert::raw2sql($fileClass);
$match[$fileClass] = "(Name LIKE '%$keywords%' OR Title LIKE '%$keywords%') AND ClassName = '$fileClassSQL'"; $match[$fileClass] =
"(Name LIKE '%$keywords%' OR Title LIKE '%$keywords%') AND ClassName = '$fileClassSQL'";
// We make the relevance search by converting a boolean mode search into a normal one // We make the relevance search by converting a boolean mode search into a normal one
$relevanceKeywords = $keywords; $relevanceKeywords = $keywords;
$htmlEntityRelevanceKeywords = $htmlEntityKeywords; $htmlEntityRelevanceKeywords = $htmlEntityKeywords;
$relevance[$pageClass] = "(Title LIKE '%$relevanceKeywords%' OR MenuTitle LIKE '%$relevanceKeywords%' OR Content LIKE '%$relevanceKeywords%' OR MetaDescription LIKE '%$relevanceKeywords%') + (Title LIKE '%$htmlEntityRelevanceKeywords%' OR MenuTitle LIKE '%$htmlEntityRelevanceKeywords%' OR Content LIKE '%$htmlEntityRelevanceKeywords%' OR MetaDescription LIKE '%$htmlEntityRelevanceKeywords%')"; $relevance[$pageClass] =
"(Title LIKE '%$relevanceKeywords%' OR MenuTitle LIKE '%$relevanceKeywords%'"
. " OR Content LIKE '%$relevanceKeywords%' OR MetaDescription LIKE '%$relevanceKeywords%')"
. " + (Title LIKE '%$htmlEntityRelevanceKeywords%' OR MenuTitle LIKE '%$htmlEntityRelevanceKeywords%'"
. " OR Content LIKE '%$htmlEntityRelevanceKeywords%' OR MetaDescriptio "
. " LIKE '%$htmlEntityRelevanceKeywords%')";
$relevance[$fileClass] = "(Name LIKE '%$relevanceKeywords%' OR Title LIKE '%$relevanceKeywords%')"; $relevance[$fileClass] = "(Name LIKE '%$relevanceKeywords%' OR Title LIKE '%$relevanceKeywords%')";
} else { } else {
$relevance[$pageClass] = $relevance[$fileClass] = 1; $relevance[$pageClass] = $relevance[$fileClass] = 1;
@ -464,7 +490,12 @@ class SQLite3Database extends Database
$this->query("DELETE FROM \"$table\""); $this->query("DELETE FROM \"$table\"");
} }
public function comparisonClause($field, $value, $exact = false, $negate = false, $caseSensitive = null, public function comparisonClause(
$field,
$value,
$exact = false,
$negate = false,
$caseSensitive = null,
$parameterised = false $parameterised = false
) { ) {
if ($exact && !$caseSensitive) { if ($exact && !$caseSensitive) {

View File

@ -73,7 +73,6 @@ class SQLite3SchemaManager extends DBSchemaManager
$databases = array(); $databases = array();
if ($files !== false) { if ($files !== false) {
foreach ($files as $file) { foreach ($files as $file) {
// Filter non-files // Filter non-files
if (!is_file("$directory/$file")) { if (!is_file("$directory/$file")) {
continue; continue;
@ -172,8 +171,14 @@ class SQLite3SchemaManager extends DBSchemaManager
return $table; return $table;
} }
public function alterTable($tableName, $newFields = null, $newIndexes = null, $alteredFields = null, public function alterTable(
$alteredIndexes = null, $alteredOptions = null, $advancedOptions = null $tableName,
$newFields = null,
$newIndexes = null,
$alteredFields = null,
$alteredIndexes = null,
$alteredOptions = null,
$advancedOptions = null
) { ) {
if ($newFields) { if ($newFields) {
foreach ($newFields as $fieldName => $fieldSpec) { foreach ($newFields as $fieldName => $fieldSpec) {
@ -310,10 +315,12 @@ class SQLite3SchemaManager extends DBSchemaManager
} }
// SQLite doesn't support direct renames through ALTER TABLE // SQLite doesn't support direct renames through ALTER TABLE
$oldColsStr = implode(',', $oldCols);
$newColsSpecStr = implode(',', $newColsSpec);
$queries = array( $queries = array(
"BEGIN TRANSACTION", "BEGIN TRANSACTION",
"CREATE TABLE \"{$tableName}_renamefield_{$oldName}\" (" . implode(',', $newColsSpec) . ")", "CREATE TABLE \"{$tableName}_renamefield_{$oldName}\" ({$newColsSpecStr})",
"INSERT INTO \"{$tableName}_renamefield_{$oldName}\" SELECT " . implode(',', $oldCols) . " FROM \"$tableName\"", "INSERT INTO \"{$tableName}_renamefield_{$oldName}\" SELECT {$oldColsStr} FROM \"$tableName\"",
"DROP TABLE \"$tableName\"", "DROP TABLE \"$tableName\"",
"ALTER TABLE \"{$tableName}_renamefield_{$oldName}\" RENAME TO \"$tableName\"", "ALTER TABLE \"{$tableName}_renamefield_{$oldName}\" RENAME TO \"$tableName\"",
"COMMIT" "COMMIT"
@ -329,9 +336,24 @@ class SQLite3SchemaManager extends DBSchemaManager
// Recreate the indexes // Recreate the indexes
foreach ($oldIndexList as $indexName => $indexSpec) { foreach ($oldIndexList as $indexName => $indexSpec) {
// Rename columns to new columns // Map index columns
$indexSpec['value'] = preg_replace("/\"$oldName\"/i", "\"$newName\"", $indexSpec['value']); $columns = array_filter(array_map(function ($column) use ($newName, $oldName) {
$this->createIndex($tableName, $indexName, $indexSpec); // Unchanged
if ($column !== $oldName) {
return $column;
}
// Skip obsolete fields
if (stripos($newName, '_obsolete_') === 0) {
return null;
}
return $newName;
}, $indexSpec['columns']));
// Create index if column count unchanged
if (count($columns) === count($indexSpec['columns'])) {
$indexSpec['columns'] = $columns;
$this->createIndex($tableName, $indexName, $indexSpec);
}
} }
} }
@ -344,8 +366,10 @@ class SQLite3SchemaManager extends DBSchemaManager
$fieldList = array(); $fieldList = array();
if ($sqlCreate && $sqlCreate['sql']) { if ($sqlCreate && $sqlCreate['sql']) {
preg_match('/^[\s]*CREATE[\s]+TABLE[\s]+[\'"]?[a-zA-Z0-9_\\\]+[\'"]?[\s]*\((.+)\)[\s]*$/ims', preg_match(
$sqlCreate['sql'], $matches '/^[\s]*CREATE[\s]+TABLE[\s]+[\'"]?[a-zA-Z0-9_\\\]+[\'"]?[\s]*\((.+)\)[\s]*$/ims',
$sqlCreate['sql'],
$matches
); );
$fields = isset($matches[1]) $fields = isset($matches[1])
? preg_split('/,(?=(?:[^\'"]*$)|(?:[^\'"]*[\'"][^\'"]*[\'"][^\'"]*)*$)/x', $matches[1]) ? preg_split('/,(?=(?:[^\'"]*$)|(?:[^\'"]*[\'"][^\'"]*[\'"][^\'"]*)*$)/x', $matches[1])
@ -411,7 +435,6 @@ class SQLite3SchemaManager extends DBSchemaManager
// Enumerate each index and related fields // Enumerate each index and related fields
foreach ($this->query("PRAGMA index_list(\"$table\")") as $index) { foreach ($this->query("PRAGMA index_list(\"$table\")") as $index) {
// The SQLite internal index name, not the actual Silverstripe name // The SQLite internal index name, not the actual Silverstripe name
$indexName = $index["name"]; $indexName = $index["name"];
$indexType = $index['unique'] ? 'unique' : 'index'; $indexType = $index['unique'] ? 'unique' : 'index';
@ -501,7 +524,9 @@ class SQLite3SchemaManager extends DBSchemaManager
// Ensure the cache table exists // Ensure the cache table exists
if (empty($this->enum_map)) { if (empty($this->enum_map)) {
$this->query("CREATE TABLE IF NOT EXISTS \"SQLiteEnums\" (\"TableColumn\" TEXT PRIMARY KEY, \"EnumList\" TEXT)"); $this->query(
"CREATE TABLE IF NOT EXISTS \"SQLiteEnums\" (\"TableColumn\" TEXT PRIMARY KEY, \"EnumList\" TEXT)"
);
} }
// Ensure the table row exists // Ensure the table row exists

View File

@ -41,7 +41,11 @@ class SQLiteDatabaseConfigurationHelper implements DatabaseConfigurationHelper
if (empty($databaseConfig['key'])) { if (empty($databaseConfig['key'])) {
$conn = @new SQLite3($file, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE); $conn = @new SQLite3($file, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE);
} else { } else {
$conn = @new SQLite3($file, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE, $databaseConfig['key']); $conn = @new SQLite3(
$file,
SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE,
$databaseConfig['key']
);
} }
break; break;
case 'SQLite3PDODatabase': case 'SQLite3PDODatabase':
@ -106,15 +110,15 @@ class SQLiteDatabaseConfigurationHelper implements DatabaseConfigurationHelper
// Do additional validation around file paths // Do additional validation around file paths
if (empty($databaseConfig['path'])) { if (empty($databaseConfig['path'])) {
return array( return array(
'success' => false, 'success' => false,
'error' => "Missing directory path" 'error' => "Missing directory path"
); );
} }
if (empty($databaseConfig['database'])) { if (empty($databaseConfig['database'])) {
return array( return array(
'success' => false, 'success' => false,
'error' => "Missing database filename" 'error' => "Missing database filename"
); );
} }
// Create and secure db directory // Create and secure db directory
@ -122,16 +126,16 @@ class SQLiteDatabaseConfigurationHelper implements DatabaseConfigurationHelper
$dirCreated = self::create_db_dir($path); $dirCreated = self::create_db_dir($path);
if (!$dirCreated) { if (!$dirCreated) {
return array( return array(
'success' => false, 'success' => false,
'error' => sprintf('Cannot create path: "%s"', $path) 'error' => sprintf('Cannot create path: "%s"', $path)
); );
} }
$dirSecured = self::secure_db_dir($path); $dirSecured = self::secure_db_dir($path);
if (!$dirSecured) { if (!$dirSecured) {
return array( return array(
'success' => false, 'success' => false,
'error' => sprintf('Cannot secure path through .htaccess: "%s"', $path) 'error' => sprintf('Cannot secure path through .htaccess: "%s"', $path)
); );
} }
$conn = $this->createConnection($databaseConfig, $error); $conn = $this->createConnection($databaseConfig, $error);

View File

@ -30,6 +30,10 @@
"SilverStripe\\SQLite\\": "code/" "SilverStripe\\SQLite\\": "code/"
} }
}, },
"scripts": {
"lint": "phpcs code/ *.php",
"lint-clean": "phpcbf code/ *.php"
},
"minimum-stability": "dev", "minimum-stability": "dev",
"prefer-stable": true "prefer-stable": true
} }

11
phpcs.xml.dist Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="SilverStripe">
<description>CodeSniffer ruleset for SilverStripe coding conventions.</description>
<!-- base rules are PSR-2 -->
<rule ref="PSR2" >
<!-- Current exclusions -->
<exclude name="PSR1.Methods.CamelCapsMethodName" />
</rule>
</ruleset>