├── copy_this └── modules │ └── oxps │ ├── modulegenerator │ ├── core │ │ ├── module.tpl │ │ │ ├── module │ │ │ │ ├── models │ │ │ │ │ └── .gitkeep │ │ │ │ ├── tests │ │ │ │ │ └── .gitkeep │ │ │ │ ├── views │ │ │ │ │ ├── blocks │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ ├── pages │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ ├── widgets │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ └── admin │ │ │ │ │ │ ├── popups │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ │ ├── en │ │ │ │ │ │ └── oxpsmodule_lang.php.tpl │ │ │ │ │ │ └── de │ │ │ │ │ │ └── oxpsmodule_lang.php.tpl │ │ │ │ ├── controllers │ │ │ │ │ └── admin │ │ │ │ │ │ └── .gitkeep │ │ │ │ ├── components │ │ │ │ │ └── widgets │ │ │ │ │ │ └── .gitkeep │ │ │ │ ├── docs │ │ │ │ │ ├── install.sql │ │ │ │ │ ├── uninstall.sql │ │ │ │ │ └── README.txt │ │ │ │ ├── out │ │ │ │ │ └── pictures │ │ │ │ │ │ └── picture.png │ │ │ │ ├── translations │ │ │ │ │ ├── en │ │ │ │ │ │ └── oxpsmodule_lang.php.tpl │ │ │ │ │ └── de │ │ │ │ │ │ └── oxpsmodule_lang.php.tpl │ │ │ │ ├── metadata.php.tpl │ │ │ │ └── core │ │ │ │ │ └── oxpsmodule.php.tpl │ │ │ ├── oxpscomment.inc.php.tpl │ │ │ ├── oxpsextendclass.php.tpl │ │ │ ├── oxpswidgetclass.php.tpl │ │ │ ├── oxpslistmodelclass.php.tpl │ │ │ ├── oxpsmodelclass.php.tpl │ │ │ ├── oxpscontrollerclass.php.tpl │ │ │ └── oxpstestclass.php.tpl │ │ ├── oxpsmodulegeneratorvalidator.php │ │ ├── oxpsmodulegeneratorfilesystem.php │ │ ├── oxpsmodulegeneratormodule.php │ │ ├── oxpsmodulegeneratorrender.php │ │ ├── oxpsmodulegeneratorsettings.php │ │ ├── oxpsmodulegeneratorhelper.php │ │ └── oxpsmodulegeneratoroxmodule.php │ ├── out │ │ ├── pictures │ │ │ └── oxpsmodulegenerator.png │ │ └── src │ │ │ └── css │ │ │ └── admin_oxpsmodulegenerator.css │ ├── tests │ │ ├── unit │ │ │ ├── testdata │ │ │ │ ├── testdata_remove.sql │ │ │ │ └── testdata_add.sql │ │ │ └── core │ │ │ │ ├── oxpsModuleGeneratorModuleTest.php │ │ │ │ ├── oxpsModuleGeneratorValidatorTest.php │ │ │ │ ├── oxpsModuleGeneratorSettingsTest.php │ │ │ │ ├── oxpsModuleGeneratorFileSystemTest.php │ │ │ │ └── oxpsModuleGeneratorRenderTest.php │ │ └── additional.inc.php │ ├── docs │ │ ├── CHANGELOG.txt │ │ └── README.txt │ ├── menu.xml │ ├── metadata.php │ ├── views │ │ └── admin │ │ │ ├── de │ │ │ └── oxpsmodulegenerator_admin_de_lang.php │ │ │ ├── en │ │ │ └── oxpsmodulegenerator_admin_en_lang.php │ │ │ └── admin_oxpsmodulegenerator.tpl │ └── controllers │ │ └── admin │ │ └── admin_oxpsmodulegenerator.php │ └── vendormetadata.php ├── .gitignore ├── composer.json ├── CHANGELOG.md ├── CONTRIBUTING.md └── README.md /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/models/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/tests/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/views/blocks/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/views/pages/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/controllers/admin/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/views/widgets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/components/widgets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/views/admin/popups/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/vendormetadata.php: -------------------------------------------------------------------------------- 1 | getTitle()}] module install SQL file -- 2 | [{if $oModule->renderTasks()}]-- TODO: Add Your installation SQL here or delete the file --[{/if}] 3 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/docs/uninstall.sql: -------------------------------------------------------------------------------- 1 | -- [{$oModule->getTitle()}] module uninstall SQL file -- 2 | [{if $oModule->renderTasks()}]-- TODO: Add Your uninstall SQL here or delete the file --[{/if}] 3 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/out/pictures/picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OXID-eSales/module_skeleton_generator/HEAD/copy_this/modules/oxps/modulegenerator/core/module.tpl/module/out/pictures/picture.png -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/tests/unit/testdata/testdata_remove.sql: -------------------------------------------------------------------------------- 1 | -- Test data removal script 2 | 3 | -- Sample CMS snippet deletion 4 | DELETE FROM `oxcontents` WHERE `OXID` = 'oxpstestident'; 5 | 6 | -- Model related test table 7 | DROP TABLE IF EXISTS `testspecial_offer`; 8 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/docs/CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | OXID Module Skeleton Generator changelog 2 | ======================================== 3 | 4 | v0.5.0 5 | ------ 6 | * First standalone release of the OXID Module Skeleton Generator 7 | * Formatted for OXID PSR coding standards and refactored 8 | * Covered with PHPUnit tests 9 | * Styles, translations and documentation adjusted 10 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/oxpscomment.inc.php.tpl: -------------------------------------------------------------------------------- 1 | /** 2 | [{$oModule->getAuthorData('info')}] 3 | * 4 | * @category module 5 | * @package [{$oModule->getModuleFolderName()}] 6 | * @author [{$oModule->getAuthorData('name')}] 7 | * @link [{$oModule->getAuthorData('link')}] 8 | * @copyright (C) [{$oModule->getAuthorData('copy')}][{$smarty.now|date_format:"%Y"}] 9 | */ -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/translations/en/oxpsmodule_lang.php.tpl: -------------------------------------------------------------------------------- 1 | renderFileComment()}] 3 | 4 | $sLangName = 'English'; 5 | 6 | $aLang = array( 7 | 'charset' => 'UTF-8', 8 | 9 | [{if $oModule->renderTasks()}]// TODO: Follow this pattern to add more translation. Delete this comment. 10 | [{/if}][{if $oModule->renderSamples()}]//'[{$oModule->getVendorPrefix(true)}]_[{$oModule->getModuleFolderName(true)}]_[KEY]' => 'Value', 11 | [{/if}]); 12 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log for OXID Module Skeleton Generator 2 | 3 | All notable changes to this project will be documented in this file. 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/). 6 | 7 | 8 | ## [Unreleased] 9 | 10 | ### Added 11 | 12 | ### Changed 13 | 14 | ### Deprecated 15 | 16 | ### Removed 17 | 18 | ### Fixed 19 | 20 | ### Security 21 | 22 | [Unreleased]: https://github.com/OXID-eSales/module_skeleton_generator/compare/HEAD...HEAD 23 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/translations/de/oxpsmodule_lang.php.tpl: -------------------------------------------------------------------------------- 1 | renderFileComment()}] 3 | 4 | $sLangName = 'Deutsch'; 5 | 6 | $aLang = array( 7 | 'charset' => 'UTF-8', // Supports german language specific chars like: ä, ö. ß, etc. 8 | 9 | [{if $oModule->renderTasks()}]// TODO: Follow this pattern to add more translation. Delete this comment. 10 | [{/if}][{if $oModule->renderSamples()}]//'[{$oModule->getVendorPrefix(true)}]_[{$oModule->getModuleFolderName(true)}]_[KEY]' => '[TR - Value]', 11 | [{/if}]); 12 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/tests/additional.inc.php: -------------------------------------------------------------------------------- 1 | "vendor/mymodule/core/myarticle.php", 18 | )); 19 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/docs/README.txt: -------------------------------------------------------------------------------- 1 | ==Title== 2 | OXID Module Skeleton Generator 3 | 4 | ==Author== 5 | OXID Professional Services 6 | 7 | ==Prefix== 8 | oxps 9 | 10 | ==Shop Version== 11 | 5.0.x/4.7.x-5.2.x/4.9.x 12 | 13 | ==Version== 14 | 0.5.0 15 | 16 | ==Link== 17 | http://www.oxid-esales.com 18 | 19 | ==Mail== 20 | info@oxid-esales.com 21 | 22 | ==Description== 23 | Folders structure, empty classes and metadata generation for new OXID eShop modules. 24 | 25 | ==Installation== 26 | * Copy the content of `copy_this/` folder to OXID eShop root folder 27 | * Activate the module in administration area 28 | * Set eShop `modules/` folder writable while generating new modules 29 | 30 | ==Extend== 31 | * oxmodule 32 | 33 | ==Modules== 34 | 35 | ==Modified original templates== 36 | 37 | ==Uninstall== 38 | * Deactivate the module in administration area 39 | * Delete module folder 40 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/docs/README.txt: -------------------------------------------------------------------------------- 1 | ==Title== 2 | [{$oModule->getTitle()}] 3 | 4 | ==Author== 5 | [{$oModule->getAuthorData('name')}] 6 | 7 | ==Prefix== 8 | [{$oModule->getVendorPrefix()}] 9 | 10 | ==Shop Version== 11 | 5.2.x/4.9.x 12 | 13 | ==Version== 14 | [{$oModule->getInitialVersion()}] 15 | 16 | ==Link== 17 | [{$oModule->getAuthorData('link')}] 18 | 19 | ==Mail== 20 | [{$oModule->getAuthorData('mail')}] 21 | 22 | ==Description== 23 | [{$oModule->getDescription()}] 24 | 25 | ==Installation== 26 | Activate the module in administration area. 27 | 28 | ==Extend== 29 | [{assign var="aExtendClasses" value=$oModule->getClassesToExtend()}] 30 | [{if $aExtendClasses}] 31 | [{foreach from=$aExtendClasses key="sExtendClass" item="mApplicationPath"}] 32 | * [{$sExtendClass}] 33 | [{/foreach}] 34 | [{else}] 35 | 36 | [{/if}] 37 | 38 | ==Modules== 39 | 40 | ==Modified original templates== 41 | 42 | ==Uninstall== 43 | Disable the module in administration area and delete module folder. 44 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/tests/unit/testdata/testdata_add.sql: -------------------------------------------------------------------------------- 1 | -- Test data creation script 2 | 3 | -- Sample CMS snippet insertion 4 | INSERT INTO `oxcontents` (`OXID`, `OXLOADID`, `OXSHOPID`, `OXSNIPPET`, `OXTYPE`, `OXACTIVE`, `OXACTIVE_1`, `OXPOSITION`, `OXTITLE`, `OXCONTENT`, `OXTITLE_1`, `OXCONTENT_1`, `OXACTIVE_2`, `OXTITLE_2`, `OXCONTENT_2`, `OXACTIVE_3`, `OXTITLE_3`, `OXCONTENT_3`, `OXCATID`, `OXFOLDER`, `OXTERMVERSION`, `OXTIMESTAMP`) VALUES ('oxpstestident', 'oxpstestident', '1', '1', '0', '1', '1', '', 'Test', '

Hello,

World!

', 'Test', '

Hello,

World!

', '1', 'Test', '

Hello,

World!

', '1', '', '

Hello,

World!

', '30e44ab83fdee7564.23264141', '', '', CURRENT_TIMESTAMP); 5 | 6 | -- Model related test table 7 | 8 | -- 9 | -- Table structure for table `testspecial_offer` 10 | -- 11 | 12 | CREATE TABLE IF NOT EXISTS `testspecial_offer` ( 13 | `OXID` char(32) COLLATE latin1_general_ci NOT NULL, 14 | PRIMARY KEY (`OXID`) 15 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci; 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ###How to Contribute 2 | 3 | Before contributing for the first time, you must sign the Contributor License Agreement. 4 | You can find more information about it on the FAQ page OXID Contribution and Contributor Agreement FAQ: 5 | http://wiki.oxidforge.org/OXID_Contribution_and_Contributor_Agreement_FAQ 6 | 7 | First off, you have to fork current repository. 8 | 9 | Best practice: 10 | * Please leave the the branch names as they are. 11 | * If you want to fix a bug or develop a new feature, define an own branch in your repository. Name it e.g. "feature/foo" or "bug/bugname" for better traceability. 12 | * Change whatever you want and send a pull request back to the original branch. 13 | 14 | For more information about this, please see:
15 | http://codeinthehole.com/writing/pull-requests-and-other-good-practices-for-teams-using-github/ 16 | 17 | You will find technical help with Git and GitHub on this place:
18 | https://help.github.com/ 19 | 20 | When sending your pull request, please provide a clear, meaningful and detailed information about what your code is about and what it will do, best including a screen shot if possible. 21 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/out/src/css/admin_oxpsmodulegenerator.css: -------------------------------------------------------------------------------- 1 | /* OXID Module Skeleton Generator - Admin Styles */ 2 | 3 | div.box { 4 | border: none; 5 | height: 100% !important; 6 | padding: 0; 7 | } 8 | 9 | div#oxpsmodulegenerator div.export { 10 | width: 99%; 11 | padding: 0; 12 | } 13 | 14 | div#oxpsmodulegenerator div.export span { 15 | margin: 0 10px; 16 | } 17 | 18 | table.oxpsmodulegenerator-wrapper { 19 | border: 1px solid #000000; 20 | border-top: none; 21 | width: 99%; 22 | } 23 | 24 | table.oxpsmodulegenerator-wrapper td.edittext { 25 | padding: 5px 10px; 26 | } 27 | 28 | table.oxpsmodulegenerator-wrapper td.edittext-label { 29 | width: 180px; 30 | } 31 | 32 | div#oxpsmodulegenerator input[type="text"], 33 | div#oxpsmodulegenerator select, 34 | div#oxpsmodulegenerator textarea { 35 | border: 1px solid #808080; 36 | } 37 | 38 | div#oxpsmodulegenerator input[type="text"], 39 | div#oxpsmodulegenerator select { 40 | height: 20px; 41 | } 42 | 43 | div#oxpsmodulegenerator input[type="text"], 44 | div#oxpsmodulegenerator textarea { 45 | width: 200px; 46 | } 47 | 48 | div#oxpsmodulegenerator textarea.wider { 49 | width: 360px; 50 | } 51 | 52 | div#oxpsmodulegenerator textarea[rows="3"] { 53 | height: 64px; 54 | } 55 | 56 | div#oxpsmodulegenerator textarea[rows="1"] { 57 | height: 36px; 58 | } 59 | 60 | div#oxpsmodulegenerator span.req { 61 | color: red; 62 | } 63 | 64 | div#oxpsmodulegenerator input[type="submit"] { 65 | padding: 6px 20px; 66 | } 67 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/views/admin/en/oxpsmodule_lang.php.tpl: -------------------------------------------------------------------------------- 1 | renderFileComment()}] 3 | 4 | [{assign var='sModuleCamelCaseId' value=$oModule->getModuleId(true)}] 5 | [{assign var='aModuleSettings' value=$oModule->getSettings()}] 6 | 7 | $sLangName = 'English'; 8 | 9 | $aLang = array( 10 | 'charset' => 'UTF-8', 11 | '[{$oModule->getModuleId()}]' => '[{$oModule->getTitle()}]', 12 | 13 | [{if $aModuleSettings}] 14 | // Settings interface translations 15 | [{if $oModule->renderTasks()}]// TODO: Adjust the settings translation if needed. 16 | [{/if}] 17 | 'SHOP_MODULE_GROUP_[{$sModuleCamelCaseId}]Settings' => '[{$oModule->getTitle()}] Module Settings', 18 | [{foreach from=$aModuleSettings key='iSettingKey' item='aModuleSetting'}] 19 | 'SHOP_MODULE_[{$sModuleCamelCaseId}][{$aModuleSetting->name}]' => '[{$oModule->camelCaseToHumanReadable($aModuleSetting->name)}]', 20 | [{if $aModuleSetting->type eq 'select'}] 21 | 'SHOP_MODULE_[{$sModuleCamelCaseId}][{$aModuleSetting->name}]_' => ' - ', 22 | [{assign var='aSelectOptions' value=$oModule->getSelectSettingOptions($aModuleSetting->constrains)}] 23 | [{foreach from=$aSelectOptions item='sOption'}] 24 | 'SHOP_MODULE_[{$sModuleCamelCaseId}][{$aModuleSetting->name}]_[{$sOption}]' => '[{$sOption}]', 25 | [{/foreach}] 26 | [{/if}] 27 | [{/foreach}] 28 | [{/if}] 29 | 30 | [{if $oModule->renderTasks()}]// TODO: Follow this pattern to add more translation. Delete this comment. 31 | [{/if}][{if $oModule->renderSamples()}]//'[{$oModule->getVendorPrefix(true)}]_[{$oModule->getModuleFolderName(true)}]_ADMIN_[KEY]' => 'Value', 32 | [{/if}]); 33 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/views/admin/de/oxpsmodule_lang.php.tpl: -------------------------------------------------------------------------------- 1 | renderFileComment()}] 3 | 4 | [{assign var='sModuleCamelCaseId' value=$oModule->getModuleId(true)}] 5 | [{assign var='aModuleSettings' value=$oModule->getSettings()}] 6 | 7 | $sLangName = 'Deutsch'; 8 | 9 | $aLang = array( 10 | 'charset' => 'UTF-8', // Supports german language specific chars like: ä, ö. ß, etc. 11 | '[{$oModule->getModuleId()}]' => '[{$oModule->getTitle()}]', 12 | 13 | [{if $aModuleSettings}] 14 | // Settings interface translations 15 | [{if $oModule->renderTasks()}]// TODO: Adjust the settings translation if needed. 16 | [{/if}] 17 | 'SHOP_MODULE_GROUP_[{$sModuleCamelCaseId}]Settings' => '[TR - [{$oModule->getTitle()}] Module Settings]', 18 | [{foreach from=$aModuleSettings key='iSettingKey' item='aModuleSetting'}] 19 | 'SHOP_MODULE_[{$sModuleCamelCaseId}][{$aModuleSetting->name}]' => '[TR - [{$oModule->camelCaseToHumanReadable($aModuleSetting->name)}]]', 20 | [{if $aModuleSetting->type eq 'select'}] 21 | 'SHOP_MODULE_[{$sModuleCamelCaseId}][{$aModuleSetting->name}]_' => ' - ', 22 | [{assign var='aSelectOptions' value=$oModule->getSelectSettingOptions($aModuleSetting->constrains)}] 23 | [{foreach from=$aSelectOptions item='sOption'}] 24 | 'SHOP_MODULE_[{$sModuleCamelCaseId}][{$aModuleSetting->name}]_[{$sOption}]' => '[{$sOption}]', 25 | [{/foreach}] 26 | [{/if}] 27 | [{/foreach}] 28 | [{/if}] 29 | 30 | [{if $oModule->renderTasks()}]// TODO: Follow this pattern to add more translation. Delete this comment. 31 | [{/if}][{if $oModule->renderSamples()}]//'[{$oModule->getVendorPrefix(true)}]_[{$oModule->getModuleFolderName(true)}]_ADMIN_[KEY]' => '[TR - Value]', 32 | [{/if}]); 33 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/oxpsextendclass.php.tpl: -------------------------------------------------------------------------------- 1 | renderFileComment()}] 3 | [{assign var='sClassNamePrefix' value=$oModule->getModuleClassName()}] 4 | [{if $sClassRealName}] 5 | [{assign var='sClassName' value=$sClassRealName}] 6 | [{else}] 7 | [{assign var='sClassName' value=$oModule->getFileNameSuffix($sFilePath)}] 8 | [{/if}] 9 | [{assign var='sReadableClassName' value=$sClassName|capitalize}] 10 | 11 | /** 12 | * Class [{$sClassNamePrefix}][{$sReadableClassName}]. 13 | * Extends [{$sClassName}]. 14 | * 15 | * @see [{$sClassName}] 16 | */ 17 | class [{$sClassNamePrefix}][{$sReadableClassName}] extends [{$sClassNamePrefix}][{$sReadableClassName}]_parent 18 | { 19 | [{if $oModule->renderTasks()}] 20 | // TODO: Overload parent class methods or implement new methods for the extended class. 21 | [{/if}] 22 | 23 | [{if $oModule->renderSamples()}] 24 | // An example of an overloaded method which already exists in parent class 25 | // public function [myMethod]($[sSomeParameter] = '') 26 | // { 27 | // /** @var [{$sClassNamePrefix}][{$sReadableClassName}]|[{$sClassName}] $this */ 28 | // 29 | [{if $oModule->renderTasks()}] 30 | // // TODO: Implement Your custom logic here or delete this sample 31 | [{/if}] 32 | // 33 | // return $this->_[{$sClassNamePrefix}][{$sReadableClassName}]_[myMethod]_parent($[sSomeParameter]); 34 | // } 35 | 36 | 37 | /** 38 | * Parent `[myMethod]` call. Method required for mocking. 39 | * 40 | * @codeCoverageIgnore 41 | * 42 | * @return mixed 43 | */ 44 | /* protected function _[{$sClassNamePrefix}][{$sReadableClassName}]_[myMethod]_parent($[sSomeParameter] = '') 45 | { 46 | return parent::[myMethod]($[sSomeParameter]); 47 | } */ 48 | [{/if}] 49 | } 50 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/oxpswidgetclass.php.tpl: -------------------------------------------------------------------------------- 1 | renderFileComment()}] 3 | 4 | [{assign var='sClassNamePrefix' value=$oModule->getModuleClassName()}] 5 | [{if $sClassRealName}] 6 | [{assign var='sClassName' value=$sClassRealName}] 7 | [{else}] 8 | [{assign var='sClassName' value=$oModule->getFileNameSuffix($sFilePath)}] 9 | [{/if}] 10 | 11 | /** 12 | * Class [{$sClassNamePrefix}][{$sClassName}]. 13 | */ 14 | class [{$sClassNamePrefix}][{$sClassName}] extends oxWidget 15 | { 16 | 17 | /** 18 | * Names of components (classes) that are initiated and executed 19 | * before any other regular operation. 20 | [{if $oModule->renderTasks()}] 21 | * 22 | * @TODO: Enter components You need for the widget to be loaded. As example ... array('oxcmp_cur' => 1, ...); 23 | [{/if}] 24 | * 25 | * @var array 26 | */ 27 | protected $_aComponentNames = array([{if $oModule->renderSamples()}]/*'oxcmp_shop' => 1, 'oxcmp_basket' => 1, 'oxcmp_user' => 1*/[{/if}]); 28 | 29 | /** 30 | * Widget template name. 31 | * 32 | * @var string 33 | */ 34 | protected $_sThisTemplate = '[{$oModule->getModuleId()}][{$sClassName|lower}].tpl'; 35 | 36 | 37 | [{if $oModule->renderTasks()}] 38 | // TODO: Implement public methods to use in the template to get data. Also You can overload render() method here. 39 | // NOTE: Widget is very close to a controller and works very similar as a controller. 40 | [{/if}] 41 | 42 | [{if $oModule->renderSamples()}] 43 | /** 44 | * A sample method that could be called in the widget template as "$oView->getData()" 45 | * 46 | * @return array 47 | */ 48 | /* public function getData() 49 | { 50 | return array('mySampleData'); 51 | } */ 52 | [{/if}] 53 | 54 | /** 55 | * Returns if view should be cached. 56 | * 57 | * @return bool 58 | */ 59 | public function isCacheable() 60 | { 61 | [{if $oModule->renderTasks()}] 62 | // TODO: You can make it false of implement some logic when to cache it and when not. 63 | [{/if}] 64 | return true; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/oxpslistmodelclass.php.tpl: -------------------------------------------------------------------------------- 1 | renderFileComment()}] 3 | [{assign var='sClassNamePrefix' value=$oModule->getModuleClassName()}] 4 | [{if $sClassRealName}] 5 | [{assign var='sClassName' value=$sClassRealName}] 6 | [{else}] 7 | [{assign var='sClassName' value=$oModule->getFileNameSuffix($sFilePath)}] 8 | [{/if}] 9 | [{assign var='iListClassNameLength' value=$sClassName|count_characters}] 10 | [{math assign='iTruncateLength' equation='iListClassNameLength - 4' iListClassNameLength=$iListClassNameLength}] 11 | [{assign var='sListObjectsClassName' value=$sClassName|truncate:$iTruncateLength:''}] 12 | [{assign var='sTableName' value=$oModule->getModuleId()|cat:'_'}] 13 | [{assign var='sTableName' value=$sTableName|cat:$sListObjectsClassName|lower}] 14 | [{assign var='sFullClassName' value=$sClassNamePrefix|cat:$sClassName}] 15 | [{assign var='sFullObjectName' value=$sClassNamePrefix|cat:$sListObjectsClassName}] 16 | 17 | /** 18 | * Class [{$sFullClassName}]. 19 | * [{$sFullObjectName}] list model. 20 | */ 21 | class [{$sFullClassName}] extends oxList 22 | { 23 | 24 | /** 25 | * List Object class name 26 | * 27 | * @var string 28 | */ 29 | protected $_sObjectsInListName = '[{$sFullObjectName}]'; 30 | 31 | [{if $oModule->renderSamples()}] 32 | 33 | // !!!EXAMPLES!!! 34 | [{if $oModule->renderTasks()}] 35 | // TODO: Implement real loaders and delete the examples. 36 | 37 | // NOTE: List class assign loaded object ot itself, so use methods like: 38 | // $this->count / key / next / prev / clear / assign / getArray / getBaseObject / ... and so on! 39 | // If You user objects list in other class, define it with /** @var [{$sFullClassName}][] $oMyObjectsList */ 40 | [{/if}] 41 | 42 | /** 43 | * Loads all entries from the table. 44 | */ 45 | /* public function loadAll() 46 | { 47 | [{if $oModule->renderTasks()}] 48 | // TODO: Create other loaders like this using `selectString` method. 49 | // NOTE: For MySQL queries user proper case, backticks (`) and keep it clear and readable. 50 | [{/if}] 51 | $sSql = "SELECT * FROM " . getViewName('[{$sTableName}]'); 52 | 53 | $this->selectString($sSql); 54 | } */ 55 | [{/if}] 56 | } 57 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/oxpsmodelclass.php.tpl: -------------------------------------------------------------------------------- 1 | renderFileComment()}] 3 | [{assign var='sClassNamePrefix' value=$oModule->getModuleClassName()}] 4 | [{if $sClassRealName}] 5 | [{assign var='sClassName' value=$sClassRealName}] 6 | [{else}] 7 | [{assign var='sClassName' value=$oModule->getFileNameSuffix($sFilePath)}] 8 | [{/if}] 9 | [{assign var='sTableName' value=$oModule->getModuleId()|cat:'_'}] 10 | [{assign var='sTableName' value=$sTableName|cat:$sClassName|lower}] 11 | 12 | /** 13 | * Class [{$sClassNamePrefix}][{$sClassName}]. 14 | * [{$sClassName}] model. 15 | */ 16 | [{if $oModule->renderTasks()}] 17 | //TODO: Extend oxI18n - if multilingual fields are used 18 | [{/if}] 19 | class [{$sClassNamePrefix}][{$sClassName}] extends oxBase 20 | { 21 | 22 | /** 23 | * Class constructor. 24 | */ 25 | public function __construct() 26 | { 27 | parent::__construct(); 28 | 29 | [{if $oModule->renderTasks()}] 30 | // TODO: Adjust the table name if needed! Create the table in docs/install.sql. 31 | [{/if}] 32 | $this->init('[{$sTableName}]'); 33 | } 34 | 35 | [{if $oModule->renderTasks()}] 36 | // NOTE: If You overload parent methods like save, load, delete, etc., 37 | // call parent methods through protected functions like "[{$sClassNamePrefix}][{$sClassName}]_[someMethod]_parent(..." 38 | 39 | // For empty OXID use $this->getId(); 40 | // And You can use methods like $this-getClassName / getCoreTableName / getViewName / isLoaded ... and so on. 41 | [{/if}] 42 | [{if $oModule->renderSamples()}] 43 | 44 | // !!!EXAMPLES!!! 45 | [{if $oModule->renderTasks()}] 46 | // TODO: Implement real getters, setter, loaders, etc. and delete the examples. 47 | [{/if}] 48 | 49 | /** 50 | * Set [somefield]. 51 | * 52 | * @param mixed [someField] 53 | */ 54 | /*public function set[SomeField]([someValue]) 55 | { 56 | $this->[{$sTableName}]__[somefield] = new oxField([someValue]); 57 | }*/ 58 | 59 | /** 60 | * Get [somefield]. 61 | * 62 | * @return double 63 | */ 64 | /*public function get[SomeField]() 65 | { 66 | return $this->[{$sTableName}]__[somefield]->value; 67 | }*/ 68 | 69 | /** 70 | * Load by... [sample function] 71 | * 72 | * @param mixed [mSomeField] 73 | * 74 | * @return mixed 75 | */ 76 | // TODO: Replace [mSomeField] and [SOME_FIELD] with real values You need! 77 | /* public function loadBy...([mSomeField]) 78 | { 79 | [{if $oModule->renderTasks()}] 80 | // NOTE: For MySQL queries user proper case, backticks (`) and keep it clear and readable. 81 | // NOTE: Database tables are name lowercase, as example "[{$sTableName}]" 82 | // Each new table MUST have a primary key named "OXID" of type char(32) 83 | // Custom fields are named UPPERCASE with Your vendor prefix each, for example "[{$oModule->getVendorPrefix(true)}]MYFIELD" 84 | [{/if}] 85 | $sQuery = sprintf( 86 | "SELECT * FROM `%s` WHERE `[SOME_FIELD]` = %s LIMIT 1", 87 | getViewName('[{$sTableName}]'), 88 | oxDb::getDb()->quote(trim([mSomeField])) 89 | ); 90 | 91 | return $this->assignRecord($sQuery); 92 | } */ 93 | [{/if}] 94 | } 95 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/oxpscontrollerclass.php.tpl: -------------------------------------------------------------------------------- 1 | renderFileComment()}] 3 | 4 | [{assign var='sClassNamePrefix' value=$oModule->getModuleClassName()}] 5 | [{if $sClassRealName}] 6 | [{assign var='sClassName' value=$sClassRealName}] 7 | [{else}] 8 | [{assign var='sClassName' value=$oModule->getFileNameSuffix($sFilePath)}] 9 | [{/if}] 10 | 11 | /** 12 | * Class [{$sClassNamePrefix}][{$sClassName}]. 13 | */ 14 | class [{$sClassNamePrefix}][{$sClassName}] extends oxUBase 15 | { 16 | 17 | /** 18 | * Controller template name. 19 | * 20 | * @var string 21 | */ 22 | protected $_sThisTemplate = '[{$oModule->getModuleId()}][{$sClassName|lower}].tpl'; 23 | 24 | 25 | [{if $oModule->renderSamples()}]// This is an example of overridden init method that goes before any action and render. 26 | /* public function init() 27 | { 28 | [{if $oModule->renderTasks()}] 29 | // TODO: Implement Your custom logic here or delete this sample 30 | [{/if}] 31 | //$this->_[{$sClassNamePrefix}][{$sClassName}]_init_parent(); 32 | } */ 33 | [{/if}] 34 | 35 | /** 36 | * Overridden parent method. 37 | [{if $oModule->renderTasks()}] 38 | * TODO: Write a comment on what You will implement here. 39 | [{/if}] 40 | * 41 | * @return mixed 42 | */ 43 | public function render() 44 | { 45 | $mReturn = $this->_[{$sClassNamePrefix}][{$sClassName}]_render_parent(); 46 | 47 | [{if $oModule->renderTasks()}] 48 | // TODO: Implement Your custom logic here 49 | [{/if}] 50 | [{if $oModule->renderSamples()}] 51 | // $this->setViewData(array('[mMyParam]' => ...)); // To set ir modify view data 52 | 53 | // ... = $this->getConfig()->getRequestParameter('[request_parameter]'); // To get GET/POST parameters 54 | 55 | // $oModule = oxRegistry::get('[{$sClassNamePrefix}]Module'); // Get the module instance 56 | 57 | // /** @var myObject|myObjectParent $oObject */ 58 | // $oObject = oxNew('myObject'); // To create new object 59 | 60 | // oxRegistry::getUtils()->redirect(...); // For redirect 61 | 62 | // $this->_oaComponents['oxcmp_..']->...; // To access components 63 | 64 | // $this->getUser(); // To get active shop user 65 | 66 | // oxRegistry::get("oxUtilsView")->addErrorToDisplay(...); // To set error 67 | [{/if}] 68 | 69 | return $mReturn; 70 | } 71 | 72 | [{if $oModule->renderSamples()}]// This is an example of an action (called with '...?...&fnc=[myAction]'. It is triggered before render. 73 | /* public function [myAction]() 74 | { 75 | [{if $oModule->renderTasks()}] 76 | // TODO: Implement Your custom logic here or delete this sample 77 | [{/if}] 78 | } */ 79 | [{/if}] 80 | 81 | [{if $oModule->renderSamples()}] 82 | // An example of getter that could be used in template as $oView->[getMyData]() 83 | /* public function [getMyData]() 84 | { 85 | [{if $oModule->renderTasks()}] 86 | // TODO: Implement Your custom logic here or delete this sample 87 | //return ...; 88 | [{/if}] 89 | } */ 90 | [{/if}] 91 | 92 | /** 93 | * Parent `render` call. Method required for mocking. 94 | * 95 | * @codeCoverageIgnore 96 | * 97 | * @return mixed 98 | */ 99 | protected function _[{$sClassNamePrefix}][{$sClassName}]_render_parent() 100 | { 101 | return parent::render(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/oxpsmodulegeneratorvalidator.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | /** 28 | * Class oxpsModuleGeneratorValidator. 29 | * Validation helpers used in module generation processes and data access helpers. 30 | */ 31 | class oxpsModuleGeneratorValidator extends oxSuperCfg 32 | { 33 | 34 | /** 35 | * Check if vendor prefix matches official format: 2 to 4 latin lowercase letters. 36 | * 37 | * @param string $sVendorPrefix 38 | * 39 | * @return bool 40 | */ 41 | public function validateVendorPrefix($sVendorPrefix) 42 | { 43 | return (bool) preg_match('/^([a-z]{2,4})$/', (string) $sVendorPrefix); 44 | } 45 | 46 | /** 47 | * Validate a name in UpperCamelCase style. 48 | * Accepts only latin letters and numbers, first char is always capitalized latin letter. 49 | * 50 | * @param string $sVariableName 51 | * 52 | * @return bool 53 | */ 54 | public function validateCamelCaseName($sVariableName) 55 | { 56 | return ( 57 | !empty($sVariableName) and 58 | preg_match('/^([A-Z]{1})([a-zA-Z0-9]{1,63})$/', (string) $sVariableName) 59 | ); 60 | } 61 | 62 | /** 63 | * Converts camel case string to human readable string with spaces between words. 64 | * Treats UPPERCASE abbreviations and numbers as separate words. 65 | * 66 | * @param string $sCamelCaseString 67 | * 68 | * @return string 69 | */ 70 | public function camelCaseToHumanReadable($sCamelCaseString) 71 | { 72 | // Split CamelCase 73 | $sHumanReadableString = preg_replace('/([A-Z]{1}[a-z]+)/', ' $1', (string) $sCamelCaseString); 74 | 75 | // Split numbers attached to letters 76 | $sHumanReadableString = preg_replace('/([a-zA-Z])([0-9]{1})/', '$1 $2', $sHumanReadableString); 77 | 78 | // Split UPPERCASE attached to words 79 | $sHumanReadableString = preg_replace('/([a-z0-9])([A-Z]{1})/', '$1 $2', $sHumanReadableString); 80 | 81 | return !is_null($sHumanReadableString) ? trim($sHumanReadableString) : $sCamelCaseString; 82 | } 83 | 84 | /** 85 | * Get array value by key, optionally casting its type to desired one. 86 | * 87 | * @param array $aDataArray 88 | * @param mixed $mArrayKey 89 | * @param string $sType 90 | * 91 | * @return bool 92 | */ 93 | public function getArrayValue(array $aDataArray, $mArrayKey, $sType = 'string') 94 | { 95 | $mValue = isset($aDataArray[$mArrayKey]) ? $aDataArray[$mArrayKey] : null; 96 | 97 | return settype($mValue, $sType) ? $mValue : null; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OXID Module Skeleton Generator 2 | 3 | ---- 4 | 5 | Folders structure, empty classes and metadata generation for new OXID eShop modules. 6 | 7 | ### Concentrate only on features - let OXID Module Skeleton Generator create all the rest! 8 | * **Enter Your copyright data in the module settings** 9 | * **Open an easy to use Module Generator Wizard** 10 | * **Enter new module name and optional components** 11 | * **Press "Generate New Module" and its done - new module is now ready to be activated and filled with features!** 12 | 13 | ## OXID Module Skeleton Generator features 14 | - Fully configurable vendor/author parameters for new modules creation 15 | - Vendor folder and vendor metadata automatic creation 16 | - Standard module folders structure creation 17 | - Completely filled module medatada file generation 18 | - Naming based on vendor data and module name 19 | - Created modules follow OXID standards 20 | - Automatic creation of pre-filled README file 21 | - Generation of PHP files comments with all vendor and module data 22 | - Main module class is included in each generated module 23 | - It contains activation/deactivation events 24 | - Support automatic SQL execution on the events 25 | - The class "knows" about its module and provides useful methods 26 | - Generation of skeleton files for... 27 | - Overloaded (extend) classes 28 | - New controllers (also templates are created) 29 | - Model classes 30 | - List model classes (linked with item model classes) 31 | - Widgets (also with templates) 32 | - Smarty blocks metadata and templates generation 33 | - Module settings metadata and translations generation 34 | - Translation files creation 35 | - Module version 36 | - Automatic checkout of tests folder 37 | - And generation of pre-filled tests classes for each new module class 38 | - Configurable GIT repository URL to get tests folder from 39 | - Learning mode 40 | - Creation of hints and to do tasks inside generated files to help proceed with development 41 | - Sample source code generation to give a hint what each class could/should contain 42 | - Generated module is immediately working 43 | - Activate it and events, settings, blocks, controllers, etc. will already be in action! 44 | 45 | ## Installation 46 | - Copy the content of `copy_this/` folder to OXID eShop root folder 47 | - Activate the module in administration area 48 | - Set eShop `modules/` folder writable while generating new modules 49 | 50 | ## Usage 51 | - Make sure eShop `modules/` folder (and also Your vendor sub-folder, if it exists) is writable 52 | - Log in to eShop administration area 53 | - (for first run) Go to _Extensions -> Modules -> OXID Module Skeleton Generator -> Settings -> Vendor and Copyright Settings_ and enter Your vendor, copyright and author data 54 | - Open _Module Generator -> Wizard_ (refresh page if it did not appear after module activation) 55 | - Enter a name for a new module in "UpperCamelCase" format, e.g. "MyModule" 56 | - (optionally) Enter any other options required in a new module (refer to help hints for more info) 57 | - Press "Generate New Module" button 58 | - The module skeleton source is now available in Your vendor sub-folder 59 | - And the module could be activated already in _Extensions -> Modules_ 60 | 61 | ## To do and nice to have features for future releases 62 | - Refactor longer classes to move some methods elsewhere 63 | - Extend blocks definition validation and blocks templates naming 64 | - EDIT mode feature: for existing modules, generate/add extra stuff 65 | - Create nice looking generation form with JS/AJAX events to validate and help enter proper values (auto-complete) 66 | - Admin interface presets generation, also with menu.xml 67 | - Generate picture with PNG text overlay with real module name 68 | - PHPStorm style schemes (or some code beautifier) integration - after generation do code formatting 69 | - Copy not all folders, but only required ones (Refactor copyDir by providing "copy scenario" array) 70 | - dbEvent fail on multi-shops and multi-lang in real life projects - need PHP based DB installation 71 | 72 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/oxpstestclass.php.tpl: -------------------------------------------------------------------------------- 1 | renderFileComment()}] 3 | 4 | [{assign var='sClassNamePrefix' value=$oModule->getModuleClassName()}] 5 | [{if $sClassRealName}] 6 | [{assign var='sClassName' value=$sClassRealName}] 7 | [{else}] 8 | [{assign var='sClassName' value=$oModule->getFileNameSuffix($sFilePath)}] 9 | [{/if}] 10 | [{assign var="sClassFullName" value=$sClassNamePrefix|cat:$sClassName}] 11 | 12 | /** 13 | * Class [{$sClassFullName}]Test 14 | * Tests for core class [{$sClassFullName}]. 15 | * 16 | * @see [{$sClassFullName}] 17 | */ 18 | class [{$sClassFullName}]Test extends OxidTestCase 19 | { 20 | 21 | /** 22 | * Subject under the test. 23 | * 24 | * @var [{$sClassFullName}] 25 | */ 26 | protected $SUT; 27 | 28 | 29 | /** 30 | * Set SUT state before test. 31 | */ 32 | public function setUp() 33 | { 34 | parent::setUp(); 35 | 36 | [{if $oModule->renderTasks()}] 37 | //TODO: Add more methods to mock. 38 | [{/if}] 39 | $this->SUT = $this->getMock('[{$sClassFullName}]', array('__call')); 40 | } 41 | 42 | 43 | [{if $oModule->renderTasks()}] 44 | // TODO: Implement tests here... 45 | // TODO: Test method naming is: "test[method_name]_[condition_answering_questions_when]_[expected_action_following_word_should]" 46 | 47 | [{/if}] 48 | [{if $oModule->renderSamples()}] 49 | /* public function testMyMethod_thisAndThatConditionMet_doThisAndThatAction() 50 | { 51 | [{if $oModule->renderTasks()}] 52 | // General Good Practices: 53 | // - Keep test method as small and as simple as possible 54 | // - Test one condition per one test 55 | // - Write as many tests as neded to test all conditions 56 | 57 | // TODO: For mocking use techniques like this: 58 | // Create mock object and define itsx expected behavior 59 | $oMyMock = $this->getMock('[someClass]', array('[someMethod]', '[otherClassMethod]')); 60 | $oMyMock->expects($this->once()/exactly($i[x])/never()/at($i[x])/atLeastOnce()) 61 | ->method('[otherClassMethod]') 62 | ->with('[Val1]', '[Val2]' / $this->equalTo($m[Val])/anything()/isTrue/False/Null/Json/Type/InstanceOf...()/contains/arrayHasKey/...) 63 | ->will($this->returnValue($m[Val])/returnArgument($i[x])/throwException($o[Exc])/returnValueMap($a[Val])/returnSelf/...); 64 | 65 | // You can set mock inside mock 66 | $oMyClassMock->expects($this->any())->method('myMethod')->with($this->equalTo('argument'))->will( 67 | $this->returnValue($this->getMock(…)) 68 | ); 69 | 70 | // Also create mocks for protected methods access 71 | $this->getProxyClass('MyClass'); 72 | $this->getMock($this->getProxyClassName('MyClass'), array(…)); 73 | 74 | // Mock request, cnfig and session data 75 | modConfig::setParameter('param', 'value'); 76 | modConfig::getInstance()->setConfigParam('setting', 'value'); 77 | modSession::getInstance()->setVar('key', 'value'); 78 | 79 | // Set mocks instead of real objects 80 | oxTestModules::addModuleObject('MyClass', $oMyClassMock); 81 | oxRegistry::set('MyClass', $oMyClassMock); 82 | 83 | // Use all the variety of PHPUnit assertions 84 | $this->assert... 85 | 86 | // Create tearDown() method to clear state, reset test data, etc. 87 | [{/if}] 88 | $this->asset[...](..., $this->SUT->myMethod()); 89 | } */ 90 | 91 | // An example of data provider used for testing 92 | /* public function myDataProvider() 93 | { 94 | return array( 95 | array([val1], [val2]), 96 | array([valA], [valB]), 97 | ... 98 | ); 99 | } */ 100 | 101 | /** 102 | * @dataProvider myDataProvider 103 | */ 104 | /* public function testSomeMethod($mArg, $mExpectedResult) 105 | { 106 | $this->assertSame($mExpectedResult, $this->SUT->someMethod($mArg)); 107 | } */ 108 | [{/if}] 109 | } 110 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/metadata.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | /** 28 | * Metadata version 29 | */ 30 | $sMetadataVersion = '1.1'; 31 | 32 | /** 33 | * Module information 34 | */ 35 | $aModule = array( 36 | 'id' => 'oxpsmodulegenerator', 37 | 'title' => 'OXID Module Skeleton Generator', 38 | 'description' => array( 39 | 'de' => 'Die Erzeugung von Ordner-Struktur, leere Klassen und Metadata-Datei für neue OXID eShop Module', 40 | 'en' => 'Folders structure, empty classes and metadata generation for new OXID eShop modules.', 41 | ), 42 | 'thumbnail' => 'out/pictures/oxpsmodulegenerator.png', 43 | 'version' => '0.5.0', 44 | 'author' => 'OXID Professional Services', 45 | 'url' => 'http://www.oxid-esales.com', 46 | 'email' => 'info@oxid-esales.com', 47 | 'extend' => array( 48 | 'oxmodule' => 'oxps/modulegenerator/core/oxpsmodulegeneratoroxmodule', 49 | ), 50 | 'files' => array( 51 | 'admin_oxpsmodulegenerator' => 'oxps/modulegenerator/controllers/admin/admin_oxpsmodulegenerator.php', 52 | 'oxpsmodulegeneratorfilesystem' => 'oxps/modulegenerator/core/oxpsmodulegeneratorfilesystem.php', 53 | 'oxpsmodulegeneratorhelper' => 'oxps/modulegenerator/core/oxpsmodulegeneratorhelper.php', 54 | 'oxpsmodulegeneratormodule' => 'oxps/modulegenerator/core/oxpsmodulegeneratormodule.php', 55 | 'oxpsmodulegeneratorrender' => 'oxps/modulegenerator/core/oxpsmodulegeneratorrender.php', 56 | 'oxpsmodulegeneratorsettings' => 'oxps/modulegenerator/core/oxpsmodulegeneratorsettings.php', 57 | 'oxpsmodulegeneratorvalidator' => 'oxps/modulegenerator/core/oxpsmodulegeneratorvalidator.php', 58 | ), 59 | 'templates' => array( 60 | 'admin_oxpsmodulegenerator.tpl' => 'oxps/modulegenerator/views/admin/admin_oxpsmodulegenerator.tpl', 61 | ), 62 | 'settings' => array( 63 | array( 64 | 'group' => 'oxpsModuleGeneratorVendor', 65 | 'name' => 'oxpsModuleGeneratorVendorPrefix', 66 | 'type' => 'str', 67 | 'value' => '' 68 | ), 69 | array( 70 | 'group' => 'oxpsModuleGeneratorVendor', 71 | 'name' => 'oxpsModuleGeneratorModuleAuthor', 72 | 'type' => 'str', 73 | 'value' => '' 74 | ), 75 | array( 76 | 'group' => 'oxpsModuleGeneratorVendor', 77 | 'name' => 'oxpsModuleGeneratorAuthorLink', 78 | 'type' => 'str', 79 | 'value' => '' 80 | ), 81 | array( 82 | 'group' => 'oxpsModuleGeneratorVendor', 83 | 'name' => 'oxpsModuleGeneratorAuthorMail', 84 | 'type' => 'str', 85 | 'value' => '' 86 | ), 87 | array( 88 | 'group' => 'oxpsModuleGeneratorVendor', 89 | 'name' => 'oxpsModuleGeneratorCopyright', 90 | 'type' => 'str', 91 | 'value' => '' 92 | ), 93 | array( 94 | 'group' => 'oxpsModuleGeneratorVendor', 95 | 'name' => 'oxpsModuleGeneratorComment', 96 | 'type' => 'arr', 97 | 'value' => array() 98 | ), 99 | array( 100 | 'group' => 'oxpsModuleGeneratorTests', 101 | 'name' => 'oxpsModuleGeneratorTestsGitUrl', 102 | 'type' => 'str', 103 | 'value' => '', 104 | ), 105 | ), 106 | 'events' => array( 107 | 'onActivate' => 'oxpsModuleGeneratorModule::onActivate', 108 | 'onDeactivate' => 'oxpsModuleGeneratorModule::onDeactivate', 109 | ), 110 | ); 111 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/oxpsmodulegeneratorfilesystem.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | /** 28 | * Class oxpsModuleGeneratorFileSystem. 29 | * A helper class for files and folders verification, creation and management methods. 30 | */ 31 | class oxpsModuleGeneratorFileSystem extends oxSuperCfg 32 | { 33 | 34 | /** 35 | * An alias for PHP function `is_file`. 36 | * 37 | * @param string $sPath 38 | * 39 | * @return bool 40 | */ 41 | public function isFile($sPath) 42 | { 43 | return is_file($sPath); 44 | } 45 | 46 | /** 47 | * An alias for PHP function `is_dir`. 48 | * 49 | * @param string $sPath 50 | * 51 | * @return bool 52 | */ 53 | public function isDir($sPath) 54 | { 55 | return is_dir($sPath); 56 | } 57 | 58 | /** 59 | * Check if folder exists and create folder(s) recursively if missing. 60 | * 61 | * @param string $sFolderFullPath 62 | */ 63 | public function createFolder($sFolderFullPath) 64 | { 65 | if (!$this->isDir($sFolderFullPath)) { 66 | 67 | mkdir($sFolderFullPath, 0777, true); 68 | } 69 | } 70 | 71 | /** 72 | * Create a file using provided path and content, set full access permissions. 73 | * 74 | * @param string $sFileFullPath 75 | * @param string $sFileContent 76 | */ 77 | public function createFile($sFileFullPath, $sFileContent, $blIfDoesNotExist = false) 78 | { 79 | $blFileCreated = false; 80 | 81 | if (!$this->isFile($sFileFullPath) or empty($blIfDoesNotExist)) { 82 | $blFileCreated = (bool) file_put_contents($sFileFullPath, $sFileContent); 83 | } 84 | 85 | if ($blFileCreated) { 86 | chmod($sFileFullPath, 0777); 87 | } 88 | } 89 | 90 | /** 91 | * Rename a file. 92 | * 93 | * @param string $sOldPathAndName 94 | * @param string $sNewPathAndName 95 | */ 96 | public function renameFile($sOldPathAndName, $sNewPathAndName) 97 | { 98 | if ($this->isFile($sOldPathAndName)) { 99 | rename($sOldPathAndName, $sNewPathAndName); 100 | } 101 | } 102 | 103 | /** 104 | * Recursive directory copying. 105 | * Copies all files and folders to a new location. 106 | * 107 | * @param string $sSourcePath Where to copy from. 108 | * @param string $sDestinationPath Where to copy to. 109 | * 110 | * @return bool 111 | */ 112 | public function copyFolder($sSourcePath, $sDestinationPath) 113 | { 114 | $sDS = DIRECTORY_SEPARATOR; 115 | 116 | if (!$this->isDir($sSourcePath) or !($hDir = opendir($sSourcePath))) { 117 | return false; 118 | } 119 | 120 | // Check module path to make sure nothing is missing 121 | $this->createFolder($sDestinationPath); 122 | 123 | while (false !== ($sFile = readdir($hDir))) { 124 | $this->_copy($sFile, $sSourcePath . $sDS . $sFile, $sDestinationPath . $sDS . $sFile); 125 | } 126 | 127 | closedir($hDir); 128 | 129 | return true; 130 | } 131 | 132 | /** 133 | * File copying. 134 | * 135 | * @param string $sSourcePath 136 | * @param string $sDestinationPath 137 | */ 138 | public function copyFile($sSourcePath, $sDestinationPath) 139 | { 140 | if ($this->isFile($sSourcePath) and copy($sSourcePath, $sDestinationPath)) { 141 | chmod($sDestinationPath, 0777); 142 | } 143 | } 144 | 145 | 146 | /** 147 | * Check if resource could be copied. 148 | * If it's a file, copy it. If it's a folder, call recursive folder copy. 149 | * 150 | * @param string $sFile 151 | * @param string $sSourcePath 152 | * @param string $sDestinationPath 153 | */ 154 | protected function _copy($sFile, $sSourcePath, $sDestinationPath) 155 | { 156 | if (!in_array($sFile, array('.', '..', '.gitkeep'))) { 157 | if ($this->isDir($sSourcePath)) { 158 | $this->copyFolder($sSourcePath, $sDestinationPath); 159 | } else { 160 | $this->copyFile($sSourcePath, $sDestinationPath); 161 | } 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/metadata.php.tpl: -------------------------------------------------------------------------------- 1 | renderFileComment()}] 3 | 4 | [{assign var='sVendorDir' value=$oModule->getVendorPrefix()}] 5 | [{assign var='sModuleId' value=$oModule->getModuleId()}] 6 | [{assign var='sModuleCamelCaseId' value=$oModule->getModuleId(true)}] 7 | [{assign var='sModuleFolderName' value=$oModule->getModuleFolderName()}] 8 | [{assign var='aNewClasses' value=$oModule->getClassesToCreate()}] 9 | [{assign var='aControllersClasses' value=$oModule->getClassesToCreate('controllers', 'aClasses')}] 10 | [{assign var='aWidgetsClasses' value=$oModule->getClassesToCreate('widgets', 'aClasses')}] 11 | [{assign var='aExtendClasses' value=$oModule->getClassesToExtend()}] 12 | [{assign var='aModuleBlocks' value=$oModule->getBlocks()}] 13 | [{assign var='aModuleSettings' value=$oModule->getSettings()}] 14 | /** 15 | * Metadata version 16 | */ 17 | $sMetadataVersion = '1.1'; 18 | 19 | /** 20 | * Module information 21 | */ 22 | [{if $oModule->renderTasks()}]/** 23 | * TODO: Replace sample names and paths (like '[ParentClassName]', '[your_template]', etc.) with real ones You need. 24 | * TODO: Uncomment lines You need, add more if needed, delete not required. 25 | * TODO: Remove all this TODO comment. 26 | */ 27 | [{/if}] 28 | $aModule = array( 29 | 'id' => '[{$sModuleId}]', 30 | 'title' => array( 31 | 'de' => '[TR - [{$oModule->getTitle()}]]', 32 | 'en' => '[{$oModule->getTitle()}]', 33 | ), 34 | 'description' => array( 35 | 'de' => '[TR - [{$oModule->getDescription()}]]', 36 | 'en' => '[{$oModule->getDescription()}]', 37 | ), 38 | 'thumbnail' => 'out/pictures/picture.png', 39 | 'version' => '[{$oModule->getInitialVersion()}]', 40 | 'author' => '[{$oModule->getAuthorData('name')}]', 41 | 'url' => '[{$oModule->getAuthorData('link')}]', 42 | 'email' => '[{$oModule->getAuthorData('mail')}]', 43 | 'extend' => array( 44 | [{if $aExtendClasses}] 45 | [{foreach from=$aExtendClasses key='sExtendClass' item='mApplicationPath'}] 46 | '[{$sExtendClass}]' => '[{$sVendorDir}]/[{$sModuleFolderName}]/[{$mApplicationPath}][{$sModuleId}][{$sExtendClass}]', 47 | [{/foreach}] 48 | [{/if}] 49 | [{if $oModule->renderSamples()}]//'[ParentClassName]' => '[{$sVendorDir}]/[{$sModuleFolderName}]/[appropriate_folder]/[{$sModuleId}][parent_class_name]', 50 | [{/if}] 51 | ), 52 | 'files' => array( 53 | '[{$sModuleId}]module' => '[{$sVendorDir}]/[{$sModuleFolderName}]/core/[{$sModuleId}]module.php', 54 | [{if $aNewClasses}] 55 | [{foreach from=$aNewClasses key='sObjectType' item='aClassesData'}] 56 | [{assign var='aClasses' value=$aClassesData.aClasses}] 57 | [{foreach from=$aClasses key='sClassKey' item='sClassName'}] 58 | '[{$sModuleId}][{$sClassName|lower}]' => '[{$sVendorDir}]/[{$sModuleFolderName}]/[{$aClassesData.sInModulePath}][{$sModuleId}][{$sClassName|lower}].php', 59 | [{/foreach}] 60 | [{/foreach}] 61 | [{/if}] 62 | [{if $oModule->renderSamples()}] 63 | //'[your_class_name]' => '[{$sVendorDir}]/[{$sModuleFolderName}]/[appropriate_folder]/[{$sModuleId}][your_class_name].php', 64 | [{/if}] 65 | ), 66 | 'templates' => array( 67 | [{if $aControllersClasses}] 68 | [{foreach from=$aControllersClasses item='sControllerClassName'}] 69 | '[{$sModuleId}][{$sControllerClassName|lower}].tpl' => '[{$sVendorDir}]/[{$sModuleFolderName}]/views/pages/[{$sModuleId}][{$sControllerClassName|lower}].tpl', 70 | [{/foreach}] 71 | [{/if}] 72 | [{if $aWidgetsClasses}] 73 | [{foreach from=$aWidgetsClasses item='sWidgetClassName'}] 74 | '[{$sModuleId}][{$sWidgetClassName|lower}].tpl' => '[{$sVendorDir}]/[{$sModuleFolderName}]/views/widgets/[{$sModuleId}][{$sWidgetClassName|lower}].tpl', 75 | [{/foreach}] 76 | [{/if}] 77 | [{if $oModule->renderSamples()}] 78 | //'[your_template].tpl' => '[{$sVendorDir}]/[{$sModuleFolderName}]/views/pages/[theme_folder_path]/[{$sModuleId}][your_template].tpl', 79 | [{/if}] 80 | ), 81 | 'blocks' => array( 82 | [{if $aModuleBlocks}] 83 | [{foreach from=$aModuleBlocks item='aModuleBlock'}] 84 | array( 85 | 'template' => '[{$aModuleBlock->template}]', 86 | 'block' => '[{$aModuleBlock->block}]', 87 | 'file' => '[{$aModuleBlock->file}]', 88 | ), 89 | [{/foreach}] 90 | [{else}] 91 | [{if $oModule->renderSamples()}]/*array( 92 | 'template' => '[theme_folder]/[theme_template].tpl', 93 | 'block' => '[{$sModuleId}]_[your_block_name]', 94 | 'file' => 'views/blocks/[{$sModuleId}][your_block_name].tpl', 95 | ),*/ 96 | [{/if}] 97 | [{/if}] 98 | ), 99 | 'settings' => array( 100 | [{if $aModuleSettings}] 101 | [{foreach from=$aModuleSettings key='iSettingKey' item='aModuleSetting'}] 102 | array( 103 | 'group' => '[{$sModuleCamelCaseId}]Settings', 104 | 'name' => '[{$sModuleCamelCaseId}][{$aModuleSetting->name}]', 105 | 'type' => '[{$aModuleSetting->type}]', 106 | 'value' => [{$aModuleSetting->value}], 107 | [{if $aModuleSetting->type eq 'select'}] 108 | 'constrains' => [{$aModuleSetting->constrains}], 109 | [{/if}] 110 | ), 111 | [{/foreach}] 112 | [{else}] 113 | [{if $oModule->renderSamples()}]/*array( 114 | 'group' => '[{$sModuleCamelCaseId}][SettingsGroup]', 115 | 'name' => '[{$sModuleCamelCaseId}][SettingName]', 116 | [{if $oModule->renderTasks()}] 117 | //TODO: Change type to one You need: 'bool', 'str', 'num', 'arr', 'aarr', 'select'. Remove this comment. 118 | [{/if}] 119 | 'type' => 'str', 120 | 'value' => '[initial_setting_value]', 121 | ),*/ 122 | [{/if}] 123 | [{/if}] 124 | ), 125 | 'events' => array( 126 | 'onActivate' => '[{$oModule->getModuleClassName()}]Module::onActivate', 127 | 'onDeactivate' => '[{$oModule->getModuleClassName()}]Module::onDeactivate', 128 | ), 129 | ); 130 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/oxpsmodulegeneratormodule.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | /** 28 | * Class oxpsModuleGeneratorModule. 29 | * Handles module setup, provides additional tools and module related helpers. 30 | */ 31 | class oxpsModuleGeneratorModule extends oxModule 32 | { 33 | 34 | /** 35 | * Class constructor. 36 | * Sets current module main data and loads the rest module info. 37 | */ 38 | function __construct() 39 | { 40 | $sModuleId = 'oxpsmodulegenerator'; 41 | 42 | $this->setModuleData( 43 | array( 44 | 'id' => $sModuleId, 45 | 'title' => 'OXID Module Skeleton Generator', 46 | 'description' => 'Folders structure, empty classes and metadata generation for new OXID eShop modules.', 47 | ) 48 | ); 49 | 50 | $this->load($sModuleId); 51 | 52 | oxRegistry::set('oxpsModuleGeneratorModule', $this); 53 | } 54 | 55 | 56 | /** 57 | * Module activation script. 58 | */ 59 | public static function onActivate() 60 | { 61 | self::clearTmp(); 62 | } 63 | 64 | /** 65 | * Module deactivation script. 66 | */ 67 | public static function onDeactivate() 68 | { 69 | self::clearTmp(); 70 | } 71 | 72 | /** 73 | * Clean temp folder content. 74 | * NOTE: The method is not in File System Helper, because it will also be same in generated modules, 75 | * so it requires to be covered with tests in this class. 76 | * 77 | * @param string $sClearFolderPath Sub-folder path to delete from. Should be a full, valid path inside temp folder. 78 | * 79 | * @return boolean 80 | */ 81 | public static function clearTmp($sClearFolderPath = '') 82 | { 83 | $sFolderPath = self::_getFolderToClear($sClearFolderPath); 84 | $hDirHandler = opendir($sFolderPath); 85 | 86 | if (!empty($hDirHandler)) { 87 | while (false !== ($sFileName = readdir($hDirHandler))) { 88 | $sFilePath = $sFolderPath . DIRECTORY_SEPARATOR . $sFileName; 89 | self::_clear($sFileName, $sFilePath); 90 | } 91 | 92 | closedir($hDirHandler); 93 | } 94 | 95 | return true; 96 | } 97 | 98 | /** 99 | * Get translated string by the translation code. 100 | * 101 | * @param string $sCode 102 | * @param boolean $blUseModulePrefix If True - adds the module translations prefix, if False - not. 103 | * 104 | * @return string 105 | */ 106 | public function translate($sCode, $blUseModulePrefix = true) 107 | { 108 | if ($blUseModulePrefix) { 109 | $sCode = 'OXPS_MODULEGENERATOR_' . $sCode; 110 | } 111 | 112 | return oxRegistry::getLang()->translateString($sCode, oxRegistry::getLang()->getBaseLanguage(), false); 113 | } 114 | 115 | /** 116 | * Get CMS snippet content by identified ID. 117 | * 118 | * @param string $sIdentifier 119 | * @param bool $blNoHtml 120 | * 121 | * @return string 122 | */ 123 | public function getCmsContent($sIdentifier, $blNoHtml = true) 124 | { 125 | $sValue = ''; 126 | 127 | /** @var oxContent|oxI18n $oContent */ 128 | $oContent = oxNew('oxContent'); 129 | $oContent->loadByIdent(trim((string) $sIdentifier)); 130 | 131 | if ($oContent->oxcontents__oxcontent instanceof oxField) { 132 | $sValue = (string) $oContent->oxcontents__oxcontent->getRawValue(); 133 | $sValue = (empty($blNoHtml) ? $sValue : nl2br(strip_tags($sValue))); 134 | } 135 | 136 | return $sValue; 137 | } 138 | 139 | /** 140 | * Get module setting value. 141 | * 142 | * @param string $sModuleSettingName Module setting parameter name (key). 143 | * @param boolean $blUseModulePrefix If True - adds the module settings prefix, if False - not. 144 | * 145 | * @return mixed 146 | */ 147 | public function getSetting($sModuleSettingName, $blUseModulePrefix = true) 148 | { 149 | if ($blUseModulePrefix) { 150 | $sModuleSettingName = 'oxpsModuleGenerator' . (string) $sModuleSettingName; 151 | } 152 | 153 | return oxRegistry::getConfig()->getConfigParam((string) $sModuleSettingName); 154 | } 155 | 156 | /** 157 | * Get module path. 158 | * 159 | * @return string Full path to the module directory. 160 | */ 161 | public function getPath() 162 | { 163 | return oxRegistry::getConfig()->getModulesDir() . 'oxps/modulegenerator/'; 164 | } 165 | 166 | 167 | /** 168 | * Check if provided path is inside eShop `tpm/` folder or use the `tmp/` folder path. 169 | * 170 | * @param string $sClearFolderPath 171 | * 172 | * @return string 173 | */ 174 | protected static function _getFolderToClear($sClearFolderPath = '') 175 | { 176 | $sTempFolderPath = (string) oxRegistry::getConfig()->getConfigParam('sCompileDir'); 177 | 178 | if (!empty($sClearFolderPath) and (strpos($sClearFolderPath, $sTempFolderPath) !== false)) { 179 | $sFolderPath = $sClearFolderPath; 180 | } else { 181 | $sFolderPath = $sTempFolderPath; 182 | } 183 | 184 | return $sFolderPath; 185 | } 186 | 187 | /** 188 | * Check if resource could be deleted, then delete it's a file or 189 | * call recursive folder deletion if it's a directory. 190 | * 191 | * @param string $sFileName 192 | * @param string $sFilePath 193 | */ 194 | protected static function _clear($sFileName, $sFilePath) 195 | { 196 | if (!in_array($sFileName, array('.', '..', '.gitkeep', '.htaccess'))) { 197 | if (is_file($sFilePath)) { 198 | @unlink($sFilePath); 199 | } else { 200 | self::clearTmp($sFilePath); 201 | } 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/tests/unit/core/oxpsModuleGeneratorModuleTest.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | /** 28 | * Class oxpsModuleGeneratorModuleTest 29 | * INTEGRATION tests for core class oxpsModuleGeneratorModule. 30 | * 31 | * @see oxpsModuleGeneratorModule 32 | */ 33 | class oxpsModuleGeneratorModuleTest extends OxidTestCase 34 | { 35 | 36 | /** 37 | * Subject under the test. 38 | * 39 | * @var oxpsModuleGeneratorModule 40 | */ 41 | protected $SUT; 42 | 43 | 44 | /** 45 | * Set SUT state before test. 46 | */ 47 | public function setUp() 48 | { 49 | parent::setUp(); 50 | 51 | $this->SUT = new oxpsModuleGeneratorModule(); 52 | } 53 | 54 | public static function setUpBeforeClass() 55 | { 56 | parent::setUpBeforeClass(); 57 | 58 | importTestdataFile('testdata_remove.sql'); 59 | importTestdataFile('testdata_add.sql'); 60 | } 61 | 62 | public static function tearDownAfterClass() 63 | { 64 | parent::tearDownAfterClass(); 65 | 66 | importTestdataFile('testdata_remove.sql'); 67 | } 68 | 69 | 70 | public function testConstructor_loadModuleData() 71 | { 72 | $this->assertSame('oxpsmodulegenerator', $this->SUT->getId()); 73 | $this->assertSame('OXID Module Skeleton Generator', $this->SUT->getTitle()); 74 | $this->assertSame( 75 | 'Folders structure, empty classes and metadata generation for new OXID eShop modules.', 76 | $this->SUT->getDescription() 77 | ); 78 | } 79 | 80 | 81 | public function testOnActivate_clearTempFiles() 82 | { 83 | $sTestFilePath = oxRegistry::getConfig()->getConfigParam('sCompileDir') . DIRECTORY_SEPARATOR . 'test.file'; 84 | 85 | file_put_contents($sTestFilePath, 'TEST' . PHP_EOL); 86 | 87 | $this->assertFileExists($sTestFilePath); 88 | 89 | $SUT = $this->SUT; 90 | $SUT::onActivate(); 91 | 92 | $this->assertFileNotExists($sTestFilePath); 93 | } 94 | 95 | 96 | public function testOnDeactivate_clearTempFiles() 97 | { 98 | $sTestFilePath = oxRegistry::getConfig()->getConfigParam('sCompileDir') . DIRECTORY_SEPARATOR . 'test.file'; 99 | 100 | file_put_contents($sTestFilePath, 'TEST' . PHP_EOL); 101 | 102 | $this->assertFileExists($sTestFilePath); 103 | 104 | $SUT = $this->SUT; 105 | $SUT::onDeactivate(); 106 | 107 | $this->assertFileNotExists($sTestFilePath); 108 | } 109 | 110 | 111 | public function testClearTmp_argumentDirProvided_clearsOnlyInsideProvidedDirectory() 112 | { 113 | $sTestFilePath = oxRegistry::getConfig()->getConfigParam('sCompileDir') . 'test.file'; 114 | $sSmartyDirPath = oxRegistry::getConfig()->getConfigParam('sCompileDir') . 'smarty'; 115 | 116 | // since this is a test, the smarty subdir might not yet exist 117 | if(!is_dir($sSmartyDirPath)) { 118 | mkdir($sSmartyDirPath); 119 | } 120 | 121 | $sSmartyFilePath = $sSmartyDirPath . DIRECTORY_SEPARATOR . 'test.file'; 122 | 123 | file_put_contents($sTestFilePath, 'TEST' . PHP_EOL); 124 | file_put_contents($sSmartyFilePath, 'TEST' . PHP_EOL); 125 | 126 | $this->assertFileExists($sTestFilePath); 127 | $this->assertFileExists($sSmartyFilePath); 128 | 129 | $SUT = $this->SUT; 130 | $SUT::clearTmp(oxRegistry::getConfig()->getConfigParam('sCompileDir') . DIRECTORY_SEPARATOR . 'smarty'); 131 | 132 | $this->assertFileExists($sTestFilePath); 133 | $this->assertFileNotExists($sSmartyFilePath); 134 | } 135 | 136 | 137 | public function testClearTmp_noArguments_clearsTempFolder() 138 | { 139 | $sTestFilePath = oxRegistry::getConfig()->getConfigParam('sCompileDir') . DIRECTORY_SEPARATOR . 'test.file'; 140 | 141 | file_put_contents($sTestFilePath, 'TEST' . PHP_EOL); 142 | 143 | $this->assertFileExists($sTestFilePath); 144 | 145 | $SUT = $this->SUT; 146 | $SUT::clearTmp(); 147 | 148 | $this->assertFileNotExists($sTestFilePath); 149 | } 150 | 151 | 152 | public function testTranslate_noSecondArgument_returnModuleTranslationStringByCode() 153 | { 154 | $this->assertSame('OXPS_MODULEGENERATOR_SOME_CODE', $this->SUT->translate('SOME_CODE')); 155 | } 156 | 157 | 158 | public function testTranslate_secondArgumentIsFalse_returnGlobalTranslationStringByCode() 159 | { 160 | $this->assertSame('SOME_CODE', $this->SUT->translate('SOME_CODE', false)); 161 | } 162 | 163 | 164 | public function testGetCmsContent_noIdentFound_returnEmptyString() 165 | { 166 | $this->assertSame('', $this->SUT->getCmsContent('oxps_non_existing_ident!')); 167 | } 168 | 169 | 170 | public function testGetCmsContent_noSecondArgument_returnCmsSnippetContentByIdentWithNoHtml() 171 | { 172 | $this->assertSame('Hello, World! ', $this->SUT->getCmsContent('oxpstestident')); 173 | } 174 | 175 | 176 | public function testGetCmsContent_secondArgumentIsFalse_returnCmsSnippetContentByIdentInHtml() 177 | { 178 | $this->assertSame('

Hello,

World!

', $this->SUT->getCmsContent('oxpstestident', false)); 179 | } 180 | 181 | 182 | public function testGetSetting_noSecondArgument_returnModuleSettingByItsNameWithNoModulePrefix() 183 | { 184 | oxRegistry::getConfig()->setConfigParam('oxpsModuleGeneratorVendorPrefix', 'test'); 185 | 186 | $this->assertSame('test', $this->SUT->getSetting('VendorPrefix')); 187 | } 188 | 189 | 190 | public function testGetSetting_secondArgumentIsFalse_returnModuleSettingByItsNameWithNoModulePrefix() 191 | { 192 | oxRegistry::getConfig()->setConfigParam('sAdminEmail', 'test@example.com'); 193 | 194 | $this->assertSame('test@example.com', $this->SUT->getSetting('sAdminEmail', false)); 195 | } 196 | 197 | 198 | public function testGetPath() 199 | { 200 | $sPath = $this->SUT->getPath(); 201 | 202 | $this->assertStringEndsWith('/oxps/modulegenerator/', $sPath); 203 | $this->assertFileExists($sPath); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/tests/unit/core/oxpsModuleGeneratorValidatorTest.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | /** 28 | * Class oxpsModuleGeneratorValidatorTest 29 | * UNIT tests for core class oxpsModuleGeneratorValidator. 30 | * 31 | * @see oxpsModuleGeneratorValidator 32 | */ 33 | class oxpsModuleGeneratorValidatorTest extends OxidTestCase 34 | { 35 | 36 | /** 37 | * Subject under the test. 38 | * 39 | * @var oxpsModuleGeneratorValidator 40 | */ 41 | protected $SUT; 42 | 43 | 44 | /** 45 | * Set SUT state before test. 46 | */ 47 | public function setUp() 48 | { 49 | parent::setUp(); 50 | 51 | $this->SUT = $this->getMock('oxpsModuleGeneratorValidator', array('__call')); 52 | } 53 | 54 | 55 | /** 56 | * @dataProvider vendorPrefixDataProvider 57 | */ 58 | public function testValidateVendorPrefix($mValue, $blExpectedResult) 59 | { 60 | $this->assertSame($blExpectedResult, $this->SUT->validateVendorPrefix($mValue)); 61 | } 62 | 63 | public function vendorPrefixDataProvider() 64 | { 65 | return array( 66 | 67 | // Invalid values 68 | array('', false), 69 | array(' ', false), 70 | array(0, false), 71 | array(1, false), 72 | array('0000', false), 73 | array('1111', false), 74 | array('OXPS', false), 75 | array('oXps', false), 76 | array('o', false), 77 | array('oxpss', false), 78 | 79 | // Valid values 80 | array('oxps', true), 81 | array('oe', true), 82 | array('abc', true), 83 | array('abcd', true), 84 | ); 85 | } 86 | 87 | 88 | /** 89 | * @dataProvider camelCaseNameDataProvider 90 | */ 91 | public function testValidateCamelCaseName($mValue, $blExpectedResult) 92 | { 93 | $this->assertSame($blExpectedResult, $this->SUT->validateCamelCaseName($mValue)); 94 | } 95 | 96 | public function camelCaseNameDataProvider() 97 | { 98 | return array( 99 | 100 | // Invalid values 101 | array('', false), 102 | array(' ', false), 103 | array(0, false), 104 | array(1, false), 105 | array('0000', false), 106 | array('abc', false), 107 | array('myModule', false), 108 | array('A', false), 109 | array('1module', false), 110 | array('1MyModule', false), 111 | array('MyModuleVeryVeryVeryLongLongLongNameThatIsLongLongAndEvenLongerTheNameReallyIs', false), 112 | array(' MyModule', false), 113 | array('MyModule ', false), 114 | 115 | // Valid values 116 | array('MyModule', true), 117 | array('SuperModuleOne', true), 118 | array('SuperModuleOne2Three', true), 119 | array('OtherModuleABCName', true), 120 | array('MyModuleVeryVeryVeryLongLongLongNameThatIsLongLong', true), 121 | array('Good', true), 122 | array('One', true), 123 | array('Ab', true), 124 | array('Module1', true), 125 | array('Module1And2', true), 126 | ); 127 | } 128 | 129 | 130 | /** 131 | * @dataProvider camelCaseToHumanReadableDataProvider 132 | */ 133 | public function testCamelCaseToHumanReadable($mValue, $sExpectedResult) 134 | { 135 | $this->assertSame($sExpectedResult, $this->SUT->camelCaseToHumanReadable($mValue)); 136 | } 137 | 138 | public function camelCaseToHumanReadableDataProvider() 139 | { 140 | return array( 141 | array('', ''), 142 | array(' ', ''), 143 | array(0, '0'), 144 | array(1, '1'), 145 | array('0000', '0000'), 146 | array('abc', 'abc'), 147 | array('myModule', 'my Module'), 148 | array('A', 'A'), 149 | array('1module', '1module'), 150 | array('1MyModule', '1 My Module'), 151 | array( 152 | 'MyModuleVeryVeryVeryLongLongLongNameThatIsLongLongAndEvenLongerTheNameReallyIs', 153 | 'My Module Very Very Very Long Long Long Name That Is Long Long And Even Longer The Name Really Is' 154 | ), 155 | array('MyModule', 'My Module'), 156 | array('SuperModuleOne', 'Super Module One'), 157 | array('SuperModuleOne2Three', 'Super Module One 2 Three'), 158 | array('OtherModuleABCName', 'Other Module ABC Name'), 159 | array( 160 | 'MyModuleVeryVeryVeryLongLongLongNameThatIsLongLong', 161 | 'My Module Very Very Very Long Long Long Name That Is Long Long' 162 | ), 163 | array('Good', 'Good'), 164 | array('One', 'One'), 165 | array('Ab', 'Ab'), 166 | array('Module1', 'Module 1'), 167 | array('Module1And2', 'Module 1 And 2'), 168 | ); 169 | } 170 | 171 | 172 | /** 173 | * @dataProvider arrayValuesDataProvider 174 | */ 175 | public function testGetArrayValue(array $aData, $mKey, $sType, $mExpectedResult) 176 | { 177 | $this->assertSame($mExpectedResult, $this->SUT->getArrayValue($aData, $mKey, $sType)); 178 | } 179 | 180 | public function arrayValuesDataProvider() 181 | { 182 | return array( 183 | array(array(), '', 'string', ''), 184 | array(array(), 'a', 'string', ''), 185 | array(array('a'), 'a', 'string', ''), 186 | array(array('b' => 'a'), 'a', 'string', ''), 187 | array(array('b' => 'a'), 'a', 'integer', 0), 188 | array(array('b' => 'a'), 'a', 'double', 0.0), 189 | array(array('A' => 2), 'a', 'string', ''), 190 | array(array('a' => 2), 'a', 'string', '2'), 191 | array(array('b' => 3, 'a' => 2), 'a', 'string', '2'), 192 | array(array('b' => 3, 'a' => 2), 'a', 'integer', 2), 193 | array(array('b' => 3, 'a' => 2), 'a', 'double', 2.0), 194 | array(array('b' => 3, 'a' => 2), 'a', 'array', array(2)), 195 | ); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/oxpsmodulegeneratorrender.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | /** 28 | * Class oxpsModuleGeneratorRender 29 | * Smarty templates (module files) rendering helper for new copied module files. 30 | */ 31 | class oxpsModuleGeneratorRender extends oxSuperCfg 32 | { 33 | 34 | /** 35 | * A module instance to generate stuff for. 36 | * 37 | * @var oxModule 38 | */ 39 | protected $_oModule = null; 40 | 41 | 42 | /** 43 | * Alias for `setModule`. 44 | * 45 | * @param oxModule|oxpsModuleGeneratorOxModule $oModule 46 | */ 47 | public function init(oxpsModuleGeneratorOxModule $oModule) 48 | { 49 | $this->setModule($oModule); 50 | } 51 | 52 | /** 53 | * Set module instance to generate stuff for. 54 | * 55 | * @param oxModule|oxpsModuleGeneratorOxModule $oModule 56 | */ 57 | public function setModule(oxpsModuleGeneratorOxModule $oModule) 58 | { 59 | $this->_oModule = $oModule; 60 | } 61 | 62 | /** 63 | * Get module instance to generate stuff for. 64 | * 65 | * @return oxModule|oxpsModuleGeneratorOxModule. 66 | */ 67 | public function getModule() 68 | { 69 | return $this->_oModule; 70 | } 71 | 72 | /** 73 | * Open each given file to render it with Smarty and write processed output back to corresponding file. 74 | * After that file is optionally renamed using files array key as a name. 75 | * 76 | * @param array $aClassesToExtend Module extended classes. 77 | * @param array $aNewClasses New module classes. 78 | * 79 | * @return bool 80 | */ 81 | public function renderModuleFiles($aClassesToExtend, $aNewClasses) 82 | { 83 | $aFilesToProcess = $this->_getFilesToProcess($aClassesToExtend, $aNewClasses); 84 | $aNewClasses = array_merge($aClassesToExtend, $aNewClasses); 85 | 86 | $this->renderWithSmartyAndRename($aFilesToProcess, $aNewClasses); 87 | 88 | return true; 89 | } 90 | 91 | /** 92 | * Open each class as Smarty template, render the template and write rendered content back to proper file, 93 | * then rename the file. 94 | * Sets module and class data to Smarty. 95 | * 96 | * @param array $aClasses 97 | * @param array $sClassesNames 98 | */ 99 | public function renderWithSmartyAndRename(array $aClasses, array $sClassesNames) 100 | { 101 | $oModule = $this->getModule(); 102 | $sModulePath = $oModule->getFullPath(); 103 | 104 | /** @var oxpsModuleGeneratorValidator $oValidator */ 105 | $oValidator = oxRegistry::get('oxpsModuleGeneratorValidator'); 106 | 107 | /** @var oxpsModuleGeneratorFileSystem $oFileSystemHelper */ 108 | $oFileSystemHelper = oxRegistry::get('oxpsModuleGeneratorFileSystem'); 109 | 110 | // Initialize Smarty and process template files 111 | /** @var Smarty $oSmarty */ 112 | $oSmarty = oxRegistry::get("oxUtilsView")->getSmarty(); 113 | $oSmarty->assign('oModule', $oModule); 114 | 115 | foreach ($aClasses as $sFileName => $sFilePath) { 116 | $oSmarty->assign('sFilePath', $sFilePath); 117 | $oSmarty->assign('sClassRealName', $oValidator->getArrayValue($sClassesNames, $sFilePath)); 118 | 119 | $sFileFullPath = $sModulePath . $sFilePath; 120 | 121 | // Render template file with Smarty and overwrite it 122 | $oFileSystemHelper->createFile($sFileFullPath, $oSmarty->fetch($sFileFullPath)); 123 | 124 | if (is_string($sFileName)) { 125 | 126 | // Renaming the file 127 | $sFileName = str_replace('.php.tpl', '.php', $sFileName); 128 | $sNewFullPath = str_replace(basename($sFileFullPath), $sFileName, $sFileFullPath); 129 | $oFileSystemHelper->renameFile($sFileFullPath, $sNewFullPath); 130 | } 131 | 132 | $oSmarty->clear_assign('sFilePath'); 133 | $oSmarty->clear_assign('sClassRealName'); 134 | } 135 | } 136 | 137 | /** 138 | * Render file comment using a template and author/vendor data. 139 | * 140 | * @param string $sSubPackage Optional subpackage title. 141 | * 142 | * @return mixed 143 | */ 144 | public function renderFileComment($sSubPackage = '') 145 | { 146 | $sBaseModulePath = realpath(dirname(__FILE__) . '/../../') . '/'; 147 | $sCommentTemplate = $sBaseModulePath . 'modulegenerator/core/module.tpl/oxpscomment.inc.php.tpl'; 148 | 149 | /** @var Smarty $oSmarty */ 150 | $oSmarty = oxRegistry::get("oxUtilsView")->getSmarty(); 151 | $oSmarty->assign('oModule', $this->getModule()); 152 | 153 | if (!empty($sSubPackage)) { 154 | $oSmarty->assign('sSubPackage', (string) $sSubPackage); 155 | } 156 | 157 | return $oSmarty->fetch($sCommentTemplate); 158 | } 159 | 160 | 161 | /** 162 | * Collect copied module files, that need to be processed (rendered) with Smarty. 163 | * 164 | * @param array $aClassesToExtend Generated classes that overload (extend) eShop classes. 165 | * @param array $aNewClasses Other newly generated classes. 166 | * 167 | * @return array 168 | */ 169 | protected function _getFilesToProcess(array $aClassesToExtend, array $aNewClasses) 170 | { 171 | $sModuleId = $this->getModule()->getModuleId(); 172 | 173 | $aFilesToProcess = array( 174 | $sModuleId . '_de_lang.php' => 'translations/de/oxpsmodule_lang.php.tpl', 175 | $sModuleId . '_en_lang.php' => 'translations/en/oxpsmodule_lang.php.tpl', 176 | $sModuleId . 'module.php' => 'core/oxpsmodule.php.tpl', 177 | 'docs/install.sql', 178 | 'docs/README.txt', 179 | 'docs/uninstall.sql', 180 | $sModuleId . '_admin_de_lang.php' => 'views/admin/de/oxpsmodule_lang.php.tpl', 181 | $sModuleId . '_admin_en_lang.php' => 'views/admin/en/oxpsmodule_lang.php.tpl', 182 | 'metadata.php' => 'metadata.php.tpl', 183 | ); 184 | 185 | $aFilesToProcess = array_merge($aFilesToProcess, array_keys($aClassesToExtend), array_keys($aNewClasses)); 186 | 187 | return $aFilesToProcess; 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/views/admin/de/oxpsmodulegenerator_admin_de_lang.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | $sLangName = 'Deutsch'; 28 | 29 | $aLang = array( 30 | 'charset' => 'UTF-8', 31 | 'oxpsmodulegenerator' => 'Modul Generator', 32 | 'oxpsmodulegeneratormodule' => 'Wizard', 33 | 'OXPS_MODULEGENERATOR_ADMIN_TITLE' => 'Modul Skeleton Generator', 34 | 35 | // Settings 36 | 'SHOP_MODULE_GROUP_oxpsModuleGeneratorVendor' => 'Hersteller und Copyright Einstellungen', 37 | 'SHOP_MODULE_oxpsModuleGeneratorVendorPrefix' => 'Hersteller-Präfix für das neue Modul. Es sollte ab zwei bis vier Klein lateinische Buchstaben enthalten, z.B. "abc"', 38 | 'SHOP_MODULE_oxpsModuleGeneratorModuleAuthor' => 'Name von Unternehmen oder Entwickler', 39 | 'SHOP_MODULE_oxpsModuleGeneratorAuthorLink' => 'Website URL des Modulauthors', 40 | 'SHOP_MODULE_oxpsModuleGeneratorAuthorMail' => 'E-Mail-Adresse des Modulauthors', 41 | 'SHOP_MODULE_oxpsModuleGeneratorCopyright' => 'Copyright bis zum aktuellen Jahr. z.B. "My Company, 2001-"', 42 | 'SHOP_MODULE_oxpsModuleGeneratorComment' => 'Kommentar-Text für PHP Dateien. Jede Zeile beginnt mit *
' . 43 | 'Normalerweise sollte es Hinweise und Kurz Lizenz Info stehen', 44 | 45 | 'SHOP_MODULE_GROUP_oxpsModuleGeneratorTests' => 'Module Tests Einstellungen', 46 | 'SHOP_MODULE_oxpsModuleGeneratorTestsGitUrl' => 'URL eines entfernten GIT-Repository für Tests-Ordner für generierte Module zu klonen', 47 | 48 | // Module generation form 49 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_NAME' => 'Modul Name', 50 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_NAME_HINT' => 'Kurzbezeichnung des Moduls (Großbuchstaben, camel case, z.B. "MyModule")', 51 | 'OXPS_MODULEGENERATOR_ADMIN_RENDER_TASKS' => 'Lernhinweise', 52 | 'OXPS_MODULEGENERATOR_ADMIN_RENDER_TASKS_HINT' => 'Hilfreiche Hinweise, die den Lernprozess unterstützen.', 53 | 'OXPS_MODULEGENERATOR_ADMIN_RENDER_SAMPLES' => 'Beispiel erstellen', 54 | 'OXPS_MODULEGENERATOR_ADMIN_RENDER_SAMPLES_HINT' => 'Kommentierten Beispielinhalt erstellen um die Entwicklung zu beschleunigen und an jede Klassenfunktionalität zu erinnern.', 55 | 'OXPS_MODULEGENERATOR_ADMIN_OVERRIDE_CLASSES' => 'Erweiterte Klassen', 56 | 'OXPS_MODULEGENERATOR_ADMIN_OVERRIDE_CLASSES_HINT' => 'Liste aller zu erweiternder Klassen, eine pro Zeile z.B. "oxarticle"', 57 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_CONTROLLERS' => 'Controller erstellen', 58 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_CONTROLLERS_HINT' => 'Einen Controller Namen pro Zeile (Großbuchstaben, camel case z.B. "MyController")', 59 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_MODELS' => 'Models erstellen', 60 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_MODELS_HINT' => 'Einen Model Namen pro Zeile (Großbuchstaben, camel case z.B. "MyItemModel")', 61 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_LISTS' => 'Listen erstellen', 62 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_LISTS_HINT' => 'Wiederhole die Namen der Modelle um eine Liste zu generieren, z.B. "MyItemModel"', 63 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_WIDGETS' => 'Widgets erstellen', 64 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_WIDGETS_HINT' => 'Einen Widget pro Zeile (Großbuchstaben, camel case z.B. "MyWidget")', 65 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_BLOCKS' => 'Blocks erstellen', 66 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_BLOCKS_HINT' => 'Einen Block pro Zeile (Name und Template-Pfad, kleingeschrieben und durch "@" getrennt, ein Paar pro Zeile z.B. "details_productmain_title@page/details/inc/productmain.tpl")', 67 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_SETTINGS' => 'Modul Settings erstellen', 68 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_SETTING_NAME' => 'Name', 69 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_SETTING_TYPE' => 'Typ', 70 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_SETTING_VALUE' => 'Standardwert', 71 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_SETTINGS_HINT' => 'Initialwert (z.B. Checkbox - "0" or "1", String - "my value", Nummer - "7.88", usw. - Ein Wert pro Zeile.
' . 72 | 'Alte Shop Versionen unterstützen nicht den Einstellungs-Typ "Number"', 73 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_INIT_VERSION' => 'Initiale Modulversion', 74 | 'OXPS_MODULEGENERATOR_ADMIN_HAS_ADMINISTRATION' => 'Adminoberfläche erstellen', 75 | 'OXPS_MODULEGENERATOR_ADMIN_HAS_ADMINISTRATION_HINT' => 'Gibt an ob das Modul eine Adminoberfläche benötigt.', 76 | 'OXPS_MODULEGENERATOR_ADMIN_CHECKOUT_UNIT_TESTS' => 'Ckeckout Unit tests', 77 | 'OXPS_MODULEGENERATOR_ADMIN_CHECKOUT_UNIT_TESTS_HINT' => 'Klone den neuesten Generic-Test-Ordner aus dem GIT. Anmerkung: Die Umgebung sollte entsprechend konfiguriert sein!', 78 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_GENERATE' => 'Neues Modul anlegen', 79 | 80 | // Module generation form errors and messages 81 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_ERROR_NO_VENDOR' => 'Achtung! Hersteller oder Autor Parameter sind nicht konfiguriert.
' . 82 | 'Bitte öffnen Sie Erweiterungen -> Module -> OXID Module Skeleton Generator -> Einstell. -> Hersteller und Copyright Einstellungen ' . 83 | 'und geben Sie Hersteller, Copyright und Autor an.', 84 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_ERROR_INVALID_VENDOR' => 'ERROR! Hersteller-Präfix ist ungültig. Es sollte aus zwei bis vier lateinischen Kleinbuchstaben bestehen.', 85 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_ERROR_INVALID_NAME' => 'ERROR! Module Name ist ungültig oder existiert bereits. Bitte nur eindeutige Großbuchstaben (camel case) verwenden, z.B. "MyModule"', 86 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_MSG_GENERATION_SUCCESS' => 'Ihr Modul wurde erfolgreich generiert! Bitte prüfen Sie in Erweiterungen -> Module und den Source-Code in Ihrem Hersteller-Verzeichnis.' 87 | ); 88 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/views/admin/en/oxpsmodulegenerator_admin_en_lang.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | $sLangName = 'English'; 28 | 29 | $aLang = array( 30 | 'charset' => 'UTF-8', 31 | 'oxpsmodulegenerator' => 'Module Generator', 32 | 'oxpsmodulegeneratormodule' => 'Wizard', 33 | 'OXPS_MODULEGENERATOR_ADMIN_TITLE' => 'Module Skeleton Generator', 34 | 35 | // Settings 36 | 'SHOP_MODULE_GROUP_oxpsModuleGeneratorVendor' => 'Vendor and Copyright Settings', 37 | 'SHOP_MODULE_oxpsModuleGeneratorVendorPrefix' => 'Vendor prefix used for module generation. It should contain two to four lowercase latin letters, e.g. "abc"', 38 | 'SHOP_MODULE_oxpsModuleGeneratorModuleAuthor' => 'Module authors\' name. Company or developer full name.', 39 | 'SHOP_MODULE_oxpsModuleGeneratorAuthorLink' => 'Module authors\' website URL.', 40 | 'SHOP_MODULE_oxpsModuleGeneratorAuthorMail' => 'Module authors\' contact email.', 41 | 'SHOP_MODULE_oxpsModuleGeneratorCopyright' => 'Module copyright part that goes before current year. For example: "My Company, 2001-"', 42 | 'SHOP_MODULE_oxpsModuleGeneratorComment' => 'File comment text used in PHP files. Start each line with an asterisk: `*`.
' . 43 | 'Normally it should contain legal notices and short license info.', 44 | 45 | 'SHOP_MODULE_GROUP_oxpsModuleGeneratorTests' => 'Generated Modules Tests Settings', 46 | 'SHOP_MODULE_oxpsModuleGeneratorTestsGitUrl' => 'URL of a remote GIT repository to clone tests folder from for generated modules.', 47 | 48 | // Module generation form 49 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_NAME' => 'Module name', 50 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_NAME_HINT' => 'Enter short, capitalized camel case name of new module, e.g. "MyModule"', 51 | 'OXPS_MODULEGENERATOR_ADMIN_RENDER_TASKS' => 'Learning hints', 52 | 'OXPS_MODULEGENERATOR_ADMIN_RENDER_TASKS_HINT' => 'Renders To Do comments, explanations and useful hints for learning.', 53 | 'OXPS_MODULEGENERATOR_ADMIN_RENDER_SAMPLES' => 'Create examples', 54 | 'OXPS_MODULEGENERATOR_ADMIN_RENDER_SAMPLES_HINT' => 'Renders commented sample content to make development faster and remind of each class features.', 55 | 'OXPS_MODULEGENERATOR_ADMIN_OVERRIDE_CLASSES' => 'Extend classes', 56 | 'OXPS_MODULEGENERATOR_ADMIN_OVERRIDE_CLASSES_HINT' => 'List classes to overload (extend), each from new line, e.g. "oxarticle"', 57 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_CONTROLLERS' => 'Create controllers', 58 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_CONTROLLERS_HINT' => 'Enter capitalized camel case names each from new line, e.g. "MyController"', 59 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_MODELS' => 'Create models', 60 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_MODELS_HINT' => 'Enter capitalized camel case names each from new line, e.g. "MyItemModel"', 61 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_LISTS' => 'Create lists', 62 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_LISTS_HINT' => 'Repeat item models names, to create list models, e.g. "MyItemModel"', 63 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_WIDGETS' => 'Create widgets', 64 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_WIDGETS_HINT' => 'Enter capitalized camel case names each from new line, e.g. "MyWidget"', 65 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_BLOCKS' => 'Create blocks', 66 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_BLOCKS_HINT' => 'Enter block name and template path, both lowercase, separated by "@", each pair from new line, e.g. "details_productmain_title@page/details/inc/productmain.tpl"', 67 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_SETTINGS' => 'Create module settings', 68 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_SETTING_NAME' => 'Name', 69 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_SETTING_TYPE' => 'Type', 70 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_SETTING_VALUE' => 'Default value', 71 | 'OXPS_MODULEGENERATOR_ADMIN_CREATE_SETTINGS_HINT' => 'Enter initial values like in examples: Checkbox - "0" or "1", String - "my value", Number - "7.88", for other types - each value from new line.
' . 72 | 'NOTE: Older eShop versions don\'t support "Number" setting type.', 73 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_INIT_VERSION' => 'Initial module version', 74 | 'OXPS_MODULEGENERATOR_ADMIN_HAS_ADMINISTRATION' => 'Has admin interface', 75 | 'OXPS_MODULEGENERATOR_ADMIN_HAS_ADMINISTRATION_HINT' => 'Select this option if module requires administration interface.', 76 | 'OXPS_MODULEGENERATOR_ADMIN_CHECKOUT_UNIT_TESTS' => 'Ckeckout Unit tests', 77 | 'OXPS_MODULEGENERATOR_ADMIN_CHECKOUT_UNIT_TESTS_HINT' => 'Clone latest version of generic tests folder from GIT. NOTE: Your environment should be configured to access configured GIT repository!', 78 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_GENERATE' => 'Create New Module', 79 | 80 | // Module generation form errors and messages 81 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_ERROR_NO_VENDOR' => 'Attention! Vendor or author parameters are not configured.
' . 82 | 'Please open Extensions -> Modules -> OXID Module Skeleton Generator -> Settings -> Vendor and Copyright Settings ' . 83 | 'and enter Your vendor, copyright and author data.', 84 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_ERROR_INVALID_VENDOR' => 'ERROR! Module vendor prefix configured in settings is invalid. It should contain two to four lowercase latin letters.', 85 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_ERROR_INVALID_NAME' => 'ERROR! Module name is invalid or module exists already. Use unique capitalized camel case name, e.g. "MyModule"', 86 | 'OXPS_MODULEGENERATOR_ADMIN_MODULE_MSG_GENERATION_SUCCESS' => 'Success! New module have been generated! Please check in Extensions -> Modules and the source code in Your vendor sub-folder.', 87 | ); 88 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/module.tpl/module/core/oxpsmodule.php.tpl: -------------------------------------------------------------------------------- 1 | renderFileComment()}] 3 | 4 | [{assign var='sModuleClassName' value=$oModule->getModuleClassName()|cat:'Module'}] 5 | /** 6 | * Class [{$sModuleClassName}] 7 | * Handles module setup, provides additional tools and module related helpers. 8 | * 9 | * @codeCoverageIgnore 10 | */ 11 | class [{$sModuleClassName}] extends oxModule 12 | { 13 | 14 | /** 15 | * Class constructor. 16 | * Sets current module main data and loads the rest module info. 17 | */ 18 | function __construct() 19 | { 20 | $sModuleId = '[{$oModule->getModuleId()}]'; 21 | 22 | $this->setModuleData( 23 | array( 24 | 'id' => $sModuleId, 25 | 'title' => '[{$oModule->getTitle()}]', 26 | 'description' => '[{$oModule->getTitle()}] Module', 27 | ) 28 | ); 29 | 30 | $this->load($sModuleId); 31 | 32 | oxRegistry::set('[{$sModuleClassName}]', $this); 33 | } 34 | 35 | 36 | /** 37 | * Module activation script. 38 | */ 39 | public static function onActivate() 40 | { 41 | return self::_dbEvent('install.sql', 'Error activating module: '); 42 | } 43 | 44 | /** 45 | * Module deactivation script. 46 | */ 47 | public static function onDeactivate() 48 | { 49 | self::_dbEvent('uninstall.sql', 'Error deactivating module: '); 50 | } 51 | 52 | /** 53 | * Clean temp folder content. 54 | * 55 | * @param string $sClearFolderPath Sub-folder path to delete from. Should be a full, valid path inside temp folder. 56 | * 57 | * @return boolean 58 | */ 59 | public static function clearTmp($sClearFolderPath = '') 60 | { 61 | $sFolderPath = self::_getFolderToClear($sClearFolderPath); 62 | $hDirHandler = opendir($sFolderPath); 63 | 64 | if (!empty($hDirHandler)) { 65 | while (false !== ($sFileName = readdir($hDirHandler))) { 66 | $sFilePath = $sFolderPath . DIRECTORY_SEPARATOR . $sFileName; 67 | self::_clear($sFileName, $sFilePath); 68 | } 69 | 70 | closedir($hDirHandler); 71 | } 72 | 73 | return true; 74 | } 75 | 76 | /** 77 | * Get translated string by the translation code. 78 | * 79 | * @param string $sCode 80 | * @param boolean $blUseModulePrefix If True - adds the module translations prefix, if False - not. 81 | * 82 | * @return string 83 | */ 84 | public function translate($sCode, $blUseModulePrefix = true) 85 | { 86 | if ($blUseModulePrefix) { 87 | $sCode = '[{$oModule->getVendorPrefix(true)}]_[{$oModule->getModuleFolderName(true)}]_' . $sCode; 88 | } 89 | 90 | return oxRegistry::getLang()->translateString($sCode, oxRegistry::getLang()->getBaseLanguage(), false); 91 | } 92 | 93 | /** 94 | * Get CMS snippet content by identified ID. 95 | * 96 | * @param string $sIdentifier 97 | * @param bool $blNoHtml 98 | * 99 | * @return string 100 | */ 101 | public function getCmsContent($sIdentifier, $blNoHtml = true) 102 | { 103 | $sValue = ''; 104 | 105 | /** @var oxContent|oxI18n $oContent */ 106 | $oContent = oxNew('oxContent'); 107 | $oContent->loadByIdent(trim((string) $sIdentifier)); 108 | 109 | if ($oContent->oxcontents__oxcontent instanceof oxField) { 110 | $sValue = (string) $oContent->oxcontents__oxcontent->getRawValue(); 111 | $sValue = (empty($blNoHtml) ? $sValue : nl2br(strip_tags($sValue))); 112 | } 113 | 114 | return $sValue; 115 | } 116 | 117 | /** 118 | * Get module setting value. 119 | * 120 | * @param string $sModuleSettingName Module setting parameter name (key). 121 | * @param boolean $blUseModulePrefix If True - adds the module settings prefix, if False - not. 122 | * 123 | * @return mixed 124 | */ 125 | public function getSetting($sModuleSettingName, $blUseModulePrefix = true) 126 | { 127 | if ($blUseModulePrefix) { 128 | $sModuleSettingName = '[{$oModule->getModuleClassName()}]' . (string) $sModuleSettingName; 129 | } 130 | 131 | return oxRegistry::getConfig()->getConfigParam((string) $sModuleSettingName); 132 | } 133 | 134 | /** 135 | * Get module path. 136 | * 137 | * @return string Full path to the module directory. 138 | */ 139 | public function getPath() 140 | { 141 | return oxRegistry::getConfig()->getModulesDir() . '[{$oModule->getVendorPrefix()}]/[{$oModule->getModuleFolderName()}]/'; 142 | } 143 | 144 | 145 | /** 146 | * Install/uninstall event. 147 | * Executes SQL queries form a file. 148 | * 149 | * @param string $sSqlFile SQL file located in module docs folder (usually install.sql or uninstall.sql). 150 | * @param string $sFailureError An error message to show on failure. 151 | */ 152 | protected static function _dbEvent($sSqlFile, $sFailureError = 'Operation failed: ') 153 | { 154 | try { 155 | $oDb = oxDb::getDb(); 156 | $sSql = file_get_contents(dirname(__FILE__) . '/../docs/' . (string) $sSqlFile); 157 | $aSql = (array) preg_split("/;\s*\R/", $sSql); 158 | 159 | foreach ($aSql as $sQuery) { 160 | if (!empty($sQuery)) { 161 | $oDb->execute($sQuery); 162 | } 163 | } 164 | } catch (Exception $ex) { 165 | error_log($sFailureError . $ex->getMessage()); 166 | } 167 | 168 | [{if $oModule->renderSamples()}] 169 | [{if $oModule->renderTasks()}] 170 | // TODO: Use following lines to update database views if You need that. 171 | [{/if}] 172 | /** @var oxDbMetaDataHandler $oDbHandler */ 173 | //$oDbHandler = oxNew('oxDbMetaDataHandler'); 174 | //$oDbHandler->updateViews(); 175 | [{/if}] 176 | 177 | self::clearTmp(); 178 | 179 | return true; 180 | } 181 | 182 | /** 183 | * Check if provided path is inside eShop `tpm/` folder or use the `tmp/` folder path. 184 | * 185 | * @param string $sClearFolderPath 186 | * 187 | * @return string 188 | */ 189 | protected static function _getFolderToClear($sClearFolderPath = '') 190 | { 191 | $sTempFolderPath = (string) oxRegistry::getConfig()->getConfigParam('sCompileDir'); 192 | 193 | if (!empty($sClearFolderPath) and (strpos($sClearFolderPath, $sTempFolderPath) !== false)) { 194 | $sFolderPath = $sClearFolderPath; 195 | } else { 196 | $sFolderPath = $sTempFolderPath; 197 | } 198 | 199 | return $sFolderPath; 200 | } 201 | 202 | /** 203 | * Check if resource could be deleted, then delete it's a file or 204 | * call recursive folder deletion if it's a directory. 205 | * 206 | * @param string $sFileName 207 | * @param string $sFilePath 208 | */ 209 | protected static function _clear($sFileName, $sFilePath) 210 | { 211 | if (!in_array($sFileName, array('.', '..', '.gitkeep', '.htaccess'))) { 212 | if (is_file($sFilePath)) { 213 | @unlink($sFilePath); 214 | } else { 215 | self::clearTmp($sFilePath); 216 | } 217 | } 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/oxpsmodulegeneratorsettings.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | /** 28 | * Class oxpsModuleGeneratorSettings 29 | * Generated module settings parsing and validation helper. 30 | */ 31 | class oxpsModuleGeneratorSettings extends oxSuperCfg 32 | { 33 | 34 | /** 35 | * Cleans settings array got from request to make it suitable for a module metadata file generation. 36 | * 37 | * @param array $aModuleSettings Raw array got from request, could contain empty or faulty values. 38 | * 39 | * @return array Clean settings array, that could be used in metadata generation. 40 | */ 41 | public function getModuleSettings(array $aModuleSettings) 42 | { 43 | /** @var oxpsModuleGeneratorValidator $oValidator */ 44 | $oValidator = oxRegistry::get('oxpsModuleGeneratorValidator'); 45 | 46 | $aCleanSettings = array(); 47 | 48 | foreach ($aModuleSettings as $aModuleSetting) { 49 | 50 | // Get clean name, type and value 51 | $aModuleSetting = (array) $aModuleSetting; 52 | $sSettingName = trim($oValidator->getArrayValue($aModuleSetting, 'name', 'string')); 53 | $sSettingType = $oValidator->getArrayValue($aModuleSetting, 'type', 'string'); 54 | $sInitialValue = $oValidator->getArrayValue($aModuleSetting, 'value'); 55 | 56 | // Check if name and type are valid 57 | if ($oValidator->validateCamelCaseName($sSettingName) and 58 | in_array($sSettingType, array('bool', 'str', 'num', 'arr', 'aarr', 'select')) 59 | ) { 60 | // Prepare for rendering as raw value (variable as string with quotes and so on) 61 | $aSetting = (array) $this->_getRawSettingValue($sSettingName, $sSettingType, $sInitialValue); 62 | 63 | // Add clean settings entry 64 | $aCleanSettings[] = (object) $aSetting; 65 | } 66 | } 67 | 68 | return $aCleanSettings; 69 | } 70 | 71 | 72 | /** 73 | * Compile a settings entry array to be used in metadata generation. 74 | * Value is a raw output to be rendered in metadata (variable as string with quotes and so on). 75 | * 76 | * @param string $sSettingName 77 | * @param string $sSettingType 78 | * @param string $sInitialValue 79 | * 80 | * @return array 81 | */ 82 | protected function _getRawSettingValue($sSettingName, $sSettingType, $sInitialValue) 83 | { 84 | $aSettingParsersMap = array( 85 | 'bool' => '_getBooleanSettingValue', 86 | 'num' => '_getNumericSettingValue', 87 | 'arr' => '_getArraySettingValue', 88 | 'aarr' => '_getAssocArraySettingValue', 89 | 'select' => '_getSelectSettingValue', 90 | ); 91 | 92 | if (array_key_exists($sSettingType, $aSettingParsersMap)) { 93 | $sMethod = $aSettingParsersMap[$sSettingType]; 94 | $sValue = $this->$sMethod((string) $sInitialValue); 95 | } else { 96 | 97 | // String ("str") type is the default fallback 98 | $sValue = "'" . (string) $sInitialValue . "'"; 99 | } 100 | 101 | $aSetting = array( 102 | 'name' => $sSettingName, 103 | 'type' => $sSettingType, 104 | 'value' => $sValue, 105 | ); 106 | 107 | if ($sSettingType == 'select') { 108 | 109 | // For "select" type also adds options string under "constrains" key 110 | $aSetting['constrains'] = $this->_getSelectSettingValue($sInitialValue, true); 111 | } 112 | 113 | return $aSetting; 114 | } 115 | 116 | /** 117 | * Boolean type value parser. 118 | * 119 | * @param string $sInitialValue 120 | * 121 | * @return string 122 | */ 123 | protected function _getBooleanSettingValue($sInitialValue) 124 | { 125 | return (empty($sInitialValue) or oxStr::getStr()->strtolower($sInitialValue) == 'false') 126 | ? 'false' 127 | : 'true'; 128 | } 129 | 130 | /** 131 | * Numeric type value parser. 132 | * 133 | * @param string $sInitialValue 134 | * 135 | * @return float 136 | */ 137 | protected function _getNumericSettingValue($sInitialValue) 138 | { 139 | return (double) $sInitialValue; 140 | } 141 | 142 | /** 143 | * Array type value parser. 144 | * 145 | * @param string $sInitialValue 146 | * 147 | * @return string 148 | */ 149 | protected function _getArraySettingValue($sInitialValue) 150 | { 151 | $sValue = str_replace(array("\r\n", "\n\r", "\r"), PHP_EOL, $sInitialValue); 152 | 153 | return "array('" . implode("', '", explode(PHP_EOL, $sValue)) . "')"; 154 | } 155 | 156 | /** 157 | * Parse clean initial value for assoc array ("aarr") setting type. 158 | * 159 | * @param string $sInitialValue 160 | * 161 | * @return string 162 | */ 163 | protected function _getAssocArraySettingValue($sInitialValue) 164 | { 165 | $sInitialValue = str_replace(array("\r\n", "\n\r", "\r"), PHP_EOL, $sInitialValue); 166 | $aInitialValue = array(); 167 | 168 | $aLines = explode(PHP_EOL, $sInitialValue); 169 | 170 | foreach ($aLines as $sLine) { 171 | $aKeyAndValue = explode('=>', $sLine); 172 | 173 | if (count($aKeyAndValue) == 2) { 174 | $aInitialValue[] = sprintf( 175 | "'%s' => '%s'", 176 | trim($aKeyAndValue[0]), 177 | trim($aKeyAndValue[1]) 178 | ); 179 | } 180 | } 181 | 182 | return "array(" . implode(", ", $aInitialValue) . ")"; 183 | } 184 | 185 | /** 186 | * Select (drop down) type value parser. 187 | * 188 | * @param string $sInitialValue 189 | * @param bool $blReturnOptions If False returns default select value, if True - options string is returned. 190 | * 191 | * @return string 192 | */ 193 | protected function _getSelectSettingValue($sInitialValue, $blReturnOptions = false) 194 | { 195 | $sInitialValue = str_replace(array("\r\n", "\n\r", "\r"), PHP_EOL, $sInitialValue); 196 | $aOptions = explode(PHP_EOL, $sInitialValue); 197 | $sOptions = "'" . implode("|", $aOptions) . "'"; 198 | $sInitialValue = "'" . reset($aOptions) . "'"; 199 | 200 | return empty($blReturnOptions) ? $sInitialValue : $sOptions; 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/tests/unit/core/oxpsModuleGeneratorSettingsTest.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | /** 28 | * Class oxpsModuleGeneratorSettingsTest 29 | * UNIT tests for core class oxpsModuleGeneratorSettings. 30 | * 31 | * @see oxpsModuleGeneratorSettings 32 | */ 33 | class oxpsModuleGeneratorSettingsTest extends OxidTestCase 34 | { 35 | 36 | /** 37 | * Subject under the test. 38 | * 39 | * @var oxpsModuleGeneratorSettings 40 | */ 41 | protected $SUT; 42 | 43 | 44 | /** 45 | * Set SUT state before test. 46 | */ 47 | public function setUp() 48 | { 49 | parent::setUp(); 50 | 51 | $this->SUT = $this->getMock('oxpsModuleGeneratorSettings', array('__call')); 52 | } 53 | 54 | 55 | /** 56 | * @dataProvider moduleSettingsDataProvider 57 | */ 58 | public function testGetModuleSettings($sCondition, array $aRawSettings, array $aParsedReturn) 59 | { 60 | $this->assertEquals($aParsedReturn, $this->SUT->getModuleSettings($aRawSettings), $sCondition); 61 | } 62 | 63 | public function moduleSettingsDataProvider() 64 | { 65 | return array( 66 | 67 | // Invalid or empty data 68 | array('Empty input', array(), array()), 69 | array('Empty setting name', array(array('name' => '', 'type' => 'str', 'value' => 'TEST')), array()), 70 | array('Invalid setting name', array(array('name' => 'my_setting', 'type' => 'str', 'value' => 'TEST')), array()), 71 | array('Empty setting type', array(array('name' => 'MySetting', 'type' => '', 'value' => 'TEST')), array()), 72 | array('Invalid setting type', array(array('name' => 'MySetting', 'type' => 'obj', 'value' => 'TEST')), array()), 73 | array('Corrupt data structure', array('name' => 'MySetting', 'type' => 'str', 'value' => 'TEST'), array()), 74 | 75 | // Valid data 76 | array( 77 | 'Boolean setting type - empty value', 78 | array(array('name' => 'MySetting', 'type' => 'bool', 'value' => '')), 79 | array((object) array('name' => 'MySetting', 'type' => 'bool', 'value' => "false")) 80 | ), 81 | array( 82 | 'Boolean setting type - "false" value', 83 | array(array('name' => 'MySetting', 'type' => 'bool', 'value' => 'false')), 84 | array((object) array('name' => 'MySetting', 'type' => 'bool', 'value' => "false")) 85 | ), 86 | array( 87 | 'Boolean setting type - "False" value', 88 | array(array('name' => 'MySetting', 'type' => 'bool', 'value' => 'False')), 89 | array((object) array('name' => 'MySetting', 'type' => 'bool', 'value' => "false")) 90 | ), 91 | array( 92 | 'Boolean setting type - "FALSE" value', 93 | array(array('name' => 'MySetting', 'type' => 'bool', 'value' => 'FALSE')), 94 | array((object) array('name' => 'MySetting', 'type' => 'bool', 'value' => "false")) 95 | ), 96 | array( 97 | 'Boolean setting type - true value', 98 | array(array('name' => 'MySetting', 'type' => 'bool', 'value' => 'true')), 99 | array((object) array('name' => 'MySetting', 'type' => 'bool', 'value' => "true")) 100 | ), 101 | array( 102 | 'Boolean setting type - value 1', 103 | array(array('name' => 'MySetting', 'type' => 'bool', 'value' => '1')), 104 | array((object) array('name' => 'MySetting', 'type' => 'bool', 'value' => "true")) 105 | ), 106 | array( 107 | 'Boolean setting type - value true-like', 108 | array(array('name' => 'MySetting', 'type' => 'bool', 'value' => 'TEST')), 109 | array((object) array('name' => 'MySetting', 'type' => 'bool', 'value' => "true")) 110 | ), 111 | 112 | array( 113 | 'String setting type - empty value', 114 | array(array('name' => 'MySetting', 'type' => 'str', 'value' => '')), 115 | array((object) array('name' => 'MySetting', 'type' => 'str', 'value' => "''")) 116 | ), 117 | array( 118 | 'String setting type - string value', 119 | array(array('name' => 'MySetting', 'type' => 'str', 'value' => 'TEST')), 120 | array((object) array('name' => 'MySetting', 'type' => 'str', 'value' => "'TEST'")) 121 | ), 122 | array( 123 | 'String setting type - name with trash', 124 | array(array('name' => ' MySetting2' . PHP_EOL, 'type' => 'str', 'value' => " TEST\t")), 125 | array((object) array('name' => 'MySetting2', 'type' => 'str', 'value' => "' TEST\t'")) 126 | ), 127 | 128 | array( 129 | 'Numeric setting type - empty value', 130 | array(array('name' => 'MySetting', 'type' => 'num', 'value' => '')), 131 | array((object) array('name' => 'MySetting', 'type' => 'num', 'value' => 0.0)) 132 | ), 133 | array( 134 | 'Numeric setting type - value is zero', 135 | array(array('name' => 'MySetting', 'type' => 'num', 'value' => '0')), 136 | array((object) array('name' => 'MySetting', 'type' => 'num', 'value' => 0.0)) 137 | ), 138 | array( 139 | 'Numeric setting type - value is integer', 140 | array(array('name' => 'MySetting', 'type' => 'num', 'value' => '10')), 141 | array((object) array('name' => 'MySetting', 'type' => 'num', 'value' => 10.0)) 142 | ), 143 | array( 144 | 'Numeric setting type - value is float', 145 | array(array('name' => 'MySetting', 'type' => 'num', 'value' => '10.88')), 146 | array((object) array('name' => 'MySetting', 'type' => 'num', 'value' => 10.88)) 147 | ), 148 | array( 149 | 'Numeric setting type - value is a number with trash symbols', 150 | array(array('name' => 'MySetting', 'type' => 'num', 'value' => ' 10.88 ')), 151 | array((object) array('name' => 'MySetting', 'type' => 'num', 'value' => 10.88)) 152 | ), 153 | 154 | array( 155 | 'Array setting type - empty value', 156 | array(array('name' => 'MySetting', 'type' => 'arr', 'value' => '')), 157 | array((object) array('name' => 'MySetting', 'type' => 'arr', 'value' => "array('')")) 158 | ), 159 | array( 160 | 'Array setting type - one line input', 161 | array(array('name' => 'MySetting', 'type' => 'arr', 'value' => 'item one')), 162 | array((object) array('name' => 'MySetting', 'type' => 'arr', 'value' => "array('item one')")) 163 | ), 164 | array( 165 | 'Array setting type - multi-line input', 166 | array(array('name' => 'MySetting', 'type' => 'arr', 'value' => 'item one' . PHP_EOL . 'item2')), 167 | array((object) array('name' => 'MySetting', 'type' => 'arr', 'value' => "array('item one', 'item2')")) 168 | ), 169 | 170 | array( 171 | 'Assoc array setting type - empty value', 172 | array(array('name' => 'MySetting', 'type' => 'aarr', 'value' => '')), 173 | array((object) array('name' => 'MySetting', 'type' => 'aarr', 'value' => "array()")) 174 | ), 175 | array( 176 | 'Assoc array setting type - invalid input', 177 | array(array('name' => 'MySetting', 'type' => 'aarr', 'value' => 'a' . PHP_EOL . 'b')), 178 | array((object) array('name' => 'MySetting', 'type' => 'aarr', 'value' => "array()")) 179 | ), 180 | array( 181 | 'Assoc array setting type - one line input', 182 | array(array('name' => 'MySetting', 'type' => 'aarr', 'value' => 'a => b')), 183 | array((object) array('name' => 'MySetting', 'type' => 'aarr', 'value' => "array('a' => 'b')")) 184 | ), 185 | array( 186 | 'Assoc array setting type - multi-line input', 187 | array(array('name' => 'MySetting', 'type' => 'aarr', 'value' => 'a => b' . PHP_EOL . '1=>VALUE')), 188 | array((object) array('name' => 'MySetting', 'type' => 'aarr', 'value' => "array('a' => 'b', '1' => 'VALUE')")) 189 | ), 190 | 191 | array( 192 | 'Select setting type - empty value', 193 | array(array('name' => 'MySetting', 'type' => 'select', 'value' => '')), 194 | array((object) array('name' => 'MySetting', 'type' => 'select', 'value' => "''", 'constrains' => "''")) 195 | ), 196 | array( 197 | 'Select setting type - one line input', 198 | array(array('name' => 'MySetting', 'type' => 'select', 'value' => 'VAL_1')), 199 | array((object) array('name' => 'MySetting', 'type' => 'select', 'value' => "'VAL_1'", 'constrains' => "'VAL_1'")) 200 | ), 201 | array( 202 | 'Select setting type - multi-line input', 203 | array(array('name' => 'MySetting', 'type' => 'select', 'value' => 'VAL_1' . PHP_EOL . '2' . PHP_EOL . 'b')), 204 | array((object) array('name' => 'MySetting', 'type' => 'select', 'value' => "'VAL_1'", 'constrains' => "'VAL_1|2|b'")) 205 | ), 206 | ); 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/tests/unit/core/oxpsModuleGeneratorFileSystemTest.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | /** 28 | * Class oxpsModuleGeneratorFileSystemTest 29 | * INTEGRATION tests for core class oxpsModuleGeneratorFileSystem. 30 | * 31 | * @see oxpsModuleGeneratorFileSystem 32 | */ 33 | class oxpsModuleGeneratorFileSystemTest extends OxidTestCase 34 | { 35 | 36 | /** 37 | * Subject under the test. 38 | * 39 | * @var oxpsModuleGeneratorFileSystem 40 | */ 41 | protected $SUT; 42 | 43 | 44 | /** 45 | * Set SUT state before test. 46 | * Create test files and folders. 47 | */ 48 | public function setUp() 49 | { 50 | parent::setUp(); 51 | 52 | $this->SUT = new oxpsModuleGeneratorFileSystem(); 53 | 54 | @mkdir($this->_getTestPath()); 55 | @mkdir($this->_getTestPath('folder')); 56 | @file_put_contents($this->_getTestPath('file.txt'), PHP_EOL); 57 | @file_put_contents($this->_getTestPath('folder/file.txt'), PHP_EOL); 58 | } 59 | 60 | /** 61 | * Clean state after test. 62 | * Remove test files and folders. 63 | */ 64 | public function tearDown() 65 | { 66 | @shell_exec('rm -rf ' . $this->_getTestPath()); 67 | 68 | parent::tearDown(); 69 | } 70 | 71 | 72 | public function testIsDir_directoryDoeNotExist_returnFalse() 73 | { 74 | $this->assertFalse($this->SUT->isDir($this->_getTestPath('not_existing_folder'))); 75 | } 76 | 77 | public function testIsDir_pathIsFile_returnFalse() 78 | { 79 | $this->assertFalse($this->SUT->isDir($this->_getTestPath('file.txt'))); 80 | } 81 | 82 | public function testIsDir_pathIsExistingFolder_returnTrue() 83 | { 84 | $this->assertTrue($this->SUT->isDir($this->_getTestPath('folder'))); 85 | } 86 | 87 | 88 | public function testIsFile_fileDoeNotExist_returnFalse() 89 | { 90 | $this->assertFalse($this->SUT->isFile($this->_getTestPath('not_existing_file.txt'))); 91 | } 92 | 93 | public function testIsFile_pathIsFolder_returnFalse() 94 | { 95 | $this->assertFalse($this->SUT->isFile($this->_getTestPath('folder'))); 96 | } 97 | 98 | public function testIsFile_pathIsExistingFile_returnTrue() 99 | { 100 | $this->assertTrue($this->SUT->isFile($this->_getTestPath('file.txt'))); 101 | } 102 | 103 | 104 | public function testCreateFolder_folderExists_notTryToCreateIt() 105 | { 106 | $sPath = $this->_getTestPath('folder'); 107 | 108 | $this->assertFileExists($sPath); 109 | $this->SUT->createFolder($sPath); 110 | $this->assertFileExists($sPath); 111 | } 112 | 113 | public function testCreateFolder_folderDoeNotExists_createFolder() 114 | { 115 | $sPath = $this->_getTestPath('new_folder'); 116 | 117 | $this->assertFileNotExists($sPath); 118 | $this->SUT->createFolder($sPath); 119 | $this->assertFileExists($sPath); 120 | } 121 | 122 | public function testCreateFolder_pathIsInsideNonExistingFolder_createFoldersRecursively() 123 | { 124 | $sPath = $this->_getTestPath('sub_folder/new_folder'); 125 | 126 | $this->assertFileNotExists($sPath); 127 | $this->SUT->createFolder($sPath); 128 | $this->assertFileExists($sPath); 129 | } 130 | 131 | 132 | public function testCreateFile_fileDoesNotExist_createFile() 133 | { 134 | $sPath = $this->_getTestPath('new_file.txt'); 135 | 136 | $this->assertFileNotExists($sPath); 137 | $this->SUT->createFile($sPath, 'TEST NEW FILE'); 138 | $this->assertFileExists($sPath); 139 | $this->assertStringEqualsFile($sPath, 'TEST NEW FILE'); 140 | } 141 | 142 | public function testCreateFile_fileExistsThirdArgumentEmpty_overwriteFile() 143 | { 144 | $sPath = $this->_getTestPath('file.txt'); 145 | 146 | $this->assertFileExists($sPath); 147 | $this->assertStringEqualsFile($sPath, PHP_EOL); 148 | 149 | $this->SUT->createFile($sPath, '!TEST FILE - changed'); 150 | $this->assertStringEqualsFile($sPath, '!TEST FILE - changed'); 151 | } 152 | 153 | public function testCreateFile_fileExistsThirdArgumentTrue_fileRemainUnchanged() 154 | { 155 | $sPath = $this->_getTestPath('file.txt'); 156 | 157 | $this->assertFileExists($sPath); 158 | $this->assertStringEqualsFile($sPath, PHP_EOL); 159 | 160 | $this->SUT->createFile($sPath, '!TEST NEW FILE - changed', true); 161 | $this->assertStringEqualsFile($sPath, PHP_EOL); 162 | } 163 | 164 | 165 | public function testRenameFile_fileDoesNotExist_notIssueRename() 166 | { 167 | $sOldPath = $this->_getTestPath('file-one.txt'); 168 | $sNewPath = $this->_getTestPath('file-two.txt'); 169 | 170 | $this->assertFileNotExists($sOldPath); 171 | $this->assertFileNotExists($sNewPath); 172 | 173 | $this->SUT->renameFile($sOldPath, $sNewPath); 174 | 175 | $this->assertFileNotExists($sOldPath); 176 | $this->assertFileNotExists($sNewPath); 177 | } 178 | 179 | public function testRenameFile_fileExists_renameTheFile() 180 | { 181 | $sOldPath = $this->_getTestPath('file.txt'); 182 | $sNewPath = $this->_getTestPath('file-two.txt'); 183 | 184 | $this->assertFileExists($sOldPath); 185 | $this->assertFileNotExists($sNewPath); 186 | 187 | $this->SUT->renameFile($sOldPath, $sNewPath); 188 | 189 | $this->assertFileNotExists($sOldPath); 190 | $this->assertFileExists($sNewPath); 191 | } 192 | 193 | 194 | public function testCopyFolder_folderDoesNotExist_returnFalse() 195 | { 196 | $sOldPath = $this->_getTestPath('folder-one'); 197 | $sNewPath = $this->_getTestPath('folder-two'); 198 | 199 | $this->assertFileNotExists($sOldPath); 200 | $this->assertFileNotExists($sNewPath); 201 | 202 | $this->assertFalse($this->SUT->copyFolder($sOldPath, $sNewPath)); 203 | 204 | $this->assertFileNotExists($sOldPath); 205 | $this->assertFileNotExists($sNewPath); 206 | } 207 | 208 | public function testCopyFolder_folderExists_copyContentAndReturnTrue() 209 | { 210 | $sOldPath = $this->_getTestPath('folder'); 211 | $sNewPath = $this->_getTestPath('folder-two'); 212 | 213 | $this->assertFileExists($sOldPath); 214 | $this->assertFileNotExists($sNewPath); 215 | 216 | $this->assertTrue($this->SUT->copyFolder($sOldPath, $sNewPath)); 217 | 218 | $this->assertFileExists($sOldPath); 219 | $this->assertFileExists($sNewPath); 220 | $this->assertFileExists($this->_getTestPath('folder-two/file.txt')); 221 | } 222 | 223 | public function testCopyFolder_folderExistsWithSubFoldersAndFiles_copyAllContentRecursivelyAndReturnTrue() 224 | { 225 | $sOldPath = $this->_getTestPath('folder'); 226 | $sNewPath = $this->_getTestPath('folder-two'); 227 | 228 | @mkdir($this->_getTestPath('folder/sub-folder')); 229 | @mkdir($this->_getTestPath('folder/sub-folder/sub-sub-folder')); 230 | @file_put_contents($this->_getTestPath('folder/sub-folder/file-one.txt'), '1'); 231 | @file_put_contents($this->_getTestPath('folder/sub-folder/file-two.txt'), '2'); 232 | @file_put_contents($this->_getTestPath('folder/sub-folder/sub-sub-folder/file-three.txt'), '3'); 233 | 234 | $this->assertFileExists($sOldPath); 235 | $this->assertFileNotExists($sNewPath); 236 | 237 | $this->assertTrue($this->SUT->copyFolder($sOldPath, $sNewPath)); 238 | 239 | $this->assertFileExists($sOldPath); 240 | $this->assertFileExists($sNewPath); 241 | $this->assertFileExists($this->_getTestPath('folder-two/file.txt')); 242 | $this->assertFileExists($this->_getTestPath('folder-two/sub-folder')); 243 | $this->assertFileExists($this->_getTestPath('folder-two/sub-folder/file-one.txt')); 244 | $this->assertStringEqualsFile($this->_getTestPath('folder-two/sub-folder/file-one.txt'), '1'); 245 | $this->assertFileExists($this->_getTestPath('folder-two/sub-folder/file-two.txt')); 246 | $this->assertStringEqualsFile($this->_getTestPath('folder-two/sub-folder/file-two.txt'), '2'); 247 | $this->assertFileExists($this->_getTestPath('folder-two/sub-folder/sub-sub-folder')); 248 | $this->assertFileExists($this->_getTestPath('folder-two/sub-folder/sub-sub-folder/file-three.txt')); 249 | $this->assertStringEqualsFile($this->_getTestPath('folder-two/sub-folder/sub-sub-folder/file-three.txt'), '3'); 250 | } 251 | 252 | 253 | public function testCopyFile_fileDoesNotExist_notCopyAnything() 254 | { 255 | $sOldPath = $this->_getTestPath('file-one.txt'); 256 | $sNewPath = $this->_getTestPath('file-two.txt'); 257 | 258 | $this->assertFileNotExists($sOldPath); 259 | $this->assertFileNotExists($sNewPath); 260 | 261 | $this->SUT->copyFile($sOldPath, $sNewPath); 262 | 263 | $this->assertFileNotExists($sOldPath); 264 | $this->assertFileNotExists($sNewPath); 265 | } 266 | 267 | public function testCopyFile_fileExists_copyTheFile() 268 | { 269 | $sOldPath = $this->_getTestPath('file.txt'); 270 | $sNewPath = $this->_getTestPath('file-two.txt'); 271 | 272 | $this->assertFileExists($sOldPath); 273 | $this->assertFileNotExists($sNewPath); 274 | 275 | $this->SUT->copyFile($sOldPath, $sNewPath); 276 | 277 | $this->assertFileExists($sOldPath); 278 | $this->assertFileExists($sNewPath); 279 | $this->assertStringEqualsFile($sNewPath, PHP_EOL); 280 | } 281 | 282 | 283 | /** 284 | * Get a path inside test folder in temp directory. 285 | * 286 | * @param string $sPathSuffix 287 | * 288 | * @return string 289 | */ 290 | protected function _getTestPath($sPathSuffix = '') 291 | { 292 | return oxRegistry::getConfig()->getConfigParam('sCompileDir') . DIRECTORY_SEPARATOR . 293 | 'test' . DIRECTORY_SEPARATOR . (string) $sPathSuffix; 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/tests/unit/core/oxpsModuleGeneratorRenderTest.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | /** 28 | * Class oxpsModuleGeneratorRenderTest 29 | * UNIT tests for core class oxpsModuleGeneratorRender. 30 | * 31 | * @see oxpsModuleGeneratorRender 32 | */ 33 | class oxpsModuleGeneratorRenderTest extends OxidTestCase 34 | { 35 | 36 | /** 37 | * Subject under the test. 38 | * 39 | * @var oxpsModuleGeneratorRender 40 | */ 41 | protected $SUT; 42 | 43 | 44 | /** 45 | * Set SUT state before test. 46 | */ 47 | public function setUp() 48 | { 49 | parent::setUp(); 50 | 51 | $this->SUT = $this->getMock('oxpsModuleGeneratorRender', array('__call')); 52 | } 53 | 54 | 55 | public function testInit() 56 | { 57 | // Module instance mock 58 | $oModule = $this->getMock('oxpsModuleGeneratorOxModule', array('__construct', '__call')); 59 | 60 | $this->SUT->init($oModule); 61 | 62 | $this->assertSame($oModule, $this->SUT->getModule()); 63 | } 64 | 65 | 66 | public function testGetModule() 67 | { 68 | // Module instance mock 69 | $oModule = $this->getMock('oxpsModuleGeneratorOxModule', array('__construct', '__call')); 70 | 71 | $this->SUT->setModule($oModule); 72 | 73 | $this->assertSame($oModule, $this->SUT->getModule()); 74 | } 75 | 76 | 77 | /** 78 | * Test expect the following sequence of... 79 | * 80 | * ---------------------------------------------------------------------------------------------------------- 81 | * Rename file name => Template path FS exec Smarty exec 82 | * ---------------------------------------------------------------------------------------------------------- 83 | * 'oxpsmymodule_de_lang.php' => 'translations/de/oxpsmodule_lang.php.tpl', 0-1 1-5 84 | * 'oxpsmymodule_en_lang.php' => 'translations/en/oxpsmodule_lang.php.tpl', 2-3 6-10 85 | * 'oxpsmymodulemodule.php' => 'core/oxpsmodule.php.tpl', 4-5 11-15 86 | * 'docs/install.sql', 6 16-20 87 | * 'docs/README.txt', 7 21-25 88 | * 'docs/uninstall.sql', 8 26-30 89 | * 'oxpsmymodule_admin_de_lang.php' => 'views/admin/de/oxpsmodule_lang.php.tpl', 9-10 31-35 90 | * 'oxpsmymodule_admin_en_lang.php' => 'views/admin/en/oxpsmodule_lang.php.tpl', 11-12 36-40 91 | * 'metadata.php' => 'metadata.php.tpl', 13-14 41-45 92 | * 'models/oxpsmymoduleoxarticle.php', 15 46-50 93 | * 'controllers/oxpsmymodulepage.php', 16 51-55 94 | * 'models/oxpsmymoduleitem.php', 17 56-60 95 | * ---------------------------------------------------------------------------------------------------------- 96 | */ 97 | public function testRenderModuleFiles() 98 | { 99 | // File system helper mock 100 | $oFileSystem = $this->getMock('oxpsModuleGeneratorFileSystem', array('__call', 'createFile', 'renameFile')); 101 | 102 | /* German translation file */ 103 | $oFileSystem->expects($this->at(0))->method('createFile') 104 | ->with( 105 | '/path/to/modules/oxps/mymodule/translations/de/oxpsmodule_lang.php.tpl', 106 | '_processed_de_trans_content_' 107 | ); 108 | $oFileSystem->expects($this->at(1))->method('renameFile') 109 | ->with( 110 | '/path/to/modules/oxps/mymodule/translations/de/oxpsmodule_lang.php.tpl', 111 | '/path/to/modules/oxps/mymodule/translations/de/oxpsmymodule_de_lang.php' 112 | ); 113 | 114 | /* Readme file */ 115 | $oFileSystem->expects($this->at(7))->method('createFile') 116 | ->with('/path/to/modules/oxps/mymodule/docs/README.txt', '_processed_readme_content_'); 117 | 118 | /* Extended oxArticle model */ 119 | $oFileSystem->expects($this->at(15))->method('createFile') 120 | ->with('/path/to/modules/oxps/mymodule/models/oxpsmymoduleoxarticle.php', '_processed_oxarticle_content_'); 121 | 122 | /* New "Item" model */ 123 | $oFileSystem->expects($this->at(17))->method('createFile') 124 | ->with('/path/to/modules/oxps/mymodule/models/oxpsmymoduleitem.php', '_processed_item_content_'); 125 | 126 | oxRegistry::set('oxpsModuleGeneratorFileSystem', $oFileSystem); 127 | 128 | // Module instance mock 129 | $oModule = $this->getMock( 130 | 'oxpsModuleGeneratorOxModule', 131 | array('__construct', '__call', 'getModuleId', 'getFullPath') 132 | ); 133 | $oModule->expects($this->once())->method('getModuleId')->will($this->returnValue('oxpsmymodule')); 134 | $oModule->expects($this->once())->method('getFullPath')->will($this->returnValue('/path/to/modules/oxps/mymodule/')); 135 | 136 | // Smarty mock 137 | /* German translation file */ 138 | $oSmarty = $this->getMock('Smarty', array('assign', 'fetch', 'clear_assign')); 139 | $oSmarty->expects($this->at(0))->method('assign')->with('oModule', $oModule); 140 | 141 | $oSmarty->expects($this->at(1))->method('assign')->with('sFilePath', 'translations/de/oxpsmodule_lang.php.tpl'); 142 | $oSmarty->expects($this->at(2))->method('assign')->with('sClassRealName', ''); 143 | $oSmarty->expects($this->at(3))->method('fetch') 144 | ->with('/path/to/modules/oxps/mymodule/translations/de/oxpsmodule_lang.php.tpl') 145 | ->will($this->returnValue('_processed_de_trans_content_')); 146 | $oSmarty->expects($this->at(4))->method('clear_assign')->with('sFilePath'); 147 | $oSmarty->expects($this->at(5))->method('clear_assign')->with('sClassRealName'); 148 | 149 | /* Readme file */ 150 | $oSmarty->expects($this->at(21))->method('assign')->with('sFilePath', 'docs/README.txt'); 151 | $oSmarty->expects($this->at(23))->method('fetch') 152 | ->with('/path/to/modules/oxps/mymodule/docs/README.txt') 153 | ->will($this->returnValue('_processed_readme_content_')); 154 | 155 | /* Extended oxArticle model */ 156 | $oSmarty->expects($this->at(46))->method('assign')->with('sFilePath', 'models/oxpsmymoduleoxarticle.php'); 157 | $oSmarty->expects($this->at(47))->method('assign')->with('sClassRealName', 'oxArticle'); 158 | $oSmarty->expects($this->at(48))->method('fetch') 159 | ->with('/path/to/modules/oxps/mymodule/models/oxpsmymoduleoxarticle.php') 160 | ->will($this->returnValue('_processed_oxarticle_content_')); 161 | 162 | /* Extended oxArticle model */ 163 | $oSmarty->expects($this->at(56))->method('assign')->with('sFilePath', 'models/oxpsmymoduleitem.php'); 164 | $oSmarty->expects($this->at(57))->method('assign')->with('sClassRealName', 'Item'); 165 | $oSmarty->expects($this->at(58))->method('fetch') 166 | ->with('/path/to/modules/oxps/mymodule/models/oxpsmymoduleitem.php') 167 | ->will($this->returnValue('_processed_item_content_')); 168 | 169 | // View utils mock 170 | $oViewUtils = $this->getMock('oxUtilsView', array('__call', 'getSmarty')); 171 | $oViewUtils->expects($this->once())->method('getSmarty')->will($this->returnValue($oSmarty)); 172 | oxRegistry::set('oxUtilsView', $oViewUtils); 173 | 174 | $this->SUT->init($oModule); 175 | 176 | $this->assertTrue( 177 | $this->SUT->renderModuleFiles( 178 | array('models/oxpsmymoduleoxarticle.php' => 'oxArticle'), 179 | array( 180 | 'controllers/oxpsmymodulepage.php' => 'Page', 181 | 'models/oxpsmymoduleitem.php' => 'Item', 182 | ) 183 | ) 184 | ); 185 | } 186 | 187 | 188 | public function testRenderFileComment_emptyArgument_rendersCommentWithNoSubPackageInfo() 189 | { 190 | // Module instance mock 191 | $oModule = $this->getMock('oxpsModuleGeneratorOxModule', array('__construct', '__call')); 192 | 193 | // Smarty mock 194 | $oSmarty = $this->getMock('Smarty', array('assign', 'fetch')); 195 | $oSmarty->expects($this->at(0))->method('assign')->with('oModule', $oModule); 196 | $oSmarty->expects($this->at(1))->method('fetch') 197 | ->with($this->stringEndsWith('modulegenerator/core/module.tpl/oxpscomment.inc.php.tpl')) 198 | ->will($this->returnValue('_processed_comment_content_')); 199 | 200 | // View utils mock 201 | $oViewUtils = $this->getMock('oxUtilsView', array('__call', 'getSmarty')); 202 | $oViewUtils->expects($this->once())->method('getSmarty')->will($this->returnValue($oSmarty)); 203 | oxRegistry::set('oxUtilsView', $oViewUtils); 204 | 205 | $this->SUT->init($oModule); 206 | 207 | $this->assertSame('_processed_comment_content_', $this->SUT->renderFileComment()); 208 | } 209 | 210 | public function testRenderFileComment_argumentNotEmpty_rendersCommentWithSubPackageArgumentInfo() 211 | { 212 | // Module instance mock 213 | $oModule = $this->getMock('oxpsModuleGeneratorOxModule', array('__construct', '__call')); 214 | 215 | // Smarty mock 216 | $oSmarty = $this->getMock('Smarty', array('assign', 'fetch')); 217 | $oSmarty->expects($this->at(0))->method('assign')->with('oModule', $oModule); 218 | $oSmarty->expects($this->at(1))->method('assign')->with('sSubPackage', 'mySubModule'); 219 | $oSmarty->expects($this->at(2))->method('fetch') 220 | ->with($this->stringEndsWith('modulegenerator/core/module.tpl/oxpscomment.inc.php.tpl')) 221 | ->will($this->returnValue('_processed_comment_content_')); 222 | 223 | // View utils mock 224 | $oViewUtils = $this->getMock('oxUtilsView', array('__call', 'getSmarty')); 225 | $oViewUtils->expects($this->once())->method('getSmarty')->will($this->returnValue($oSmarty)); 226 | oxRegistry::set('oxUtilsView', $oViewUtils); 227 | 228 | $this->SUT->init($oModule); 229 | 230 | $this->assertSame('_processed_comment_content_', $this->SUT->renderFileComment('mySubModule')); 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/views/admin/admin_oxpsmodulegenerator.tpl: -------------------------------------------------------------------------------- 1 | [{include file="headitem.tpl" title="OXPS_MODULEGENERATOR_ADMIN_TITLE"|oxmultilangassign}] 2 | [{oxstyle include=$oViewConf->getModuleUrl('oxps/modulegenerator', 'out/src/css/admin_oxpsmodulegenerator.css')}] 3 | [{oxstyle}] 4 |
5 |
6 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_TITLE"}] 7 |
8 | 10 | 11 | 235 | 236 |
12 | [{if $sMessage}] 13 |
14 |
    15 |
  • [{oxmultilang ident=$sMessage}]
  • 16 |
17 |
18 | [{/if}] 19 |
20 | 21 | 22 | 232 | 233 |
23 |
25 | 26 | 27 | 31 | 36 | 37 | 38 | 39 | 40 | 41 | 44 | 49 | 50 | 51 | 54 | 59 | 60 | 61 | 64 | 69 | 70 | 71 | 74 | 79 | 80 | 81 | 84 | 89 | 90 | 91 | 94 | 99 | 100 | 101 | 102 | 103 | 106 | 159 | 160 | 161 | 162 | 163 | 167 | 171 | 172 | 173 | 174 | 175 | [{* todo (nice2have) Implement this feature: administration area presets and menu.xml*}] 176 | [{* 177 | 180 | 185 | *}] 186 | 187 | 190 | 195 | 196 | 197 | 198 | 199 | 200 | 203 | 208 | 209 | 210 | 213 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 228 | 229 |
28 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_MODULE_NAME"}] 29 | * 30 | 32 | 34 | [{oxinputhelp ident="OXPS_MODULEGENERATOR_ADMIN_MODULE_NAME_HINT"}] 35 |
 
42 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_OVERRIDE_CLASSES"}] 43 | 45 | 47 | [{oxinputhelp ident="OXPS_MODULEGENERATOR_ADMIN_OVERRIDE_CLASSES_HINT"}] 48 |
52 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_CREATE_CONTROLLERS"}] 53 | 55 | 57 | [{oxinputhelp ident="OXPS_MODULEGENERATOR_ADMIN_CREATE_CONTROLLERS_HINT"}] 58 |
62 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_CREATE_MODELS"}] 63 | 65 | 67 | [{oxinputhelp ident="OXPS_MODULEGENERATOR_ADMIN_CREATE_MODELS_HINT"}] 68 |
72 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_CREATE_LISTS"}] 73 | 75 | 77 | [{oxinputhelp ident="OXPS_MODULEGENERATOR_ADMIN_CREATE_LISTS_HINT"}] 78 |
82 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_CREATE_WIDGETS"}] 83 | 85 | 87 | [{oxinputhelp ident="OXPS_MODULEGENERATOR_ADMIN_CREATE_WIDGETS_HINT"}] 88 |
92 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_CREATE_BLOCKS"}] 93 | 95 | 97 | [{oxinputhelp ident="OXPS_MODULEGENERATOR_ADMIN_CREATE_BLOCKS_HINT"}] 98 |
 
104 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_MODULE_SETTINGS"}] 105 | 107 | 108 | 109 | 110 | 112 | 114 | 117 | 118 | 119 | 120 | [{section name=settings start=0 loop=3}] 121 | [{assign var='i' value=$smarty.section.settings.index}] 122 | [{assign var='aSetting' value=$oValues->settings.$i}] 123 | [{assign var='sType' value=$aSetting.type}] 124 | [{if not $sType}] 125 | [{assign var='sType' value='str'}] 126 | [{/if}] 127 | 128 | 132 | 149 | 153 | 154 | [{/section}] 155 | 156 |
[{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_MODULE_SETTING_NAME"}] 111 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_MODULE_SETTING_TYPE"}] 113 | 115 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_MODULE_SETTING_VALUE"}] 116 |
129 | 131 | 133 | 148 | 150 | 152 |
157 | [{oxinputhelp ident="OXPS_MODULEGENERATOR_ADMIN_CREATE_SETTINGS_HINT"}] 158 |
 
164 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_MODULE_INIT_VERSION"}] 165 | * 166 | 168 | 170 |
 
178 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_HAS_ADMINISTRATION"}] 179 | 181 | 183 | [{oxinputhelp ident="OXPS_MODULEGENERATOR_ADMIN_HAS_ADMINISTRATION_HINT"}] 184 |
188 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_CHECKOUT_UNIT_TESTS"}] 189 | 191 | tests}]checked="checked"[{/if}]/> 193 | [{oxinputhelp ident="OXPS_MODULEGENERATOR_ADMIN_CHECKOUT_UNIT_TESTS_HINT"}] 194 |
 
201 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_RENDER_TASKS"}] 202 | 204 | tasks}]checked="checked"[{/if}]/> 206 | [{oxinputhelp ident="OXPS_MODULEGENERATOR_ADMIN_RENDER_TASKS_HINT"}] 207 |
211 | [{oxmultilang ident="OXPS_MODULEGENERATOR_ADMIN_RENDER_SAMPLES"}] 212 | 214 | samples}]checked="checked"[{/if}]/> 216 | [{oxinputhelp ident="OXPS_MODULEGENERATOR_ADMIN_RENDER_SAMPLES_HINT"}] 217 |
 
  225 | 227 |
