Source of file Populate.php
Size: 6,165 Bytes - Last Modified: 2021-12-24T06:45:02+00:00
/var/www/docs.ssmods.com/process/src/code/Populate.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 | <?php namespace DNADesign\Populate; use Exception; use SilverStripe\Assets\File; use SilverStripe\Control\Director; use SilverStripe\Core\ClassInfo; use SilverStripe\Core\Config\Configurable; use SilverStripe\Core\Extensible; use SilverStripe\Core\Injector\Injector; use SilverStripe\Dev\YamlFixture; use SilverStripe\ORM\Connect\DatabaseException; use SilverStripe\ORM\DataList; use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DB; use SilverStripe\Versioned\Versioned; /** * @package populate */ class Populate { use Configurable; use Extensible; /** * @config * * @var array */ private static $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 = []; /** * @config * * @var array - Tables that will be truncated */ private static $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; /** * @var string[] - Used internally to not truncate multiple tables multiple times */ private static $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 { if (self::$ran && !$force) { return true; } self::$ran = true; if (!self::canBuildOnEnvironment()) { throw new Exception('requireRecords can only be run in development or test environments'); } /** @var PopulateFactory $factory */ $factory = Injector::inst()->create(PopulateFactory::class); foreach (self::config()->get('truncate_objects') as $className) { self::truncateObject($className); } foreach (self::config()->get('truncate_tables') as $table) { self::truncateTable($table); } foreach (self::config()->get('include_yaml_fixtures') as $fixtureFile) { DB::alteration_message(sprintf('Processing %s', $fixtureFile), 'created'); $fixture = new YamlFixture($fixtureFile); $fixture->writeInto($factory); $fixture = null; } $factory->processFailedFixtures(); $populate = Injector::inst()->create(Populate::class); $populate->extend('onAfterPopulateRecords'); return true; } /** * Delete all the associated tables for a class * * @param string $className */ private static function truncateObject(string $className): void { if (in_array($className, ClassInfo::subclassesFor(File::class))) { foreach (DataList::create($className) as $obj) { /** @var File $obj */ $obj->deleteFile(); } } $tables = []; // All ancestors or children with tables $withTables = array_filter( array_merge( ClassInfo::ancestry($className), ClassInfo::subclassesFor($className) ), function ($next) { return DataObject::getSchema()->classHasTable($next); } ); $classTables = []; foreach ($withTables as $className) { $classTables[$className] = DataObject::getSchema()->tableName($className); } // Establish tables which store object data that needs to be truncated foreach ($classTables as $className => $baseTable) { /** @var DataObject|Versioned $obj */ $obj = Injector::inst()->get($className); // Include base tables $tables[$baseTable] = $baseTable; if (!$obj->hasExtension(Versioned::class)) { // No versioned tables to clear continue; } $stages = $obj->getVersionedStages(); foreach ($stages as $stage) { $table = $obj->stageTable($baseTable, $stage); // Include staged table(s) $tables[$table] = $table; } $versionedTable = "{$baseTable}_Versions"; // Include versions table $tables[$versionedTable] = $versionedTable; } $populate = Injector::inst()->create(Populate::class); $populate->extend('updateTruncateObjectTables', $tables, $className, $classTables); foreach ($tables as $table) { if (!DB::get_schema()->hasTable($table)) { // No table to clear continue; } self::truncateTable($table); } } /** * 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 { if (array_key_exists($table, self::$clearedTables)) { DB::alteration_message("$table already truncated", "deleted"); return; } DB::alteration_message("Truncating table $table", "deleted"); try { DB::get_conn()->clearTable($table); } catch (DatabaseException $databaseException) { DB::alteration_message("Couldn't truncate table $table as it doesn't exist", "deleted"); } self::$clearedTables[$table] = true; } private static function canBuildOnEnvironment(): bool { // Populate (by default) is allowed to run on dev and test environments if (Director::isDev() || Director::isTest()) { return true; } // Check if developer/s have specified that Populate can run on live return (bool) self::config()->get('allow_build_on_live'); } } |