diff --git a/_build/test/Tests/Processors/Element/CategoryTest.php b/_build/test/Tests/Processors/Element/CategoryTest.php index 7079c1a69bb..e9ad2eb4044 100644 --- a/_build/test/Tests/Processors/Element/CategoryTest.php +++ b/_build/test/Tests/Processors/Element/CategoryTest.php @@ -179,6 +179,25 @@ public function providerCategoryGetList() { ]; } + /** + * Tests that createdon is set when creating a Category and editedon remains null + */ + public function testCategoryCreateSetsCreatedon() { + /** @var ProcessorResponse $result */ + $result = $this->modx->runProcessor(Create::class, [ + 'category' => 'UnitTestCatTimestamp', + ]); + $this->assertTrue($this->checkForSuccess($result), 'Could not create Category for timestamp test'); + + /** @var modCategory $category */ + $category = $this->modx->getObject(modCategory::class, ['category' => 'UnitTestCatTimestamp']); + $this->assertNotNull($category, 'Category not found after creation'); + + $this->assertNotNull($category->get('createdon'), 'createdon should be set on new Category'); + $this->assertNotEmpty($category->get('createdon'), 'createdon should not be empty on new Category'); + $this->assertNull($category->get('editedon'), 'editedon should be null on new Category'); + } + /** * Tests the element/category/remove processor, which removes a Category * diff --git a/_build/test/Tests/Processors/Element/ChunkTest.php b/_build/test/Tests/Processors/Element/ChunkTest.php index 7fb565cac39..8e54a24e0a9 100644 --- a/_build/test/Tests/Processors/Element/ChunkTest.php +++ b/_build/test/Tests/Processors/Element/ChunkTest.php @@ -326,6 +326,47 @@ public function providerChunkGetList() { ]; } + /** + * Tests that createdon is set when creating a Chunk and editedon remains null + */ + public function testChunkCreateSetsCreatedon() { + $result = $this->modx->runProcessor(Create::class, [ + 'name' => 'UnitTestChunkTimestamp', + ]); + $this->assertTrue($this->checkForSuccess($result), 'Could not create Chunk for timestamp test'); + + /** @var modChunk $chunk */ + $chunk = $this->modx->getObject(modChunk::class, ['name' => 'UnitTestChunkTimestamp']); + $this->assertNotNull($chunk, 'Chunk not found after creation'); + + $this->assertNotNull($chunk->get('createdon'), 'createdon should be set on new Chunk'); + $this->assertNotEmpty($chunk->get('createdon'), 'createdon should not be empty on new Chunk'); + $this->assertNull($chunk->get('editedon'), 'editedon should be null on new Chunk'); + } + + /** + * Tests that createdon is preserved after updating a Chunk + */ + public function testChunkUpdatePreservesCreatedon() { + /** @var modChunk $chunk */ + $chunk = $this->modx->getObject(modChunk::class, ['name' => 'UnitTestChunk']); + $this->assertNotNull($chunk, 'UnitTestChunk not found'); + + $createdon = $chunk->get('createdon'); + $this->assertNotNull($createdon, 'createdon should be set on fixture chunk'); + + $result = $this->modx->runProcessor(Update::class, [ + 'id' => $chunk->get('id'), + 'name' => 'UnitTestChunk', + 'description' => 'Updated for timestamp test', + ]); + $this->assertTrue($this->checkForSuccess($result), 'Could not update Chunk for timestamp test'); + + // Re-fetch to get fresh data + $chunk = $this->modx->getObject(modChunk::class, ['name' => 'UnitTestChunk']); + $this->assertEquals($createdon, $chunk->get('createdon'), 'createdon should not change on update'); + } + /** * Tests the element/chunk/remove processor, which removes a Chunk * @dataProvider providerChunkRemove diff --git a/core/model/schema/modx.mysql.schema.xml b/core/model/schema/modx.mysql.schema.xml index 1d4a75635fb..c5102c3ddc8 100644 --- a/core/model/schema/modx.mysql.schema.xml +++ b/core/model/schema/modx.mysql.schema.xml @@ -286,6 +286,8 @@ + + @@ -350,6 +352,8 @@ + + @@ -755,6 +759,8 @@ + + @@ -784,6 +790,8 @@ + + @@ -1011,6 +1019,8 @@ + + @@ -1068,6 +1078,8 @@ + + @@ -1113,6 +1125,8 @@ + + @@ -1151,6 +1165,8 @@ + + @@ -1170,6 +1186,8 @@ + + @@ -1184,6 +1202,8 @@ + + diff --git a/core/src/Revolution/modCategory.php b/core/src/Revolution/modCategory.php index 65047ac06fa..1b7aaf0e5c1 100644 --- a/core/src/Revolution/modCategory.php +++ b/core/src/Revolution/modCategory.php @@ -91,6 +91,10 @@ public function save($cacheFlag = null) { $isNew = $this->isNew(); + if ($isNew && !$this->get('createdon')) { + $this->set('createdon', date('Y-m-d H:i:s')); + } + if ($this->xpdo instanceof modX) { $this->xpdo->invokeEvent('OnCategoryBeforeSave', [ 'mode' => $isNew ? modSystemEvent::MODE_NEW : modSystemEvent::MODE_UPD, diff --git a/core/src/Revolution/modElement.php b/core/src/Revolution/modElement.php index 3df81a99042..5cc998796d4 100644 --- a/core/src/Revolution/modElement.php +++ b/core/src/Revolution/modElement.php @@ -192,6 +192,10 @@ public function get($k, $format = null, $formatTemplate = null) */ public function save($cacheFlag = null) { + if ($this->isNew() && !$this->get('createdon')) { + $this->set('createdon', date('Y-m-d H:i:s')); + } + if (!$this->getOption(xPDO::OPT_SETUP)) { if ($this->staticSourceChanged()) { $staticContent = $this->getFileContent(); diff --git a/core/src/Revolution/mysql/modCategory.php b/core/src/Revolution/mysql/modCategory.php index 9b03b8facc2..dbc363330b8 100644 --- a/core/src/Revolution/mysql/modCategory.php +++ b/core/src/Revolution/mysql/modCategory.php @@ -20,6 +20,8 @@ class modCategory extends \MODX\Revolution\modCategory 'parent' => 0, 'category' => '', 'rank' => 0, + 'createdon' => NULL, + 'editedon' => NULL, ), 'fieldMeta' => array ( @@ -43,7 +45,7 @@ class modCategory extends \MODX\Revolution\modCategory 'index' => 'unique', 'indexgrp' => 'category', ), - 'rank' => + 'rank' => array ( 'dbtype' => 'int', 'precision' => '11', @@ -52,6 +54,20 @@ class modCategory extends \MODX\Revolution\modCategory 'default' => 0, 'index' => 'index', ), + 'createdon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + ), + 'editedon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + 'default' => NULL, + 'attributes' => 'ON UPDATE CURRENT_TIMESTAMP', + ), ), 'indexes' => array ( diff --git a/core/src/Revolution/mysql/modChunk.php b/core/src/Revolution/mysql/modChunk.php index 7ad3eca1369..d0b0e6970e5 100644 --- a/core/src/Revolution/mysql/modChunk.php +++ b/core/src/Revolution/mysql/modChunk.php @@ -27,6 +27,8 @@ class modChunk extends \MODX\Revolution\modChunk 'properties' => NULL, 'static' => 0, 'static_file' => '', + 'createdon' => NULL, + 'editedon' => NULL, ), 'fieldMeta' => array ( @@ -103,7 +105,7 @@ class modChunk extends \MODX\Revolution\modChunk 'default' => 0, 'index' => 'index', ), - 'static_file' => + 'static_file' => array ( 'dbtype' => 'varchar', 'precision' => '255', @@ -111,6 +113,20 @@ class modChunk extends \MODX\Revolution\modChunk 'null' => false, 'default' => '', ), + 'createdon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + ), + 'editedon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + 'default' => NULL, + 'attributes' => 'ON UPDATE CURRENT_TIMESTAMP', + ), ), 'fieldAliases' => array ( diff --git a/core/src/Revolution/mysql/modPlugin.php b/core/src/Revolution/mysql/modPlugin.php index da5815ba1a1..a01810451fc 100644 --- a/core/src/Revolution/mysql/modPlugin.php +++ b/core/src/Revolution/mysql/modPlugin.php @@ -25,6 +25,8 @@ class modPlugin extends \MODX\Revolution\modPlugin 'moduleguid' => '', 'static' => 0, 'static_file' => '', + 'createdon' => NULL, + 'editedon' => NULL, ), 'fieldMeta' => array ( @@ -88,7 +90,7 @@ class modPlugin extends \MODX\Revolution\modPlugin 'default' => 0, 'index' => 'index', ), - 'static_file' => + 'static_file' => array ( 'dbtype' => 'varchar', 'precision' => '255', @@ -96,6 +98,20 @@ class modPlugin extends \MODX\Revolution\modPlugin 'null' => false, 'default' => '', ), + 'createdon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + ), + 'editedon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + 'default' => NULL, + 'attributes' => 'ON UPDATE CURRENT_TIMESTAMP', + ), ), 'fieldAliases' => array ( diff --git a/core/src/Revolution/mysql/modPluginEvent.php b/core/src/Revolution/mysql/modPluginEvent.php index c6981f6ae60..dc67044cdcf 100644 --- a/core/src/Revolution/mysql/modPluginEvent.php +++ b/core/src/Revolution/mysql/modPluginEvent.php @@ -21,6 +21,8 @@ class modPluginEvent extends \MODX\Revolution\modPluginEvent 'event' => '', 'priority' => 0, 'propertyset' => 0, + 'createdon' => NULL, + 'editedon' => NULL, ), 'fieldMeta' => array ( @@ -51,7 +53,7 @@ class modPluginEvent extends \MODX\Revolution\modPluginEvent 'default' => 0, 'index' => 'index', ), - 'propertyset' => + 'propertyset' => array ( 'dbtype' => 'int', 'precision' => '10', @@ -61,6 +63,20 @@ class modPluginEvent extends \MODX\Revolution\modPluginEvent 'default' => 0, 'index' => 'index', ), + 'createdon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + ), + 'editedon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + 'default' => NULL, + 'attributes' => 'ON UPDATE CURRENT_TIMESTAMP', + ), ), 'indexes' => array ( diff --git a/core/src/Revolution/mysql/modSnippet.php b/core/src/Revolution/mysql/modSnippet.php index d454adb0b25..bacde3fd3da 100644 --- a/core/src/Revolution/mysql/modSnippet.php +++ b/core/src/Revolution/mysql/modSnippet.php @@ -24,6 +24,8 @@ class modSnippet extends \MODX\Revolution\modSnippet 'moduleguid' => '', 'static' => 0, 'static_file' => '', + 'createdon' => NULL, + 'editedon' => NULL, ), 'fieldMeta' => array ( @@ -75,7 +77,7 @@ class modSnippet extends \MODX\Revolution\modSnippet 'default' => 0, 'index' => 'index', ), - 'static_file' => + 'static_file' => array ( 'dbtype' => 'varchar', 'precision' => '255', @@ -83,8 +85,22 @@ class modSnippet extends \MODX\Revolution\modSnippet 'null' => false, 'default' => '', ), + 'createdon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + ), + 'editedon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + 'default' => NULL, + 'attributes' => 'ON UPDATE CURRENT_TIMESTAMP', + ), ), - 'fieldAliases' => + 'fieldAliases' => array ( 'content' => 'snippet', ), diff --git a/core/src/Revolution/mysql/modTemplate.php b/core/src/Revolution/mysql/modTemplate.php index fa6d55b7b1d..bf9bfac4980 100644 --- a/core/src/Revolution/mysql/modTemplate.php +++ b/core/src/Revolution/mysql/modTemplate.php @@ -27,6 +27,8 @@ class modTemplate extends \MODX\Revolution\modTemplate 'static' => 0, 'static_file' => '', 'preview_file' => '', + 'createdon' => NULL, + 'editedon' => NULL, ), 'fieldMeta' => array ( @@ -121,7 +123,7 @@ class modTemplate extends \MODX\Revolution\modTemplate 'null' => false, 'default' => '', ), - 'preview_file' => + 'preview_file' => array ( 'dbtype' => 'varchar', 'precision' => '191', @@ -129,6 +131,20 @@ class modTemplate extends \MODX\Revolution\modTemplate 'null' => false, 'default' => '', ), + 'createdon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + ), + 'editedon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + 'default' => NULL, + 'attributes' => 'ON UPDATE CURRENT_TIMESTAMP', + ), ), 'indexes' => array ( diff --git a/core/src/Revolution/mysql/modTemplateVar.php b/core/src/Revolution/mysql/modTemplateVar.php index 189680974af..5837d396679 100644 --- a/core/src/Revolution/mysql/modTemplateVar.php +++ b/core/src/Revolution/mysql/modTemplateVar.php @@ -33,6 +33,8 @@ class modTemplateVar extends \MODX\Revolution\modTemplateVar 'output_properties' => NULL, 'static' => 0, 'static_file' => '', + 'createdon' => NULL, + 'editedon' => NULL, ), 'fieldMeta' => array ( @@ -151,7 +153,7 @@ class modTemplateVar extends \MODX\Revolution\modTemplateVar 'default' => 0, 'index' => 'index', ), - 'static_file' => + 'static_file' => array ( 'dbtype' => 'varchar', 'precision' => '255', @@ -159,8 +161,22 @@ class modTemplateVar extends \MODX\Revolution\modTemplateVar 'null' => false, 'default' => '', ), + 'createdon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + ), + 'editedon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + 'default' => NULL, + 'attributes' => 'ON UPDATE CURRENT_TIMESTAMP', + ), ), - 'fieldAliases' => + 'fieldAliases' => array ( 'content' => 'default_text', ), diff --git a/core/src/Revolution/mysql/modTemplateVarResource.php b/core/src/Revolution/mysql/modTemplateVarResource.php index e0e310bb4a2..30d7ac4f736 100644 --- a/core/src/Revolution/mysql/modTemplateVarResource.php +++ b/core/src/Revolution/mysql/modTemplateVarResource.php @@ -20,6 +20,8 @@ class modTemplateVarResource extends \MODX\Revolution\modTemplateVarResource 'tmplvarid' => 0, 'contentid' => 0, 'value' => NULL, + 'createdon' => NULL, + 'editedon' => NULL, ), 'fieldMeta' => array ( @@ -43,12 +45,26 @@ class modTemplateVarResource extends \MODX\Revolution\modTemplateVarResource 'default' => 0, 'index' => 'index', ), - 'value' => + 'value' => array ( 'dbtype' => 'mediumtext', 'phptype' => 'string', 'null' => false, ), + 'createdon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + ), + 'editedon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + 'default' => NULL, + 'attributes' => 'ON UPDATE CURRENT_TIMESTAMP', + ), ), 'indexes' => array ( diff --git a/core/src/Revolution/mysql/modTemplateVarResourceGroup.php b/core/src/Revolution/mysql/modTemplateVarResourceGroup.php index db91ce8e893..2528f64cb14 100644 --- a/core/src/Revolution/mysql/modTemplateVarResourceGroup.php +++ b/core/src/Revolution/mysql/modTemplateVarResourceGroup.php @@ -19,6 +19,8 @@ class modTemplateVarResourceGroup extends \MODX\Revolution\modTemplateVarResourc array ( 'tmplvarid' => 0, 'documentgroup' => 0, + 'createdon' => NULL, + 'editedon' => NULL, ), 'fieldMeta' => array ( @@ -31,7 +33,7 @@ class modTemplateVarResourceGroup extends \MODX\Revolution\modTemplateVarResourc 'null' => false, 'default' => 0, ), - 'documentgroup' => + 'documentgroup' => array ( 'dbtype' => 'int', 'precision' => '10', @@ -39,6 +41,20 @@ class modTemplateVarResourceGroup extends \MODX\Revolution\modTemplateVarResourc 'null' => false, 'default' => 0, ), + 'createdon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + ), + 'editedon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + 'default' => NULL, + 'attributes' => 'ON UPDATE CURRENT_TIMESTAMP', + ), ), 'indexes' => array ( diff --git a/core/src/Revolution/mysql/modTemplateVarTemplate.php b/core/src/Revolution/mysql/modTemplateVarTemplate.php index d7f49142770..2b71946eb23 100644 --- a/core/src/Revolution/mysql/modTemplateVarTemplate.php +++ b/core/src/Revolution/mysql/modTemplateVarTemplate.php @@ -20,6 +20,8 @@ class modTemplateVarTemplate extends \MODX\Revolution\modTemplateVarTemplate 'tmplvarid' => 0, 'templateid' => 0, 'rank' => 0, + 'createdon' => NULL, + 'editedon' => NULL, ), 'fieldMeta' => array ( @@ -43,7 +45,7 @@ class modTemplateVarTemplate extends \MODX\Revolution\modTemplateVarTemplate 'default' => 0, 'index' => 'pk', ), - 'rank' => + 'rank' => array ( 'dbtype' => 'int', 'precision' => '11', @@ -51,6 +53,20 @@ class modTemplateVarTemplate extends \MODX\Revolution\modTemplateVarTemplate 'null' => false, 'default' => 0, ), + 'createdon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + ), + 'editedon' => + array ( + 'dbtype' => 'datetime', + 'phptype' => 'datetime', + 'null' => true, + 'default' => NULL, + 'attributes' => 'ON UPDATE CURRENT_TIMESTAMP', + ), ), 'indexes' => array ( diff --git a/setup/includes/upgrades/common/3.2.1-element-timestamps.php b/setup/includes/upgrades/common/3.2.1-element-timestamps.php new file mode 100644 index 00000000000..10cfa34b91e --- /dev/null +++ b/setup/includes/upgrades/common/3.2.1-element-timestamps.php @@ -0,0 +1,42 @@ +getTableName($class); + + $description = $this->install->lexicon('add_column', ['column' => 'createdon', 'table' => $table]); + $this->processResults($class, $description, [$modx->manager, 'addField'], [$class, 'createdon']); + + $description = $this->install->lexicon('add_column', ['column' => 'editedon', 'table' => $table]); + $this->processResults($class, $description, [$modx->manager, 'addField'], [$class, 'editedon']); +}