230 |
231 |
234 |
237 |
238 | [{include file="bottomitem.tpl"}] -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/oxpsmodulegeneratorhelper.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | /** 28 | * Class oxpsModuleGeneratorHelper. 29 | * Implement helpers and additional methods for module generation. 30 | */ 31 | class oxpsModuleGeneratorHelper extends oxSuperCfg 32 | { 33 | 34 | /** 35 | * A module instance to generate stuff for. 36 | * 37 | * @var oxModule 38 | */ 39 | protected $_oModule = null; 40 | 41 | /** 42 | * File system helper instance. 43 | * 44 | * @var null 45 | */ 46 | protected $_oFileSystemHelper = null; 47 | 48 | 49 | /** 50 | * Alias for `setModule`. 51 | * 52 | * @param oxModule|oxpsModuleGeneratorOxModule $oModule 53 | */ 54 | public function init(oxpsModuleGeneratorOxModule $oModule) 55 | { 56 | $this->setModule($oModule); 57 | } 58 | 59 | /** 60 | * Set module instance to generate stuff for. 61 | * 62 | * @param oxModule|oxpsModuleGeneratorOxModule $oModule 63 | */ 64 | public function setModule(oxpsModuleGeneratorOxModule $oModule) 65 | { 66 | $this->_oModule = $oModule; 67 | } 68 | 69 | /** 70 | * Get module instance to generate stuff for. 71 | * 72 | * @return oxModule|oxpsModuleGeneratorOxModule. 73 | */ 74 | public function getModule() 75 | { 76 | return $this->_oModule; 77 | } 78 | 79 | /** 80 | * Get file system management helper instance. 81 | * 82 | * @return oxpsModuleGeneratorFileSystem 83 | */ 84 | public function getFileSystemHelper() 85 | { 86 | if (is_null($this->_oFileSystemHelper)) { 87 | $this->_oFileSystemHelper = oxRegistry::get('oxpsModuleGeneratorFileSystem'); 88 | } 89 | 90 | return $this->_oFileSystemHelper; 91 | } 92 | 93 | /** 94 | * Check if vendor metadata file is present and crates one if it's missing. 95 | * 96 | * @param string $sVendorFolderPath 97 | */ 98 | public function createVendorMetadata($sVendorFolderPath) 99 | { 100 | $oFileSystemHelper = $this->getFileSystemHelper(); 101 | 102 | $oFileSystemHelper->createFolder($sVendorFolderPath); 103 | $sVendorMetadataPath = $sVendorFolderPath . DIRECTORY_SEPARATOR . 'vendormetadata.php'; 104 | 105 | $oFileSystemHelper->createFile( 106 | $sVendorMetadataPath, 107 | 'getFileSystemHelper(); 127 | $oModule = $this->getModule(); 128 | 129 | $aClassesToExtend = (array) $oModule->getClassesToExtend(); 130 | $sModulePath = $oModule->getFullPath(); 131 | $sModuleId = $oModule->getModuleId(); 132 | 133 | $aExtendedClasses = array(); 134 | 135 | if (!$oFileSystemHelper->isFile($sClassExtendTemplatePath) or !$oFileSystemHelper->isDir($sModulePath)) { 136 | return $aExtendedClasses; 137 | } 138 | 139 | foreach ($aClassesToExtend as $sClassName => $mApplicationPath) { 140 | $sInModulePath = $this->_getPathInsideModule($sModulePath, $mApplicationPath); 141 | $sDestinationPath = $sModulePath . $sInModulePath; 142 | $sClassFileName = $sModuleId . oxStr::getStr()->strtolower($sClassName) . '.php'; 143 | $sClassFilePath = $sDestinationPath . $sClassFileName; 144 | 145 | $oFileSystemHelper->copyFile($sClassExtendTemplatePath, $sClassFilePath); 146 | 147 | $aExtendedClasses[$sInModulePath . $sClassFileName] = $this->_getCoreClassName($sClassName); 148 | } 149 | 150 | return $aExtendedClasses; 151 | } 152 | 153 | /** 154 | * Collect information of new classes to create, copy new classes from corresponding templates, 155 | * create templates for controllers and widgets. 156 | * 157 | * @param string $sModuleGeneratorPath 158 | * 159 | * @return array 160 | */ 161 | public function createNewClassesAndTemplates($sModuleGeneratorPath) 162 | { 163 | /** @var oxpsModuleGeneratorValidator $oValidator */ 164 | $oValidator = oxRegistry::get('oxpsModuleGeneratorValidator'); 165 | 166 | $aClassesToCreate = (array) $this->getModule()->getClassesToCreate(); 167 | $aCreatedClasses = array(); 168 | 169 | foreach ($aClassesToCreate as $sObjectType => $aClassesData) { 170 | $aClassesData = (array) $aClassesData; 171 | $aClasses = (array) $oValidator->getArrayValue($aClassesData, 'aClasses', 'array'); 172 | $sClassTemplate = $oValidator->getArrayValue($aClassesData, 'sTemplateName'); 173 | $sClassPath = $oValidator->getArrayValue($aClassesData, 'sInModulePath'); 174 | $sTemplatePath = $oValidator->getArrayValue($aClassesData, 'sTemplatesPath'); 175 | 176 | if (empty($aClasses)) { 177 | continue; 178 | } 179 | 180 | $aNewFiles = $this->_createNewClasses($aClasses, $sClassTemplate, $sClassPath, $sModuleGeneratorPath); 181 | $this->_createNewTemplates($sObjectType, $aNewFiles, $sTemplatePath); 182 | 183 | $aCreatedClasses = array_merge($aCreatedClasses, $aNewFiles); 184 | } 185 | 186 | return $aCreatedClasses; 187 | } 188 | 189 | /** 190 | * Create module blocks templates. 191 | * 192 | * @param string $sModulePath 193 | */ 194 | public function createBlock($sModulePath) 195 | { 196 | $aBlock = $this->getModule()->getBlocks(); 197 | 198 | if (!empty($aBlock)) { 199 | $this->_createTemplates(array_keys($aBlock), sprintf('%sviews/blocks/', $sModulePath), true); 200 | } 201 | } 202 | 203 | /** 204 | * Clone and copy tests folder into generated module, 205 | * create pre-configured unit test class for each generated module class. 206 | * 207 | * @param oxpsModuleGeneratorRender $oRenderHelper 208 | * @param string $sModuleGeneratorPath 209 | * @param string $sModulePath 210 | * @param array $aClassesToExtend 211 | * @param array $aNewClasses 212 | */ 213 | public function fillTestsFolder(oxpsModuleGeneratorRender $oRenderHelper, $sModuleGeneratorPath, $sModulePath, 214 | array $aClassesToExtend, array $aNewClasses) 215 | { 216 | if ($this->_cloneUnitTests($sModulePath)) { 217 | $aAllFiles = array_merge($aClassesToExtend, $aNewClasses); 218 | $sTemplate = sprintf('%score/module.tpl/oxpstestclass.php.tpl', $sModuleGeneratorPath); 219 | $aNewFiles = (array) $this->_copyNewClasses($aAllFiles, $sTemplate, 'tests/unit/modules/', true); 220 | 221 | if (!empty($aNewFiles)) { 222 | $oRenderHelper->renderWithSmartyAndRename(array_keys($aNewFiles), $aNewFiles); 223 | } 224 | } 225 | } 226 | 227 | /** 228 | * Check if provided path inside a module exists, if not choose "core" folder as internal path. 229 | * 230 | * @param string $sModulePath 231 | * @param string $mInnerPath 232 | * 233 | * @return string 234 | */ 235 | protected function _getPathInsideModule($sModulePath, $mInnerPath) 236 | { 237 | if (!empty($mInnerPath) and $this->getFileSystemHelper()->isDir($sModulePath . $mInnerPath)) { 238 | $sPathInsideModule = $mInnerPath; 239 | } else { 240 | $sPathInsideModule = 'core/'; 241 | } 242 | 243 | return $sPathInsideModule; 244 | } 245 | 246 | /** 247 | * Check if class template file and path are valid and create new classes using the provided class template and path. 248 | * 249 | * @param array $aClasses 250 | * @param string $sClassTemplate 251 | * @param string $sClassPath 252 | * @param string $sModuleGeneratorPath 253 | * 254 | * @return array 255 | */ 256 | protected function _createNewClasses(array $aClasses, $sClassTemplate, $sClassPath, $sModuleGeneratorPath) 257 | { 258 | $aNewFiles = array(); 259 | 260 | if (!empty($sClassTemplate) and !empty($sClassPath)) { 261 | $sTemplatePath = sprintf('%score/module.tpl/%s', $sModuleGeneratorPath, $sClassTemplate); 262 | $aNewFiles = $this->_copyNewClasses($aClasses, $sTemplatePath, $sClassPath); 263 | } 264 | 265 | return $aNewFiles; 266 | } 267 | 268 | /** 269 | * Check if class type requires a template to be created, 270 | * check template path and the classes and then create new templates. 271 | * 272 | * @param string $sObjectType 273 | * @param array $aNewFiles 274 | * @param string $sTemplatePath 275 | */ 276 | protected function _createNewTemplates($sObjectType, array $aNewFiles, $sTemplatePath) 277 | { 278 | if (in_array($sObjectType, array('controllers', 'widgets')) and 279 | !empty($aNewFiles) and !empty($sTemplatePath) 280 | ) { 281 | $sTemplateDestination = sprintf('%sviews/%s/', $this->getModule()->getFullPath(), $sTemplatePath); 282 | $this->_createTemplates($aNewFiles, $sTemplateDestination); 283 | } 284 | } 285 | 286 | /** 287 | * Get format string for newly generated templates demo content. 288 | * 289 | * @param bool $blBlocks If True, renders block template content, if False - controller/widget template content. 290 | * 291 | * @return string 292 | */ 293 | protected function _getTemplateContentFormat($blBlocks = false) 294 | { 295 | if (empty($blBlocks)) { 296 | $sDemoContent = '

A Blank %s Template

' . PHP_EOL . 297 | '

This is a template located in %s belonging to class %s

'; 298 | } else { 299 | $sDemoContent = '

A Blank Block Template

' . PHP_EOL . 300 | '

This is a template for block %s located in %s

' . PHP_EOL . 301 | '[{$smarty.block.parent}]'; 302 | } 303 | 304 | return $sDemoContent; 305 | } 306 | 307 | /** 308 | * Create new classes using a template and provided class names by copying this template to the provided path. 309 | * 310 | * @param array $aClasses Class names array. 311 | * @param string $sTemplatePath Template file full path. 312 | * @param string $sInModulePath Module inner path to copy to. 313 | * @param bool $blTestClasses If True, treat as test classes. 314 | * 315 | * @return array 316 | */ 317 | protected function _copyNewClasses(array $aClasses, $sTemplatePath, $sInModulePath, $blTestClasses = false) 318 | { 319 | $oFileSystemHelper = $this->getFileSystemHelper(); 320 | $aCopiedClasses = array(); 321 | 322 | if (!$oFileSystemHelper->isFile($sTemplatePath) or 323 | !$oFileSystemHelper->isDir($this->getModule()->getFullPath() . $sInModulePath) 324 | ) { 325 | return $aCopiedClasses; 326 | } 327 | 328 | foreach ($aClasses as $mKey => $sClass) { 329 | list($sClassFilePath, $sProcessedFileKey) = $this->_getNewClassPathAndKey( 330 | $mKey, $sClass, $sInModulePath, $blTestClasses 331 | ); 332 | $oFileSystemHelper->copyFile($sTemplatePath, $sClassFilePath); 333 | 334 | $aCopiedClasses[$sProcessedFileKey] = $sClass; 335 | } 336 | 337 | return $aCopiedClasses; 338 | } 339 | 340 | /** 341 | * Compile full path to a new class and a key value to use for created classes array. 342 | * It depends on whatever it is a Unit test class or general PHP class. 343 | * 344 | * @param int|string $mKey 345 | * @param string $sClass 346 | * @param string $sInModulePath 347 | * @param bool $blTestClasses 348 | * 349 | * @return array 350 | */ 351 | protected function _getNewClassPathAndKey($mKey, $sClass, $sInModulePath, $blTestClasses = false) 352 | { 353 | $oModule = $this->getModule(); 354 | 355 | $sModuleId = $oModule->getModuleId(); 356 | $sModulePath = $oModule->getFullPath(); 357 | 358 | if (empty($blTestClasses)) { 359 | $sClassFileName = sprintf('%s%s.php', $sModuleId, oxStr::getStr()->strtolower($sClass)); 360 | $sClassFilePath = $sModulePath . $sInModulePath . $sClassFileName; 361 | $sProcessedFileKey = $sInModulePath . $sClassFileName; 362 | } else { 363 | $sClassFileName = sprintf('%s%sTest.php', $sModuleId, oxStr::getStr()->strtolower($sClass)); 364 | $sClassDirPath = $sModulePath . $sInModulePath . dirname($mKey) . DIRECTORY_SEPARATOR; 365 | $this->getFileSystemHelper()->createFolder($sClassDirPath); 366 | $sClassFilePath = $sClassDirPath . $sClassFileName; 367 | $sProcessedFileKey = $sInModulePath . dirname($mKey) . DIRECTORY_SEPARATOR . $sClassFileName; 368 | } 369 | 370 | return array($sClassFilePath, $sProcessedFileKey); 371 | } 372 | 373 | /** 374 | * Create template files for a given classes in provided location. 375 | * 376 | * @param array $aClasses Class names array to create templates for. 377 | * @param string $sDestinationPath A full path to folder to create templates in. 378 | * @param bool $blBlocks If true block templates are generated. 379 | * 380 | * @return bool 381 | */ 382 | protected function _createTemplates(array $aClasses, $sDestinationPath, $blBlocks = false) 383 | { 384 | $oFileSystemHelper = $this->getFileSystemHelper(); 385 | 386 | if (!$oFileSystemHelper->isDir($sDestinationPath)) { 387 | return false; 388 | } 389 | 390 | $oModule = $this->getModule(); 391 | 392 | $sModuleId = $oModule->getModuleId(); 393 | $sClassPrefix = $oModule->getModuleClassName(); 394 | 395 | $sDemoContentFormat = $this->_getTemplateContentFormat($blBlocks); 396 | 397 | foreach ($aClasses as $sClass) { 398 | $sTemplateFileName = sprintf('%s%s.tpl', $sModuleId, oxStr::getStr()->strtolower($sClass)); 399 | $sTemplateFilePath = $sDestinationPath . $sTemplateFileName; 400 | $sTemplateContent = sprintf($sDemoContentFormat, $sClass, $sTemplateFilePath, $sClassPrefix . $sClass); 401 | 402 | $oFileSystemHelper->createFile($sTemplateFilePath, $sTemplateContent); 403 | } 404 | 405 | return true; 406 | } 407 | 408 | /** 409 | * Get real class name of existing core class (for class that are being extended). 410 | * 411 | * @param string $sClassName 412 | * 413 | * @return string 414 | */ 415 | protected function _getCoreClassName($sClassName) 416 | { 417 | if (!class_exists($sClassName)) { 418 | return $sClassName; 419 | } 420 | 421 | $oReflection = new ReflectionClass(new $sClassName()); 422 | 423 | return $oReflection->getName(); 424 | } 425 | 426 | /** 427 | * Clone tests library (Generic Test Folder) to temp location, 428 | * then copy tests library into the module and do a cleanup. 429 | * 430 | * @param string $sModulePath Full path to a module. 431 | * 432 | * @return bool 433 | */ 434 | protected function _cloneUnitTests($sModulePath) 435 | { 436 | /** @var oxpsModuleGeneratorModule $oModule */ 437 | $oModule = oxRegistry::get('oxpsModuleGeneratorModule'); 438 | $sGitUrl = (string) $oModule->getSetting('TestsGitUrl'); 439 | 440 | if (empty($sGitUrl)) { 441 | return false; 442 | } 443 | 444 | $sTmpDir = sys_get_temp_dir() . '/tests' . date('YmdHis') . mt_rand(10000, 99999) . '/'; 445 | $aCommands = array( 446 | sprintf('git clone %s %s', $sGitUrl, $sTmpDir), 447 | sprintf('cp -R %stests/* %stests/', $sTmpDir, $sModulePath), 448 | sprintf('chmod 0777 -R %stests', $sModulePath), 449 | sprintf('dos2unix %stests/*.sh', $sModulePath), 450 | sprintf('rm -rf %s', $sTmpDir), 451 | ); 452 | 453 | foreach ($aCommands as $sCommand) { 454 | $this->_shellExec($sCommand); 455 | } 456 | 457 | return $this->getFileSystemHelper()->isDir($sModulePath . 'tests/unit/'); 458 | } 459 | 460 | /** 461 | * An alias for PHP function `shell_exec`. 462 | * Errors are suspended. 463 | * 464 | * @codeCoverageIgnore 465 | * 466 | * @param string $sCommand 467 | */ 468 | protected function _shellExec($sCommand) 469 | { 470 | @shell_exec((string) $sCommand); 471 | } 472 | } 473 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/core/oxpsmodulegeneratoroxmodule.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | /** 28 | * Class oxpsModuleGeneratorOxModule overloads oxModule 29 | * Extends oxModule class to add extra fields and tools for modules generation. 30 | * The class becomes a container for all information required to generate module. 31 | * NOTE: This class is very long, but it cannot be split since consists mostly of getters and setters. 32 | * 33 | * @see oxModule 34 | */ 35 | class oxpsModuleGeneratorOxModule extends oxpsModuleGeneratorOxModule_parent 36 | { 37 | 38 | /** 39 | * Vendor directory name and module vendor prefix. 40 | * 41 | * @var string 42 | */ 43 | protected $_sVendorPrefix = ''; 44 | 45 | /** 46 | * Module author/vendor data: name, link, mail, copyright and file comment. 47 | * 48 | * @var array 49 | */ 50 | protected $_aAuthorData = array(); 51 | 52 | /** 53 | * Validator helper instance. 54 | * 55 | * @var null|oxpsModuleGeneratorValidator 56 | */ 57 | protected $_oValidator = null; 58 | 59 | 60 | /** 61 | * Set module vendor prefix. It is also a vendor directory name. 62 | * 63 | * @param string $sVendorPrefix 64 | * 65 | * @return string 66 | */ 67 | public function setVendorPrefix($sVendorPrefix) 68 | { 69 | $this->_sVendorPrefix = $sVendorPrefix; 70 | } 71 | 72 | /** 73 | * Get module vendor prefix. It is also vendor directory name. 74 | * 75 | * @param bool $blUppercase 76 | * 77 | * @return string 78 | */ 79 | public function getVendorPrefix($blUppercase = false) 80 | { 81 | if (!empty($blUppercase)) { 82 | return oxStr::getStr()->strtoupper($this->_sVendorPrefix); 83 | } 84 | 85 | return $this->_sVendorPrefix; 86 | } 87 | 88 | /** 89 | * Set module author/vendor data. It is used in metadata, README file and PHP files comments. 90 | * 91 | * @param array $aAuthorData 92 | */ 93 | public function setAuthorData(array $aAuthorData) 94 | { 95 | $this->_aAuthorData = $aAuthorData; 96 | } 97 | 98 | /** 99 | * Get module author/vendor data. It is used in metadata, README file and PHP files comments. 100 | * 101 | * @param string $mField 102 | * 103 | * @return array|string 104 | */ 105 | public function getAuthorData($mField = null) 106 | { 107 | if (!is_null($mField)) { 108 | return $this->getArrayValue($this->_aAuthorData, $mField); 109 | } 110 | 111 | return $this->_aAuthorData; 112 | } 113 | 114 | /** 115 | * Get validation and data access helper instance. 116 | * 117 | * @return oxpsModuleGeneratorValidator 118 | */ 119 | public function getValidator() 120 | { 121 | if (is_null($this->_oValidator)) { 122 | $this->_oValidator = oxRegistry::get('oxpsModuleGeneratorValidator'); 123 | } 124 | 125 | return $this->_oValidator; 126 | } 127 | 128 | /** 129 | * Get module ID. 130 | * 131 | * @param bool $blCamelCase If True - returns CamelCase ID interpretation (module classes prefix), 132 | * if False - a lowercase value. 133 | * 134 | * @return string|null 135 | */ 136 | public function getModuleId($blCamelCase = false) 137 | { 138 | /** @var oxpsModuleGeneratorOxModule|oxModule $this */ 139 | 140 | return empty($blCamelCase) ? $this->getId() : $this->getInfo('oxpsmodulegenerator_class'); 141 | } 142 | 143 | /** 144 | * Get module folder name. 145 | * 146 | * @param boolean $blUppercase If True - returns uppercase name, if False - lowercase. 147 | * 148 | * @return string|null 149 | */ 150 | public function getModuleFolderName($blUppercase = false) 151 | { 152 | /** @var oxpsModuleGeneratorOxModule|oxModule $this */ 153 | 154 | $sFolderName = $this->getInfo('oxpsmodulegenerator_folder'); 155 | 156 | if ($blUppercase and !is_null($sFolderName)) { 157 | $sFolderName = oxStr::getStr()->strtoupper($sFolderName); 158 | } 159 | 160 | return $sFolderName; 161 | } 162 | 163 | /** 164 | * Get module main class name. An alias for getModuleId method with True argument. 165 | * 166 | * @return string|boolean 167 | */ 168 | public function getModuleClassName() 169 | { 170 | return $this->getModuleId(true); 171 | } 172 | 173 | /** 174 | * Get a list of classes to overload (extend). 175 | * 176 | * @return array 177 | */ 178 | public function getClassesToExtend() 179 | { 180 | /** @var oxpsModuleGeneratorOxModule|oxModule $this */ 181 | 182 | return (array) $this->getInfo('oxpsmodulegenerator_extend_classes'); 183 | } 184 | 185 | /** 186 | * Get a list of new classes to create. 187 | * Each entry comes as array with: 188 | * `aClasses` - An array of classes names. 189 | * `sTemplateName` - A template to use for new classes creation. 190 | * `sInModulePath` - A path inside a module to place files in. 191 | * `sTemplatesPath` - A folder to keep related class template in. 192 | * 193 | * @param null|string $sObjectType Objects type to return, e.g. 'models'. Returns all if null. 194 | * @param null|string $sObjectsParam Objects param to return, e.g. 'aClasses'. Returns all if null. 195 | * 196 | * @return array|string 197 | */ 198 | public function getClassesToCreate($sObjectType = null, $sObjectsParam = null) 199 | { 200 | /** @var oxpsModuleGeneratorOxModule|oxModule $this */ 201 | 202 | $mData = array( 203 | 'widgets' => array( 204 | 'aClasses' => (array) $this->getInfo('oxpsmodulegenerator_widgets'), 205 | 'sTemplateName' => 'oxpswidgetclass.php.tpl', 206 | 'sInModulePath' => 'components/widgets/', 207 | 'sTemplatesPath' => 'widgets', 208 | ), 209 | 'controllers' => array( 210 | 'aClasses' => (array) $this->getInfo('oxpsmodulegenerator_controllers'), 211 | 'sTemplateName' => 'oxpscontrollerclass.php.tpl', 212 | 'sInModulePath' => 'controllers/', 213 | 'sTemplatesPath' => 'pages', 214 | ), 215 | 'models' => array( 216 | 'aClasses' => (array) $this->getInfo('oxpsmodulegenerator_models'), 217 | 'sTemplateName' => 'oxpsmodelclass.php.tpl', 218 | 'sInModulePath' => 'models/', 219 | ), 220 | 'list_models' => array( 221 | 'aClasses' => (array) $this->getInfo('oxpsmodulegenerator_list_models'), 222 | 'sTemplateName' => 'oxpslistmodelclass.php.tpl', 223 | 'sInModulePath' => 'models/', 224 | ), 225 | ); 226 | 227 | if (!is_null($sObjectType)) { 228 | 229 | // Get only one type of classes 230 | $mData = (array) $this->getArrayValue($mData, $sObjectType, 'array'); 231 | 232 | if (!is_null($sObjectsParam)) { 233 | 234 | // Get only one param of one class type 235 | $sType = ($sObjectsParam == 'aClasses') ? 'array' : 'string'; 236 | $mData = $this->getArrayValue($mData, $sObjectsParam, $sType); 237 | } 238 | } 239 | 240 | return $mData; 241 | } 242 | 243 | /** 244 | * Get module blocks array. 245 | * 246 | * @return array 247 | */ 248 | public function getBlocks() 249 | { 250 | /** @var oxpsModuleGeneratorOxModule|oxModule $this */ 251 | 252 | return (array) $this->getInfo('oxpsmodulegenerator_blocks'); 253 | } 254 | 255 | /** 256 | * Get module settings array. 257 | * 258 | * @return array 259 | */ 260 | public function getSettings() 261 | { 262 | /** @var oxpsModuleGeneratorOxModule|oxModule $this */ 263 | 264 | return (array) $this->getInfo('oxpsmodulegenerator_module_settings'); 265 | } 266 | 267 | /** 268 | * Parser setting type "select" options. 269 | * 270 | * @param string $sOptions 271 | * 272 | * @return array 273 | */ 274 | public function getSelectSettingOptions($sOptions) 275 | { 276 | return (array) explode('|', str_replace("'", "", trim($sOptions))); 277 | } 278 | 279 | /** 280 | * Get module version. 281 | * 282 | * @return string 283 | */ 284 | public function getInitialVersion() 285 | { 286 | /** @var oxpsModuleGeneratorOxModule|oxModule $this */ 287 | 288 | return (string) $this->getInfo('oxpsmodulegenerator_module_init_version'); 289 | } 290 | 291 | /** 292 | * Should the generator render "To Do" hints and tasks, e.g. hints how to use metadata samples, etc. 293 | * 294 | * @return bool 295 | */ 296 | public function renderTasks() 297 | { 298 | /** @var oxpsModuleGeneratorOxModule|oxModule $this */ 299 | 300 | return (bool) $this->getInfo('oxpsmodulegenerator_render_tasks'); 301 | } 302 | 303 | /** 304 | * Should the generator render sample data and example code, e.g. sample metadata lines, etc. 305 | * 306 | * @return bool 307 | */ 308 | public function renderSamples() 309 | { 310 | /** @var oxpsModuleGeneratorOxModule|oxModule $this */ 311 | 312 | return (bool) $this->getInfo('oxpsmodulegenerator_render_samples'); 313 | } 314 | 315 | /** 316 | * Get a full path of vendor directory. 317 | * 318 | * @return string 319 | */ 320 | public function getVendorPath() 321 | { 322 | /** @var oxpsModuleGeneratorOxModule|oxModule $this */ 323 | 324 | return $this->getConfig()->getModulesDir() . $this->getVendorPrefix() . '/'; 325 | } 326 | 327 | /** 328 | * Get a full path to the module directory. 329 | * 330 | * @return string 331 | */ 332 | public function getFullPath() 333 | { 334 | return $this->getVendorPath() . $this->getModuleFolderName() . '/'; 335 | } 336 | 337 | 338 | /** 339 | * Generate a module. 340 | * Creates blank pre-configure module skeleton in a vendor folder. 341 | * 342 | * @todo (nice2have): move to generation helper class. 343 | * 344 | * @param string $sModuleName CamelCase module name to use as a base for new module naming. 345 | * @param array $aGenerationOptions Additional module generation options: 346 | * `aExtendClasses` - A list of classes to overload (extend). 347 | * `aNewControllers` - A list of controllers to create. 348 | * `aNewModels` - A list of models (item models) to create. 349 | * `aNewLists` - Repeat some or all of item models to create list models. 350 | * `aNewWidgets` - A list of widgets to create. 351 | * `aNewBlocks` - A list of blocks data to create. 352 | * `aModuleSettings` - Data for module settings to create. 353 | * `sInitialVersion` - Initial version value for a new module. 354 | * `blFetchUnitTests` - Whatever to clone PHPUnit tests from GIT or not. 355 | * `blRenderTasks` - Option to render "To Do" tasks comments. 356 | * `blRenderSamples` - Option to render sample data comments. 357 | * 358 | * @return bool 359 | */ 360 | public function generateModule($sModuleName, array $aGenerationOptions = array()) 361 | { 362 | // Initialize helpers 363 | /** @var oxpsModuleGeneratorHelper $oHelper */ 364 | $oHelper = oxRegistry::get('oxpsModuleGeneratorHelper'); 365 | $oHelper->init($this); 366 | 367 | /** @var oxpsModuleGeneratorRender $oRenderHelper */ 368 | $oRenderHelper = oxRegistry::get('oxpsModuleGeneratorRender'); 369 | $oRenderHelper->init($this); 370 | 371 | // Set module data - initializes it with new module info 372 | $this->_setNewModuleData($sModuleName, $aGenerationOptions); 373 | 374 | // Get new module and module generation template full paths 375 | $sModuleGeneratorPath = oxRegistry::get('oxpsModuleGeneratorModule')->getPath(); 376 | $sModulePath = $this->getFullPath(); 377 | 378 | // Copy the module from a folder structure with templates to a new module path 379 | $oHelper->createVendorMetadata($this->getVendorPath()); 380 | $oHelper->getFileSystemHelper()->copyFolder($sModuleGeneratorPath . 'core/module.tpl/module/', $sModulePath); 381 | 382 | // Create classes to overload (extend) 383 | $aClassesToExtend = (array) $oHelper->createClassesToExtend( 384 | $sModuleGeneratorPath . 'core/module.tpl/oxpsextendclass.php.tpl' 385 | ); 386 | 387 | // Create new module classes and templates 388 | $aNewClasses = (array) $oHelper->createNewClassesAndTemplates($sModuleGeneratorPath); 389 | 390 | // Create blocks templates 391 | $oHelper->createBlock($sModulePath); 392 | 393 | // Process copied module files as Smarty templates to fill them with the real module data 394 | $oRenderHelper->renderModuleFiles($aClassesToExtend, $aNewClasses); 395 | 396 | // Clone PHP Unit tests libraries if the option is checked and configured 397 | if ($this->getArrayValue($aGenerationOptions, 'blFetchUnitTests')) { 398 | $oHelper->fillTestsFolder($oRenderHelper, $sModuleGeneratorPath, $sModulePath, $aClassesToExtend, $aNewClasses); 399 | } 400 | 401 | return true; 402 | } 403 | 404 | 405 | /** 406 | * Validate new module name: should be "UpperCamelCase" and not yet exist in the configured vendor directory. 407 | * 408 | * @param string $sModuleName 409 | * 410 | * @return boolean 411 | */ 412 | public function validateModuleName($sModuleName) 413 | { 414 | return ($this->getValidator()->validateCamelCaseName($sModuleName) and !$this->_moduleExists($sModuleName)); 415 | } 416 | 417 | /** 418 | * Get suffix of module file name by its path. 419 | * Expects argument to be something like "path/to/[vendor_prefix][module_name][desired_suffix].php" 420 | * 421 | * @param string $sPath 422 | * 423 | * @return string 424 | */ 425 | public function getFileNameSuffix($sPath) 426 | { 427 | $sSuffix = ''; 428 | $sFileName = basename($sPath); 429 | 430 | if (!empty($sFileName)) { 431 | $aFileName = explode('.', $sFileName); 432 | 433 | if (!empty($aFileName[0])) { 434 | $sSuffix = str_replace($this->getModuleId(), '', $aFileName[0]); 435 | } 436 | } 437 | 438 | return $sSuffix; 439 | } 440 | 441 | /** 442 | * Render file comment using a template and author/vendor data. 443 | * 444 | * @param string $sSubPackage Optional subpackage title. 445 | * 446 | * @return mixed 447 | */ 448 | public function renderFileComment($sSubPackage = '') 449 | { 450 | /** @var oxpsModuleGeneratorRender $oRenderHelper */ 451 | $oRenderHelper = oxRegistry::get('oxpsModuleGeneratorRender'); 452 | $oRenderHelper->init($this); 453 | 454 | return $oRenderHelper->renderFileComment($sSubPackage); 455 | } 456 | 457 | /** 458 | * An alias for validator class method. 459 | * Converts camel case string to human readable string with spaces between words. 460 | * Treats UPPERCASE abbreviations and numbers as separate words. 461 | * 462 | * @param string $sCamelCaseString 463 | * 464 | * @return string 465 | */ 466 | public function camelCaseToHumanReadable($sCamelCaseString) 467 | { 468 | return $this->getValidator()->camelCaseToHumanReadable($sCamelCaseString); 469 | } 470 | 471 | /** 472 | * An alias for validator class method. 473 | * Get array value by key, optionally casting its type to desired one. 474 | * 475 | * @param array $aDataArray 476 | * @param mixed $mArrayKey 477 | * @param string $sType 478 | * 479 | * @return bool 480 | */ 481 | public function getArrayValue(array $aDataArray, $mArrayKey, $sType = 'string') 482 | { 483 | return $this->getValidator()->getArrayValue($aDataArray, $mArrayKey, $sType); 484 | } 485 | 486 | 487 | /** 488 | * Compile additional module params and set all module data. 489 | * 490 | * @param string $sModuleName Module name in CamelCase style. 491 | * @param array $aOptions Additional module generation options. 492 | */ 493 | protected function _setNewModuleData($sModuleName, array $aOptions = array()) 494 | { 495 | /** @var oxpsModuleGeneratorOxModule|oxModule $this */ 496 | /** @var oxpsModuleGeneratorSettings $oSettingsParser */ 497 | $oSettingsParser = oxRegistry::get('oxpsModuleGeneratorSettings'); 498 | $oStr = oxStr::getStr(); 499 | $sVendorPrefix = $this->getVendorPrefix(); 500 | $sVarPrefix = $oStr->strtoupper($sVendorPrefix); 501 | $sModuleFolder = $oStr->strtolower($sModuleName); 502 | $sModuleClass = $sVendorPrefix . $sModuleName; 503 | $sModuleId = $oStr->strtolower($sModuleClass); 504 | $sReadableName = $this->camelCaseToHumanReadable($sModuleName); 505 | $aModuleData = array( 506 | // Default parent class params 507 | 'id' => $sModuleId, 508 | 'title' => $sVarPrefix . ' ' . $sReadableName, 509 | 'description' => $sVarPrefix . ' ' . $sReadableName . ' Module', 510 | 511 | // Additional params for new module generation 512 | 'oxpsmodulegenerator_name' => $sModuleName, 513 | 'oxpsmodulegenerator_folder' => $sModuleFolder, 514 | 'oxpsmodulegenerator_class' => $sModuleClass, 515 | 'oxpsmodulegenerator_extend_classes' => $this->getArrayValue($aOptions, 'aExtendClasses', 'array'), 516 | 'oxpsmodulegenerator_controllers' => $this->getArrayValue($aOptions, 'aNewControllers', 'array'), 517 | 'oxpsmodulegenerator_models' => $this->getArrayValue($aOptions, 'aNewModels', 'array'), 518 | 'oxpsmodulegenerator_list_models' => $this->getArrayValue($aOptions, 'aNewLists', 'array'), 519 | 'oxpsmodulegenerator_widgets' => $this->getArrayValue($aOptions, 'aNewWidgets', 'array'), 520 | 'oxpsmodulegenerator_blocks' => $this->getArrayValue($aOptions, 'aNewBlocks', 'array'), 521 | 'oxpsmodulegenerator_module_settings' => $oSettingsParser->getModuleSettings( 522 | (array) $this->getArrayValue($aOptions, 'aModuleSettings', 'array') 523 | ), 524 | 'oxpsmodulegenerator_module_init_version' => $this->getArrayValue($aOptions, 'sInitialVersion'), 525 | 'oxpsmodulegenerator_render_tasks' => $this->getArrayValue($aOptions, 'blRenderTasks', 'bool'), 526 | 'oxpsmodulegenerator_render_samples' => $this->getArrayValue($aOptions, 'blRenderSamples', 'bool'), 527 | ); 528 | 529 | $this->setModuleData($aModuleData); 530 | } 531 | 532 | /** 533 | * Check if module with provided name exists in the configured vendor directory. 534 | * 535 | * @param string $sModuleName 536 | * 537 | * @return boolean 538 | */ 539 | protected function _moduleExists($sModuleName) 540 | { 541 | /** @var oxpsModuleGeneratorFileSystem $oFileSystemHelper */ 542 | $oFileSystemHelper = oxRegistry::get('oxpsModuleGeneratorFileSystem'); 543 | 544 | return $oFileSystemHelper->isDir($this->getVendorPath() . oxStr::getStr()->strtolower($sModuleName)); 545 | } 546 | } 547 | -------------------------------------------------------------------------------- /copy_this/modules/oxps/modulegenerator/controllers/admin/admin_oxpsmodulegenerator.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | * @category module 21 | * @package modulegenerator 22 | * @author OXID Professional services 23 | * @link http://www.oxid-esales.com 24 | * @copyright (C) OXID eSales AG 2003-2014 25 | */ 26 | 27 | /** 28 | * Class Admin_oxpsModuleGenerator. 29 | * Module Generator GUI controller. 30 | * 31 | * @todo (nice2have) Class got too long -> move some methods to validation helper or some other class. 32 | */ 33 | class Admin_oxpsModuleGenerator extends oxAdminView 34 | { 35 | 36 | /** 37 | * Current class template name. 38 | * 39 | * @var string 40 | */ 41 | protected $_sThisTemplate = 'admin_oxpsmodulegenerator.tpl'; 42 | 43 | /** 44 | * Module instance used as information container for new module generation. 45 | * 46 | * @var oxpsModuleGeneratorOxModule 47 | */ 48 | protected $_oModule; 49 | 50 | 51 | /** 52 | * Overridden parent method. 53 | * Initializes internal variables for module instance. 54 | */ 55 | public function init() 56 | { 57 | /** @var oxpsModuleGeneratorOxModule $oModule */ 58 | $oModule = oxNew('oxpsModuleGeneratorOxModule'); 59 | $oModule->setVendorPrefix($this->getVendorPrefix()); 60 | $oModule->setAuthorData($this->getAuthorData()); 61 | 62 | $this->_oModule = $oModule; 63 | 64 | // Parent call 65 | $this->_Admin_oxpsModuleGenerator_init_parent(); 66 | } 67 | 68 | /** 69 | * Overridden parent method. 70 | * Adds module instance to view data. 71 | * 72 | * @return string 73 | */ 74 | public function render() 75 | { 76 | // Assign additional view data 77 | $this->_addViewData(array('oModule' => $this->getModule())); 78 | 79 | // Set an error if vendor/author data is not configured in the module settings 80 | if (!$this->_isVendorConfigured()) { 81 | $this->_setMessage('OXPS_MODULEGENERATOR_ADMIN_MODULE_ERROR_NO_VENDOR'); 82 | } 83 | 84 | // Add clean module generation options and form values to view data 85 | $this->_addViewData(array('oValues' => (object) $this->_getFormValues())); 86 | 87 | // Parent render call 88 | return $this->_Admin_oxpsModuleGenerator_render_parent(); 89 | } 90 | 91 | 92 | /** 93 | * Get module instance. 94 | * 95 | * @return oxpsModuleGeneratorOxModule 96 | */ 97 | public function getModule() 98 | { 99 | return $this->_oModule; 100 | } 101 | 102 | /** 103 | * Get vendor prefix stored in settings. 104 | * 105 | * @return string 106 | */ 107 | public function getVendorPrefix() 108 | { 109 | return (string) oxRegistry::get('oxpsModuleGeneratorModule')->getSetting('VendorPrefix'); 110 | } 111 | 112 | /** 113 | * Get module author/vendor data from settings: name, link, mail, copyright and file comment. 114 | * 115 | * @return array 116 | */ 117 | public function getAuthorData() 118 | { 119 | /** @var oxpsModuleGeneratorModule $oModuleGeneratorModule */ 120 | $oModuleGeneratorModule = oxRegistry::get('oxpsModuleGeneratorModule'); 121 | 122 | return array( 123 | 'name' => (string) $oModuleGeneratorModule->getSetting('ModuleAuthor'), 124 | 'link' => (string) $oModuleGeneratorModule->getSetting('AuthorLink'), 125 | 'mail' => (string) $oModuleGeneratorModule->getSetting('AuthorMail'), 126 | 'copy' => (string) $oModuleGeneratorModule->getSetting('Copyright'), 127 | 'info' => ' ' . trim(implode(PHP_EOL . ' ', (array) $oModuleGeneratorModule->getSetting('Comment'))), 128 | ); 129 | } 130 | 131 | /** 132 | * Module generation action. 133 | * Collects, cleans and validates form data, calls generation, sets messages. 134 | */ 135 | public function generateModule() 136 | { 137 | // Get module name from request 138 | $sModuleName = $this->_getTextParam('modulegenerator_module_name'); 139 | 140 | // Get module generation options 141 | $aGenerationOptions = $this->_getGenerationOptions(); 142 | 143 | /** @var oxpsModuleGeneratorValidator $oValidator */ 144 | $oValidator = oxRegistry::get('oxpsModuleGeneratorValidator'); 145 | 146 | if (!$oValidator->validateVendorPrefix($this->getVendorPrefix())) { 147 | 148 | // Set an error if configured module vendor prefix is not valid 149 | $this->_setMessage('OXPS_MODULEGENERATOR_ADMIN_MODULE_ERROR_INVALID_VENDOR'); 150 | } elseif (!$this->getModule()->validateModuleName($sModuleName)) { 151 | 152 | // Set an error if module name is not valid 153 | $this->_setMessage('OXPS_MODULEGENERATOR_ADMIN_MODULE_ERROR_INVALID_NAME'); 154 | } elseif ($this->getModule()->generateModule($sModuleName, $aGenerationOptions) 155 | ) { 156 | 157 | // Set success massage 158 | $this->_setMessage('OXPS_MODULEGENERATOR_ADMIN_MODULE_MSG_GENERATION_SUCCESS', false); 159 | } 160 | } 161 | 162 | 163 | /** 164 | * Check if vendor/author data is configured in the module settings. 165 | * 166 | * @return bool 167 | */ 168 | protected function _isVendorConfigured() 169 | { 170 | $sVendorPrefix = $this->getVendorPrefix(); 171 | 172 | return !empty($sVendorPrefix); 173 | } 174 | 175 | /** 176 | * Add additional array to the view data. 177 | * 178 | * @param array $aViewData Assoc array of parameters to add to view data. 179 | */ 180 | protected function _addViewData($aViewData) 181 | { 182 | if (!empty($aViewData) and is_array($aViewData)) { 183 | $this->setViewData(array_merge($this->getViewData(), $aViewData)); 184 | } 185 | } 186 | 187 | /** 188 | * Collect request data, parse it and compile to module generation options array. 189 | * 190 | * @return array 191 | */ 192 | protected function _getGenerationOptions() 193 | { 194 | $oConfig = $this->getConfig(); 195 | 196 | $aGenerationOptions = array( 197 | 'aExtendClasses' => $this->_validateAndLinkClasses($this->_getTextParam('modulegenerator_extend_classes')), 198 | 'aNewControllers' => $this->_parseMultiLineInput($this->_getTextParam('modulegenerator_controllers')), 199 | 'aNewModels' => $this->_parseMultiLineInput($this->_getTextParam('modulegenerator_models')), 200 | 'aNewLists' => $this->_parseMultiLineInput($this->_getTextParam('modulegenerator_lists')), 201 | 'aNewWidgets' => $this->_parseMultiLineInput($this->_getTextParam('modulegenerator_widgets')), 202 | 'aNewBlocks' => $this->_parseBlocksData( 203 | $this->_getTextParam('modulegenerator_blocks'), 204 | $this->getVendorPrefix(), 205 | $this->_getTextParam('modulegenerator_module_name') 206 | ), 207 | 'aModuleSettings' => (array) $oConfig->getRequestParameter('modulegenerator_settings'), 208 | 'sInitialVersion' => (string) $oConfig->getRequestParameter('modulegenerator_init_version'), 209 | 'blFetchUnitTests' => (bool) $oConfig->getRequestParameter('modulegenerator_fetch_unit_tests'), 210 | 'blRenderTasks' => (bool) $oConfig->getRequestParameter('modulegenerator_render_tasks'), 211 | 'blRenderSamples' => (bool) $oConfig->getRequestParameter('modulegenerator_render_samples'), 212 | ); 213 | 214 | return $this->_filterListModels($aGenerationOptions); 215 | } 216 | 217 | /** 218 | * Get initial form values for a case when the form was submitted. 219 | * 220 | * @return array 221 | */ 222 | protected function _getFormValues() 223 | { 224 | /** @var oxpsModuleGeneratorValidator $oValidator */ 225 | $oValidator = oxRegistry::get('oxpsModuleGeneratorValidator'); 226 | 227 | $aOptions = (array) $this->_getGenerationOptions(); 228 | 229 | return array( 230 | 'name' => $this->_getTextParam('modulegenerator_module_name'), 231 | 'extend' => $this->_toString(array_keys($oValidator->getArrayValue($aOptions, 'aExtendClasses', 'array'))), 232 | 'controllers' => $this->_toString($oValidator->getArrayValue($aOptions, 'aNewControllers', 'array')), 233 | 'models' => $this->_toString($oValidator->getArrayValue($aOptions, 'aNewModels', 'array')), 234 | 'lists' => $this->_getListModelsFieldValue($oValidator->getArrayValue($aOptions, 'aNewLists', 'array')), 235 | 'widgets' => $this->_toString($oValidator->getArrayValue($aOptions, 'aNewWidgets', 'array')), 236 | 'blocks' => $this->_getBlocksFieldValue($oValidator->getArrayValue($aOptions, 'aNewBlocks', 'array')), 237 | 'settings' => $oValidator->getArrayValue($aOptions, 'aModuleSettings', 'array'), 238 | 'version' => $this->_getFormVersionFieldValue($oValidator->getArrayValue($aOptions, 'sInitialVersion')), 239 | 'tests' => $oValidator->getArrayValue($aOptions, 'blFetchUnitTests', 'boolean'), 240 | 'tasks' => $oValidator->getArrayValue($aOptions, 'blRenderTasks', 'boolean'), 241 | 'samples' => $oValidator->getArrayValue($aOptions, 'blRenderSamples', 'boolean'), 242 | ); 243 | } 244 | 245 | /** 246 | * Convert array to a multi-line string. 247 | * 248 | * @param array $aData 249 | * 250 | * @return string 251 | */ 252 | protected function _toString(array $aData) 253 | { 254 | return trim((string) implode(PHP_EOL, $aData)); 255 | } 256 | 257 | /** 258 | * Get initial value for list models field. 259 | * Removes "List" suffixes from names. 260 | * 261 | * @param array $aRequestListModels 262 | * 263 | * @return string 264 | */ 265 | protected function _getListModelsFieldValue(array $aRequestListModels) 266 | { 267 | /** @var oxStrMb|oxStrRegular $oStr */ 268 | $oStr = oxStr::getStr(); 269 | 270 | $aLists = array(); 271 | 272 | foreach ($aRequestListModels as $sListClassName) { 273 | $aLists[] = $oStr->substr($sListClassName, 0, ($oStr->strlen($sListClassName) - 4)); 274 | } 275 | 276 | return $this->_toString($aLists); 277 | } 278 | 279 | /** 280 | * Get initial value for module blocks field. 281 | * 282 | * @param array $aRequestBlocks 283 | * 284 | * @return string 285 | */ 286 | protected function _getBlocksFieldValue(array $aRequestBlocks) 287 | { 288 | /** @var oxpsModuleGeneratorValidator $oValidator */ 289 | $oValidator = oxRegistry::get('oxpsModuleGeneratorValidator'); 290 | 291 | $aBlocks = array(); 292 | 293 | foreach ($aRequestBlocks as $oBlock) { 294 | $aBlock = (array) $oBlock; 295 | $aBlocks[] = $oValidator->getArrayValue($aBlock, 'block') . '@' . 296 | $oValidator->getArrayValue($aBlock, 'template'); 297 | } 298 | 299 | return $this->_toString($aBlocks); 300 | } 301 | 302 | /** 303 | * Get initial value for module version field. 304 | * 305 | * @param string $sRequestVersion 306 | * 307 | * @return string 308 | */ 309 | protected function _getFormVersionFieldValue($sRequestVersion) 310 | { 311 | $sModuleVersion = trim((string) $sRequestVersion); 312 | 313 | if (empty($sModuleVersion)) { 314 | $sModuleVersion = '1.0.0'; 315 | } 316 | 317 | return $sModuleVersion; 318 | } 319 | 320 | /** 321 | * Get request parameter as trimmed string. 322 | * 323 | * @param string $sKey 324 | * 325 | * @return string 326 | */ 327 | protected function _getTextParam($sKey) 328 | { 329 | return trim((string) oxRegistry::getConfig()->getRequestParameter($sKey)); 330 | } 331 | 332 | /** 333 | * Set a message to view data. 334 | * Uses key `sMessage` for the message. 335 | * Sets key `blError` True if it is an error, False for a success/info message. 336 | * 337 | * @param string $sMessage 338 | * @param bool $blError 339 | */ 340 | protected function _setMessage($sMessage, $blError = true) 341 | { 342 | $this->_addViewData(array('sMessage' => (string) $sMessage, 'blError' => !empty($blError))); 343 | } 344 | 345 | /** 346 | * Check list of classes and link it with its relative path for each valid class. 347 | * 348 | * @param string $sClasses List of classes names separated with a new line. 349 | * 350 | * @return array With relative application path as value and clean class name as key for each valid class. 351 | */ 352 | protected function _validateAndLinkClasses($sClasses) 353 | { 354 | /** @var oxpsModuleGeneratorFileSystem $oFileSystemHelper */ 355 | $oFileSystemHelper = oxRegistry::get('oxpsModuleGeneratorFileSystem'); 356 | $aClasses = $this->_parseMultiLineInput($sClasses, 'not_empty'); 357 | $aValidLinkedClasses = array(); 358 | $oConfig = $this->getConfig(); 359 | $sBasePath = $oConfig->getConfigParam('sShopDir'); 360 | 361 | foreach ($aClasses as $sClassName) { 362 | if (!class_exists($sClassName)) { 363 | continue; 364 | } 365 | 366 | // Build reflection object to get path to a class 367 | $oReflection = new ReflectionClass(new $sClassName()); 368 | $sClassPath = (string) $oReflection->getFilename(); 369 | 370 | if ($oFileSystemHelper->isFile($sClassPath)) { 371 | $sClassName = oxStr::getStr()->strtolower($sClassName); 372 | $sNoAppPath = str_replace('application' . DIRECTORY_SEPARATOR, '', dirname($sClassPath)); 373 | $sClassPath = str_replace($sBasePath, '', $sNoAppPath) . DIRECTORY_SEPARATOR; 374 | 375 | $aValidLinkedClasses[$sClassName] = $sClassPath; 376 | } 377 | } 378 | 379 | return $aValidLinkedClasses; 380 | } 381 | 382 | /** 383 | * Parse new blocks multi-line data to valid metadata blocks definition. 384 | * Each valid element will have a template, block and file keys. 385 | * 386 | * @todo (nice2have): When using block name as blocks list key, block becomes unique in a module. 387 | * Maybe it should not be unique, i.e. module could extend same block many times, or not? 388 | * 389 | * @param string $sBlocks 390 | * @param string $sVendorPrefix 391 | * @param string $sModuleName 392 | * 393 | * @return array 394 | */ 395 | protected function _parseBlocksData($sBlocks, $sVendorPrefix, $sModuleName) 396 | { 397 | $sModuleId = oxStr::getStr()->strtolower(sprintf('%s%s', $sVendorPrefix, $sModuleName)); 398 | $aBlocks = $this->_parseMultiLineInput($sBlocks, 'not_empty'); 399 | $aValidBlocks = array(); 400 | 401 | foreach ($aBlocks as $sBlockDefinition) { 402 | $aBlock = $this->_parseBlockDefinition($sBlockDefinition, $sModuleId); 403 | 404 | if (isset($aBlock['template'], $aBlock['block'], $aBlock['file'])) { 405 | $aValidBlocks[sprintf('_%s', $aBlock['block'])] = (object) $aBlock; 406 | } 407 | } 408 | 409 | return $aValidBlocks; 410 | } 411 | 412 | /** 413 | * Parse block definition from string to metadata block entry array. 414 | * 415 | * @todo (nice2have): Validate block name [a-z{1}a-z_{1,}] and check if template exists in active theme? 416 | * 417 | * @param string $sBlockDefinition String in format "[block_name]@[path/to/existing/template.tpl]" 418 | * @param string $sModuleId 419 | * 420 | * @return array 421 | */ 422 | protected function _parseBlockDefinition($sBlockDefinition, $sModuleId) 423 | { 424 | /** @var oxpsModuleGeneratorValidator $oValidator */ 425 | $oValidator = oxRegistry::get('oxpsModuleGeneratorValidator'); 426 | 427 | $sBlockDefinition = trim((string) $sBlockDefinition); 428 | $aBlockDefinition = !empty($sBlockDefinition) ? explode("@", $sBlockDefinition) : array(); 429 | 430 | $sBlockName = $oValidator->getArrayValue($aBlockDefinition, 0); 431 | $sTemplatePath = $oValidator->getArrayValue($aBlockDefinition, 1); 432 | 433 | if (empty($sBlockName) or empty($sTemplatePath)) { 434 | return array(); 435 | } 436 | 437 | return array( 438 | 'template' => $sTemplatePath, 439 | 'block' => $sBlockName, 440 | 'file' => sprintf('views/blocks/%s_%s.tpl', $sModuleId, $sBlockName), 441 | ); 442 | } 443 | 444 | /** 445 | * Parse multi-line string input as array and validate each line. 446 | * Line validation is one of following: 447 | * `not_empty` - there must be something in the line 448 | * `camel_case` - a value must be in "UpperCamelCase" format 449 | * 450 | * @todo (nice2have): Check class names among all types to be unique 451 | * 452 | * @param string $sInput 453 | * @param string $sLineValidation A validation rule name. 454 | * 455 | * @return array 456 | */ 457 | protected function _parseMultiLineInput($sInput, $sLineValidation = 'camel_case') 458 | { 459 | $aInput = (array) explode(PHP_EOL, (string) $sInput); 460 | $aValidInput = array(); 461 | 462 | foreach ($aInput as $sLine) { 463 | $sLine = trim((string) $sLine); 464 | 465 | if ($this->_isLineInputValid($sLine, $sLineValidation) and !in_array($sLine, $aValidInput)) { 466 | $aValidInput[] = $sLine; 467 | } 468 | } 469 | 470 | return $aValidInput; 471 | } 472 | 473 | /** 474 | * Check if a value passes specified validation rule. 475 | * 476 | * @param string $sValue 477 | * @param string $sValidationRule 478 | * 479 | * @return bool 480 | */ 481 | protected function _isLineInputValid($sValue, $sValidationRule) 482 | { 483 | $blIsValid = false; 484 | 485 | switch ($sValidationRule) { 486 | case 'not_empty'; 487 | $blIsValid = !empty($sValue); 488 | break; 489 | 490 | case 'camel_case': 491 | /** @var oxpsModuleGeneratorValidator $oValidator */ 492 | $oValidator = oxRegistry::get('oxpsModuleGeneratorValidator'); 493 | $blIsValid = (bool) $oValidator->validateCamelCaseName($sValue); 494 | break; 495 | } 496 | 497 | return $blIsValid; 498 | } 499 | 500 | /** 501 | * Filter generation options to check if list models were set and if those list models match item models. 502 | * List model is added only if item model with same name was also set. 503 | * Adds "List" prefix for each valid list model. 504 | * 505 | * @param array $aData 506 | * 507 | * @return array 508 | */ 509 | protected function _filterListModels(array $aData) 510 | { 511 | /** @var oxpsModuleGeneratorValidator $oValidator */ 512 | $oValidator = oxRegistry::get('oxpsModuleGeneratorValidator'); 513 | 514 | $aLists = (array) $oValidator->getArrayValue($aData, 'aNewLists', 'array'); 515 | $aModels = (array) $oValidator->getArrayValue($aData, 'aNewModels', 'array'); 516 | 517 | foreach ($aLists as $mKey => $sNewListClass) { 518 | if (!in_array($sNewListClass, $aModels)) { 519 | unset($aLists[$mKey]); 520 | } else { 521 | $aLists[$mKey] = sprintf('%sList', $sNewListClass); 522 | } 523 | } 524 | 525 | $aData['aNewLists'] = $aLists; 526 | 527 | return $aData; 528 | } 529 | 530 | 531 | /** 532 | * Parent `init` call. Method required for mocking. 533 | * 534 | * @codeCoverageIgnore 535 | * 536 | * @return null 537 | */ 538 | protected function _Admin_oxpsModuleGenerator_init_parent() 539 | { 540 | return parent::init(); 541 | } 542 | 543 | /** 544 | * Parent `render` call. Method required for mocking. 545 | * 546 | * @codeCoverageIgnore 547 | * 548 | * @return null 549 | */ 550 | protected function _Admin_oxpsModuleGenerator_render_parent() 551 | { 552 | return parent::render(); 553 | } 554 | } 555 | --------------------------------------------------------------------------------