jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/385375 )
Change subject: BSFoundation: Added settings data store
......................................................................
BSFoundation: Added settings data store
TODO: We still need config cache invalidation when written into db
Change-Id: I1776ef3ba3e00963a342c01bcb717249c50b7de9
---
M includes/ExtensionMW.class.php
M includes/GenericTagExtensionHandler.php
M maintenance/BSMigrateSettings.php
M src/Config.php
M src/Context.php
M src/Data/DatabaseWriter.php
M src/Data/FieldType.php
M src/Data/IRecord.php
M src/Data/IWriter.php
M src/Data/LimitOffsetTrimmer.php
M src/Data/Reader.php
M src/Data/ReaderParams.php
M src/Data/Record.php
A src/Data/RecordSet.php
M src/Data/ResultSet.php
A src/Data/Settings/PrimaryDataProvider.php
A src/Data/Settings/Reader.php
A src/Data/Settings/Record.php
A src/Data/Settings/Schema.php
A src/Data/Settings/Store.php
A src/Data/Settings/Writer.php
A src/Data/Writer.php
A src/ITagExtensionDefinitionProvider.php
M tests/phpunit/ConfigTest.php
24 files changed, 649 insertions(+), 63 deletions(-)
Approvals:
Robert Vogel: Looks good to me, approved
jenkins-bot: Verified
diff --git a/includes/ExtensionMW.class.php b/includes/ExtensionMW.class.php
index 1a79b04..875bf62 100644
--- a/includes/ExtensionMW.class.php
+++ b/includes/ExtensionMW.class.php
@@ -1,11 +1,12 @@
<?php
use BlueSpice\Extension;
+use BlueSpice\ITagExtensionDefinitionProvider;
/**
* @deprecated since version 3.0.0 - Use \BlueSpice\Extension instead
*/
-abstract class BsExtensionMW extends Extension {
+abstract class BsExtensionMW extends Extension implements
ITagExtensionDefinitionProvider {
protected $mExtensionKey = null;
protected $mExtensionFile = null;
@@ -236,11 +237,9 @@
/**
* Returns an array of tag extension definitions
- * @deprecated since version 3.0.0
* @return array
*/
public function makeTagExtensionDefinitions() {
- wfDeprecated( __METHOD__, '3.0.0' );
return array();
}
}
diff --git a/includes/GenericTagExtensionHandler.php
b/includes/GenericTagExtensionHandler.php
index f6d9df0..89b1e3e 100644
--- a/includes/GenericTagExtensionHandler.php
+++ b/includes/GenericTagExtensionHandler.php
@@ -56,6 +56,9 @@
*/
public static function setupHandlers( $aExtensions, $parser ) {
foreach( $aExtensions as $oExtension ) {
+ if( !$oExtension instanceof
BlueSpice\ITagExtensionDefinitionProvider ) {
+ continue;
+ }
$aExtensionTags =
$oExtension->makeTagExtensionDefinitions();
foreach( $aExtensionTags as $sTagName => $aTagDef ) {
$oTagHandler = new self( $sTagName, $aTagDef );
diff --git a/maintenance/BSMigrateSettings.php
b/maintenance/BSMigrateSettings.php
index 555beea..848db80 100644
--- a/maintenance/BSMigrateSettings.php
+++ b/maintenance/BSMigrateSettings.php
@@ -2,18 +2,7 @@
require_once( 'BSMaintenance.php' );
-class BSMigrateSettings extends Maintenance {
-
- public function execute() {
- if( $this->noDataToMigrate() ) {
- $this->output( "bs_settings -> bs_settings3: No data to
migrate" );
- return;
- }
-
- $this->readOldData();
- $this->convertData();
- $this->saveConvertedData();
- }
+class BSMigrateSettings extends LoggedUpdateMaintenance {
protected function noDataToMigrate() {
return $this->getDB( DB_REPLICA )->tableExists( 'bs_settings' )
=== false;
@@ -38,19 +27,34 @@
}
protected function makeNewName( $oldName ) {
- if( $oldName === 'MW::LogoPath' ) {
- return 'wgLogo';
+ if( $deviatingName = $this->fromDeviatingNames( $oldName ) ) {
+ return $deviatingName;
}
//$oldName = "MW::TopMenuBarCustomizer::NumberOfSubEntries"
$nameParts = explode( '::', $oldName );
array_shift( $nameParts ); //MW
- $newName = 'bsg' . implode( '', $nameParts );
+ $newName = implode( '', $nameParts );
if( strlen( $newName ) > 255 ) {
throw new Exception( "Variable name '$newName' is too
long!" );
}
+ return $newName;
+ }
+
+ protected function fromDeviatingNames( $oldName ) {
+ if( $oldName === 'MW::LogoPath' ) {
+ return 'Logo';
+ }
+ if( $oldName === 'MW::FaviconPath' ) {
+ return 'Favicon';
+ }
+ $newName = false;
+ \Hooks::run( 'BSMigrateSettingsFromDeviatingNames', [
+ $oldName,
+ &$newName
+ ]);
return $newName;
}
@@ -82,11 +86,21 @@
return FormatJson::encode( $newValue );
}
-}
+ protected function doDBUpdates() {
+ if( $this->noDataToMigrate() ) {
+ $this->output( "bs_settings -> bs_settings3: No data to
migrate" );
+ return true;
+ }
-$maintClass = 'BSMigrateSettings';
-if (defined('RUN_MAINTENANCE_IF_AIN')) {
- require_once( RUN_MAINTENANCE_IF_MAIN );
-} else {
- require_once( DO_MAINTENANCE ); # Make this work on versions before 1.17
-}
\ No newline at end of file
+ $this->readOldData();
+ $this->convertData();
+ $this->saveConvertedData();
+
+ return true;
+ }
+
+ protected function getUpdateKey() {
+ return 'bs_settings3-migration';
+ }
+
+}
diff --git a/src/Config.php b/src/Config.php
index e81912b..c94e899 100644
--- a/src/Config.php
+++ b/src/Config.php
@@ -1,6 +1,9 @@
<?php
namespace BlueSpice;
+use BlueSpice\Data\Settings\Store;
+use BlueSpice\Data\Settings\Record;
+use BlueSpice\Context;
class Config extends \MultiConfig implements \Serializable {
@@ -59,25 +62,42 @@
return new self( $lb );
}
+ /**
+ * //TODO: We need a config chache invalidation when writing to the db!
+ * Invalidates the cache of config stored in the database
+ * @return boolean
+ */
+ public function invalidateCache() {
+ //TODO: We need a config chache invalidation when writing to
the db!
+ return true;
+ }
+
protected function makeDatabaseConfig() {
$hash = [];
$dbr = $this->loadBalancer->getConnection( DB_REPLICA );
- //when config get initialized before the database is created
- //(f.e.: in update.php)
- //TODO: Cache this config
if( !$dbr->tableExists( 'bs_settings3' ) ) {
return new \HashConfig( $hash );
}
- $res = $dbr->select( 'bs_settings3', '*' );
+ $store = $this->getStore();
+ $resultSet = $store->getReader()->read(
+ new Data\ReaderParams( [
+ 'limit' => Data\ReaderParams::LIMIT_INFINITE
+ ] )
+ );
- foreach( $res as $row ) {
- if( strpos( $row->s_name, 'bsg' ) === 0 ) {
- $name = substr( $row->s_name, 3 );
- $hash[$name] = \FormatJson::decode(
$row->s_value );
- }
+ foreach( $resultSet->getRecords() as $record ) {
+ $name = $record->get( Record::NAME );
+ $hash[ $name ] = $record->get( Record::VALUE );
}
return new \HashConfig( $hash );
}
+ protected function getStore() {
+ return new Store(
+ new Context( \RequestContext::getMain(), $this ),
+ $this->loadBalancer
+ );
+ }
+
}
diff --git a/src/Context.php b/src/Context.php
index a369f4e..40510c0 100644
--- a/src/Context.php
+++ b/src/Context.php
@@ -1,7 +1,7 @@
<?php
namespace BlueSpice;
-abstract class Context implements \IContextSource {
+class Context implements \IContextSource {
/**
*
diff --git a/src/Data/DatabaseWriter.php b/src/Data/DatabaseWriter.php
index 979b2cf..895a809 100644
--- a/src/Data/DatabaseWriter.php
+++ b/src/Data/DatabaseWriter.php
@@ -1,8 +1,9 @@
<?php
namespace BlueSpice\Data;
+use BlueSpice\Data\RecordSet;
-abstract class DatabaseWriter implements IWriter {
+abstract class DatabaseWriter extends Writer {
/**
*
@@ -12,9 +13,234 @@
/**
*
- * @param \LoadBalancer $loadBalancer
+ * @var IReader
*/
- public function __construct( $loadBalancer ) {
+ protected $reader = null;
+
+ abstract protected function getIdentifierFields();
+
+ abstract protected function getTableName();
+
+ /**
+ *
+ * @param IReader $reader
+ * @param \Wikimedia\Rdbms\LoadBalancer $loadBalancer
+ * @param \IContextSource $context
+ * @param \Config $config
+ */
+ public function __construct( IReader $reader, $loadBalancer,
\IContextSource $context = null, \Config $config = null ) {
+ parent::__construct( $context, $config );
+ $this->reader = $reader;
$this->db = $loadBalancer->getConnection( DB_MASTER );
}
+
+ /**
+ * Create or Update given records
+ * @param RecordSet $recordSet
+ * @return RecordSet
+ */
+ public function write( $recordSet ) {
+ foreach( $recordSet->getRecords() as $record ) {
+ if( !$record->getStatus()->isOK() ) {
+ continue;
+ }
+ if( !$existingRecord = $this->getExistingRecord(
$record ) ) {
+ $this->insert( $record );
+ continue;
+ }
+ $this->modify( $existingRecord, $record );
+ }
+ return $recordSet;
+ }
+
+ /**
+ * Remove given records
+ * @param RecordSet $recordSet
+ * @return RecordSet
+ */
+ public function remove( $recordSet ) {
+ foreach( $recordSet->getRecords() as $record ) {
+ if( !$record->getStatus()->isOK() ) {
+ continue;
+ }
+ if( !$existingRecord = $this->getExistingRecord(
$record ) ) {
+ $record->getStatus()->fatal(
+ "Record not found in table:
".$this->getTableName()
+ );
+ continue;
+ }
+ $this->delete( $existingRecord, $record );
+ }
+ return $recordSet;
+ }
+
+ /**
+ *
+ * @param \BlueSpice\Data\IRecord $record
+ */
+ protected function insert( $record ) {
+ $record->getData();
+ try {
+ $success = $this->db->insert(
+ $this->getTableName(),
+ $this->makeInsertFields( $record ),
+ __METHOD__
+ );
+ } catch ( \Exception $e ) {
+ $record->getStatus()->fatal( $e );
+ return;
+ }
+ if( !$success ) {
+ $record->getStatus()->fatal(
+ "Error writing into: ".$this->getTableName()
+ );
+ }
+ }
+
+ /**
+ *
+ * @param \BlueSpice\Data\IRecord $existingRecord
+ * @param \BlueSpice\Data\IRecord $record
+ */
+ protected function modify( $existingRecord, $record ) {
+ $record->getData();
+ try {
+ $success = $this->db->update(
+ $this->getTableName(),
+ $this->makeUpdateFields( $existingRecord,
$record ),
+ $this->makeUpdateConditions( $existingRecord,
$record ),
+ __METHOD__
+ );
+ } catch ( \Exception $e ) {
+ $record->getStatus()->fatal( $e );
+ return;
+ }
+ if( !$success ) {
+ $record->getStatus()->fatal(
+ "Error writing into: ".$this->getTableName()
+ );
+ }
+ }
+
+ /**
+ *
+ * @param \BlueSpice\Data\IRecord $existingRecord
+ * @param \BlueSpice\Data\IRecord $record
+ */
+ protected function delete( $existingRecord, $record ) {
+ $record->getData();
+ try {
+ $success = $this->db->delete(
+ $this->getTableName(),
+ $this->makeDeleteConditions( $existingRecord,
$record ),
+ __METHOD__
+ );
+ } catch ( \Exception $e ) {
+ $record->getStatus()->fatal( $e );
+ return;
+ }
+ if( !$success ) {
+ $record->getStatus()->fatal(
+ "Error deleting from: ".$this->getTableName()
+ );
+ }
+ }
+
+ /**
+ *
+ * @param \BlueSpice\Data\IRecord $record
+ */
+ protected function makeInsertFields( $record ) {
+ return (array) $record->getData();
+ }
+
+ /**
+ *
+ * @param \BlueSpice\Data\IRecord $existingRecord
+ * @param \BlueSpice\Data\IRecord $record
+ */
+ protected function makeUpdateFields( $existingRecord, $record ) {
+ $return = [];
+ foreach( (array) $record->getData() as $fieldName => $mValue ) {
+ if( in_array( $fieldName, $this->getIdentifierFields()
) ) {
+ continue;
+ }
+ $return[$fieldName] = $mValue;
+ }
+ return $return;
+ }
+
+ /**
+ *
+ * @param \BlueSpice\Data\IRecord $existingRecord
+ * @param \BlueSpice\Data\IRecord $record
+ */
+ protected function makeUpdateConditions( $existingRecord, $record ) {
+ $return = [];
+ foreach( $this->getIdentifierFields() as $fieldName ) {
+ $return[$fieldName] = $existingRecord->get( $fieldName
);
+ }
+ return $return;
+ }
+
+ /**
+ *
+ * @param \BlueSpice\Data\IRecord $existingRecord
+ * @param \BlueSpice\Data\IRecord $record
+ */
+ protected function makeDeleteConditions( $existingRecord, $record ) {
+ $return = [];
+ foreach( $this->getIdentifierFields() as $fieldName ) {
+ $return[$fieldName] = $existingRecord->get( $fieldName
);
+ }
+ return $return;
+ }
+
+ /**
+ *
+ * @param BlueSpice\Data\Record $record
+ */
+ protected function getExistingRecord( $record ) {
+ $recordSet = $this->reader->read( new
\BlueSpice\Data\ReaderParams( [
+ 'filter' => $this->makeExistingRecordFilters( $record )
+ ]));
+ $records = $recordSet->getRecords();
+ if( count( $records ) < 1 ) {
+ return false;
+ }
+ return $records[0];
+ }
+
+ /**
+ *
+ * @param BlueSpice\Data\Record $record
+ */
+ protected function makeExistingRecordFilters( $record ) {
+ $filters = [];
+ foreach( $this->getIdentifierFields() as $fieldName ) {
+ $filters[] = $this->makeExistingRecordFilter(
+ $record,
+ $fieldName
+ );
+ }
+ return $filters;
+ }
+
+ /**
+ *
+ * @param BlueSpice\Data\Record $record
+ */
+ protected function makeExistingRecordFilter( $record, $fieldName ) {
+ return [
+ Filter::KEY_FIELD => $fieldName,
+ Filter::KEY_VALUE => $record->get( $fieldName ),
+ Filter::KEY_TYPE => $this->getFieldType( $fieldName ),
+ Filter::KEY_COMPARISON => Filter::COMPARISON_EQUALS,
+ ];
+ }
+
+ protected function getFieldType( $fieldName ) {
+ $schema = $this->getSchema();
+ return $schema[$fieldName][Schema::TYPE];
+ }
}
diff --git a/src/Data/FieldType.php b/src/Data/FieldType.php
index 672a7b6..d419cf2 100644
--- a/src/Data/FieldType.php
+++ b/src/Data/FieldType.php
@@ -13,4 +13,5 @@
const INT = 'int';
const STRING = 'string';
const LISTVALUE = 'list';
+ const MIXED = 'mixed';
}
diff --git a/src/Data/IRecord.php b/src/Data/IRecord.php
index fa2b839..517665c 100644
--- a/src/Data/IRecord.php
+++ b/src/Data/IRecord.php
@@ -22,4 +22,9 @@
* @return \stdClass
*/
public function getData();
+
+ /**
+ * @return \Status
+ */
+ public function getStatus();
}
diff --git a/src/Data/IWriter.php b/src/Data/IWriter.php
index 5668374..4df58b3 100644
--- a/src/Data/IWriter.php
+++ b/src/Data/IWriter.php
@@ -5,9 +5,22 @@
interface IWriter {
/**
- *
- * @param array $dataSet
- * @return \Status
+ * Create or Update given records
+ * @param RecordSet $recordSet
+ * @return RecordSet
*/
- public function write( $dataSet );
+ public function write( $recordSet );
+
+ /**
+ * Delete given records
+ * @param RecordSet $dataSet
+ * @return RecordSet
+ */
+ public function remove( $recordSet );
+
+ /**
+ * @return Schema Column definition compatible to
+ * https://docs.sencha.com/extjs/4.2.1/#!/api/Ext.grid.Panel-cfg-columns
+ */
+ public function getSchema();
}
\ No newline at end of file
diff --git a/src/Data/LimitOffsetTrimmer.php b/src/Data/LimitOffsetTrimmer.php
index 0b3e1e2..a81bbda 100644
--- a/src/Data/LimitOffsetTrimmer.php
+++ b/src/Data/LimitOffsetTrimmer.php
@@ -28,7 +28,10 @@
*/
public function trim( $dataSets ) {
$total = count( $dataSets );
- $end = $this->limit + $this->offset;
+ $end = $total;
+ if( $this->limit !== ReaderParams::LIMIT_INFINITE ) {
+ $end = $this->limit + $this->offset;
+ }
if( $end > $total || $end === 0 ) {
$end = $total;
diff --git a/src/Data/Reader.php b/src/Data/Reader.php
index 6afc5f3..5e1d519 100644
--- a/src/Data/Reader.php
+++ b/src/Data/Reader.php
@@ -74,7 +74,9 @@
$dataSets = $trimmer->trim( $dataSets );
$secondaryDataProvider = $this->makeSecondaryDataProvider();
- $dataSets = $secondaryDataProvider->extend( $dataSets );
+ if( $secondaryDataProvider instanceof ISecondaryDataProvider ) {
+ $dataSets = $secondaryDataProvider->extend( $dataSets );
+ }
$resultSet = new ResultSet( $dataSets, $total );
return $resultSet;
@@ -114,7 +116,7 @@
}
/**
- * @return ISecondaryDataProvider
+ * @return ISecondaryDataProvider | null to skip
*/
protected abstract function makeSecondaryDataProvider();
}
\ No newline at end of file
diff --git a/src/Data/ReaderParams.php b/src/Data/ReaderParams.php
index b7390ab..05de0a9 100644
--- a/src/Data/ReaderParams.php
+++ b/src/Data/ReaderParams.php
@@ -6,6 +6,7 @@
use BlueSpice\Data\Filter;
class ReaderParams {
+ const LIMIT_INFINITE = -1;
/**
* For pre filtering
diff --git a/src/Data/Record.php b/src/Data/Record.php
index bc3bc06..2c753bd 100644
--- a/src/Data/Record.php
+++ b/src/Data/Record.php
@@ -12,10 +12,17 @@
/**
*
+ * @var \Status
+ */
+ protected $status = null;
+
+ /**
+ *
* @param \stdClass $dataSet
*/
- public function __construct( $dataSet ) {
+ public function __construct( $dataSet, \Status $status = null ) {
$this->dataSet = $dataSet;
+ $this->status = $status;
}
/**
@@ -56,5 +63,17 @@
return $this->dataSet;
}
+ /**
+ *
+ * @return \Status
+ */
+ public function getStatus() {
+ if( $this->status ) {
+ return $this->status;
+ }
+ $this->status = \Status::newGood();
+ return $this->status;
+ }
+
}
diff --git a/src/Data/RecordSet.php b/src/Data/RecordSet.php
new file mode 100644
index 0000000..68433f7
--- /dev/null
+++ b/src/Data/RecordSet.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace BlueSpice\Data;
+
+class RecordSet {
+
+ /**
+ *
+ * @var \BlueSpice\Data\Record[]
+ */
+ protected $records = [];
+
+ /**
+ *
+ * @param \BlueSpice\Data\Record[] $records
+ */
+ public function __construct( $records ) {
+ $this->records = $records;
+ }
+
+ /**
+ *
+ * @return \BlueSpice\Data\Record[]
+ */
+ public function getRecords() {
+ return $this->records;
+ }
+}
\ No newline at end of file
diff --git a/src/Data/ResultSet.php b/src/Data/ResultSet.php
index f4fbf60..54a0569 100644
--- a/src/Data/ResultSet.php
+++ b/src/Data/ResultSet.php
@@ -2,13 +2,7 @@
namespace BlueSpice\Data;
-class ResultSet {
-
- /**
- *
- * @var \BlueSpice\Data\Record[]
- */
- protected $records = [];
+class ResultSet extends RecordSet {
/**
*
@@ -22,16 +16,8 @@
* @param int $total
*/
public function __construct( $records, $total ) {
- $this->records = $records;
+ parent::__construct( $records );
$this->total = $total;
- }
-
- /**
- *
- * @return \BlueSpice\Data\Record[]
- */
- public function getRecords() {
- return $this->records;
}
/**
diff --git a/src/Data/Settings/PrimaryDataProvider.php
b/src/Data/Settings/PrimaryDataProvider.php
new file mode 100644
index 0000000..7e5285f
--- /dev/null
+++ b/src/Data/Settings/PrimaryDataProvider.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace BlueSpice\Data\Settings;
+
+use \BlueSpice\Data\IPrimaryDataProvider;
+
+class PrimaryDataProvider implements IPrimaryDataProvider {
+
+ /**
+ *
+ * @var \BlueSpice\Data\Record[]
+ */
+ protected $data = [];
+
+ /**
+ *
+ * @var \Wikimedia\Rdbms\IDatabase
+ */
+ protected $db = null;
+
+ /**
+ *
+ * @param \Wikimedia\Rdbms\IDatabase $db
+ */
+ public function __construct( $db ) {
+ $this->db = $db;
+ }
+
+ /**
+ *
+ * @param string $query
+ * @param type $preFilters
+ */
+ public function makeData( $query = '', $preFilters = [] ) {
+ $res = $this->db->select( 'bs_settings3', '*' );
+
+ $this->data = [];
+ foreach( $res as $row ) {
+ $this->appendRowToData( $row );
+ }
+
+ return $this->data;
+ }
+
+ protected function appendRowToData( $row ) {
+ $this->data[] = new Record( (object) [
+ Record::NAME => $row->s_name,
+ Record::VALUE => \FormatJson::decode( $row->s_value )
+ ]);
+ }
+}
\ No newline at end of file
diff --git a/src/Data/Settings/Reader.php b/src/Data/Settings/Reader.php
new file mode 100644
index 0000000..9b4899d
--- /dev/null
+++ b/src/Data/Settings/Reader.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace BlueSpice\Data\Settings;
+
+use \BlueSpice\Data\DatabaseReader;
+
+class Reader extends DatabaseReader {
+ /**
+ *
+ * @param \LoadBalancer $loadBalancer
+ * @param \IContextSource $context
+ */
+ public function __construct( $loadBalancer, \IContextSource $context =
null ) {
+ parent::__construct( $loadBalancer, $context,
$context->getConfig() );
+ }
+
+ protected function makePrimaryDataProvider( $params ) {
+ return new PrimaryDataProvider( $this->db );
+ }
+
+ protected function makeSecondaryDataProvider() {
+ return null;
+ }
+
+ public function getSchema() {
+ return new Schema();
+ }
+
+}
\ No newline at end of file
diff --git a/src/Data/Settings/Record.php b/src/Data/Settings/Record.php
new file mode 100644
index 0000000..6fd09c2
--- /dev/null
+++ b/src/Data/Settings/Record.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace BlueSpice\Data\Settings;
+
+class Record extends \BlueSpice\Data\Record {
+ const NAME = 's_name';
+ const VALUE = 's_value';
+}
\ No newline at end of file
diff --git a/src/Data/Settings/Schema.php b/src/Data/Settings/Schema.php
new file mode 100644
index 0000000..f73a153
--- /dev/null
+++ b/src/Data/Settings/Schema.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace BlueSpice\Data\Settings;
+
+use BlueSpice\Data\FieldType;
+
+class Schema extends \BlueSpice\Data\Schema {
+ public function __construct() {
+ parent::__construct( [
+ Record::NAME => [
+ self::FILTERABLE => true,
+ self::SORTABLE => true,
+ self::TYPE => FieldType::STRING
+ ],
+ Record::VALUE => [
+ self::FILTERABLE => false,
+ self::SORTABLE => false,
+ self::TYPE => FieldType::MIXED
+ ],
+ ]);
+ }
+}
\ No newline at end of file
diff --git a/src/Data/Settings/Store.php b/src/Data/Settings/Store.php
new file mode 100644
index 0000000..ec217da
--- /dev/null
+++ b/src/Data/Settings/Store.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace BlueSpice\Data\Settings;
+
+class Store implements \BlueSpice\Data\IStore {
+
+ /**
+ *
+ * @var \IContextSource
+ */
+ protected $context = null;
+
+ /**
+ *
+ * @param \IContextSource $context
+ */
+ public function __construct( $context, $loadBalancer ) {
+ $this->context = $context;
+ $this->loadBalancer = $loadBalancer;
+ }
+
+ public function getReader() {
+ return new Reader( $this->loadBalancer, $this->context );
+ }
+
+ public function getWriter() {
+ return new Writer(
+ $this->getReader(),
+ $this->loadBalancer,
+ $this->context
+ );
+ }
+}
\ No newline at end of file
diff --git a/src/Data/Settings/Writer.php b/src/Data/Settings/Writer.php
new file mode 100644
index 0000000..9b67263
--- /dev/null
+++ b/src/Data/Settings/Writer.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace BlueSpice\Data\Settings;
+use BlueSpice\Data\RecordSet;
+
+class Writer extends \BlueSpice\Data\DatabaseWriter {
+
+ /**
+ *
+ * @param \BlueSpice\Data\IReader $reader
+ * @param \LoadBalancer $loadBalancer
+ * @param \IContextSource $context
+ */
+ public function __construct( \BlueSpice\Data\IReader $reader,
$loadBalancer, \IContextSource $context = null ) {
+ parent::__construct( $reader, $loadBalancer, $context,
$context->getConfig() );
+ }
+
+ protected function getTableName() {
+ return 'bs_settings3';
+ }
+
+ /**
+ *
+ * @param \BlueSpice\Data\IRecord $record
+ */
+ protected function makeInsertFields( $record ) {
+ $fields = parent::makeInsertFields( $record );
+ $fields[Record::VALUE] = \FormatJson::encode(
$fields[Record::VALUE] );
+ return $fields;
+ }
+
+ /**
+ *
+ * @param \BlueSpice\Data\IRecord $existingRecord
+ * @param \BlueSpice\Data\IRecord $record
+ */
+ protected function makeUpdateFields( $existingRecord, $record ) {
+ $fields = parent::makeUpdateFields( $existingRecord, $record );
+ $fields[Record::VALUE] = \FormatJson::encode(
$fields[Record::VALUE] );
+ return $fields;
+ }
+
+ /**
+ * @return Schema Column definition compatible to
+ * https://docs.sencha.com/extjs/4.2.1/#!/api/Ext.grid.Panel-cfg-columns
+ */
+ public function getSchema() {
+ return new Schema();
+ }
+
+ protected function getIdentifierFields() {
+ return [ Record::NAME ];
+ }
+}
diff --git a/src/Data/Writer.php b/src/Data/Writer.php
new file mode 100644
index 0000000..ffa0180
--- /dev/null
+++ b/src/Data/Writer.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace BlueSpice\Data;
+
+use \BlueSpice\Data\IWriter;
+
+abstract class Writer implements IWriter {
+
+ /**
+ *
+ * @var \IContextSource
+ */
+ protected $context = null;
+
+ /**
+ *
+ * @var \Config
+ */
+ protected $config = null;
+
+ /**
+ *
+ * @param \IContextSource $context
+ * @param \Config $config
+ */
+ public function __construct( \IContextSource $context = null, \Config
$config = null ) {
+ $this->context = $context;
+ if( $this->context === null ) {
+ $this->context = \RequestContext::getMain();
+ }
+
+ $this->config = $config;
+ if( $this->config === null ) {
+ $this->config =
\MediaWiki\MediaWikiServices::getInstance()->getMainConfig();
+ }
+ }
+
+ /**
+ *
+ * @return \User
+ */
+ protected function getUser() {
+ return $this->context->getUser();
+ }
+
+ /**
+ *
+ * @return \Title
+ */
+ protected function getTitle() {
+ return $this->context->getTitle();
+ }
+}
\ No newline at end of file
diff --git a/src/ITagExtensionDefinitionProvider.php
b/src/ITagExtensionDefinitionProvider.php
new file mode 100644
index 0000000..ffe73e2
--- /dev/null
+++ b/src/ITagExtensionDefinitionProvider.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace BlueSpice;
+
+interface ITagExtensionDefinitionProvider {
+
+ /**
+ * Returns an array of tag extension definitions
+ * @return array
+ */
+ public function makeTagExtensionDefinitions();
+}
\ No newline at end of file
diff --git a/tests/phpunit/ConfigTest.php b/tests/phpunit/ConfigTest.php
index fb3dcd5..aa28c6b 100644
--- a/tests/phpunit/ConfigTest.php
+++ b/tests/phpunit/ConfigTest.php
@@ -22,9 +22,13 @@
public function addDBData() {
parent::addDBData();
$this->db->insert( 'bs_settings3', [
- 's_name' => 'bsgUnitTestSetting',
+ 's_name' => 'UnitTestSetting',
's_value' => '"9"' //JSON formatted
] );
+ $config = new \BlueSpice\Config(
+
\MediaWiki\MediaWikiServices::getInstance()->getDBLoadBalancer()
+ );
+ $config->invalidateCache();
}
public function testFactoryReturn() {
--
To view, visit https://gerrit.wikimedia.org/r/385375
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I1776ef3ba3e00963a342c01bcb717249c50b7de9
Gerrit-PatchSet: 14
Gerrit-Project: mediawiki/extensions/BlueSpiceFoundation
Gerrit-Branch: master
Gerrit-Owner: Pwirth <[email protected]>
Gerrit-Reviewer: Ljonka <[email protected]>
Gerrit-Reviewer: Mglaser <[email protected]>
Gerrit-Reviewer: Pwirth <[email protected]>
Gerrit-Reviewer: Robert Vogel <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits