diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 746c84d..f681e1e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,19 +17,3 @@ jobs: with: # Turn phpcoverage off because it causes a segfault phpcoverage_force_off: true - dynamic_matrix: false - extra_jobs: | - - php: 7.4 - phplinting: true - - php: 7.4 - phpunit: true - - php: 8.0 - phpunit: true - - php: 8.1 - db: mysql57pdo - phpunit: true - - php: 8.1 - db: mysql80 - phpunit: true - - php: 8.1 - phpunit: true diff --git a/README.md b/README.md index 9adae2f..9ed5455 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,9 @@ objects can be defined in YAML and shared around developers. This extends the ## Requirements -* PHP 7.1 -* SilverStripe [Framework ^4](https://github.com/silverstripe/silverstripe-framework) -* SilverStripe [Versioned ^1](https://github.com/silverstripe/silverstripe-versioned) +* PHP 8.1 +* SilverStripe [Framework ^5](https://github.com/silverstripe/silverstripe-framework) +* SilverStripe [Versioned ^2](https://github.com/silverstripe/silverstripe-versioned) ## Installation Instructions diff --git a/code/Populate.php b/code/Populate.php index c07321d..4bc16d5 100644 --- a/code/Populate.php +++ b/code/Populate.php @@ -16,57 +16,37 @@ use SilverStripe\ORM\DB; use SilverStripe\Versioned\Versioned; -/** - * @package populate - */ class Populate { use Configurable; use Extensible; - /** - * @config - * - * @var array - */ - private static $include_yaml_fixtures = []; + private static array $include_yaml_fixtures = []; /** - * @config - * * An array of classes to clear from the database before importing. While * populating SiteTree it may be worth clearing the 'SiteTree' table. - * - * @var array */ - private static $truncate_classes = []; + private static array $truncate_classes = []; - /** - * @config - * - * @var array - Tables that will be truncated - */ - private static $truncate_tables = []; + private static array $truncate_tables = []; /** * Flag to determine if we're already run for this session (i.e to prevent * parent calls invoking {@link requireRecords} twice). - * - * @var bool */ - private static $ran = false; + private static bool $ran = false; /** - * @var string[] - Used internally to not truncate multiple tables multiple times + * Used internally to not truncate multiple tables multiple times */ - private static $clearedTables = []; + private static array $clearedTables = []; /** * @param bool $force - allows you to bypass the ran check to run this multiple times - * @return bool * @throws Exception */ - public static function requireRecords($force = false): bool + public static function requireRecords(bool $force = false): bool { if (self::$ran && !$force) { return true; @@ -107,8 +87,6 @@ public static function requireRecords($force = false): bool /** * Delete all the associated tables for a class - * - * @param string $className */ private static function truncateObject(string $className): void { @@ -182,8 +160,6 @@ function ($next) { /** * Attempts to truncate a table. Outputs messages to indicate if table has * already been truncated or cannot be truncated - * - * @param string $table */ private static function truncateTable(string $table): void { diff --git a/code/PopulateFactory.php b/code/PopulateFactory.php index e427e05..3e4435a 100644 --- a/code/PopulateFactory.php +++ b/code/PopulateFactory.php @@ -11,7 +11,9 @@ use SilverStripe\Dev\FixtureBlueprint; use SilverStripe\Dev\FixtureFactory; use SilverStripe\ORM\DataList; +use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DB; +use SilverStripe\ORM\ValidationException; use SilverStripe\Versioned\Versioned; use function basename; use function dirname; @@ -21,29 +23,26 @@ use function sizeof; use function str_replace; -/** - * @package populate - */ class PopulateFactory extends FixtureFactory { /** * List of fixtures that failed to be created due to YAML fixture lookup failures (e.g. because of a dependency that * isn't met at the time of creation). We re-try creation of these after all other fixtures have been created. - * - * @var array */ - private $failedFixtures = []; + private array $failedFixtures = []; /** * Creates the object in the database as the original object will be wiped. * - * @param string $class - * @param string $identifier - * @param array $data + * @param string $name Name of the {@link FixtureBlueprint} to use, usually a DataObject subclass. + * @param string $identifier Unique identifier for this fixture type + * @param array $data Map of properties. Overrides default data + * @return bool|DataObject|null + * @throws ValidationException */ - public function createObject($class, $identifier, $data = null) + public function createObject($name, $identifier, $data = null) { - DB::alteration_message("Creating $identifier ($class)", "created"); + DB::alteration_message("Creating $identifier ($name)", "created"); if ($data) { foreach ($data as $k => $v) { @@ -65,11 +64,12 @@ public function createObject($class, $identifier, $data = null) if ($file) { // Skip the rest of this method (populateFile sets all other values on the object), just return the created file - if (!isset($this->fixtures[$class])) { - $this->fixtures[$class] = []; + if (!isset($this->fixtures[$name])) { + $this->fixtures[$name] = []; } - $this->fixtures[$class][$identifier] = $file->ID; + $this->fixtures[$name][$identifier] = $file->ID; + return $file; } } @@ -79,7 +79,7 @@ public function createObject($class, $identifier, $data = null) $lookup = null; if (isset($data['PopulateMergeWhen'])) { - $lookup = DataList::create($class)->where( + $lookup = DataList::create($name)->where( $data['PopulateMergeWhen'] ); @@ -95,11 +95,11 @@ public function createObject($class, $identifier, $data = null) throw new Exception('Not a valid PopulateMergeMatch filter'); } - $lookup = DataList::create($class)->filter($filter); + $lookup = DataList::create($name)->filter($filter); unset($data['PopulateMergeMatch']); } elseif (isset($data['PopulateMergeAny'])) { - $lookup = DataList::create($class); + $lookup = DataList::create($name); unset($data['PopulateMergeAny']); } @@ -121,7 +121,7 @@ public function createObject($class, $identifier, $data = null) $old->delete(); } - $blueprint = new FixtureBlueprint($class); + $blueprint = new FixtureBlueprint($name); $obj = $blueprint->createObject($identifier, $data, $this->fixtures); $latest = $obj->toMap(); @@ -132,16 +132,16 @@ public function createObject($class, $identifier, $data = null) $obj->delete(); - $this->fixtures[$class][$identifier] = $existing->ID; + $this->fixtures[$name][$identifier] = $existing->ID; $obj = $existing; $obj->flushCache(); } else { try { - $obj = parent::createObject($class, $identifier, $data); + $obj = parent::createObject($name, $identifier, $data); } catch (InvalidArgumentException $e) { $this->failedFixtures[] = [ - 'class' => $class, + 'class' => $name, 'id' => $identifier, 'data' => $data, ]; @@ -149,7 +149,7 @@ public function createObject($class, $identifier, $data = null) DB::alteration_message(sprintf('Exception: %s', $e->getMessage()), 'error'); DB::alteration_message( - sprintf('Failed to create %s (%s), queueing for later', $identifier, $class), + sprintf('Failed to create %s (%s), queueing for later', $identifier, $name), 'error' ); @@ -174,7 +174,7 @@ public function createObject($class, $identifier, $data = null) * @param bool $recurse Marker for whether we are recursing - should be false when calling from outside this method * @throws Exception */ - public function processFailedFixtures($recurse = false) + public function processFailedFixtures(bool $recurse = false): void { if (!$this->failedFixtures) { DB::alteration_message('No failed fixtures to process', 'created'); @@ -225,10 +225,10 @@ public function processFailedFixtures($recurse = false) /** * @param array $data - * @return File|bool The created (or updated) File object + * @return File|bool The created (or updated) File object, or true if the file already existed * @throws Exception If anything is missing and the file can't be processed */ - private function populateFile($data) + private function populateFile(array $data): File|bool { if (!isset($data['Filename']) || !isset($data['PopulateFileFrom'])) { throw new Exception('When passing "PopulateFileFrom", you must also pass "Filename" with the path that you want to file to be stored at (e.g. assets/test.jpg)'); @@ -285,6 +285,7 @@ private function populateFile($data) $file->write(); $file->publishRecursive(); } catch (Exception $e) { + throw $e; DB::alteration_message($e->getMessage(), "error"); } diff --git a/code/PopulateTask.php b/code/PopulateTask.php index cad556e..ba14a6e 100644 --- a/code/PopulateTask.php +++ b/code/PopulateTask.php @@ -6,13 +6,10 @@ use SilverStripe\Control\HTTPRequest; use SilverStripe\Dev\BuildTask; -/** - * @package populate - */ class PopulateTask extends BuildTask { - private static $segment = 'PopulateTask'; - + private static string $segment = 'PopulateTask'; + /** * @param HTTPRequest $request * @throws Exception diff --git a/code/extensions/PopulateMySQLExport.php b/code/extensions/PopulateMySQLExport.php index 29c0813..e464167 100644 --- a/code/extensions/PopulateMySQLExport.php +++ b/code/extensions/PopulateMySQLExport.php @@ -25,8 +25,6 @@ * extensions * - PopulateMySQLExportExtension * - * - * @package populate */ class PopulateMySQLExportExtension extends Extension { diff --git a/composer.json b/composer.json index 83c3ce3..7fbe9a2 100644 --- a/composer.json +++ b/composer.json @@ -9,12 +9,12 @@ "email": "will@fullscreen.io" }], "require": { - "php": "^7.4 || ^8.0", - "silverstripe/framework": "^4", - "silverstripe/versioned": "^1" + "php": "^8.1", + "silverstripe/framework": "^5", + "silverstripe/versioned": "^2" }, "require-dev": { - "phpunit/phpunit": "^9.5", + "silverstripe/recipe-testing": "^3", "squizlabs/php_codesniffer": "^3.0" }, "autoload": { @@ -28,5 +28,11 @@ "branch-alias": { "dev-master": "2.0.x-dev" } + }, + "config": { + "allow-plugins": { + "composer/installers": true, + "silverstripe/vendor-plugin": true + } } } diff --git a/tests/php/PopulateFactoryTest.php b/tests/php/PopulateFactoryTest.php index b5ab57c..53f556e 100644 --- a/tests/php/PopulateFactoryTest.php +++ b/tests/php/PopulateFactoryTest.php @@ -7,14 +7,10 @@ use DNADesign\Populate\Tests\PopulateFactoryTest\PopulateFactoryTestVersionedObject; use SilverStripe\Assets\File; use SilverStripe\Assets\Image; -use SilverStripe\Core\Injector\Injector; use SilverStripe\Dev\SapphireTest; use SilverStripe\Dev\TestOnly; use SilverStripe\Versioned\Versioned; -/** - * @package populate - */ class PopulateFactoryTest extends SapphireTest implements TestOnly { /** @@ -46,7 +42,7 @@ public function testVersionedObjects(): void { $versioned = $this->objFromFixture(PopulateFactoryTestVersionedObject::class, 'objV1'); - $versioned->publish('Stage', 'Live'); + $versioned->publishSingle(); $obj = $this->factory->createObject(PopulateFactoryTestVersionedObject::class, 'test', [ 'Content' => 'Updated Version Foo', @@ -153,14 +149,19 @@ public function testCreatingFileOrImage() // Create a file/image, check if data stored in database with expected DataObject class and file exists foreach ($files as $name => $class) { - $this->factory->createObject(File::class, $name, [ - 'Filename' => $name, - 'PopulateFileFrom' => sprintf('tests/assets/%s', $name), - ]); - - $file = Injector::inst()->get($class)->get()->filter('Name', $name)->first(); - $this->assertEquals($class, get_class($file)); - $this->assertTrue($file->exists()); + // BASE_PATH is prepended to the file path during populateFile(), so we need to remove it here + $filePath = str_replace(BASE_PATH, '', sprintf('%s/../assets/%s', dirname(__FILE__), $name)); + $file = $this->factory->createObject( + File::class, + $name, + [ + 'Filename' => $name, + 'PopulateFileFrom' => $filePath, + ] + ); + + $this->assertTrue((bool) $file?->exists()); + $this->assertEquals($class, $file->ClassName); } } } diff --git a/tests/php/PopulateFactoryTest/PopulateFactoryTestObject.php b/tests/php/PopulateFactoryTest/PopulateFactoryTestObject.php index f8cd6ca..37d1f3e 100644 --- a/tests/php/PopulateFactoryTest/PopulateFactoryTestObject.php +++ b/tests/php/PopulateFactoryTest/PopulateFactoryTestObject.php @@ -4,20 +4,21 @@ use SilverStripe\Dev\TestOnly; use SilverStripe\ORM\DataObject; +use SilverStripe\Versioned\Versioned; /** - * @package populate + * @mixin Versioned */ class PopulateFactoryTestObject extends DataObject implements TestOnly { - private static $table_name = 'PopulateFactoryTestObject'; + private static string $table_name = 'PopulateFactoryTestObject'; - private static $db = [ + private static array $db = [ 'Title' => 'Varchar', 'Content' => 'Varchar', ]; - private static $has_one = [ + private static array $has_one = [ 'RelatedTest' => PopulateFactoryTestObject::class, ]; } diff --git a/tests/php/PopulateFactoryTest/PopulateFactoryTestVersionedObject.php b/tests/php/PopulateFactoryTest/PopulateFactoryTestVersionedObject.php index 5b097d0..6cd3e7d 100644 --- a/tests/php/PopulateFactoryTest/PopulateFactoryTestVersionedObject.php +++ b/tests/php/PopulateFactoryTest/PopulateFactoryTestVersionedObject.php @@ -6,16 +6,19 @@ use SilverStripe\ORM\DataObject; use SilverStripe\Versioned\Versioned; +/** + * @mixin Versioned + */ class PopulateFactoryTestVersionedObject extends DataObject implements TestOnly { - private static $table_name = 'PopulateFactoryTestVersionedObject'; + private static string $table_name = 'PopulateFactoryTestVersionedObject'; - private static $db = [ + private static array $db = [ 'Title' => 'Varchar', 'Content' => 'Varchar', ]; - private static $extensions = [ + private static array $extensions = [ Versioned::class . '.versioned', ]; }