Source of file DataObjectGenerator.php
Size: 11,475 Bytes - Last Modified: 2021-12-24T06:51:36+00:00
/var/www/docs.ssmods.com/process/src/src/DataObjectGenerate/DataObjectGenerator.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 | <?php namespace Heystack\Core\DataObjectGenerate; use Heystack\Core\Exception\ConfigurationException; use Heystack\Core\Traits\HasSchemaServiceTrait; use Heystack\Core\DataObjectSchema\SchemaService; /** * Generates SilverStripe DataObject classes and extensions based on added schemas * * Schemas are retrieved via the provided schema service. Using this information this service * can generate DataObject classes that are by default saved into "mysite/code/HeystackStorage" * * The service will generate both Cached* files and Stored* file. The Cached* files are not meant * to be overwritten by developers but the Stored* file are able to be edited, and as long * as the "force" flag isn't used in the process method, the edited Stored classes will not be overwritten * * @author Cam Spiers <cameron@heyday.co.nz> * @author Stevie Mayhew <stevie@heyday.co.nz> * @package Heystack\Core\Generate */ class DataObjectGenerator { use HasSchemaServiceTrait; /** * @var array */ private $processingFlatStorage = []; /** * @var string */ private $storageLocation; /** * @param \Heystack\Core\DataObjectSchema\SchemaService $schemaService * @param string|null $storageLocation */ public function __construct(SchemaService $schemaService, $storageLocation = null) { $this->schemaService = $schemaService; if (is_string($storageLocation)) { $this->storageLocation = $storageLocation; } else { $this->storageLocation = BASE_PATH . '/mysite/code/HeystackStorage'; } } /** * @param bool $force * @return void */ public function process($force = false) { $dirCache = $this->storageLocation . '/cache'; // check if the generated directory exists, if not create it if (!is_dir($this->storageLocation)) { $this->output('Creating: ' . $this->storageLocation); mkdir($this->storageLocation); } if (!is_dir($dirCache)) { $this->output('Creating: ' . $dirCache); mkdir($dirCache); } // get all the previously created objects and delete them $cacheFiles = new \RegexIterator( new \DirectoryIterator($dirCache), '/^Cached[^.]+\.php/' ); foreach ($cacheFiles as $cacheFile) { $this->output('Deleting: ' . $cacheFile); unlink($cacheFile->getPathname()); } $managed_models = []; foreach ($this->schemaService->getSchemas() as $schema) { $identifier = $schema->getIdentifier()->getFull(); $this->output('Processing schema: ' . $identifier); $flatStorage = $this->processFlatStorage( $schema->getFlatStorage(), $identifier ); $parentStorage = $this->processParentStorage( $schema->getParentStorage() ); $childStorage = $this->processChildStorage( $schema->getChildStorage() ); // names for the created objects $cachedObjectName = 'Cached' . $identifier; $storedObjectName = 'Stored' . $identifier; $fields = array_keys(is_array($flatStorage) ? $flatStorage : []) + array_keys(is_array($parentStorage) ? $parentStorage : []); // create the cached object $this->writeDataObject( $dirCache, $cachedObjectName, [ 'db' => $flatStorage, 'has_one' => $parentStorage, 'has_many' => (array)$childStorage, 'summary_fields' => array_merge(['Created'], $fields), 'searchable_fields' => $fields, 'singular_name' => $identifier, 'plural_name' => $identifier . 's' ] ); $managed_models[] = $storedObjectName; $filename = sprintf( "%s/%s.php", $this->storageLocation, $storedObjectName ); // create the storage object if ($force || !file_exists($filename)) { $this->writeDataObject( $this->storageLocation, $storedObjectName, false, $cachedObjectName ); } $this->output('Finished ' . $identifier); } if ($managed_models && is_array($managed_models) && count($managed_models) > 0) { $this->writeModelAdmin( $dirCache, 'GeneratedModelAdmin', [ 'managed_models' => $managed_models, 'url_segment' => 'generated-admin', 'menu_title' => 'Admin' ] ); } $this->output('Finished!'); } /** * @param string $dir * @param string $name * @param bool|void $statics * @param string|void $extends * @return void */ protected function writeDataObject($dir, $name, $statics = false, $extends = 'DataObject') { $this->output('Writing DataObject: ' . $name . '...', ''); if ($statics && is_array($statics)) { foreach ($statics as $key => $static) { $statics[$key] = $this->beautify(var_export($static, true)); } } else { $statics = []; } $viewer = $this->getDataObjectSSViewer(); file_put_contents( sprintf("%s/%s.php", $dir, $name), $viewer->process( new \ArrayData( array_merge( [ 'PHPTag' => '<?php', 'Name' => $name, 'Extends' => $extends, 'db' => false, 'has_one' => false, 'has_many' => false, 'summary_fields' => false, 'searchable_fields' => false, 'singular_name' => false, 'plural_name' => false ], $statics ) ) ) ); $this->output('Done!'); } /** * @param string $dir * @param string $name * @param bool|void $statics * @param string|void $extends * @return void */ protected function writeModelAdmin($dir, $name, $statics = false, $extends = 'ModelAdmin') { $this->output('Writing ModelAdmin: ' . $name . '...', ''); if ($statics && is_array($statics)) { foreach ($statics as $key => $static) { $statics[$key] = $this->beautify(var_export($static, true)); } } else { $statics = []; } $viewer = $this->getModelAdminSSViewer(); file_put_contents( sprintf("%s/%s.php", $dir, $name), $viewer->process( new \ArrayData( [ 'PHPTag' => '<?php', 'Name' => $name, 'Extends' => $extends ] + $statics ) ) ); $this->output('Done!'); } /** * @param string $value * @return bool|string * @throws \Heystack\Core\Exception\ConfigurationException */ public function isReference($value) { $value = trim($value); if ($value[0] == '+') { $identifier = strtolower(substr($value, 1)); if ($this->schemaService->hasSchema($identifier)) { return $identifier; } throw new ConfigurationException("Reference to undefined schema: $identifier"); } return false; } /** * @param string $flatStorage * @param string $identifier * @return array * @throws \Heystack\Core\Exception\ConfigurationException */ protected function processFlatStorage($flatStorage, $identifier) { $this->processingFlatStorage[$identifier] = $identifier; if (is_array($flatStorage)) { foreach ($flatStorage as $name => $value) { if ($flatIdentifier = $this->isReference($value)) { unset($flatStorage[$name]); if (isset($this->processingFlatStorage[$flatIdentifier])) { throw new ConfigurationException('Circular reference in flat storage'); } $extraFlatStorage = $this->processFlatStorage( $this->schemaService->getSchema($flatIdentifier)->getFlatStorage(), $flatIdentifier ); if (is_array($extraFlatStorage)) { foreach ($extraFlatStorage as $extraName => $extraValue) { $flatStorage[substr($value, 1) . $extraName] = $extraValue; //TODO: Fix me. Fix what? } } } } } unset($this->processingFlatStorage[$identifier]); return $flatStorage; } /** * @param mixed $parentStorage * @return mixed */ protected function processParentStorage($parentStorage) { if (is_array($parentStorage)) { foreach ($parentStorage as $name => $value) { if ($parentIdentifier = $this->isReference($value)) { unset($parentStorage[$name]); $parentStorage[$name] = 'Stored' . $this->schemaService->getSchema($parentIdentifier)->getIdentifier()->getFull(); } } } return $parentStorage; } /** * @param mixed $childStorage * @return mixed */ protected function processChildStorage($childStorage) { if (is_array($childStorage)) { foreach ($childStorage as $name => $value) { if ($childIdentifier = $this->isReference($value)) { $childStorage[$name] = 'Stored' . $this->schemaService->getSchema($childIdentifier)->getIdentifier()->getFull(); } } } return $childStorage; } /** * @param string $content * @param string $tab * @return mixed */ protected function beautify($content, $tab = ' ') { return str_replace("\n", "\n" . $tab, $content); } /** * @param string $message * @param string $break * @return void */ protected function output($message, $break = PHP_EOL) { echo $message, $break; } /** * @return \SSViewer */ protected function getDataObjectSSViewer() { return new \SSViewer(HEYSTACK_BASE_PATH . '/src/DataObjectGenerate/templates/DataObject_php.ss'); } /** * @return \SSViewer */ protected function getModelAdminSSViewer() { return new \SSViewer(HEYSTACK_BASE_PATH . '/src/DataObjectGenerate/templates/ModelAdmin_php.ss'); } } |