diff --git a/.gitignore b/.gitignore index 573c1e2..ba2c229 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea clover.xml -vendor \ No newline at end of file +vendor +.vscode-upload.json diff --git a/README.md b/README.md index 781f62a..5ef73eb 100644 --- a/README.md +++ b/README.md @@ -9,203 +9,206 @@ Thanks to the [netz98 magerun](https://github.com/netz98/n98-magerun) project wh ## Installation -PHP 5.4 is required. +__Disclaimer:__ This fork is intended for __usage with OXID 6.x__ and up, it will not be compatible with older shop versions. Legacy commands will be removed, e.g. +"install:shop" which is now handled via Composer. -If you are using composer (which you probably are), just add `"marcharding/oxrun": "dev-master"` to your composer.json and run composer install. -You can then use oxrun by calling `vendor/bin/oxrun` or add `vendor/bin` to your $PATH to be able to just call `oxrun`. - -You can also install oxrun by simply downloading the phar file - - wget --no-check-certificate https://raw.githubusercontent.com/marcharding/oxrun/master/oxrun.phar - -You can oxrun now via `php oxrun.phar` +PHP 5.6 is required, PHP 7 or newer is recommended. -Alternatively you can also make the phar itself executable and copy it to your /usr/local/bin/ directory for global usage. +If you are using composer (which you probably are), just add `"smxsm/oxrun": "dev-develop"` to your composer.json and run composer install. - chmod +x oxrun.phar - sudo mv oxrun.phar /usr/local/bin/oxrun - -You can then run oxrun by just calling `oxrun` +You can then use oxrun by calling `vendor/bin/oxrun` or add `vendor/bin` to your $PATH to be able to just call `oxrun`. # Usage -To use oxrun just execute `php oxrun.phar` or `oxrun` (see above). +To use oxrun just execute `php oxrun.phar` or `./vendor/bin/oxrun` (see above). Execute oxrun inside your OXID eShop base directory (or subdirectory) if you want to interact with an existing shop. It will automatically try to find the oxid boostrap.php and load it. -# Available commands - -cache:clear ------------ +If you want to __run it from a different directory__, you have to add the option `"--shopDir=/path/to/your/shop"`. -* Description: Clears the cache -* Usage: `cache:clear` +You can use it e.g. to help you with an OXID 6 installation or deployment, e.g.: -### Options: +```json + "scripts": { + "post-update-cmd": [ + "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters", + "@oe:ide-helper:generate", + "@oxrun:activate-modules", + "@oxrun:set-config" + ], + "oxrun:activate-modules": [ + "./vendor/bin/oxrun module:multiactivate configs/modules.yml -c --shopDir=./source" + ], + "oxrun:set-config": [ + "./vendor/bin/oxrun config:multiset configs/malls.yml --shopDir=./source" + ], -cms:update ----------- +``` -* Description: Updates a cms page -* Usage: `cms:update [--title[="..."]] [--content[="..."]] [--language="..."] [--active="..."] ident` +This could activate some modules in different subshops and set a bunch of config variables e.g. +__Please note:__ since activating modules and updating config values requires a filled database and a valid config.inc.php file, you'd have to do some more voodoo during the OXID setup routine to make the above example work! But it should give you an idea how to use oxrun "multiactivate" and "multiset" :) -### Arguments: +# Available commands -**ident:** -* Name: ident -* Description: Content ident -### Options: +misc:phpstorm:metadata +---------------------- -**title:** +* Description: Generate a PhpStorm metadata file for auto-completion. +* Usage: -* Name: `--title` -* Is value required: no -* Description: Content title + * `misc:phpstorm:metadata [-o|--output-dir OUTPUT-DIR]` -**content:** +Generate a PhpStorm metadata file for auto-completion. -* Name: `--content` -* Is value required: no -* Description: Content body +### Options: -**language:** +**output-dir:** -* Name: `--language` +* Name: `--output-dir` +* Shortcut: `-o` * Is value required: yes -* Description: Content language +* Description: Writes the metadata for PhpStorm to the specified directory. -**active:** +misc:generate:documentation +--------------------------- -* Name: `--active` -* Is value required: yes -* Description: Content active +* Description: Generate a raw command documentation of the available commands +* Usage: -config:get ----------- + * `misc:generate:documentation` -* Description: Gets a config value -* Usage: `config:get [--shopId[="..."]] [--moduleId[="..."]] variableName` +Generate a raw command documentation of the available commands ### Arguments: -**variableName:** +**command:** -* Name: variableName -* Description: Variable name +* Name: command +* Description: The command to execute ### Options: -**shopId:** +db:query +-------- -* Name: `--shopId` -* Is value required: no -* Description: +* Description: Executes a query +* Usage: -**moduleId:** + * `db:query [--raw] [--] ` -* Name: `--moduleId` -* Is value required: no -* Description: +Executes an SQL query on the current shop database. Wrap your SQL in quotes. -config:set ----------- +If your query produces a result (e.g. a SELECT statement), the output will be returned via the table component. Add the raw option for raw output. -* Description: Sets a config value -* Usage: `config:set [--variableType="..."] [--shopId[="..."]] [--moduleId[="..."]] variableName variableValue` +Requires php exec and MySQL CLI tools installed on your system. ### Arguments: -**variableName:** - -* Name: variableName -* Description: Variable name - -**variableValue:** +**query:** -* Name: variableValue -* Description: Variable value +* Name: query +* Description: The query which is to be executed ### Options: -**variableType:** - -* Name: `--variableType` -* Is value required: yes -* Description: Variable type - -**shopId:** +**raw:** -* Name: `--shopId` +* Name: `--raw` +* Accept value: no * Is value required: no -* Description: +* Description: Raw output +* Default: `false` -**moduleId:** +db:import +--------- -* Name: `--moduleId` -* Is value required: no -* Description: +* Description: Import a sql file +* Usage: -config:shop:get ---------------- + * `db:import ` -* Description: Sets a shop config value -* Usage: `config:shop:get [--shopId[="..."]] variableName` +Imports an SQL file on the current shop database. + +Requires php exec and MySQL CLI tools installed on your system. ### Arguments: -**variableName:** +**file:** -* Name: variableName -* Description: Variable name +* Name: file +* Description: The sql file which is to be imported ### Options: -**shopId:** - -* Name: `--shopId` -* Is value required: no -* Description: oxbaseshop -* Default: `'oxbaseshop'` - -config:shop:set ---------------- - -* Description: Sets a shop config value -* Usage: `config:shop:set [--shopId[="..."]] variableName variableValue` +db:list +------- -### Arguments: +* Description: List of all Tables +* Usage: -**variableName:** + * `db:list [-p|--plain] [-t|--pattern PATTERN]` -* Name: variableName -* Description: Variable name +List Tables -**variableValue:** +usage: + oxrun db:list --pattern oxseo%,oxuser + - To dump all Tables, but `oxseo`, `oxvoucher`, and `oxvoucherseries` without data. + possibilities: oxseo%,oxuser,%logs% + -* Name: variableValue -* Description: Variable value ### Options: -**shopId:** +**plain:** -* Name: `--shopId` +* Name: `--plain` +* Shortcut: `-p` +* Accept value: no * Is value required: no -* Description: oxbaseshop -* Default: `'oxbaseshop'` +* Description: print list as comma separated. +* Default: `false` + +**pattern:** + +* Name: `--pattern` +* Shortcut: `-t` +* Is value required: yes +* Description: table name pattern test. e.g. oxseo%,oxuser db:dump ------- * Description: Dumps the the current shop database -* Usage: `db:dump [--file="..."]` - -Dumps the the current shop database. - -Requires php exec and MySQL CLI tools installed on your system. +* Usage: + + * `db:dump [--file FILE] [-t|--table TABLE] [-i|--ignoreViews] [-a|--anonymous] [-w|--withoutTableData WITHOUTTABLEDATA]` + +Dump the current shop database. + +usage: + oxrun db:dump --withoutTableData oxseo,oxvou% + - To dump all Tables, but `oxseo`, `oxvoucher`, and `oxvoucherseries` without data. + possibilities: oxseo%,oxuser,%logs% + + oxrun db:dump --table %user% + - to dump only those tables `oxuser` `oxuserbasketitems` `oxuserbaskets` `oxuserpayments` + + oxrun db:dump --anonymous # Perfect for Stage Server + - Those table without data: `oxseo`, `oxseologs`, `oxseohistory`, `oxuser`, `oxuserbasketitems`, `oxuserbaskets`, `oxuserpayments`, `oxnewssubscribed`, `oxremark`, `oxvouchers`, `oxvoucherseries`, `oxaddress`, `oxorder`, `oxorderarticles`, `oxorderfiles`, `oepaypal_order`, `oepaypal_orderpayments`. + + oxrun db:dump -v + - With verbose mode you will see the mysqldump command + (`mysqldump -u 'root' -h 'oxid_db' -p ... `) + + oxrun db:dump --file dump.sql + - Put the Output into a File + +** Only existing tables will be exported. No matter what was required. + +Requires php, exec and MySQL CLI tools installed on your system. ### Options: @@ -215,59 +218,47 @@ Requires php exec and MySQL CLI tools installed on your system. * Is value required: yes * Description: Dump sql in to this file -db:import ---------- - -* Description: Import a sql file -* Usage: `db:import file` - -Imports an SQL file on the current shop database. - -Requires php exec and MySQL CLI tools installed on your system. - -### Arguments: - -**file:** - -* Name: file -* Description: The sql file which is to be imported - -### Options: - -db:query --------- - -* Description: Executes a query -* Usage: `db:query [--raw] query` +**table:** -Executes an SQL query on the current shop database. Wrap your SQL in quotes. +* Name: `--table` +* Shortcut: `-t` +* Is value required: yes +* Description: name of table to dump only. Default all tables. Use comma separated list and or pattern e.g. %voucher% -If your query produces a result (e.g. a SELECT statement), the output will be returned via the table component. Add the raw option for raw output. +**ignoreViews:** -Requires php exec and MySQL CLI tools installed on your system. +* Name: `--ignoreViews` +* Shortcut: `-i` +* Accept value: no +* Is value required: no +* Description: Ignore views +* Default: `false` -### Arguments: +**anonymous:** -**query:** +* Name: `--anonymous` +* Shortcut: `-a` +* Accept value: no +* Is value required: no +* Description: Do not export table with person related data. +* Default: `false` -* Name: query -* Description: The query which is to be executed +**withoutTableData:** -### Options: +* Name: `--withoutTableData` +* Shortcut: `-w` +* Is value required: yes +* Description: Table name to dump without data. Use comma separated list and or pattern e.g. %voucher% -**raw:** +install:shop __[DEPRECATED]__ +----------------------------- -* Name: `--raw` -* Accept value: no -* Is value required: no -* Description: Raw output -* Default: `false` +* Description: Installs the shop, for OXID 6 composer is used instead! +* Usage: -install:shop ------------- + * `install:shop __[DEPRECATED]__ [--oxidVersion [OXIDVERSION]] [--installationFolder [INSTALLATIONFOLDER]] [--dbHost DBHOST] [--dbUser DBUSER] [--dbPwd DBPWD] [--dbName DBNAME] [--dbPort [DBPORT]] [--installSampleData [INSTALLSAMPLEDATA]] [--shopURL SHOPURL] [--adminUser ADMINUSER] [--adminPassword ADMINPASSWORD]` -* Description: Installs the shop -* Usage: `install:shop [--oxidVersion[="..."]] [--installationFolder[="..."]] [--dbHost="..."] [--dbUser="..."] [--dbPwd="..."] [--dbName="..."] [--dbPort[="..."]] [--installSampleData[="..."]] [--shopURL="..."] [--adminUser="..."] [--adminPassword="..."]` +Installs the shop, for OXID 6 composer is used instead! ### Options: @@ -276,14 +267,13 @@ install:shop * Name: `--oxidVersion` * Is value required: no * Description: Oxid version -* Default: `'v4.9.5'` **installationFolder:** * Name: `--installationFolder` * Is value required: no * Description: Installation folder -* Default: `'/vagrant/web/oxrun'` +* Default: `'/var/www/html/gerstaecker-oxid6/source'` **dbHost:** @@ -338,116 +328,540 @@ install:shop * Name: `--adminUser` * Is value required: yes * Description: Admin user email/login +* Default: `'admin@example.com'` **adminPassword:** * Name: `--adminPassword` * Is value required: yes * Description: Admin password +* Default: `'oxid-123456'` -misc:generate:documentation ---------------------------- - -* Description: Generate a raw command documentation of the available commands -* Usage: `misc:generate:documentation` +cache:clear +----------- -### Arguments: +* Description: Clears the cache +* Usage: -**command:** + * `cache:clear [-f|--force]` -* Name: command -* Description: The command to execute +Clears the cache ### Options: -misc:phpstorm:metadata ----------------------- - -* Description: Generate a PhpStorm metadata file for autocompletion -* Usage: `misc:phpstorm:metadata` +**force:** -### Options: +* Name: `--force` +* Shortcut: `-f` +* Accept value: no +* Is value required: no +* Description: Try to delete the cache anyway. [danger or permission denied] +* Default: `false` -**output-dir:** +route:debug +----------- -* Name: `--output-dir`, `-o` -* Accept value: yes -* Is value required: yes -* Description: Writes the metadata for PhpStorm to the specified directory. +* Description: Returns the route. Which controller and parameters are called. +* Usage: -module:activate ---------------- + * `route:debug [--shopId [SHOPID]] [-c|--copy] [--] ` -* Description: Activates a module -* Usage: `module:activate module` +Returns the route. Which controller and parameters are called. ### Arguments: -**module:** +**url:** -* Name: module -* Description: Module name +* Name: url +* Description: Website URL. Full or Path ### Options: -module:deactivate ------------------ +**shopId:** -* Description: Deactivates a module -* Usage: `module:deactivate module` +* Name: `--shopId` +* Is value required: no +* Description: -### Arguments: +**copy:** -**module:** +* Name: `--copy` +* Shortcut: `-c` +* Accept value: no +* Is value required: no +* Description: Copy file path from the class to the clipboard (only MacOS) +* Default: `false` -* Name: module -* Description: Module name +config:get +---------- -### Options: +* Description: Gets a config value +* Usage: -module:fix ----------- + * `config:get [--shopId [SHOPID]] [--moduleId [MODULEID]] [--] ` -* Description: Fixes a module -* Usage: `module:fix module` +Gets a config value ### Arguments: -**module:** +**variableName:** -* Name: module -* Description: Module name +* Name: variableName +* Description: Variable name ### Options: -module:generate ---------------- +**shopId:** -* Description: Generates a module skeleton -* Usage: `module:generate module` +* Name: `--shopId` +* Is value required: no +* Description: -### Arguments: +**moduleId:** -**module:** +* Name: `--moduleId` +* Is value required: no +* Description: + +config:export +------------- + +* Description: Export shop config +* Usage: + + * `config:export [--no-debug] [--env [ENV]] [--force-cleanup [FORCE-CLEANUP]]` + +Info: +Exports all config values to yaml files, interacts with the +[Modules Config](https://github.com/OXIDprojects/oxid_modules_config/) module, +[__which currently isn't fully ported to OXID 6 yet!__](https://github.com/OXIDprojects/oxid_modules_config/tree/dev-6.0-wip) + +### Options: + +**no-debug:** + +* Name: `--no-debug` +* Accept value: no +* Is value required: no +* Description: No debug ouput +* Default: `false` + +**env:** + +* Name: `--env` +* Is value required: no +* Description: set specific environment, corresponds to a specific folder for the yaml files + +**force-cleanup:** + +* Name: `--force-cleanup` +* Is value required: no +* Description: Force cleanup on error + +config:shop:set +--------------- + +* Description: Sets a shop config value +* Usage: + + * `config:shop:set [--shopId [SHOPID]] [--] ` + +Sets a shop config value + +### Arguments: + +**variableName:** + +* Name: variableName +* Description: Variable name + +**variableValue:** + +* Name: variableValue +* Description: Variable value + +### Options: + +**shopId:** + +* Name: `--shopId` +* Is value required: no +* Description: oxbaseshop +* Default: `'oxbaseshop'` + +config:set +---------- + +* Description: Sets a config value +* Usage: + + * `config:set [--variableType VARIABLETYPE] [--shopId [SHOPID]] [--moduleId [MODULEID]] [--] ` + +Sets a config value + +### Arguments: + +**variableName:** + +* Name: variableName +* Description: Variable name + +**variableValue:** + +* Name: variableValue +* Description: Variable value + +### Options: + +**variableType:** + +* Name: `--variableType` +* Is value required: yes +* Description: Variable type + +**shopId:** + +* Name: `--shopId` +* Is value required: no +* Description: + +**moduleId:** + +* Name: `--moduleId` +* Is value required: no +* Description: + +config:import +------------- + +* Description: Import shop config +* Usage: + + * `config:import [--no-debug] [--env [ENV]] [--force-cleanup [FORCE-CLEANUP]]` + +Info: +Imports all config values from yaml files, interacts with the +[Modules Config](https://github.com/OXIDprojects/oxid_modules_config/) module, +[__which currently isn't fully ported to OXID 6 yet!__](https://github.com/OXIDprojects/oxid_modules_config/tree/dev-6.0-wip) + +### Options: + +**no-debug:** + +* Name: `--no-debug` +* Accept value: no +* Is value required: no +* Description: No debug ouput +* Default: `false` + +**env:** + +* Name: `--env` +* Is value required: no +* Description: set specific environment, corresponds to a specific folder for the yaml files + +**force-cleanup:** + +* Name: `--force-cleanup` +* Is value required: no +* Description: Force cleanup on error + +config:multiset +--------------- + +* Description: Sets multiple config values from yaml file +* Usage: + + * `config:multiset ` + +YAML example: +```yaml +config: + 1: + blReverseProxyActive: + variableType: bool + variableValue: false + # simple string type + sMallShopURL: http://myshop.dev.local + sMallSSLShopURL: http://myshop.dev.local + myMultiVal: + variableType: aarr + variableValue: + - /foo/bar/ + - /bar/foo/ + # optional module id + moduleId: my_module + 2: + blReverseProxyActive: +... +``` + +If you want, you can also specify __a YAML string on the command line instead of a file__, e.g.: + +```bash +../vendor/bin/oxrun module:multiset $'config: + 1: + foobar: barfoo +' --shopId=1 +``` + +### Arguments: + +**configfile:** + +* Name: configfile +* Description: The file containing the config values, see malls.yml.dist. The file path is relative to the shop root. You can also pass a YAML string on the command line. + +### Options: + +config:shop:get +--------------- + +* Description: Sets a shop config value +* Usage: + + * `config:shop:get [--shopId [SHOPID]] [--] ` + +Sets a shop config value + +### Arguments: + +**variableName:** + +* Name: variableName +* Description: Variable name + +### Options: + +**shopId:** + +* Name: `--shopId` +* Is value required: no +* Description: oxbaseshop +* Default: `'oxbaseshop'` + +module:generate +--------------- + +* Description: Generates a module skeleton __[NOT IMPLEMENTED YET]__ +* Usage: + + * `module:generate [--shopId [SHOPID]] [--] ` + +Generates a module skeleton __[NOT IMPLEMENTED YET]__ + +### Arguments: + +**module:** * Name: module * Description: Module name ### Options: +**shopId:** + +* Name: `--shopId` +* Is value required: no +* Description: + +module:multiactivate +-------------------- + +* Description: Activates multiple modules, based on a YAML file +* Usage: + + * `module:multiactivate [--shopId SHOPID] [-s|--skipDeactivation] [-c|--skipClear] [--] ` + +usage: +oxrun module:multiactivate configs/modules.yml +- to activate all modules defined in the file "configs/modules.yml" based +on a white- or blacklist + +Example: + +```yaml +whitelist: +1: + - ocb_cleartmp + - moduleinternals + #- ddoevisualcms + #- ddoewysiwyg +2: + - ocb_cleartmp +``` + +Supports either a __"whitelist"__ or a __"blacklist"__ entry with multiple shop ids and the desired module ids to activate (whitelist) or to exclude from activation (blacklist). + +If you want, you can also specify __a YAML string on the command line instead of a file__, e.g.: + +```bash +../vendor/bin/oxrun module:multiactivate $'whitelist: + 1: + - oepaypal +' --shopId=1 +``` + +### Arguments: + +**module:** + +* Name: module +* Description: YAML module list filename or YAML string + +### Options: + +**shopId:** + +* Name: `--shopId` +* Is value required: yes +* Description: The shop id. + +**skipDeactivation:** + +* Name: `--skipDeactivation` +* Shortcut: `-s` +* Accept value: no +* Is value required: no +* Description: Skip deactivation of modules, only activate. +* Default: `false` + +**skipClear:** + +* Name: `--skipClear` +* Shortcut: `-c` +* Accept value: no +* Is value required: no +* Description: Skip cache clearing. +* Default: `false` + module:list ----------- * Description: Lists all modules -* Usage: `module:list` +* Usage: + + * `module:list [--shopId [SHOPID]]` + +Lists all modules + +### Options: + +**shopId:** + +* Name: `--shopId` +* Is value required: no +* Description: + +module:activate +--------------- + +* Description: Activates a module +* Usage: + + * `module:activate [--shopId [SHOPID]] [--] ` + +Activates a module + +### Arguments: + +**module:** + +* Name: module +* Description: Module name ### Options: +**shopId:** + +* Name: `--shopId` +* Is value required: no +* Description: + +module:deactivate +----------------- + +* Description: Deactivates a module +* Usage: + + * `module:deactivate [--shopId [SHOPID]] [--] ` + +Deactivates a module + +### Arguments: + +**module:** + +* Name: module +* Description: Module name + +### Options: + +**shopId:** + +* Name: `--shopId` +* Is value required: no +* Description: + +module:reload +------------- + +* Description: Deactivate and activate a module +* Usage: + + * `module:reload [--shopId [SHOPID]] [--] ` + +Deactivate and activate a module + +### Arguments: + +**module:** + +* Name: module +* Description: Module name + +### Options: + +**shopId:** + +* Name: `--shopId` +* Is value required: no +* Description: + +module:fix +---------- + +* Description: Fixes a module __[NOT IMPLEMENTED YET]__ +* Usage: + + * `module:fix [--shopId [SHOPID]] [--] ` + +Fixes a module __[NOT IMPLEMENTED YET]__ + +### Arguments: + +**module:** + +* Name: module +* Description: Module name + +### Options: + +**shopId:** + +* Name: `--shopId` +* Is value required: no +* Description: + user:password ------------- * Description: Sets a new password -* Usage: `user:password username password` +* Usage: + + * `user:password ` + +Sets a new password ### Arguments: @@ -463,8 +877,66 @@ user:password ### Options: +cms:update +---------- + +* Description: Updates a cms page +* Usage: + + * `cms:update [--title [TITLE]] [--content [CONTENT]] [--language LANGUAGE] [--active ACTIVE] [--] ` + +Updates a cms page + +### Arguments: + +**ident:** + +* Name: ident +* Description: Content ident + +### Options: + +**title:** + +* Name: `--title` +* Is value required: no +* Description: Content title + +**content:** + +* Name: `--content` +* Is value required: no +* Description: Content body + +**language:** + +* Name: `--language` +* Is value required: yes +* Description: Content language + +**active:** + +* Name: `--active` +* Is value required: yes +* Description: Content active + views:update ------------ * Description: Updates the views -* Usage: `views:update` +* Usage: + + * `views:update` + +Updates the views + +### Options: + + +# Run the unit tests + +The unit tests require a configured shop and a database. To start the tests, run the following command __in the "source" folder of your OXID 6 installation__ and set the correct path to the "oxrun" vendor directory, e.g.: + +```bash +../vendor/bin/phpunit /var/www/html/oxid6/vendor/smxsm/oxrun/ +``` diff --git a/composer.json b/composer.json index fefeebb..d6293cb 100644 --- a/composer.json +++ b/composer.json @@ -2,6 +2,7 @@ "name": "marcharding/oxrun", "description": "Oxrun provides a cli toolset for the OXID eShop Community Edition", "license": "MIT", + "version": "v0.2.2", "support": { "issues": "https://github.com/marcharding/oxrun/issues" }, @@ -12,9 +13,10 @@ "cli" ], "require": { - "symfony/console": "2.7.*", - "symfony/event-dispatcher":"2.7.*", - "symfony/finder":"2.7.*", + "symfony/console": "2.8.*", + "symfony/event-dispatcher":"2.8.*", + "symfony/finder":"2.8.*", + "symfony/yaml":"2.8.*", "guzzlehttp/guzzle": "^5.0", "raulfraile/distill": "0.9.*", "nikic/php-parser": "1.4.*" @@ -39,6 +41,14 @@ { "name":"Stefan Krenz", "email":"info@kyoya.de" + }, + { + "name":"Tobias Matthaiou", + "email":"matthaiou@tobimat.eu" + }, + { + "name":"Stefan Moises", + "email":"moises@shoptimax.de" } ], "bin": ["bin/oxrun"] diff --git a/malls.yml.dist b/malls.yml.dist new file mode 100644 index 0000000..20651b4 --- /dev/null +++ b/malls.yml.dist @@ -0,0 +1,28 @@ +config: + 1: + blReverseProxyActive: + variableType: bool + variableValue: false + # simple string type + sMallShopURL: http://myshop.dev.local + sMallSSLShopURL: http://myshop.dev.local + myMultiVal: + variableType: aarr + variableValue: + - /foo/bar/ + - /bar/foo/ + # optional module id + moduleId: my_module + 2: + blReverseProxyActive: + variableType: bool + variableValue: false + sMallShopURL: http://myshop2.dev.local + sMallSSLShopURL: http://myshop2.dev.local + myMultiVal: + variableType: aarr + variableValue: + - /foo/bar/ + - /bar/foo/ + # optional module id + moduleId: my_module diff --git a/modules.yml.dist b/modules.yml.dist new file mode 100644 index 0000000..6c9af9d --- /dev/null +++ b/modules.yml.dist @@ -0,0 +1,6 @@ +whitelist: + 1: + - ocb_cleartmp + - moduleinternals + 2: + - ocb_cleartmp diff --git a/oxrun.phar b/oxrun.phar old mode 100755 new mode 100644 index 12bd586..2e08ec1 Binary files a/oxrun.phar and b/oxrun.phar differ diff --git a/src/Oxrun/Application.php b/src/Oxrun/Application.php index 1372045..9f529b2 100644 --- a/src/Oxrun/Application.php +++ b/src/Oxrun/Application.php @@ -4,7 +4,7 @@ use Composer\Autoload\ClassLoader; use Oxrun\Command\Custom; -use Oxrun\Helper\DatenbaseConnection; +use Oxrun\Helper\DatabaseConnection; use Symfony\Component\Console\Application as BaseApplication; use Symfony\Component\Console\Command\HelpCommand; use Symfony\Component\Console\Input\ArgvInput; @@ -44,14 +44,19 @@ class Application extends BaseApplication protected $oxidConfigContent; /** - * @var DatenbaseConnection + * @var databaseConnection */ - protected $datenbaseConnection = null; + protected $databaseConnection = null; /** - * @param ClassLoader $autoloader - * @param string $name - * @param string $version + * @var string + */ + protected $oxid_version = "0.0.0"; + + /** + * @param ClassLoader $autoloader The composer autoloader + * @param string $name + * @param string $version */ public function __construct($autoloader = null, $name = 'UNKNOWN', $version = 'UNKNOWN') { @@ -64,7 +69,10 @@ public function __construct($autoloader = null, $name = 'UNKNOWN', $version = 'U */ protected function getDefaultCommands() { - return array(new HelpCommand(), new Custom\ListCommand()); + return array( + new HelpCommand(), + new Custom\ListCommand(), + ); } @@ -111,11 +119,12 @@ public function bootstrapOxid($blNeedDBConnection = true) * * @return bool */ - protected function findBootstrapFile() { + protected function findBootstrapFile() + { $input = new ArgvInput(); - if($input->getParameterOption('--shopDir')) { + if ($input->getParameterOption('--shopDir')) { $oxBootstrap = $input->getParameterOption('--shopDir'). '/bootstrap.php'; - if( $this->checkBootstrapOxidInclude( $oxBootstrap ) === true ) { + if ($this->checkBootstrapOxidInclude($oxBootstrap) === true ) { return true; } return false; @@ -125,7 +134,7 @@ protected function findBootstrapFile() { $currentWorkingDirectory = getcwd(); do { $oxBootstrap = $currentWorkingDirectory . '/bootstrap.php'; - if( $this->checkBootstrapOxidInclude( $oxBootstrap ) === true ) { + if ($this->checkBootstrapOxidInclude($oxBootstrap) === true ) { return true; break; } @@ -138,7 +147,8 @@ protected function findBootstrapFile() { * Check if bootstrap file exists * * @param String $oxBootstrap Path to oxid bootstrap.php - * @param bool $skipViews Add 'blSkipViewUsage' to OXIDs config. + * @param bool $skipViews Add 'blSkipViewUsage' to OXIDs config. + * * @return bool */ public function checkBootstrapOxidInclude($oxBootstrap) @@ -148,7 +158,7 @@ public function checkBootstrapOxidInclude($oxBootstrap) if (strpos(file_get_contents($oxBootstrap), 'OX_BASE_PATH') !== false) { $this->shopDir = dirname($oxBootstrap); - require_once $oxBootstrap; + include_once $oxBootstrap; // If we've an autoloader we must re-register it to avoid conflicts with a composer autoloader from shop if (null !== $this->autoloader) { @@ -165,13 +175,20 @@ public function checkBootstrapOxidInclude($oxBootstrap) /** - * @return string + * @return mixed|string + * @throws \Exception */ public function getOxidVersion() { - $oxConfig = oxNew('oxConfig'); - $pkgInfo = parse_ini_file($oxConfig->getConfigParam('sShopDir') . 'pkg.info'); - return $pkgInfo['version']; + if ($this->oxid_version != '0.0.0') { + return $this->oxid_version; + } + + if ($this->findVersionOnOxidLegacy() == false) { + $this->findVersionOnOxid6(); + } + + return $this->oxid_version; } /** @@ -196,29 +213,136 @@ public function canConnectToDB() if ($this->shopDir && file_exists($configfile)) { $oxConfigFile = new \OxConfigFile($configfile); - $datenbaseConnection = $this->getDatenbaseConnection(); - $datenbaseConnection + $databaseConnection = $this->getDatabaseConnection(); + $databaseConnection ->setHost($oxConfigFile->getVar('dbHost')) ->setUser($oxConfigFile->getVar('dbUser')) ->setPass($oxConfigFile->getVar('dbPwd')) ->setDatabase($oxConfigFile->getVar('dbName')); - return $this->hasDBConnection = $datenbaseConnection->canConnectToMysql(); + return $this->hasDBConnection = $databaseConnection->canConnectToMysql(); } return $this->hasDBConnection = false; } /** - * @return DatenbaseConnection + * @return DatabaseConnection */ - public function getDatenbaseConnection() + public function getDatabaseConnection() { - if ($this->datenbaseConnection === null) { - $this->datenbaseConnection = new DatenbaseConnection(); + if ($this->databaseConnection === null) { + $this->databaseConnection = new DatabaseConnection(); } - return $this->datenbaseConnection; + return $this->databaseConnection; } + /** + * Completely switch shop + * + * @param string $shopId The shop id + * + * @return void + */ + public function switchToShopId($shopId) + { + $oxidVersion = $this->getOxidVersion(); + if (version_compare($oxidVersion, '4.9.0') < 0) { + // old OXID versions + $oConfig = \OxidEsales\Eshop\Core\Registry::getConfig(); + $oConfig->setShopId($shopId); + \OxidEsales\Eshop\Core\Registry::set('oxConfig', $oConfig); + return; + } + + $_POST['shp'] = $shopId; + $_POST['actshop'] = $shopId; + + $keepThese = [\OxidEsales\Eshop\Core\ConfigFile::class]; + $registryKeys = \OxidEsales\Eshop\Core\Registry::getKeys(); + foreach ($registryKeys as $key) { + if (in_array($key, $keepThese)) { + continue; + } + \OxidEsales\Eshop\Core\Registry::set($key, null); + } + + $utilsObject = new \OxidEsales\Eshop\Core\UtilsObject; + $utilsObject->resetInstanceCache(); + \OxidEsales\Eshop\Core\Registry::set(\OxidEsales\Eshop\Core\UtilsObject::class, $utilsObject); + + \OxidEsales\Eshop\Core\Module\ModuleVariablesLocator::resetModuleVariables(); + \OxidEsales\Eshop\Core\Registry::getSession()->setVariable('shp', $shopId); + + //ensure we get rid of all instances of config, even the one in Core\Base + \OxidEsales\Eshop\Core\Registry::set(\OxidEsales\Eshop\Core\Config::class, null); + \OxidEsales\Eshop\Core\Registry::getConfig()->setConfig(null); + \OxidEsales\Eshop\Core\Registry::set(\OxidEsales\Eshop\Core\Config::class, null); + + $moduleVariablesCache = new \OxidEsales\Eshop\Core\FileCache(); + $shopIdCalculator = new \OxidEsales\Eshop\Core\ShopIdCalculator($moduleVariablesCache); + + if (($shopId != $shopIdCalculator->getShopId()) + || ($shopId != \OxidEsales\Eshop\Core\Registry::getConfig()->getShopId()) + ) { + throw new \Exception('Failed to switch to subshop id ' . $shopId . " Calculate ID: " . $shopIdCalculator->getShopId() . " Config ShopId: " . \OxidEsales\Eshop\Core\Registry::getConfig()->getShopId()); + } + } + + /** + * Get YAML string, either from file or from string + * + * @param string $ymlString The relative file path, from shop root OR a YAML string + * @param string $basePath Alternative root dir path, if a file is used + * + * @return string + */ + public function getYaml($ymlString, $basePath = '') + { + // is it a file? + if (strpos(strtolower($ymlString), '.yml') !== false + || strpos(strtolower($ymlString), '.yaml') !== false + ) { + if ($basePath == '') { + $basePath = $this->getShopDir() . DIRECTORY_SEPARATOR; + } + $ymlFile = $basePath . $ymlString; + if (file_exists($ymlFile)) { + $ymlString = file_get_contents($ymlFile); + } + } + + return $ymlString; + } + + + /** + * Find Version on Place into Oxid Legacy Code + * + * @return bool + */ + protected function findVersionOnOxidLegacy() + { + $pkgInfo = $this->getShopDir() . DIRECTORY_SEPARATOR . 'pkg.info'; + if (file_exists($pkgInfo)) { + $pkgInfo = parse_ini_file($pkgInfo); + $this->oxid_version = $pkgInfo['version']; + return true; + } + return false; + } + + /** + * Find Version up to OXID 6 Version + * @throws \Exception + */ + protected function findVersionOnOxid6() + { + if (!class_exists('OxidEsales\\Eshop\\Core\\ShopVersion')) { + throw new \Exception('Can\'t find Shop Version. Maybe run OXID `Unified Namespace Generator` with composer'); + } + + $this->oxid_version = \OxidEsales\Eshop\Core\ShopVersion::getVersion(); + } } diff --git a/src/Oxrun/Command/Cms/UpdateCommand.php b/src/Oxrun/Command/Cms/UpdateCommand.php index 563a614..5b2b6a8 100644 --- a/src/Oxrun/Command/Cms/UpdateCommand.php +++ b/src/Oxrun/Command/Cms/UpdateCommand.php @@ -38,7 +38,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $oxContent = oxNew('oxcontent'); + $oxContent = oxNew(\OxidEsales\Eshop\Application\Model\Content::class); $oxContent->loadByIdent($input->getArgument('ident')); if (!$oxContent) { @@ -49,13 +49,13 @@ protected function execute(InputInterface $input, OutputInterface $output) if ($input->getOption('language') !== false) { $language = $input->getOption('language'); } else { - $language = \oxRegistry::getLang()->getBaseLanguage(); + $language = \OxidEsales\Eshop\Core\Registry::getLang()->getBaseLanguage(); } $oxContent->setLanguage($language); if ($input->getOption('title')) { - $oxContent->oxcontents__oxtitle = new \oxField($input->getOption('title')); + $oxContent->oxcontents__oxtitle = new \OxidEsales\Eshop\Core\Field($input->getOption('title')); } if ($input->getOption('content')) { @@ -64,11 +64,11 @@ protected function execute(InputInterface $input, OutputInterface $output) } else { $content = $input->getOption('content'); } - $oxContent->oxcontents__oxcontent = new \oxField($content); + $oxContent->oxcontents__oxcontent = new \OxidEsales\Eshop\Core\Field($content); } if ($input->getOption('active')) { - $oxContent->oxcontents__oxactive = new \oxField($input->getOption('active')); + $oxContent->oxcontents__oxactive = new \OxidEsales\Eshop\Core\Field($input->getOption('active')); } if ($oxContent->save()) { $output->writeLn("Content with ident {$input->getArgument('ident')} updated."); diff --git a/src/Oxrun/Command/Config/ExportCommand.php b/src/Oxrun/Command/Config/ExportCommand.php new file mode 100644 index 0000000..7f6a309 --- /dev/null +++ b/src/Oxrun/Command/Config/ExportCommand.php @@ -0,0 +1,79 @@ +setName('config:export') + ->setDescription('Export shop config') + ->addOption( + 'no-debug', + null, //can not use n + InputOption::VALUE_NONE, + 'No debug ouput', + null + ) + ->addOption( + 'env', + null, + InputOption::VALUE_OPTIONAL, + 'set specific environment, corresponds to a specific folder for the yaml files', + null + ) + ->addOption( + 'force-cleanup', + null, + InputOption::VALUE_OPTIONAL, + 'Force cleanup on error', + null + ); +$help = <<Info: +Exports all config values to yaml files, interacts with the +[Modules Config](https://github.com/OXIDprojects/oxid_modules_config/) module, +[__which currently isn't fully ported to OXID 6 yet!__](https://github.com/OXIDprojects/oxid_modules_config/tree/dev-6.0-wip) +HELP; + $this->setHelp($help); + } + + /** + * Executes the current command. + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $oConfigExport = new ConfigExport(); + $oConfigExport->initialize($input, $output); + $oConfigExport->execute($input, $output); + } + + /** + * @return bool + */ + public function isEnabled() + { + return $this->getApplication()->bootstrapOxid(); + } + +} \ No newline at end of file diff --git a/src/Oxrun/Command/Config/GetCommand.php b/src/Oxrun/Command/Config/GetCommand.php index d4a0015..30479e7 100755 --- a/src/Oxrun/Command/Config/GetCommand.php +++ b/src/Oxrun/Command/Config/GetCommand.php @@ -36,7 +36,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $oxConfig = oxNew('oxConfig'); + $oxConfig = oxNew(\OxidEsales\Eshop\Core\Config::class); $shopConfVar = $oxConfig->getShopConfVar( $input->getArgument('variableName'), $input->getOption('shopId'), @@ -45,7 +45,7 @@ protected function execute(InputInterface $input, OutputInterface $output) if (is_array($shopConfVar)) { $shopConfVar = json_encode($shopConfVar, true); } - if( empty($shopConfVar)){ + if (empty($shopConfVar)) { $shopConfVar = 0; } $output->writeln("{$input->getArgument('variableName')} has value {$shopConfVar}"); diff --git a/src/Oxrun/Command/Config/ImportCommand.php b/src/Oxrun/Command/Config/ImportCommand.php new file mode 100644 index 0000000..fd52d6f --- /dev/null +++ b/src/Oxrun/Command/Config/ImportCommand.php @@ -0,0 +1,79 @@ +setName('config:import') + ->setDescription('Import shop config') + ->addOption( + 'no-debug', + null, //can not use n + InputOption::VALUE_NONE, + 'No debug ouput', + null + ) + ->addOption( + 'env', + null, + InputOption::VALUE_OPTIONAL, + 'set specific environment, corresponds to a specific folder for the yaml files', + null + ) + ->addOption( + 'force-cleanup', + null, + InputOption::VALUE_OPTIONAL, + 'Force cleanup on error', + null + ); +$help = <<Info: +Imports all config values from yaml files, interacts with the +[Modules Config](https://github.com/OXIDprojects/oxid_modules_config/) module, +[__which currently isn't fully ported to OXID 6 yet!__](https://github.com/OXIDprojects/oxid_modules_config/tree/dev-6.0-wip) +HELP; + $this->setHelp($help); + } + + /** + * Executes the current command. + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $oConfigExport = new ConfigImport(); + $oConfigExport->initialize($input, $output); + $oConfigExport->execute($input, $output); + } + + /** + * @return bool + */ + public function isEnabled() + { + return $this->getApplication()->bootstrapOxid(); + } + +} \ No newline at end of file diff --git a/src/Oxrun/Command/Config/MultiSetCommand.php b/src/Oxrun/Command/Config/MultiSetCommand.php new file mode 100644 index 0000000..96d9955 --- /dev/null +++ b/src/Oxrun/Command/Config/MultiSetCommand.php @@ -0,0 +1,135 @@ +setName('config:multiset') + ->setDescription('Sets multiple config values from yaml file') + ->addArgument('configfile', InputArgument::REQUIRED, 'The file containing the config values, see malls.yml.dist. The file path is relative to the shop root. You can also pass a YAML string on the command line.'); + +$help = <<YAML example: +```yaml +config: + 1: + blReverseProxyActive: + variableType: bool + variableValue: false + # simple string type + sMallShopURL: http://myshop.dev.local + sMallSSLShopURL: http://myshop.dev.local + myMultiVal: + variableType: aarr + variableValue: + - /foo/bar/ + - /bar/foo/ + # optional module id + moduleId: my_module + 2: + blReverseProxyActive: +... +``` + +If you want, you can also specify __a YAML string on the command line instead of a file__, e.g.: + +```bash +../vendor/bin/oxrun module:multiset $'config:\n 1:\n foobar: barfoo\n' --shopId=1 +``` +HELP; + $this->setHelp($help); + + } + + /** + * Executes the current command. + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + // do not use the registry pattern (\OxidEsales\Eshop\Core\Registry::getConfig()) here, so we do not have any caches (breaks unit tests) + $oxConfig = oxNew(\OxidEsales\Eshop\Core\Config::class); + + /* @var \Oxrun\Application $app */ + $app = $this->getApplication(); + + // now try to read YAML + $mallYml = $app->getYaml($input->getArgument('configfile')); + $mallValues = Yaml::parse($mallYml); + + if ($mallValues && is_array($mallValues['config'])) { + $mallSettings = $mallValues['config']; + foreach ($mallSettings as $shopId => $configData) { + foreach ($configData as $configKey => $configValue) { + $moduleId = ''; + if (!is_array($configValue)) { + // assume simple string + $variableType = 'str'; + $variableValue = $configValue; + } else { + $variableType = $configValue['variableType']; + $variableValue = $configValue['variableValue']; + if (isset($configValue['moduleId'])) { + $moduleId = $configValue['moduleId']; + } + } + $oxConfig->saveShopConfVar( + $variableType, + $configKey, + $variableValue, + $shopId, + $moduleId + ); + $output->writeln("Config {$configKey} for shop {$shopId} set to " . print_r($variableValue, true) . ""); + } + } + } + } + + /** + * @return bool + */ + public function isEnabled() + { + return $this->getApplication()->bootstrapOxid(); + } + +} \ No newline at end of file diff --git a/src/Oxrun/Command/Config/SetCommand.php b/src/Oxrun/Command/Config/SetCommand.php index 6e61ffd..3b659f1 100755 --- a/src/Oxrun/Command/Config/SetCommand.php +++ b/src/Oxrun/Command/Config/SetCommand.php @@ -38,8 +38,8 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - // do not use the registry pattern (\oxRegistry::getConfig()) here, so we do not have any caches (breaks unit tests) - $oxConfig = oxNew('oxConfig'); + // do not use the registry pattern (\OxidEsales\Eshop\Core\Registry::getConfig()) here, so we do not have any caches (breaks unit tests) + $oxConfig = oxNew(\OxidEsales\Eshop\Core\Config::class); // determine variable type if ($input->getOption('variableType')) { @@ -47,9 +47,9 @@ protected function execute(InputInterface $input, OutputInterface $output) } else { $sql = sprintf( "SELECT `oxconfig`.`OXVARTYPE` FROM `oxconfig` WHERE `oxconfig`.`OXVARNAME` = %s", - \oxDb::getDb()->quote($input->getArgument('variableName')) + \OxidEsales\Eshop\Core\DatabaseProvider::getDb()->quote($input->getArgument('variableName')) ); - $variableType = \oxDb::getDb()->getOne($sql); + $variableType = \OxidEsales\Eshop\Core\DatabaseProvider::getDb()->getOne($sql); } if (in_array($variableType, array('aarr', 'arr'))) { diff --git a/src/Oxrun/Command/Config/ShopGetCommand.php b/src/Oxrun/Command/Config/ShopGetCommand.php index 6ce53f6..71509fd 100644 --- a/src/Oxrun/Command/Config/ShopGetCommand.php +++ b/src/Oxrun/Command/Config/ShopGetCommand.php @@ -36,7 +36,7 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { // Shop config - $oxShop = oxNew('oxShop'); + $oxShop = oxNew(\OxidEsales\Eshop\Application\Model\Shop::class); $oxShop->load($input->getOption('shopId')); $varibaleValue = $oxShop->{'oxshops__' . $input->getArgument('variableName')}->value; $output->writeln("Config {$input->getArgument('variableName')} has value $varibaleValue"); diff --git a/src/Oxrun/Command/Config/ShopSetCommand.php b/src/Oxrun/Command/Config/ShopSetCommand.php index 54c39a7..982af97 100644 --- a/src/Oxrun/Command/Config/ShopSetCommand.php +++ b/src/Oxrun/Command/Config/ShopSetCommand.php @@ -36,7 +36,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $oxShop = oxNew('oxShop'); + $oxShop = oxNew(\OxidEsales\Eshop\Application\Model\Shop::class); $oxShop->load($input->getOption('shopId')); $oxShop->assign(array('oxshops__' . $input->getArgument('variableName') => $input->getArgument('variableValue'))); $oxShop->save(); diff --git a/src/Oxrun/Command/Custom/ListCommand.php b/src/Oxrun/Command/Custom/ListCommand.php index 003443d..6ddb6b9 100644 --- a/src/Oxrun/Command/Custom/ListCommand.php +++ b/src/Oxrun/Command/Custom/ListCommand.php @@ -28,7 +28,7 @@ protected function checkDatabase(Application $application, OutputInterface $outp if ($application->bootstrapOxid(false) && $application->canConnectToDB() == false) { $output->writeln(''); $output->writeln(' Can\'t connect to Database. Most of the Commands are disabled '); - $output->writeln(' Error Message: ' . $application->getDatenbaseConnection()->getLastErrorMsg() . ''); + $output->writeln(' Error Message: ' . $application->getDatabaseConnection()->getLastErrorMsg() . ''); } } } \ No newline at end of file diff --git a/src/Oxrun/Command/Database/DumpCommand.php b/src/Oxrun/Command/Database/DumpCommand.php index 5979f42..53cb7c7 100644 --- a/src/Oxrun/Command/Database/DumpCommand.php +++ b/src/Oxrun/Command/Database/DumpCommand.php @@ -3,8 +3,6 @@ namespace Oxrun\Command\Database; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -15,6 +13,30 @@ */ class DumpCommand extends Command { + /** + * Tables with no contents + * + * @var array + */ + protected $anonymousTables = [ + 'oxseo', + 'oxseologs', + 'oxseohistory', + 'oxuser', + 'oxuserbasketitems', + 'oxuserbaskets', + 'oxuserpayments', + 'oxnewssubscribed', + 'oxremark', + 'oxvouchers', + 'oxvoucherseries', + 'oxaddress', + 'oxorder', + 'oxorderarticles', + 'oxorderfiles', + 'oepaypal_order', + 'oepaypal_orderpayments', + ]; /** * Configures the current command. @@ -24,13 +46,62 @@ protected function configure() $this ->setName('db:dump') ->setDescription('Dumps the the current shop database') - ->addOption('file', null, InputOption::VALUE_REQUIRED, 'Dump sql in to this file') - ->addOption('ignoreViews', null, InputOption::VALUE_NONE, 'Ignore views'); + ->addOption( + 'file', + null, + InputOption::VALUE_REQUIRED, + 'Dump sql in to this file' + ) + ->addOption( + 'table', + 't', + InputOption::VALUE_REQUIRED, + 'name of table to dump only. Default all tables. Use comma separated list and or pattern e.g. %voucher%' + ) + ->addOption( + 'ignoreViews', + 'i', + InputOption::VALUE_NONE, + 'Ignore views' + ) + ->addOption( + 'anonymous', + 'a', + InputOption::VALUE_NONE, + 'Do not export table with person related data.' + ) + ->addOption( + 'withoutTableData', + 'w', + InputOption::VALUE_REQUIRED, + 'Table name to dump without data. Use comma separated list and or pattern e.g. %voucher%' + ); + $anonymousTables= implode('`, `', $this->anonymousTables); $help = <<usage: + oxrun {$this->getName()} --withoutTableData oxseo,oxvou% + - To dump all Tables, but `oxseo`, `oxvoucher`, and `oxvoucherseries` without data. + possibilities: oxseo%,oxuser,%logs% + + oxrun {$this->getName()} --table %user% + - to dump only those tables `oxuser` `oxuserbasketitems` `oxuserbaskets` `oxuserpayments` + + oxrun {$this->getName()} --anonymous # Perfect for Stage Server + - Those table without data: `{$anonymousTables}`. + + oxrun {$this->getName()} -v + - With verbose mode you will see the mysqldump command + (`mysqldump -u 'root' -h 'oxid_db' -p ... `) + + oxrun {$this->getName()} --file dump.sql + - Put the Output into a File + +** Only existing tables will be exported. No matter what was required. + +Requires php, exec and MySQL CLI tools installed on your system. HELP; $this->setHelp($help); } @@ -43,60 +114,246 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - // allow empty password - $dbPwd = \oxRegistry::getConfig()->getConfigParam('dbPwd'); + $tablesNoData = $ignoreTables = $explicatedTable = []; + $canDumpTables = true; + + $file = $input->getOption('file'); + $dbName = \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbName'); + + if ($input->getOption('ignoreViews')) { + $viewsResultArray = \OxidEsales\Eshop\Core\DatabaseProvider::getDb()->getAll("SHOW FULL TABLES IN {$dbName} WHERE TABLE_TYPE LIKE 'VIEW'"); + if (is_array($viewsResultArray)) { + foreach ($viewsResultArray as $sqlRow) { + $ignoreTables[] = $sqlRow[0]; + } + } + } + + if ($input->getOption('anonymous')) { + $ignoreTables = array_merge($ignoreTables, $this->anonymousTables); + $tablesNoData = array_merge($tablesNoData, $this->anonymousTables); + } + + if ($input->getOption('withoutTableData')) { + $argvData = $input->getOption('withoutTableData'); + $argvData = explode(',', $argvData); + + $ignoreTables = array_merge($ignoreTables, $argvData); + $tablesNoData = array_merge($tablesNoData, $argvData); + } + + if ($input->getOption('table')) { + $argvData = $input->getOption('table'); + $argvData = explode(',', $argvData); + $explicatedTable = $this->filterValidTables($argvData); + if (empty($explicatedTable)) { + $output->writeln('No table found: `'. $input->getOption('table').'`'); + exit(2); + } + $ignoreTables = []; + } + + if (!empty($tablesNoData)) { + $tables = $this->filterValidTables($tablesNoData); + + if (!empty($explicatedTable)) { + $tables = array_intersect($tables, $explicatedTable); + $explicatedTable = array_diff($explicatedTable, $tables); + if (empty($explicatedTable)) { + $canDumpTables = false; + } + } + + if (!empty($tables)) { + $tablesNoData = array_map('escapeshellarg', $tables); + $tablesNoData = implode(' ', $tablesNoData); + + $commandOnlyTable = $this->getMysqlDumpCommand() . ' ' . $tablesNoData; + $commandOnlyTable = sprintf($commandOnlyTable, ' --no-data'); + if ($file) { + $commandOnlyTable .= " > $file"; + } + } + } + + if ($ignoreTables) { + $tables = $this->filterValidTables($ignoreTables); + $ignoreTables = $this->addCommandFlag('--ignore-table=' . $dbName, $tables); + } + + $ignoreTables = implode(' ', $ignoreTables); + + $commandTable = $this->getMysqlDumpCommand(); + $commandTable = sprintf($commandTable, $ignoreTables); + if (!empty($explicatedTable)) { + $explicatedTable = array_map('escapeshellarg', $explicatedTable); + $commandTable .= implode(' ', $explicatedTable); + } + if ($file) { + $saveOperator = !empty($tablesNoData) ? '>>' : '>'; + $commandTable .= " $saveOperator $file"; + } + + if (isset($commandOnlyTable)) { + $output->writeln("-- Dump Tables without data ..."); + if ($output->getVerbosity() > $output::VERBOSITY_NORMAL) { + $output->writeln('-- ' . $this->hiddePwd($commandOnlyTable) . ''); + } + $this->executeCommand($input, $output, $commandOnlyTable); + } + + if ($canDumpTables) { + $output->writeln("-- Dump Tables ..."); + if ($output->getVerbosity() > $output::VERBOSITY_NORMAL) { + $output->writeln('-- ' . $this->hiddePwd($commandTable) . ''); + } + $this->executeCommand($input, $output, $commandTable); + } + } + + + /** + * Get the mysqldump cli command with user credentials. + * + * @return string + */ + protected function getMysqlDumpCommand() + { + $dbHost = \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbHost'); + $dbUser = \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbUser'); + $dbName = \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbName'); + + $dbPwd = \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbPwd'); if (!empty($dbPwd)) { - $dbPwd = '-p' . $dbPwd; + $dbPwd = ' -p' . $dbPwd; } - $file = $input->getOption('file'); - if (!empty($file)) { - $file = "--result-file=" . $file; - } else { - $file = ""; + $utfMode = ''; + if (\OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('iUtfMode')) { + $utfMode = ' --default-character-set=utf8'; + } + + $mysqldump = 'mysqldump' . + ' -u ' . escapeshellarg($dbUser) . + ' -h ' . escapeshellarg($dbHost) . + $dbPwd . + ' --force' . + ' --quick' . + ' --opt' . + ' --hex-blob' . + $utfMode . + ' %s ' . // argumment part + $dbName . + ' '; // bash part + + return $mysqldump; + } + + /** + * @return bool + */ + public function isEnabled() + { + return function_exists('exec') && $this->getApplication()->bootstrapOxid(); + } + + /** + * @param string $flag + * @param array $tables + * + * @return array + */ + protected function addCommandFlag($flag, $tables) + { + $flagged = []; + + foreach ($tables as $name) { + $flagged[] = $flag . '.' . $name; } - if($input->getOption('ignoreViews')) { - $dbName = \oxRegistry::getConfig()->getConfigParam('dbName'); - $viewsResultArray = \oxDb::getDb()->getArray("SHOW FULL TABLES IN {$dbName} WHERE TABLE_TYPE LIKE 'VIEW'"); - $ignoreViewTables = array(); - foreach($viewsResultArray as $viewArray) { - $ignoreViewTables[] = '--ignore-table=' . $dbName . '.' . $viewArray[0]; + return $flagged; + } + + /** + * @param array $tables + * @return array + */ + protected function filterValidTables($tables) + { + $whereIN = $whereLIKE = []; + + $dbName = \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbName'); + + foreach ($tables as $name) { + if (preg_match('/[%*]/', $name)) { + $name = str_replace(['_','*'], ['\\_', '%'], $name); + $whereLIKE[] = $name; + } else { + $whereIN[] = $name; } - $ignoreViewTables = implode(' ', $ignoreViewTables); } - $exec = sprintf( - "mysqldump -h%s %s -u%s %s %s %s 2>&1", - \oxRegistry::getConfig()->getConfigParam('dbHost'), - $dbPwd, - \oxRegistry::getConfig()->getConfigParam('dbUser'), - \oxRegistry::getConfig()->getConfigParam('dbName'), - $ignoreViewTables, - $file + $whereIN = implode("', '", $whereIN); + $conditionsIN = "Tables_in_{$dbName} IN ('{$whereIN}')"; + + $conditionsLIKE = ''; + if (!empty($whereLIKE)) { + $template = " OR Tables_in_{$dbName} LIKE ('%s')"; + foreach ($whereLIKE as $tablename) { + $conditionsLIKE .= sprintf($template, $tablename); + } + } + + $sqlstament = "SHOW FULL TABLES IN {$dbName} WHERE $conditionsIN $conditionsLIKE"; + + $result = \OxidEsales\Eshop\Core\DatabaseProvider::getDb()->getAll($sqlstament); + + $existsTable = array_map( + function ($row) { + return $row[0]; + }, $result ); + return $existsTable; + } - exec($exec, $commandOutput, $returnValue); + /** + * @param InputInterface $input + * @param OutputInterface $output + * @param $commandExportData + * @param $returnValue + * @param $commandOutput + * @param $file + */ + protected function executeCommand(InputInterface $input, OutputInterface $output, $command) + { + $error_file = tempnam(sys_get_temp_dir(), 'oxrun'); + $command .= ' 2>'.$error_file; + + exec($command, $commandOutput, $returnValue); if ($returnValue > 0) { - $output->writeln('' . implode(PHP_EOL, $commandOutput) . ''); + $output->writeln('' . file_get_contents($error_file) . ''); + @unlink($error_file); return; } + $file = $input->getOption('file'); if (!empty($file)) { - $output->writeln("Dump {$input->getOption('file')} created."); + $output->writeln("Dump {$file} created."); } else { $output->writeln($commandOutput); } - + @unlink($error_file); } /** - * @return bool + * @param $command + * @return mixed */ - public function isEnabled() + protected function hiddePwd($command) { - return function_exists('exec') && $this->getApplication()->bootstrapOxid(); + return preg_replace('/-p[^ ]+/', '-p', $command); } -} \ No newline at end of file +} + diff --git a/src/Oxrun/Command/Database/ImportCommand.php b/src/Oxrun/Command/Database/ImportCommand.php index 952375a..39436fc 100644 --- a/src/Oxrun/Command/Database/ImportCommand.php +++ b/src/Oxrun/Command/Database/ImportCommand.php @@ -48,17 +48,17 @@ protected function execute(InputInterface $input, OutputInterface $output) } // allow empty password - $dbPwd = \oxRegistry::getConfig()->getConfigParam('dbPwd'); + $dbPwd = \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbPwd'); if (!empty($dbPwd)) { $dbPwd = '-p' . $dbPwd; } $exec = sprintf( "mysql -h%s %s -u%s %s < %s 2>&1", - \oxRegistry::getConfig()->getConfigParam('dbHost'), + \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbHost'), $dbPwd, - \oxRegistry::getConfig()->getConfigParam('dbUser'), - \oxRegistry::getConfig()->getConfigParam('dbName'), + \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbUser'), + \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbName'), $file ); diff --git a/src/Oxrun/Command/Database/ListCommand.php b/src/Oxrun/Command/Database/ListCommand.php new file mode 100644 index 0000000..ef6b927 --- /dev/null +++ b/src/Oxrun/Command/Database/ListCommand.php @@ -0,0 +1,129 @@ + + * Date: 09.12.17 + * Time: 21:11 + */ + +namespace Oxrun\Command\Database; + +use Oxrun\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Helper\TableHelper; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + + +class ListCommand extends Command +{ + protected function configure() + { + $this + ->setName('db:list') + ->setDescription('List of all Tables') + + ->addOption( + 'plain', + 'p', + InputOption::VALUE_NONE, + 'print list as comma separated.' + ) + ->addOption( + 'pattern', + 't', + InputOption::VALUE_REQUIRED, + 'table name pattern test. e.g. oxseo%,oxuser' + ); + + $help = <<usage: + oxrun {$this->getName()} --pattern oxseo%,oxuser + - To dump all Tables, but `oxseo`, `oxvoucher`, and `oxvoucherseries` without data. + possibilities: oxseo%,oxuser,%logs% + + +HELP; + $this->setHelp($help); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $tables = ['%']; + + if ($input->getOption('pattern')) { + $argvData = $input->getOption('pattern'); + $tables = explode(',', $argvData); + } + + $tablenames = $this->filterValidTables($tables); + + if ($input->getOption('plain')) { + $quote = "'"; + $existsTable = array_map( + function ($row) { + return $row[0]; + }, $tablenames + ); + $list = implode("$quote, $quote", $existsTable); + $output->writeln($quote . $list . $quote); + return; + } + + /** @var TableHelper $table */ + $table = $this->getHelper('table'); + $table->setHeaders(['Table', 'Type']); + $table->addRows($tablenames); + + $table->render($output); + } + + /** + * @param array $tables + * @return array + */ + protected function filterValidTables($tables) + { + $whereIN = $whereLIKE = []; + + $dbName = \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbName'); + + foreach ($tables as $name) { + if (preg_match('/[%*]/', $name)) { + $name = str_replace(['_','*'], ['\\_', '%'], $name); + $whereLIKE[] = $name; + } else { + $whereIN[] = $name; + } + } + + $whereIN = implode("', '", $whereIN); + $conditionsIN = "Tables_in_{$dbName} IN ('{$whereIN}')"; + + $conditionsLIKE = ''; + if (!empty($whereLIKE)) { + $template = " OR Tables_in_{$dbName} LIKE ('%s')"; + foreach ($whereLIKE as $tablename) { + $conditionsLIKE .= sprintf($template, $tablename); + } + } + + $sqlstament = "SHOW FULL TABLES IN {$dbName} WHERE $conditionsIN $conditionsLIKE"; + + $existsTable = \OxidEsales\Eshop\Core\DatabaseProvider::getDb()->getAll($sqlstament); + + return $existsTable; + } + + /** + * @return bool + */ + public function isEnabled() + { + return $this->getApplication()->bootstrapOxid(); + } +} \ No newline at end of file diff --git a/src/Oxrun/Command/Database/QueryCommand.php b/src/Oxrun/Command/Database/QueryCommand.php index f415560..1ea7c0a 100644 --- a/src/Oxrun/Command/Database/QueryCommand.php +++ b/src/Oxrun/Command/Database/QueryCommand.php @@ -64,17 +64,17 @@ protected function execute(InputInterface $input, OutputInterface $output) $query = $this->getEscapedSql($input->getArgument('query')); // allow empty password - $dbPwd = \oxRegistry::getConfig()->getConfigParam('dbPwd'); + $dbPwd = \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbPwd'); if (!empty($dbPwd)) { $dbPwd = '-p' . $dbPwd; } $exec = sprintf( "mysql -h%s %s -u%s %s -e '%s' 2>&1", - \oxRegistry::getConfig()->getConfigParam('dbHost'), + \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbHost'), $dbPwd, - \oxRegistry::getConfig()->getConfigParam('dbUser'), - \oxRegistry::getConfig()->getConfigParam('dbName'), + \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbUser'), + \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('dbName'), $query ); @@ -90,9 +90,11 @@ protected function execute(InputInterface $input, OutputInterface $output) return; } - $commandOutput = array_map(function ($row) { - return explode("\t", $row); - }, $commandOutput); + $commandOutput = array_map( + function ($row) { + return explode("\t", $row); + }, $commandOutput + ); $table = new Table($output); $table->setHeaders(array_shift($commandOutput))->setRows($commandOutput); diff --git a/src/Oxrun/Command/Install/InstallCommand.php b/src/Oxrun/Command/Install/InstallCommand.php index 8efc206..5d22a5f 100755 --- a/src/Oxrun/Command/Install/InstallCommand.php +++ b/src/Oxrun/Command/Install/InstallCommand.php @@ -36,7 +36,7 @@ class InstallCommand extends Command protected function configure() { $this - ->setName('install:shop') + ->setName('install:shop __[DEPRECATED]__') ->addOption('oxidVersion', null, InputOption::VALUE_OPTIONAL, 'Oxid version') ->addOption('installationFolder', null, InputOption::VALUE_OPTIONAL, 'Installation folder', getcwd()) ->addOption('dbHost', null, InputOption::VALUE_REQUIRED, 'Database host', 'localhost') @@ -48,7 +48,7 @@ protected function configure() ->addOption('shopURL', null, InputOption::VALUE_REQUIRED, 'Installation base url') ->addOption('adminUser', null, InputOption::VALUE_REQUIRED, 'Admin user email/login', 'admin@example.com') ->addOption('adminPassword', null, InputOption::VALUE_REQUIRED, 'Admin password', 'oxid-123456') - ->setDescription('Installs the shop'); + ->setDescription('Installs the shop, for OXID 6 composer is used instead!'); } /** @@ -123,9 +123,9 @@ protected function execute(InputInterface $input, OutputInterface $output) $oxSetupController->dbCreate(); $oxSetupController->dirsWrite(); $aMessages = $oxSetupController->getView()->getMessages(); - foreach($aMessages as $message) { - $cleanMessage = str_replace(array('ERROR:','FEHLER:'), '', $message); - if($cleanMessage !== $message) { + foreach ($aMessages as $message) { + $cleanMessage = str_replace(array('ERROR:', 'FEHLER:'), '', $message); + if ($cleanMessage !== $message) { $cleanMessage = trim($cleanMessage); $output->writeln("An error occured during the installation: {$cleanMessage}"); } @@ -180,8 +180,8 @@ protected function patchOxSetup($target, $version = null) } // patch version 4.10.2 and above (broken in official installer) - if(isset($version)) { - if(version_compare($version, "v4.10.2") >= 0){ + if (isset($version)) { + if (version_compare($version, "v4.10.2") >= 0) { $code = file_get_contents($target . '/setup/oxrunsetup.php'); $code = str_replace("demodata.sql", "test_demodata.sql", $code); file_put_contents($target . '/setup/oxrunsetup.php', $code); @@ -200,8 +200,8 @@ protected function getOxidVersions() { $client = new Client(); $githubToken = getenv('GITHUB_TOKEN'); - if( $githubToken ) { - $tagsArray = $client->get('https://api.github.com/repos/OXID-eSales/oxideshop_ce/tags?per_page=9999&access_token='.$githubToken)->json(); + if ($githubToken) { + $tagsArray = $client->get('https://api.github.com/repos/OXID-eSales/oxideshop_ce/tags?per_page=9999&access_token=' . $githubToken)->json(); } else { $tagsArray = $client->get('https://api.github.com/repos/OXID-eSales/oxideshop_ce/tags?per_page=9999')->json(); } @@ -222,7 +222,7 @@ function ($result, $item) { ); $tagsArray = array_filter( $tagsArray, - function($tagArray) { + function ($tagArray) { return preg_match('#^v\d+\.\d+\.\d+$#', $tagArray['tag']); } ); @@ -247,8 +247,8 @@ protected function downloadOxid(OutputInterface $output, $version) try { $githubToken = getenv('GITHUB_TOKEN'); - if( $githubToken ) { - $request = $client->createRequest('GET', $version['zip'].'?access_token='.$githubToken, array('save_to' => $file)); + if ($githubToken) { + $request = $client->createRequest('GET', $version['zip'] . '?access_token=' . $githubToken, array('save_to' => $file)); } else { $request = $client->createRequest('GET', $version['zip'], array('save_to' => $file)); } diff --git a/src/Oxrun/Command/Ioly/IolyCommand.php b/src/Oxrun/Command/Ioly/IolyCommand.php index 09f3bc4..812f960 100644 --- a/src/Oxrun/Command/Ioly/IolyCommand.php +++ b/src/Oxrun/Command/Ioly/IolyCommand.php @@ -50,7 +50,7 @@ protected function execute(InputInterface $input, OutputInterface $output) public function isEnabled() { $ioly = getenv('IOLY_PHP'); - if( !empty( $ioly ) && is_file( $ioly ) ) { + if (!empty($ioly) && is_file($ioly) ) { return true; } return false; diff --git a/src/Oxrun/Command/Misc/GenerateDocumentationCommand.php b/src/Oxrun/Command/Misc/GenerateDocumentationCommand.php index b0e8f06..eb86a83 100644 --- a/src/Oxrun/Command/Misc/GenerateDocumentationCommand.php +++ b/src/Oxrun/Command/Misc/GenerateDocumentationCommand.php @@ -56,12 +56,14 @@ function ($item) { ); $availableCommands = array_keys($this->getApplication()->all()); - $availableCommands = array_filter($availableCommands, function ($commandName) { - if (in_array($commandName, $this->skipCommands)) { - return false; + $availableCommands = array_filter( + $availableCommands, function ($commandName) { + if (in_array($commandName, $this->skipCommands)) { + return false; + } + return true; } - return true; - }); + ); $command = $this->getApplication()->find('help'); $commandTester = new CommandTester($command); diff --git a/src/Oxrun/Command/Misc/PhpstormMetadataCommand.php b/src/Oxrun/Command/Misc/PhpstormMetadataCommand.php index 5762d77..fa65bb0 100644 --- a/src/Oxrun/Command/Misc/PhpstormMetadataCommand.php +++ b/src/Oxrun/Command/Misc/PhpstormMetadataCommand.php @@ -42,10 +42,10 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { $searchDirs = [ - OX_BASE_PATH . '/application/components', - OX_BASE_PATH . '/application/controllers', - OX_BASE_PATH . '/application/models', - OX_BASE_PATH . '/core', + OX_BASE_PATH . '../vendor/oxid-esales/oxideshop-ce/source/Application/Component', + OX_BASE_PATH . '../vendor/oxid-esales/oxideshop-ce/source/Application/Controller', + OX_BASE_PATH . '../vendor/oxid-esales/oxideshop-ce/source/Application/Model', + OX_BASE_PATH . '../vendor/oxid-esales/oxideshop-ce/source/Core', OX_BASE_PATH . '/modules', ]; $finder = new Finder(); @@ -61,9 +61,9 @@ protected function execute(InputInterface $input, OutputInterface $output) ->files(); try { - $extendedOxidClasses = \oxRegistry::get('oxModuleInstaller')->getModulesWithExtendedClass(); + $extendedOxidClasses = \OxidEsales\Eshop\Core\Registry::get('oxModuleInstaller')->getModulesWithExtendedClass(); } catch (\oxSystemComponentException $e) { - $extendedOxidClasses = \oxRegistry::getConfig()->getAllModules(); + $extendedOxidClasses = \OxidEsales\Eshop\Core\Registry::getConfig()->getAllModules(); } $classes = array(); @@ -135,7 +135,7 @@ protected function execute(InputInterface $input, OutputInterface $output) ) ); override( - \oxRegistry::get(0), + \OxidEsales\Eshop\Core\Registry::get(0), map( [ CLASSES_PLACEHOLDER diff --git a/src/Oxrun/Command/Module/ActivateCommand.php b/src/Oxrun/Command/Module/ActivateCommand.php index f7f1b7d..5ef448c 100644 --- a/src/Oxrun/Command/Module/ActivateCommand.php +++ b/src/Oxrun/Command/Module/ActivateCommand.php @@ -6,11 +6,14 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** * Class ActivateCommand + * * @package Oxrun\Command\Module + * */ class ActivateCommand extends Command { @@ -24,9 +27,11 @@ protected function configure() $this ->setName('module:activate') ->setDescription('Activates a module') - ->addArgument('module', InputArgument::REQUIRED, 'Module name'); + ->addArgument('module', InputArgument::REQUIRED, 'Module name') + ->addOption('shopId', null, InputOption::VALUE_OPTIONAL, null); } + /** * Executes the current command. * @@ -35,59 +40,14 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->checkModulelist(); - - if (version_compare($this->getApplication()->getOxidVersion(), '4.9.0') >= 0) { - $this->executeVersion490($input, $output); - } else { - if (version_compare($this->getApplication()->getOxidVersion(), '4.8.0') >= 0) { - $this->executeVersion480($input, $output); - } else { - if (version_compare($this->getApplication()->getOxidVersion(), '4.7.0') >= 0) { - $this->executeVersion470($input, $output); - } - } + $shopId = $input->getOption('shopId'); + if ($shopId) { + $this->getApplication()->switchToShopId($shopId); } - } - - /** - * Executes the current command. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - */ - protected function executeVersion490(InputInterface $input, OutputInterface $output) - { - $sModule = $input->getArgument('module'); - - $oModule = oxNew('oxModule'); - $oModuleCache = oxNew('oxModuleCache', $oModule); - $oModuleInstaller = oxNew('oxModuleInstaller', $oModuleCache); + + $this->checkModulelist($shopId); - if (!$oModule->load($sModule)) { - $output->writeLn("Cannot load module $sModule."); - } - - if (!$oModule->isActive()) { - if ($oModuleInstaller->activate($oModule) === true) { - $output->writeLn("Module $sModule activated."); - } else { - $output->writeLn("Module $sModule could not be activated."); - } - } else { - $output->writeLn("Module $sModule already activated."); - } - } - - /** - * Executes the current command. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - */ - protected function executeVersion480(InputInterface $input, OutputInterface $output) - { - $this->executeVersion470($input, $output); + $this->executeActivate($input, $output); } /** @@ -96,24 +56,31 @@ protected function executeVersion480(InputInterface $input, OutputInterface $out * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance */ - protected function executeVersion470(InputInterface $input, OutputInterface $output) + protected function executeActivate(InputInterface $input, OutputInterface $output) { $sModule = $input->getArgument('module'); + $shopId = $input->getOption('shopId'); - $oModule = oxNew('oxModule'); + $oModule = oxNew(\OxidEsales\Eshop\Core\Module\Module::class); + $oModuleCache = oxNew(\OxidEsales\Eshop\Core\Module\ModuleCache::class, $oModule); + $oModuleInstaller = oxNew(\OxidEsales\Eshop\Core\Module\ModuleInstaller::class, $oModuleCache); if (!$oModule->load($sModule)) { $output->writeLn("Cannot load module $sModule."); } if (!$oModule->isActive()) { - if ($oModule->activate() === true) { - $output->writeLn("Module $sModule activated."); - } else { - $output->writeLn("Module $sModule could not be activated."); + try { + if ($oModuleInstaller->activate($oModule) === true) { + $output->writeLn("Module $sModule activated for shopId $shopId."); + } else { + $output->writeLn("Module $sModule could not be activated for shopId $shopId."); + } + } catch (\Exception $ex) { + $output->writeLn("Exception actiating module: $sModule for shop $shopId: {$ex->getMessage()}"); } } else { - $output->writeLn("Module $sModule already activated."); + $output->writeLn("Module $sModule already activated for shopId $shopId."); } } diff --git a/src/Oxrun/Command/Module/DeactivateCommand.php b/src/Oxrun/Command/Module/DeactivateCommand.php index ce44ade..022e001 100644 --- a/src/Oxrun/Command/Module/DeactivateCommand.php +++ b/src/Oxrun/Command/Module/DeactivateCommand.php @@ -6,6 +6,7 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** @@ -24,6 +25,7 @@ protected function configure() $this ->setName('module:deactivate') ->setDescription('Deactivates a module') + ->addOption('shopId', null, InputOption::VALUE_OPTIONAL, null) ->addArgument('module', InputArgument::REQUIRED, 'Module name'); } @@ -35,49 +37,14 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->checkModulelist(); - - if (version_compare($this->getApplication()->getOxidVersion(), '4.9.0') >= 0) { - $this->executeVersion490($input, $output); - } else { - if (version_compare($this->getApplication()->getOxidVersion(), '4.8.0') >= 0) { - $this->executeVersion480($input, $output); - } else { - if (version_compare($this->getApplication()->getOxidVersion(), '4.7.0') >= 0) { - $this->executeVersion470($input, $output); - } - } - } - } - - /** - * Executes the current command. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - */ - protected function executeVersion490(InputInterface $input, OutputInterface $output) - { - $sModule = $input->getArgument('module'); - - $oModule = \oxNew('oxModule'); - $oModuleCache = oxNew('oxModuleCache', $oModule); - $oModuleInstaller = oxNew('oxModuleInstaller', $oModuleCache); - - if (!$oModule->load($sModule)) { - $output->writeLn("Cannot load module $sModule."); + $shopId = $input->getOption('shopId'); + if ($shopId) { + $this->getApplication()->switchToShopId($shopId); } - if (!$oModule->isActive()) { - $output->writeLn("Module $sModule already deactivated."); - } else { - if ($oModuleInstaller->deactivate($oModule) === true) { - $output->writeLn("Module $sModule deactivated."); - } else { - $output->writeLn("Module $sModule already activated."); - } - } + $this->checkModulelist($shopId); + $this->executeDeactivate($input, $output); } /** @@ -86,39 +53,34 @@ protected function executeVersion490(InputInterface $input, OutputInterface $out * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance */ - protected function executeVersion480(InputInterface $input, OutputInterface $output) - { - $this->executeVersion470($input, $output); - } - - /** - * Executes the current command. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - */ - protected function executeVersion470(InputInterface $input, OutputInterface $output) + protected function executeDeactivate(InputInterface $input, OutputInterface $output) { $sModule = $input->getArgument('module'); + $shopId = $input->getOption('shopId'); - $oModule = \oxNew('oxModule'); + $oModule = oxNew(\OxidEsales\Eshop\Core\Module\Module::class); + $oModuleCache = oxNew(\OxidEsales\Eshop\Core\Module\ModuleCache::class, $oModule); + $oModuleInstaller = oxNew(\OxidEsales\Eshop\Core\Module\ModuleInstaller::class, $oModuleCache); if (!$oModule->load($sModule)) { $output->writeLn("Cannot load module $sModule."); } if (!$oModule->isActive()) { - $output->writeLn("Module $sModule already deactivated."); + $output->writeLn("Module $sModule already deactivated for shopId $shopId."); } else { - if ($oModule->deactivate() === true) { - $output->writeLn("Module $sModule deactivated."); - } else { - $output->writeLn("Module $sModule already activated."); + try { + if ($oModuleInstaller->deactivate($oModule) === true) { + $output->writeLn("Module $sModule deactivated for shopId $shopId."); + } else { + $output->writeLn("Module $sModule already deactivated for shopId $shopId."); + } + } catch (\Exception $ex) { + $output->writeLn("Exception deactiating module: $sModule for shop $shopId: {$ex->getMessage()}"); } } } - /** * @return bool */ diff --git a/src/Oxrun/Command/Module/FixCommand.php b/src/Oxrun/Command/Module/FixCommand.php index f478b5a..fbbf288 100644 --- a/src/Oxrun/Command/Module/FixCommand.php +++ b/src/Oxrun/Command/Module/FixCommand.php @@ -5,6 +5,7 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** @@ -21,7 +22,8 @@ protected function configure() { $this ->setName('module:fix') - ->setDescription('Fixes a module') + ->setDescription('Fixes a module __[NOT IMPLEMENTED YET]__') + ->addOption('shopId', null, InputOption::VALUE_OPTIONAL, null) ->addArgument('module', InputArgument::REQUIRED, 'Module name'); } @@ -34,6 +36,12 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { + $shopId = $input->getOption('shopId'); + if ($shopId) { + $this->getApplication()->switchToShopId($shopId); + } + + $output->writeLn("To be implemented"); } diff --git a/src/Oxrun/Command/Module/GenerateCommand.php b/src/Oxrun/Command/Module/GenerateCommand.php index 2baccc7..2761578 100644 --- a/src/Oxrun/Command/Module/GenerateCommand.php +++ b/src/Oxrun/Command/Module/GenerateCommand.php @@ -5,6 +5,7 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** @@ -21,7 +22,8 @@ protected function configure() { $this ->setName('module:generate') - ->setDescription('Generates a module skeleton') + ->setDescription('Generates a module skeleton __[NOT IMPLEMENTED YET]__') + ->addOption('shopId', null, InputOption::VALUE_OPTIONAL, null) ->addArgument('module', InputArgument::REQUIRED, 'Module name'); } @@ -33,6 +35,11 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { + $shopId = $input->getOption('shopId'); + if ($shopId) { + $this->getApplication()->switchToShopId($shopId); + } + $output->writeLn("To be implemented"); } diff --git a/src/Oxrun/Command/Module/ListCommand.php b/src/Oxrun/Command/Module/ListCommand.php index 1f888f1..bd71529 100644 --- a/src/Oxrun/Command/Module/ListCommand.php +++ b/src/Oxrun/Command/Module/ListCommand.php @@ -6,6 +6,7 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** @@ -23,6 +24,7 @@ protected function configure() { $this ->setName('module:list') + ->addOption('shopId', null, InputOption::VALUE_OPTIONAL, null) ->setDescription('Lists all modules'); } @@ -34,24 +36,41 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->checkModulelist(); + $shopId = $input->getOption('shopId'); + if ($shopId) { + $this->getApplication()->switchToShopId($shopId); + } + + $this->checkModulelist($shopId); - $oxModuleList = oxNew('oxModuleList'); + /* @var \OxidEsales\Eshop\Core\Module\ModuleList $oxModuleList */ + $oxModuleList = oxNew(\OxidEsales\Eshop\Core\Module\ModuleList::class); $activeModules = array_keys($oxModuleList->getActiveModuleInfo()); $deactiveModules = $oxModuleList->getDisabledModules();; - $activeModules = array_map(function ($item) { - return array($item, 'yes'); - }, $activeModules); + $activeModules = array_map( + function ($item) { + // check if really active + $oModule = oxNew('oxModule'); + if ($oModule->load($item) && $oModule->isActive()) { + return array($item, 'yes'); + } + return array($item, 'no'); + }, + $activeModules + ); // Fix for older oxid version < 4.9.0 if (!is_array($deactiveModules)) { $deactiveModules = array(); } - $deactiveModules = array_map(function ($item) { - return array($item, 'no'); - }, $deactiveModules); + $deactiveModules = array_map( + function ($item) { + return array($item, 'no'); + }, + $deactiveModules + ); $table = new Table($output); $table diff --git a/src/Oxrun/Command/Module/MultiActivateCommand.php b/src/Oxrun/Command/Module/MultiActivateCommand.php new file mode 100644 index 0000000..57e2b14 --- /dev/null +++ b/src/Oxrun/Command/Module/MultiActivateCommand.php @@ -0,0 +1,179 @@ + + * Date: 07.03.18 + * Time: 08:46 + */ + +namespace Oxrun\Command\Module; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Yaml\Yaml; + +/** + * Class MultiActivateCommand + * + * @package Oxrun\Command\Module + * + * This command can be used to activate multiple modules for multiple shops. + * You need to pass it a valid yaml file as argument, relative to the shop root dir, + * containing either a "whitelist" or a + * "blacklist" with shop ids and module ids, e.g. + * whitelist: + * 1: + * - oepaypal + * - oxpspaymorrow + * 2: + * - oepaypal + * - oxpspaymorrow + */ +class MultiActivateCommand extends Command +{ + + /** + * Configures the current command. + */ + protected function configure() + { + $this + ->setName('module:multiactivate') + ->setDescription('Activates multiple modules, based on a YAML file') + ->addOption('shopId', null, InputOption::VALUE_REQUIRED, "The shop id.") + ->addOption('skipDeactivation', 's', InputOption::VALUE_NONE, "Skip deactivation of modules, only activate.") + ->addOption('skipClear', 'c', InputOption::VALUE_NONE, "Skip cache clearing.") + ->addArgument('module', InputArgument::REQUIRED, 'YAML module list filename or YAML string'); + +$help = <<usage: +oxrun module:multiactivate configs/modules.yml +- to activate all modules defined in the file "configs/modules.yml" based +on a white- or blacklist + +Example: + +```yaml +whitelist: +1: + - ocb_cleartmp + - moduleinternals + #- ddoevisualcms + #- ddoewysiwyg +2: + - ocb_cleartmp +``` + +Supports either a __"whitelist"__ or a __"blacklist"__ entry with multiple shop ids and the desired module ids to activate (whitelist) or to exclude from activation (blacklist). + +If you want, you can also specify __a YAML string on the command line instead of a file__, e.g.: + +```bash +../vendor/bin/oxrun module:multiactivate $'whitelist:\n 1:\n - oepaypal\n' --shopId=1 +``` +HELP; + $this->setHelp($help); + } + + /** + * Executes the current command. + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $activateShopId = $input->getOption('shopId'); + /* @var \Oxrun\Application $app */ + $app = $this->getApplication(); + $skipDeactivation = $input->getOption('skipDeactivation'); + $skipClear = $input->getOption('skipClear'); + + // now try to read YAML + $moduleYml = $app->getYaml($input->getArgument('module')); + $moduleValues = Yaml::parse($moduleYml); + if ($moduleValues && is_array($moduleValues)) { + // use whitelist + if (isset($moduleValues['whitelist'])) { + foreach ($moduleValues['whitelist'] as $shopId => $moduleIds) { + if ($activateShopId && $activateShopId != $shopId) { + $output->writeLn("Skipping shop '$shopId'!"); + continue; + } + foreach ($moduleIds as $moduleId) { + if (!$skipDeactivation) { + $arguments = array( + 'command' => 'module:deactivate', + 'module' => $moduleId, + '--shopId' => $shopId, + ); + $deactivateInput = new ArrayInput($arguments); + $app->find('module:deactivate')->run($deactivateInput, $output); + if (!$skipClear) { + $app->find('cache:clear')->run(new ArgvInput([]), $output); + } + } + $arguments = array( + 'command' => 'module:activate', + 'module' => $moduleId, + '--shopId' => $shopId, + ); + $activateInput = new ArrayInput($arguments); + $app->find('module:activate')->run($activateInput, $output); + } + } + } elseif (isset($moduleValues['blacklist'])) { + // use blacklist + /* @var \OxidEsales\Eshop\Core\Module\ModuleList $oxModuleList */ + $oxModuleList = oxNew(\OxidEsales\Eshop\Core\Module\ModuleList::class); + $oConfig = \OxidEsales\Eshop\Core\Registry::getConfig(); + $aModules = $oxModuleList->getModulesFromDir($oConfig->getModulesDir()); + foreach ($aModules as $moduleId => $aModuleData) { + foreach ($moduleValues['blacklist'] as $shopId => $moduleIds) { + if (in_array($moduleId, $moduleIds)) { + $output->writeLn("Module blacklisted: '$moduleId' - skipping!"); + continue 2; + } + // activate + if (!$skipDeactivation) { + $arguments = array( + 'command' => 'module:deactivate', + 'module' => $moduleId, + '--shopId' => $shopId, + ); + $deactivateInput = new ArrayInput($arguments); + $app->find('module:deactivate')->run($deactivateInput, $output); + if (!$skipClear) { + $app->find('cache:clear')->run(new ArgvInput([]), $output); + } + } + $arguments = array( + 'command' => 'module:activate', + 'module' => $moduleId, + '--shopId' => $shopId, + ); + $activateInput = new ArrayInput($arguments); + $app->find('module:activate')->run($activateInput, $output); + } + } + } else { + $output->writeLn("No modules to activate for subshop '$shopId'!"); + } + } else { + $output->writeLn("No valid YAML data found!"); + } + } + + /** + * @return bool + */ + public function isEnabled() + { + return $this->getApplication()->bootstrapOxid(); + } +} diff --git a/src/Oxrun/Command/Module/ReloadCommand.php b/src/Oxrun/Command/Module/ReloadCommand.php index 9a1a79d..c7ab2eb 100644 --- a/src/Oxrun/Command/Module/ReloadCommand.php +++ b/src/Oxrun/Command/Module/ReloadCommand.php @@ -12,6 +12,7 @@ use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class ReloadCommand extends Command @@ -25,6 +26,7 @@ protected function configure() $this ->setName('module:reload') ->setDescription('Deactivate and activate a module') + ->addOption('shopId', null, InputOption::VALUE_OPTIONAL, null) ->addArgument('module', InputArgument::REQUIRED, 'Module name'); } @@ -38,6 +40,10 @@ protected function execute(InputInterface $input, OutputInterface $output) { /** @var \Oxrun\Application $app */ $app = $this->getApplication(); + $shopId = $input->getOption('shopId'); + if ($shopId) { + $app->switchToShopId($shopId); + } $app->find('module:deactivate')->run($input, $output); $app->find('cache:clear')->run(new ArgvInput([]), $output); $app->find('module:activate')->run($input, $output); diff --git a/src/Oxrun/Command/Route/DebugCommand.php b/src/Oxrun/Command/Route/DebugCommand.php index e985010..73622e8 100644 --- a/src/Oxrun/Command/Route/DebugCommand.php +++ b/src/Oxrun/Command/Route/DebugCommand.php @@ -40,6 +40,7 @@ protected function configure() $this->setName("route:debug") ->setDescription("Returns the route. Which controller and parameters are called.") ->addArgument("url", InputArgument::REQUIRED, "Website URL. Full or Path") + ->addOption('shopId', null, InputOption::VALUE_OPTIONAL, null) ->addOption('copy', 'c', InputOption::VALUE_NONE, 'Copy file path from the class to the clipboard (only MacOS)'); } @@ -50,11 +51,15 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { $url = $this->cleanUrlPath($input); + $shopId = $input->getOption('shopId'); + if ($shopId) { + $this->getApplication()->switchToShopId($shopId); + } $output->writeln("Results for: $url"); - /** @var \oxSeoDecoder $oxSeoDecoder */ - $oxSeoDecoder = \oxNew('oxSeoDecoder'); + /** @var \OxidEsales\Eshop\Core\SeoDecoder $oxSeoDecoder */ + $oxSeoDecoder = oxNew(\OxidEsales\Eshop\Core\SeoDecoder::class); $aSeoURl = $oxSeoDecoder->decodeUrl($url); if ($aSeoURl == false) { diff --git a/src/Oxrun/Command/User/PasswordCommand.php b/src/Oxrun/Command/User/PasswordCommand.php index 8b22a83..82b8b71 100644 --- a/src/Oxrun/Command/User/PasswordCommand.php +++ b/src/Oxrun/Command/User/PasswordCommand.php @@ -34,14 +34,14 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $oxUser = \oxNew('oxUser'); + $oxUser = \oxNew(\OxidEsales\Eshop\Application\Model\User::class); $sql = sprintf( "SELECT `oxuser`.`OXID` FROM `oxuser` WHERE `oxuser`.`OXUSERNAME` = %s", - \oxDb::getDb()->quote($input->getArgument('username')) + \OxidEsales\Eshop\Core\DatabaseProvider::getDb()->quote($input->getArgument('username')) ); - $userOxid = \oxDb::getDb()->getOne($sql); - if(empty($userOxid)){ + $userOxid = \OxidEsales\Eshop\Core\DatabaseProvider::getDb()->getOne($sql); + if (empty($userOxid)) { $output->writeln('User does not exist.'); return; } diff --git a/src/Oxrun/Command/Views/UpdateCommand.php b/src/Oxrun/Command/Views/UpdateCommand.php index f9617d9..c893932 100644 --- a/src/Oxrun/Command/Views/UpdateCommand.php +++ b/src/Oxrun/Command/Views/UpdateCommand.php @@ -31,10 +31,10 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $myConfig = \oxRegistry::getConfig(); + $myConfig = \OxidEsales\Eshop\Core\Registry::getConfig(); $myConfig->setConfigParam('blSkipViewUsage', true); - $oMetaData = \oxNew('oxDbMetaDataHandler'); + $oMetaData = \oxNew(\OxidEsales\Eshop\Core\DbMetaDataHandler::class); if ($oMetaData->updateViews()) { $output->writeln('Views updated.'); } else { diff --git a/src/Oxrun/Helper/DatenbaseConnection.php b/src/Oxrun/Helper/DatabaseConnection.php similarity index 93% rename from src/Oxrun/Helper/DatenbaseConnection.php rename to src/Oxrun/Helper/DatabaseConnection.php index 49b9810..4cd1a42 100644 --- a/src/Oxrun/Helper/DatenbaseConnection.php +++ b/src/Oxrun/Helper/DatabaseConnection.php @@ -8,13 +8,13 @@ namespace Oxrun\Helper; /** - * Class DatenbaseConnection + * Class DatabaseConnection * * Connect direct to Database * * @package Oxrun\Helper */ -class DatenbaseConnection +class DatabaseConnection { /** @@ -54,7 +54,7 @@ class DatenbaseConnection /** * @param string $host - * @return DatenbaseConnection + * @return DatabaseConnection */ public function setHost($host) { @@ -78,7 +78,7 @@ public function getHost() /** * @param int $port - * @return DatenbaseConnection + * @return DatabaseConnection */ public function setPort($port) { @@ -96,7 +96,7 @@ public function getPort() /** * @param string $user - * @return DatenbaseConnection + * @return DatabaseConnection */ public function setUser($user) { @@ -106,7 +106,7 @@ public function setUser($user) /** * @param string $pass - * @return DatenbaseConnection + * @return DatabaseConnection */ public function setPass($pass) { @@ -116,7 +116,7 @@ public function setPass($pass) /** * @param string $database - * @return DatenbaseConnection + * @return DatabaseConnection */ public function setDatabase($database) { diff --git a/src/Oxrun/Traits/ModuleListCheckTrait.php b/src/Oxrun/Traits/ModuleListCheckTrait.php index 2487109..efd992d 100644 --- a/src/Oxrun/Traits/ModuleListCheckTrait.php +++ b/src/Oxrun/Traits/ModuleListCheckTrait.php @@ -16,11 +16,20 @@ trait ModuleListCheckTrait /** * Check if we have Modulelist, else create new. + * + * @param string $shopId The shop id. + * + * @return null */ - protected function checkModulelist() + protected function checkModulelist($shopId = null) { + $oConfig = \OxidEsales\Eshop\Core\Registry::getConfig(); + if ($shopId != null) { + $oConfig->setShopId($shopId); + \OxidEsales\Eshop\Core\Registry::set('oxConfig', $oConfig); + } // we must call this once, otherwise there are no modules visible in a fresh shop - $oModuleList = oxNew("oxModuleList"); - $oModuleList->getModulesFromDir(\oxRegistry::getConfig()->getModulesDir()); + $oModuleList = oxNew(\OxidEsales\Eshop\Core\Module\ModuleList::class); + $oModuleList->getModulesFromDir($oConfig->getModulesDir()); } } diff --git a/tests/Oxrun/Command/Config/MultiSetCommandTest.php b/tests/Oxrun/Command/Config/MultiSetCommandTest.php new file mode 100644 index 0000000..f31b43b --- /dev/null +++ b/tests/Oxrun/Command/Config/MultiSetCommandTest.php @@ -0,0 +1,29 @@ +add(new MultiSetCommand()); + + $command = $app->find('config:multiset'); + + $commandTester = new CommandTester($command); + $commandTester->execute( + array( + 'command' => $command->getName(), + 'configfile' => "config:\n 1:\n foobar: barfoo\n" + ) + ); + + $this->assertContains("Config foobar for shop 1 set", $commandTester->getDisplay()); + } + +} \ No newline at end of file diff --git a/tests/Oxrun/Command/Database/DumpCommandTest.php b/tests/Oxrun/Command/Database/DumpCommandTest.php index 20e4845..161cc01 100644 --- a/tests/Oxrun/Command/Database/DumpCommandTest.php +++ b/tests/Oxrun/Command/Database/DumpCommandTest.php @@ -8,6 +8,11 @@ class DumpCommandTest extends TestCase { + /** + * DB execute test + * + * @return void + */ public function testExecute() { $app = new Application(); @@ -44,7 +49,7 @@ public function testExecute() ) ); - $dump = file_get_contents( $path ); + $dump = file_get_contents($path); $this->assertContains('DROP TABLE IF EXISTS `oxacceptedterms`;', $dump); $this->assertContains('DROP TABLE IF EXISTS `oxaccessoire2article`;', $dump); $this->assertContains('DROP TABLE IF EXISTS `oxactions`;', $dump); diff --git a/tests/Oxrun/Command/Database/ListCommandTest.php b/tests/Oxrun/Command/Database/ListCommandTest.php new file mode 100644 index 0000000..c5f09c3 --- /dev/null +++ b/tests/Oxrun/Command/Database/ListCommandTest.php @@ -0,0 +1,30 @@ +add(new TestListCommand()); + + $command = $app->find('db:list'); + + $commandTester = new CommandTester($command); + $commandTester->execute( + array( + 'command' => $command->getName() + ) + ); + + $this->assertContains('Table', $commandTester->getDisplay()); + $this->assertContains('Type', $commandTester->getDisplay()); + } + +} \ No newline at end of file diff --git a/tests/Oxrun/Command/Module/ActivateCommandTest.php b/tests/Oxrun/Command/Module/ActivateCommandTest.php index e4682a9..e7f558c 100644 --- a/tests/Oxrun/Command/Module/ActivateCommandTest.php +++ b/tests/Oxrun/Command/Module/ActivateCommandTest.php @@ -20,7 +20,7 @@ public function testExecute() $commandTester->execute( array( 'command' => $command->getName(), - 'module' => 'invoicepdf' + 'module' => 'oepaypal' ) ); @@ -30,22 +30,22 @@ public function testExecute() $commandTester->execute( array( 'command' => $command->getName(), - 'module' => 'invoicepdf' + 'module' => 'oepaypal' ) ); - $this->assertContains('Module invoicepdf activated.', $commandTester->getDisplay()); + $this->assertContains('Module oepaypal activated', $commandTester->getDisplay()); $commandTester = new CommandTester($command); $commandTester->execute( array( 'command' => $command->getName(), - 'module' => 'invoicepdf' + 'module' => 'oepaypal' ) ); - $this->assertContains('Module invoicepdf already activated.', $commandTester->getDisplay()); + $this->assertContains('Module oepaypal already activated', $commandTester->getDisplay()); $commandTester = new CommandTester($command); $commandTester->execute( @@ -55,7 +55,7 @@ public function testExecute() ) ); - $this->assertContains('Cannot load module not_and_existing_module.', $commandTester->getDisplay()); + $this->assertContains('Cannot load module not_and_existing_module', $commandTester->getDisplay()); } diff --git a/tests/Oxrun/Command/Module/DeactivateCommandTest.php b/tests/Oxrun/Command/Module/DeactivateCommandTest.php index d1866b6..433d30d 100644 --- a/tests/Oxrun/Command/Module/DeactivateCommandTest.php +++ b/tests/Oxrun/Command/Module/DeactivateCommandTest.php @@ -19,11 +19,11 @@ public function testExecute() $commandTester->execute( array( 'command' => $command->getName(), - 'module' => 'invoicepdf' + 'module' => 'oepaypal' ) ); - $this->assertContains('Module invoicepdf deactivated.', $commandTester->getDisplay()); + $this->assertContains('Module oepaypal deactivated', $commandTester->getDisplay()); } } \ No newline at end of file diff --git a/tests/Oxrun/Command/Module/ListCommandTest.php b/tests/Oxrun/Command/Module/ListCommandTest.php index fa6e65b..201fbce 100644 --- a/tests/Oxrun/Command/Module/ListCommandTest.php +++ b/tests/Oxrun/Command/Module/ListCommandTest.php @@ -22,7 +22,7 @@ public function testExecute() ) ); - $this->assertContains('invoice', $commandTester->getDisplay()); + $this->assertContains('paypal', $commandTester->getDisplay()); } } \ No newline at end of file diff --git a/tests/Oxrun/Command/Module/MultiActivateCommandTest.php b/tests/Oxrun/Command/Module/MultiActivateCommandTest.php new file mode 100644 index 0000000..af4f72d --- /dev/null +++ b/tests/Oxrun/Command/Module/MultiActivateCommandTest.php @@ -0,0 +1,54 @@ +add(new ActivateCommand()); + $app->add(new ClearCommand()); + $app->add(new DeactivateCommand()); + $app->add(new MultiActivateCommand()); + + $command = $app->find('module:multiactivate'); + + $commandTester = new CommandTester($command); + $commandTester->execute( + array( + 'command' => $command->getName(), + 'module' => "whitelist:\n 1:\n - oepaypal\n" + ) + ); + + $this->assertContains('Module oepaypal activated', $commandTester->getDisplay()); + + $commandTester = new CommandTester($command); + $commandTester->execute( + array( + 'command' => $command->getName(), + 'module' => "blacklist:\n 1:\n - oepaypal\n" + ) + ); + + $this->assertContains("Module blacklisted: 'oepaypal'", $commandTester->getDisplay()); + + $commandTester = new CommandTester($command); + $commandTester->execute( + array( + 'command' => $command->getName(), + 'module' => "whitelist:\n 1:\n - not_and_existing_module\n" + ) + ); + + $this->assertContains('Cannot load module not_and_existing_module', $commandTester->getDisplay()); + + } + +} \ No newline at end of file diff --git a/tests/Oxrun/Command/Module/ReloadCommandTest.php b/tests/Oxrun/Command/Module/ReloadCommandTest.php index c6b34d8..3d8efa6 100644 --- a/tests/Oxrun/Command/Module/ReloadCommandTest.php +++ b/tests/Oxrun/Command/Module/ReloadCommandTest.php @@ -29,7 +29,7 @@ public function testExecute() $commandTester->execute( array( 'command' => $command->getName(), - 'module' => 'invoicepdf' + 'module' => 'oepaypal' ) ); diff --git a/tests/Oxrun/Command/Route/DebugTest.php b/tests/Oxrun/Command/Route/DebugTest.php index 8bd3e7f..14e660b 100644 --- a/tests/Oxrun/Command/Route/DebugTest.php +++ b/tests/Oxrun/Command/Route/DebugTest.php @@ -16,19 +16,42 @@ */ class DebugTest extends TestCase { - const commandName = 'route:debug'; + const COMMANDNAME = 'route:debug'; + + /** + * Shop URL, will be read from config + * + * @var string + */ + protected $baseUrl = 'http://localhost'; + + /** + * Seo path to search for + * + * @var string + */ + protected $seoKey = 'Nach-Hersteller'; + /** * @var Route\DebugCommand|CommandTester */ protected $commandTester; + /** + * Prepare + * + * @return void + */ protected function setUp() { $app = new Application(); $app->add(new Route\DebugCommand()); - $command = $app->find(self::commandName); + $command = $app->find(self::COMMANDNAME); + + $this->baseUrl = \OxidEsales\Eshop\Core\Registry::getConfig()->getConfigParam('sShopURL'); + // TODO - insert static seo url for seoKey!? $this->commandTester = new CommandTester($command); } @@ -36,88 +59,89 @@ public function testCompleteUrl() { $this->commandTester->execute( array( - 'url' => 'http://localhost/warenkorb/', - 'command' => self::commandName, + 'url' => $this->baseUrl . "/{$this->seoKey}/", + 'command' => self::COMMANDNAME, ) ); - $this->assertRegExp('~\|\s+Controller\s+\|\s+basket\s+\|~', $this->commandTester->getDisplay()); + //echo "\nRESULT: " . $this->commandTester->getDisplay(); + $this->assertRegExp('~\|\s+Controller\s+\|\s+manufacturerlist\s+\|~', $this->commandTester->getDisplay()); } - public function testHalfBrockenUrl() + public function testHalfBrokenUrl() { $this->commandTester->execute( array( - 'url' => 'http://localhost/warenkorb', - 'command' => self::commandName, + 'url' => $this->baseUrl . '/' . $this->seoKey, + 'command' => self::COMMANDNAME, ) ); - $this->assertRegExp('~\|\s+Controller\s+\|\s+basket\s+\|~', $this->commandTester->getDisplay()); + $this->assertRegExp('~\|\s+Controller\s+\|\s+manufacturerlist\s+\|~', $this->commandTester->getDisplay()); } public function testOnlyPath() { $this->commandTester->execute( array( - 'url' => 'warenkorb/', - 'command' => self::commandName, + 'url' => $this->seoKey. '/', + 'command' => self::COMMANDNAME, ) ); - $this->assertRegExp('~\|\s+Controller\s+\|\s+basket\s+\|~', $this->commandTester->getDisplay()); + $this->assertRegExp('~\|\s+Controller\s+\|\s+manufacturerlist\s+\|~', $this->commandTester->getDisplay()); } public function testHalfOnlyPath() { $this->commandTester->execute( array( - 'url' => 'warenkorb', - 'command' => self::commandName, + 'url' => $this->seoKey, + 'command' => self::COMMANDNAME, ) ); - $this->assertRegExp('~\|\s+Controller\s+\|\s+basket\s+\|~', $this->commandTester->getDisplay()); + $this->assertRegExp('~\|\s+Controller\s+\|\s+manufacturerlist\s+\|~', $this->commandTester->getDisplay()); } public function testGiveMeClassPath() { $this->commandTester->execute( array( - 'url' => 'warenkorb', - 'command' => self::commandName, + 'url' => $this->seoKey, + 'command' => self::COMMANDNAME, ) ); - $this->assertContains('basket.php', $this->commandTester->getDisplay()); + $this->assertContains('manufacturerlist', $this->commandTester->getDisplay()); } public function testGiveFunctionLineNumber() { - /** @var oxSeoEncoder $oxSeoEncoder */ - $oxSeoEncoder = oxNew('oxSeoEncoder'); + /** @var \OxidEsales\Eshop\Core\SeoDecoder $oxSeoEncoder */ + $oxSeoEncoder = oxNew(\OxidEsales\Eshop\Core\SeoEncoder::class); $oxSeoEncoder->getDynamicUrl('index.php?cl=news&fnc=render', 'newspage/', 0); $this->commandTester->execute( array( 'url' => 'NewsPage/', - 'command' => self::commandName, + 'command' => self::COMMANDNAME, ) ); - $this->assertRegExp('~news.php:\d+~', $this->commandTester->getDisplay()); + $this->assertRegExp('~NewsController.php:\d+~', $this->commandTester->getDisplay()); } public function testClassDontExists() { - /** @var oxSeoEncoder $oxSeoEncoder */ - $oxSeoEncoder = oxNew('oxSeoEncoder'); + /** @var \OxidEsales\Eshop\Core\SeoDecoder $oxSeoEncoder */ + $oxSeoEncoder = oxNew(\OxidEsales\Eshop\Core\SeoEncoder::class); $oxSeoEncoder->getDynamicUrl('index.php?cl=classdontexists', 'class/dont/exists/', 0); $this->commandTester->execute( array( 'url' => 'Class/Dont/Exists/', - 'command' => self::commandName, + 'command' => self::COMMANDNAME, ) ); @@ -126,14 +150,14 @@ public function testClassDontExists() public function testMethodInClassDontExists() { - /** @var oxSeoEncoder $oxSeoEncoder */ - $oxSeoEncoder = oxNew('oxSeoEncoder'); + /** @var \OxidEsales\Eshop\Core\SeoEncoder $oxSeoEncoder */ + $oxSeoEncoder = oxNew(\OxidEsales\Eshop\Core\SeoEncoder::class); $oxSeoEncoder->getDynamicUrl('index.php?cl=news&fnc=nameXYX', 'method/in/class/dont/exists/', 0); $this->commandTester->execute( array( 'url' => 'Method/In/Class/Dont/Exists/', - 'command' => self::commandName, + 'command' => self::COMMANDNAME, ) ); @@ -145,7 +169,7 @@ public function testMethodInClassDontExists() */ public static function tearDownAfterClass() { - $db = oxDb::getDb(); + $db = \OxidEsales\Eshop\Core\DatabaseProvider::getDb(); $seoURls[] = $db->quote('newspage/'); $seoURls[] = $db->quote('class/dont/exists/'); diff --git a/tests/Oxrun/Command/User/PasswordCommandTest.php b/tests/Oxrun/Command/User/PasswordCommandTest.php index 068dbf5..85c7749 100644 --- a/tests/Oxrun/Command/User/PasswordCommandTest.php +++ b/tests/Oxrun/Command/User/PasswordCommandTest.php @@ -8,6 +8,31 @@ class PasswordCommandTest extends TestCase { + /** + * Preparation + * + * @return void + */ + protected function setUp() + { + $db = \OxidEsales\Eshop\Core\DatabaseProvider::getDb(); + // insert user + $sql = "INSERT INTO `oxuser` (`OXID`, `OXACTIVE`, `OXRIGHTS`, `OXSHOPID`, `OXUSERNAME`, `OXPASSWORD`, `OXPASSSALT`, `OXCUSTNR`, `OXUSTID`, `OXCOMPANY`, `OXFNAME`, `OXLNAME`, `OXSTREET`, `OXSTREETNR`, `OXADDINFO`, `OXCITY`, `OXCOUNTRYID`, `OXSTATEID`, `OXZIP`, `OXFON`, `OXFAX`, `OXSAL`, `OXBONI`, `OXCREATE`, `OXREGISTER`, `OXPRIVFON`, `OXMOBFON`, `OXBIRTHDATE`, `OXURL`, `OXUPDATEKEY`, `OXUPDATEEXP`, `OXPOINTS`, `OXTIMESTAMP`) VALUES + ('__dummyuser__', 1, 'malladmin', '1', 'foobar@barfoo.de', '378d25534d551e83433f532f95893d7bd6ebb2727e392da65b6cd8adb06277f577325757a21ddf6b7dd68629c1f4541b1ceeff9945dec3b7c900ba1a0a05097e', '3a4e1e271e36554a6b89ef41f8a3c544', 1, '', '', 'John', 'Doe', 'Teststrasse 10', '', '', 'Any City', 'a7c40f631fc920687.20179984', '', '90410', '217-8918712', '', 'MR', 1000, '2003-01-01 00:00:00', '2003-01-01 00:00:00', '', '', '0000-00-00', '', '', 0, 0, '2016-03-15 08:19:20') + ON DUPLICATE KEY UPDATE oxrights='malladmin'"; + $db->execute($sql); + } + + /** + * Cleanup + */ + public static function tearDownAfterClass() + { + // delete user + $db = \OxidEsales\Eshop\Core\DatabaseProvider::getDb(); + $db->execute("DELETE FROM oxuser WHERE OXID = '__dummyuser__'"); + } + public function testExecute() { $app = new Application(); @@ -19,7 +44,7 @@ public function testExecute() $commandTester->execute( array( 'command' => $command->getName(), - 'username' => 'info@oxid-esales.com', + 'username' => 'foobar@barfoo.de', 'password' => 'thenewpassword' ) ); diff --git a/tests/Oxrun/Helper/DatenbaseConnectionTest.php b/tests/Oxrun/Helper/DatabaseConnectionTest.php similarity index 74% rename from tests/Oxrun/Helper/DatenbaseConnectionTest.php rename to tests/Oxrun/Helper/DatabaseConnectionTest.php index 7fc7fff..0d15618 100644 --- a/tests/Oxrun/Helper/DatenbaseConnectionTest.php +++ b/tests/Oxrun/Helper/DatabaseConnectionTest.php @@ -8,11 +8,11 @@ namespace Oxrun\Helper; -class DatenbaseConnectionTest extends \PHPUnit_Framework_TestCase +class DatabaseConnectionTest extends \PHPUnit_Framework_TestCase { /** - * @var DatenbaseConnection + * @var DatabaseConnection */ protected $testSubject; @@ -21,16 +21,17 @@ class DatenbaseConnectionTest extends \PHPUnit_Framework_TestCase */ protected function setUp() { - $datenbaseConnection = new DatenbaseConnection(); - $datenbaseConnection + $oConfig = \OxidEsales\Eshop\Core\Registry::getConfig(); + $databaseConnection = new DatabaseConnection(); + $databaseConnection // Must be right to work correct - ->setHost('127.0.0.1') + ->setHost($oConfig->getConfigParam('dbHost')) ->setPort('3306') - ->setUser('root') - ->setPass('') - ->setDatabase('oxid'); + ->setUser($oConfig->getConfigParam('dbUser')) + ->setPass($oConfig->getConfigParam('dbPwd')) + ->setDatabase($oConfig->getConfigParam('dbName')); - $this->testSubject = $datenbaseConnection; + $this->testSubject = $databaseConnection; } public function testCanParseHostPort() @@ -46,7 +47,7 @@ public function testHasNotConnected() $this->testSubject->setDatabase('oxid_unbekannt'); self::assertFalse($this->testSubject->canConnectToMysql()); - self::assertContains("Unknown database 'oxid_unbekannt'", $this->testSubject->getLastErrorMsg()); + self::assertContains("database 'oxid_unbekannt'", $this->testSubject->getLastErrorMsg()); } /**