'Module "%s" has been generated!', ]; protected $_errorMap = [ self::ERROR_INCORRECT_MODULE_NAME => 'Please set module name', self::ERROR_MODULE_IS_EXISTS => 'Module is exists. Please full remove old files', self::ERROR_TABLE_IS_EXISTS => 'Database table is exists. Please full remove old table', ]; public function generate() { if (empty($this->_name)) { throw new Qs_Db_Exception($this->_errorMap[self::ERROR_INCORRECT_MODULE_NAME]); } if ($this->_checkModuleExists()) { throw new Qs_Db_Exception($this->_errorMap[self::ERROR_MODULE_IS_EXISTS]); } if ($this->_checkTableExists()) { throw new Qs_Db_Exception($this->_errorMap[self::ERROR_TABLE_IS_EXISTS]); } $this->_generateModuleFilesystem(); if (in_array('jsPart', $this->_params['options'])) { $this->_generateJS(); } if (in_array('adminPart', $this->_params['options'])) { $this->_updateSitemapXML(); } $this->_generateDB(); return $this; } protected function _generateModuleFilesystem() { $architecture = $this->_getArchitecture(); $buildDirectory = new App_Admin_Tool_Project_Context_BuildDirectory(); $buildFile = new App_Admin_Tool_Project_Context_BuildFile(); foreach ($architecture as $directory => $files) { $directoryPath = BASE_PATH . DIRECTORY_SEPARATOR . $directory; $buildDirectory->setFullPath($directoryPath); $buildDirectory->create(); foreach ($files as $file) { $buildFile->setBaseDirectory($directory); $buildFile->setFilesystemName($file); $buildFile->setModuleName($this->_name); $buildFile->setParams($this->_params); if ($this->_params['useNameSpace'] == 'y') { $buildFile->setUseNamespace(true); } $buildFile->generate(); } } return $this; } protected function _generateJS() { $filesystemName = lcfirst($this->_jsObjectName) . '.' . App_Admin_Tool_Project_Context_BuildFile::JS_FILE_EXTENSION; $buildFile = new App_Admin_Tool_Project_Context_BuildFile(); $baseDirectory = ($this->_params['directory'] != '') ? self::MODULE_JS_APP_CONTAINER . '/' . strtolower($this->_params['directory']) : self::MODULE_JS_APP_CONTAINER; $baseDirectory .= '/' . lcfirst($this->_name); $buildFile->setBaseDirectory($baseDirectory); $buildFile->setFilesystemName($filesystemName); $buildFile->setFullPath(WWW_PATH . '/' . $baseDirectory . '/' . $filesystemName); $buildFile->setModuleName($this->_name); $buildFile->generate(); return $this; } protected function _updateSitemapXML() { $moduleName = $this->_name; $sitemap = BASE_PATH . '/sitemap.xml'; $sitemapObj = new SimpleXMLElement($sitemap, 0, true); /** @var SimpleXMLElement $sitemapModuleContainer */ $sitemapModuleContainer = $sitemapObj->admin; if (strlen($sitemapModuleContainer->{$moduleName}->getName())) { unset($sitemapModuleContainer->{$moduleName}); } $sections = explode(DIRECTORY_SEPARATOR, $this->_params['directory']); $parentSection = $sitemapModuleContainer; foreach ($sections as $section) { if (!empty($section)) { if (empty($parentSection->sub)) { $parentSection = $parentSection->addChild('sub'); } else { $parentSection = $parentSection->sub; } if (!strlen($parentSection->{strtolower($section)}->getName())) { $parentSection = $parentSection->addChild(strtolower($section)); $parentSection->addAttribute('showInMenu', 'y'); $parentSection->addAttribute('menuTitle', $section); } else { $parentSection = $parentSection->{strtolower($section)}; } } } if ($this->_params['directory'] != '' && $sitemapObj->admin->sub != $parentSection) { $parentSection = $parentSection->addChild('sub'); } else if ($this->_params['directory'] == '') { $parentSection = $parentSection->sub; } $parentSection = $parentSection->addChild($moduleName); $parentSection->addAttribute('showInMenu', 'y'); $parentSection->addAttribute('menuTitle', $moduleName); $moduleItem = $parentSection->addChild('item'); if ($this->_params['useNameSpace'] == 'y') { $type = str_replace(DIRECTORY_SEPARATOR, '\\', $this->_params['directory']) . $moduleName . '\Admin\\'; } else { $type = str_replace(DIRECTORY_SEPARATOR, '_', $this->_params['directory']) . $moduleName . '_Admin_'; } $moduleItem->addAttribute('type', $type); $sitemapObj->saveXML($sitemap); return $this; } protected function _generateDB() { $files = [ 'schema.sql', 'data.sql', ]; $moduleName = $this->_name; $db = Qs_Db::getInstance(); $dbConfig = Qs_Db::getConfig()->toArray(); $tableList = $db->listTables(); $tableName = $dbConfig['database']['tablePrefix'] . (empty($this->_params['tableAlias']) ? $moduleName : $this->_params['tableAlias']); $tablePageItemType = $dbConfig['database']['tablePrefix'] . self::TABLE_PAGE_ITEM_TYPE; if ($this->_params['useNameSpace'] == 'y') { $itemType = str_replace(DIRECTORY_SEPARATOR, '\\\\', $this->_params['directory']) . $moduleName . '\\\\'; } else { $itemType = str_replace(DIRECTORY_SEPARATOR, '_', $this->_params['directory']) . $moduleName . '_'; } $itemTitle = $moduleName; $itemSorter = (int) $db->fetchOne($db->select()->from($tablePageItemType, new Zend_Db_Expr('MAX(sorter)'))) + self::ITEM_TYPE_NEW_SORTER_STEP; if (in_array($tableName, $tableList)) { throw new Qs_Db_Exception('Table "' . $tableName . '" is exists'); } foreach ($files as $file) { $fullFilePath = dirname(__FILE__) . '/Module/Db/' . $file; if (file_exists($fullFilePath)) { try { $db->beginTransaction(); $query = ''; foreach (new SplFileObject($fullFilePath) as $line) { $params = compact('tableName', 'tablePageItemType', 'itemType', 'itemTitle', 'itemSorter'); $query .= str_replace( array_map('self::wrapSqlParams', array_keys($params)), array_values($params), $line ); if (substr(rtrim($query), -1) == ';') { $db->query($query); $query = ''; } } $db->commit(); } catch (Exception $e) { $db->rollback(); throw new Qs_Db_Exception($e->getMessage()); } } } return $this; } protected function _getArchitecture() { $moduleAppPath = self::MODULE_APP_CONTAINER . DIRECTORY_SEPARATOR . $this->_params['directory'] . $this->getModuleName(); $moduleTplPath = self::MODULE_TPL_CONTAINER . DIRECTORY_SEPARATOR . $this->_params['directory'] . $this->getModuleName(); if ($this->_params['useNameSpace'] == 'y') { $result = [ /** path: /App/MODULE_DIRECTORY/MODULE_NAME */ $moduleAppPath => [ self::CONFIG_FILE_NAME, self::OBJ_FILE_NAME, self::VIEW_FILE_NAME, self::ABSTRACT_DIRECTORY_NAME . self::OBJ_FILE_NAME, self::ABSTRACT_DIRECTORY_NAME . self::VIEW_FILE_NAME, self::ABSTRACT_DIRECTORY_NAME . self::LIST_FILE_NAME, $this->getModuleName() . self::LIST_FILE_NAME, ], ]; if (in_array('adminPart', $this->_params['options'])) { /** path: /App/MODULE_DIRECTORY/MODULE_NAME/Admin */ $result[$moduleAppPath . DIRECTORY_SEPARATOR . self::ADMIN_DIRECTORY_NAME] = [ self::OBJ_FILE_NAME, self::VIEW_FILE_NAME, $this->getModuleName() . self::LIST_FILE_NAME, ]; /** path: /App/MODULE_DIRECTORY/MODULE_NAME/Admin/Form */ $result[$moduleAppPath . DIRECTORY_SEPARATOR . self::ADMIN_DIRECTORY_NAME . DIRECTORY_SEPARATOR . self::FORM_DIRECTORY_NAME] = [ $this->_getFormFileNameForNamespace(self::ABSTRACT_FILE_NAME), $this->_getFormFileNameForNamespace(self::NEW_FORM_FILE_NAME), $this->_getFormFileNameForNamespace(self::EDIT_FORM_FILE_NAME), $this->_getFormFileNameForNamespace(self::REORDER_FORM_FILE_NAME), ]; } $tplArray = []; if (in_array('listTpl', $this->_params['options'])) { $tplArray[] = self::LIST_TPL_FILE_NAME; } if (in_array('viewTpl', $this->_params['options'])) { $tplArray[] = self::VIEW_TPL_FILE_NAME; } if (!empty($tplArray)) { /** path: /tpl/MODULE_DIRECTORY/MODULE_NAME */ $result[$moduleTplPath] = $tplArray; } } else { $result = [ /** path: /App/MODULE_DIRECTORY/MODULE_NAME */ $moduleAppPath => [ self::CONFIG_FILE_NAME, self::OBJ_FILE_NAME, self::VIEW_FILE_NAME, self::LIST_FILE_NAME, ], /** path: /App/MODULE_DIRECTORY/MODULE_NAME/Abstract */ $moduleAppPath . DIRECTORY_SEPARATOR . self::ABSTRACT_DIRECTORY_NAME => [ self::OBJ_FILE_NAME, self::VIEW_FILE_NAME, self::LIST_FILE_NAME, ], /** path: /App/MODULE_DIRECTORY/MODULE_NAME/Admin */ $moduleAppPath . DIRECTORY_SEPARATOR . self::ADMIN_DIRECTORY_NAME => [ self::OBJ_FILE_NAME, self::VIEW_FILE_NAME, self::LIST_FILE_NAME, ], /** path: /App/MODULE_DIRECTORY/MODULE_NAME/Admin/Form */ $moduleAppPath . DIRECTORY_SEPARATOR . self::ADMIN_DIRECTORY_NAME . DIRECTORY_SEPARATOR . self::FORM_DIRECTORY_NAME => [ self::ABSTRACT_FILE_NAME, self::NEW_FORM_FILE_NAME, self::EDIT_FORM_FILE_NAME, self::REORDER_FORM_FILE_NAME, ], /** path: /tpl/MODULE_DIRECTORY/MODULE_NAME */ $moduleTplPath => [ self::LIST_TPL_FILE_NAME, self::VIEW_TPL_FILE_NAME, ], ]; } return $result; } protected function _getFormFileNameForNamespace($name, $extension = '.php') { return str_replace($extension, '', $name) . self::FORM_DIRECTORY_NAME . $extension; } protected function _checkModuleExists($moduleName = null) { $moduleContext = new App_Admin_Tool_Project_Context_BuildDirectory([ 'baseDirectory' => self::MODULE_APP_CONTAINER, 'filesystemName' => $moduleName ? $moduleName : $this->getModuleName(), ]); return $moduleContext->exists(); } protected function _checkTableExists($tableAlias = null) { $db = Qs_Db::getInstance(); if (empty($tableAlias)) { $tableAlias = (empty($this->_params['tableAlias']) ? $this->_params['name'] : $this->_params['tableAlias']); } $tables = $db->query('SHOW TABLES LIKE "' . Qs_Db::getTableName($tableAlias) . '"')->fetchAll(); return !empty($tables); } public function getWorkflowAreaForm(array $options) { $formClassName = __CLASS__ . '_Form_Generate'; /** @var $form Qs_Form */ $form = new $formClassName($options); $form->setDefaults(); return $form; } public static function wrapSqlParams($value) { return '{{' . $value . '}}'; } public function setModuleName($name) { $this->_name = ucfirst(preg_replace('/[^A-Za-z0-9]/i', '', $name)); return $this; } public function setJsObjectName($name) { $this->_jsObjectName = ucfirst($name); return $this; } public function getModuleName() { return $this->_name; } public static function getMessage($key) { if (array_key_exists($key, self::$_messageMap)) { return self::$_messageMap[$key]; } return false; } public function validateForm($data) { $errors = []; if ($this->_checkModuleExists($data['name'])) { $errors['name'] = $this->_errorMap[self::ERROR_MODULE_IS_EXISTS]; } $tableAlias = empty($data['tableAlias']) ? $data['name'] : $data['tableAlias']; if ($this->_checkTableExists($tableAlias)) { $errors['tableAlias'] = $this->_errorMap[self::ERROR_TABLE_IS_EXISTS]; } return (empty($errors)) ? true : $errors; } }