├── .gitignore
├── bin
└── eecli
├── src
├── Command
│ ├── Contracts
│ │ ├── ExemptFromBootstrap.php
│ │ ├── HasExamples.php
│ │ ├── HasLongDescription.php
│ │ ├── HasOptionExamples.php
│ │ ├── Conditional.php
│ │ └── HasRuntimeOptions.php
│ ├── ShowVersionCommand.php
│ ├── CreateFieldDateCommand.php
│ ├── CreateFieldFieldpackListCommand.php
│ ├── CreateFieldCheckboxesCommand.php
│ ├── CreateFieldRadioCommand.php
│ ├── CreateFieldSelectCommand.php
│ ├── ClearStashCacheCommand.php
│ ├── CreateFieldMultiselectCommand.php
│ ├── Command.php
│ ├── CreateFieldStoreProductDetailsCommand.php
│ ├── CreateFieldFieldpackDropdownCommand.php
│ ├── CreateFieldFieldpackCheckboxesCommand.php
│ ├── CreateFieldFieldpackMultiselectCommand.php
│ ├── CreateFieldFieldpackRadioCommand.php
│ ├── CreateFieldFieldpackPillCommand.php
│ ├── AbstractCreateFieldFieldpackOptionsCommand.php
│ ├── ShowTemplatesCommand.php
│ ├── ConsoleCommand.php
│ ├── CreateFieldRteCommand.php
│ ├── ClearEECacheCommand.php
│ ├── CreateFieldGroupCommand.php
│ ├── CreateStatusGroupCommand.php
│ ├── CreateCategoryGroupCommand.php
│ ├── CreateFieldGridCommand.php
│ ├── SyncTemplatesCommand.php
│ ├── CreateFieldMatrixCommand.php
│ ├── AbstractCreateFieldNativeOptionsCommand.php
│ ├── ShowFieldGroupsCommand.php
│ ├── CreateFieldWygwamCommand.php
│ ├── InitCommand.php
│ ├── CreateFieldFieldpackSwitchCommand.php
│ ├── CreateFieldFileCommand.php
│ ├── ShowConfigCommand.php
│ ├── ShowCategoryGroupsCommand.php
│ ├── GenerateHtaccessCommand.php
│ ├── ShowMembersCommand.php
│ ├── DeleteTemplateGroupCommand.php
│ ├── ShowActionsCommand.php
│ ├── CreateFieldAssetsCommand.php
│ ├── ShowFieldsCommand.php
│ ├── GithubAddonInstallerCommand.php
│ ├── DeleteTemplateCommand.php
│ ├── CreateGlobalVariableCommand.php
│ ├── DeleteEntryCommand.php
│ ├── DeleteSnippetCommand.php
│ ├── CreateFieldTextareaCommand.php
│ ├── DeleteGlobalVariableCommand.php
│ ├── CreateSnippetCommand.php
│ ├── CreateFieldTextCommand.php
│ ├── CreateTemplateGroupCommand.php
│ ├── GenerateCommandCommand.php
│ ├── CreateUploadPrefCommand.php
│ ├── CreateStatusCommand.php
│ ├── CreateMemberCommand.php
│ ├── ClearCeCacheCommand.php
│ ├── DbDumpCommand.php
│ ├── CreateFieldRelationshipCommand.php
│ ├── CreateFieldPlayaCommand.php
│ ├── AbstractCreateFieldCommand.php
│ ├── CreateCategoryCommand.php
│ └── CreateTemplateCommand.php
├── stub.php
├── CodeIgniter
│ ├── BootableInterface.php
│ ├── Controller
│ │ ├── ContentFilesController.php
│ │ ├── MembersController.php
│ │ ├── DesignController.php
│ │ └── AdminContentController.php
│ ├── Cp.php
│ ├── Functions.php
│ └── ConsoleOutput.php
├── templates
│ ├── htaccess.handlebars
│ └── Command.php.handlebars
├── Db
│ ├── MysqliTester.php
│ ├── MysqlTester.php
│ └── ConnectionTester.php
├── bootstrap.php
├── Console
│ └── GlobalArgvInput.php
└── Handlebars
│ └── Loader
│ └── FilesystemLoader.php
├── .editorconfig
├── CONTRIBUTING.md
├── composer.json
├── LICENSE.txt
├── box.json
├── README.md
└── sample.eecli.php
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | composer.lock
3 | eecli.phar
4 |
--------------------------------------------------------------------------------
/bin/eecli:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | arguments
10 | *
11 | * @return array
12 | */
13 | public function getExamples();
14 | }
15 |
--------------------------------------------------------------------------------
/src/Command/Contracts/HasLongDescription.php:
--------------------------------------------------------------------------------
1 | option value
10 | *
11 | * @return array
12 | */
13 | public function getOptionExamples();
14 | }
15 |
--------------------------------------------------------------------------------
/src/CodeIgniter/BootableInterface.php:
--------------------------------------------------------------------------------
1 | bootCp();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Command/Contracts/Conditional.php:
--------------------------------------------------------------------------------
1 | bootCp();
15 |
16 | ee()->lang->loadfile('members');
17 | ee()->load->model('member_model');
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Command/Contracts/HasRuntimeOptions.php:
--------------------------------------------------------------------------------
1 | bootCp();
15 |
16 | ee()->load->model('template_model');
17 |
18 | ee()->lang->loadfile('design');
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/CodeIgniter/Controller/AdminContentController.php:
--------------------------------------------------------------------------------
1 | bootCp();
15 |
16 | ee()->lang->loadfile('admin');
17 | ee()->lang->loadfile('admin_content');
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Command/ShowVersionCommand.php:
--------------------------------------------------------------------------------
1 | line(sprintf('ExpressionEngine version %s', APP_VER));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/templates/htaccess.handlebars:
--------------------------------------------------------------------------------
1 |
2 | RewriteEngine On
3 | RewriteBase /
4 |
5 | # Removes index.php from ExpressionEngine URLs
6 | RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
7 | RewriteCond %{REQUEST_URI} !/{{systemFolder}}/.* [NC]
8 | RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
9 |
10 | # Directs all EE web requests through the site index file
11 | RewriteCond %{REQUEST_FILENAME} !-f
12 | RewriteCond %{REQUEST_FILENAME} !-d
13 | RewriteRule ^(.*)$ /index.php/$1 [L]
14 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldDateCommand.php:
--------------------------------------------------------------------------------
1 | '"Your Field Name" your_field_name 1',
26 | );
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldFieldpackListCommand.php:
--------------------------------------------------------------------------------
1 | '"Your Field Name" your_field_name 1',
26 | );
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldCheckboxesCommand.php:
--------------------------------------------------------------------------------
1 | '"Your Field Name" your_field_name 1',
24 | 'Create a Checkboxes field with multiple options' => '--option="Foo" --option="Bar" "Name" name 1',
25 | );
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/Db/MysqliTester.php:
--------------------------------------------------------------------------------
1 | hostname, $this->username, $this->password, $this->database);
15 |
16 | if ($connection === false) {
17 | $error = mysqli_connect_error();
18 |
19 | if ($error === 'No such file or directory') {
20 | $error = sprintf('Could not connect to socket %s', @ini_get('mysqli.default_socket'));
21 | }
22 |
23 | $this->setError($error);
24 |
25 | return false;
26 | }
27 |
28 | @mysqli_close($connection);
29 |
30 | return true;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldRadioCommand.php:
--------------------------------------------------------------------------------
1 | '"Your Field Name" your_field_name 1',
26 | 'Create a Radio field with multiple options' => '--option="Foo" --option="Bar" "Name" name 1',
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldSelectCommand.php:
--------------------------------------------------------------------------------
1 | '"Your Field Name" your_field_name 1',
26 | 'Create a Select field with multiple options' => '--option="Foo" --option="Bar" "Name" name 1',
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Command/ClearStashCacheCommand.php:
--------------------------------------------------------------------------------
1 | db->truncate('stash');
25 |
26 | $this->info('Stash cache cleared.');
27 | }
28 |
29 | /**
30 | * {@inheritdoc}
31 | */
32 | public function getExamples()
33 | {
34 | return array(
35 | 'Clear all caches' => '',
36 | );
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldMultiselectCommand.php:
--------------------------------------------------------------------------------
1 | '"Your Field Name" your_field_name 1',
26 | 'Create a Multiselect field with multiple options' => '--option="Foo" --option="Bar" "Name" name 1',
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Command/Command.php:
--------------------------------------------------------------------------------
1 | $method();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldStoreProductDetailsCommand.php:
--------------------------------------------------------------------------------
1 | array(
30 | 'enable_custom_prices' => 0,
31 | 'enable_custom_weights' => 0,
32 | ),
33 | );
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldFieldpackDropdownCommand.php:
--------------------------------------------------------------------------------
1 | '"Your Field Name" your_field_name 1',
26 | 'Create a Fieldpack Dropdown field with multiple options' => '--option="foo : Foo" --option="bar : Bar" "Name" name 1',
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "eecli/eecli",
3 | "description": "Command line interface for ExpressionEngine",
4 | "authors": [
5 | {
6 | "name": "Rob Sanchez",
7 | "email": "info@robsanchez.com"
8 | }
9 | ],
10 | "autoload": {
11 | "psr-4": { "eecli\\": "src/" }
12 | },
13 | "bin": [
14 | "bin/eecli"
15 | ],
16 | "require": {
17 | "php": ">=5.3.0",
18 | "eecli/addon-templates": "~1.0",
19 | "eecli/github-addon-installer": "~1.1",
20 | "illuminate/console": "~4.2|~5",
21 | "symfony/event-dispatcher": "~2.5|~3.0",
22 | "eecli/bootstrap": "~1.3",
23 | "d11wtq/boris": "~1.0",
24 | "xamin/handlebars.php": "~0.10",
25 | "symfony/finder": "~2.5|~3.0",
26 | "doctrine/instantiator": "~1.0,>=1.0.2",
27 | "symfony/process": "~2.5|~3.0"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldFieldpackCheckboxesCommand.php:
--------------------------------------------------------------------------------
1 | '"Your Field Name" your_field_name 1',
26 | 'Create a Fieldpack Checkboxes field with multiple options' => '--option="foo : Foo" --option="bar : Bar" "Name" name 1',
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldFieldpackMultiselectCommand.php:
--------------------------------------------------------------------------------
1 | '"Your Field Name" your_field_name 1',
26 | 'Create a Fieldpack Multiselect field with multiple options' => '--option="foo : Foo" --option="bar : Bar" "Name" name 1',
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldFieldpackRadioCommand.php:
--------------------------------------------------------------------------------
1 | '"Your Field Name" your_field_name 1',
26 | 'Create a Fieldpack Radio Buttons field with multiple options' => '--option="foo : Foo" --option="bar : Bar" "Name" name 1',
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/bootstrap.php:
--------------------------------------------------------------------------------
1 | setVendorPath($vendor_path);
22 |
23 | $app->fire('bootstrap.before');
24 |
25 | if ($app->canBeBootstrapped()) {
26 | require $vendor_path.'eecli/bootstrap/bootstrap-ee2.php';
27 | }
28 |
29 | $app->fire('bootstrap.after');
30 |
31 | $app->addComposerCommands();
32 | $app->addConditionalCommands();
33 | $app->addThirdPartyCommands();
34 | $app->addUserDefinedCommands();
35 | $app->addGlobalCommands();
36 |
37 | $app->run();
38 |
--------------------------------------------------------------------------------
/src/Db/MysqlTester.php:
--------------------------------------------------------------------------------
1 | hostname, $this->username, $this->password);
13 |
14 | if ($connection === false) {
15 | $error = @mysql_error();
16 |
17 | if ($error === 'No such file or directory') {
18 | $error = sprintf('Could not connect to socket %s', @ini_get('mysql.default_socket'));
19 | }
20 |
21 | $this->setError($error);
22 |
23 | return false;
24 | }
25 |
26 | $db = @mysql_select_db($this->database, $connection);
27 |
28 | if ($db === false) {
29 | $this->setError(@mysql_error());
30 |
31 | return false;
32 | }
33 |
34 | @mysql_close($connection);
35 |
36 | return true;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldFieldpackPillCommand.php:
--------------------------------------------------------------------------------
1 | '"Your Field Name" your_field_name 1',
31 | 'Create a Fieldpack Pill field with multiple options' => '--option="foo : Foo" --option="bar : Bar" "Name" name 1',
32 | );
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Rob Sanchez
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/Command/AbstractCreateFieldFieldpackOptionsCommand.php:
--------------------------------------------------------------------------------
1 | getOptionPrefix().'_options' => implode("\n", $this->option('option')),
31 | );
32 | }
33 |
34 | protected function getOptionPrefix()
35 | {
36 | return $this->getFieldtype();
37 | }
38 |
39 | protected function getFieldtypeOptionExamples()
40 | {
41 | return array(
42 | 'option' => 'option_value : Option Label',
43 | );
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/Command/ShowTemplatesCommand.php:
--------------------------------------------------------------------------------
1 | db->from('templates')
25 | ->select('template_id')
26 | ->select("CONCAT(IF (is_site_default = 'y' AND template_name = 'index', '*', ''), group_name, '/', template_name) AS template", false)
27 | ->join('template_groups', 'template_groups.group_id = templates.group_id')
28 | ->order_by('group_order', 'asc')
29 | ->order_by('template_name', 'asc')
30 | ->get();
31 |
32 | $templates = $query->result_array();
33 |
34 | $query->free_result();
35 |
36 | $this->table(array('ID', 'Template'), $templates);
37 | }
38 |
39 | /**
40 | * {@inheritdoc}
41 | */
42 | public function getExamples()
43 | {
44 | return array(
45 | 'List all of the templates found in the database' => '',
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Command/ConsoleCommand.php:
--------------------------------------------------------------------------------
1 | setAliases(array(
25 | 'repl',
26 | ));
27 | }
28 |
29 | /**
30 | * {@inheritdoc}
31 | */
32 | protected function fire()
33 | {
34 | $requiredExtensions = array('readline', 'posix', 'pcntl');
35 |
36 | foreach ($requiredExtensions as $extension) {
37 | if (! extension_loaded($extension)) {
38 | throw new \Exception(sprintf('PHP %s extension is required for this command.', $extension));
39 | }
40 | }
41 |
42 | $boris = new Boris('> ');
43 |
44 | $boris->start();
45 | }
46 |
47 | /**
48 | * {@inheritdoc}
49 | */
50 | public function getLongDescription()
51 | {
52 | return <<cp_theme = $theme;
17 | $this->cp_theme_url = $themeUrl;
18 | $this->EE = get_instance();
19 | }
20 |
21 | /**
22 | * Get the stored view variables
23 | * @return array
24 | */
25 | public function getVariables()
26 | {
27 | // get cached view vars
28 | $reflector = new \ReflectionClass('EE_Loader');
29 |
30 | $property = $reflector->getProperty('_ci_cached_vars');
31 |
32 | $property->setAccessible(true);
33 |
34 | $variables = $property->getValue(ee()->load);
35 |
36 | if (! is_array($variables)) {
37 | return $this->variables;
38 | }
39 |
40 | return array_merge($variables, $this->variables);
41 | }
42 |
43 | /**
44 | * Override the parent class' render method
45 | *
46 | * Don't render anything, simply save the view
47 | * variables for later usage. See getViewData().
48 | * @param string $view
49 | * @param array $data
50 | * @param boolean $return
51 | * @return void
52 | */
53 | public function render($view, $data = array(), $return = false)
54 | {
55 | $this->variables = array_merge($this->variables, $data);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldRteCommand.php:
--------------------------------------------------------------------------------
1 | $this->option('rows'),
53 | 'rte_field_text_direction' => $this->option('text_direction'),
54 | );
55 | }
56 |
57 | public function getExamples()
58 | {
59 | return array(
60 | 'Create an RTE field in field group 1' => '"Your Field Name" your_field_name 1',
61 | );
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/templates/Command.php.handlebars:
--------------------------------------------------------------------------------
1 | argument('type') ?: 'all';
42 |
43 | if (! in_array($type, $validTypes)) {
44 | $this->error('Invalid cache type');
45 |
46 | return;
47 | }
48 |
49 | ee()->functions->clear_caching($type);
50 |
51 | $suffix = $type === 'all' ? '' : ' '.$type;
52 |
53 | $this->info('EE'.$suffix.' cache cleared.');
54 | }
55 |
56 | /**
57 | * {@inheritdoc}
58 | */
59 | public function getExamples()
60 | {
61 | return array(
62 | 'Clear all EE caches' => '',
63 | 'Clear EE page caches' => 'page',
64 | 'Clear EE db caches' => 'db',
65 | 'Clear EE tag caches' => 'tag',
66 | );
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldGroupCommand.php:
--------------------------------------------------------------------------------
1 | getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\AdminContentController');
40 |
41 | $name = $this->argument('name');
42 |
43 | $_POST = array(
44 | 'group_name' => $name,
45 | );
46 |
47 | ee()->field_group_update();
48 |
49 | if (ee()->output->getErrorMessage()) {
50 | $this->error(ee()->output->getErrorMessage());
51 |
52 | return;
53 | }
54 |
55 | $query = ee()->db->select('group_id')
56 | ->where('group_name', $name)
57 | ->where('site_id', ee()->config->item('site_id'))
58 | ->get('field_groups');
59 |
60 | $this->info(sprintf('Field group %s (%s) created.', $name, $query->row('group_id')));
61 |
62 | $query->free_result();
63 | }
64 |
65 | public function getExamples()
66 | {
67 | return array(
68 | 'Create a field group' => 'Blog',
69 | );
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Command/CreateStatusGroupCommand.php:
--------------------------------------------------------------------------------
1 | getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\AdminContentController');
41 |
42 | $name = $this->argument('name');
43 |
44 | $_POST = array(
45 | 'group_name' => $name,
46 | );
47 |
48 | ee()->status_group_update();
49 |
50 | if (ee()->output->getErrorMessage()) {
51 | $this->error(ee()->output->getErrorMessage());
52 |
53 | return;
54 | }
55 |
56 | $query = ee()->db->select('group_id')
57 | ->where('group_name', $name)
58 | ->get('status_groups');
59 |
60 | $this->info(sprintf('Status group %s (%s) created.', $name, $query->row('group_id')));
61 |
62 | $query->free_result();
63 | }
64 |
65 | public function getExamples()
66 | {
67 | return array(
68 | 'Create a status group' => 'your_group_name',
69 | );
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Command/CreateCategoryGroupCommand.php:
--------------------------------------------------------------------------------
1 | getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\AdminContentController');
40 |
41 | $name = $this->argument('name');
42 |
43 | $_POST = array(
44 | 'group_name' => $name,
45 | 'field_html_formatting' => 'all',
46 | 'exclude_group' => '0',
47 | );
48 |
49 | ee()->update_category_group();
50 |
51 | $this->getApplication()->checkForErrors(true);
52 |
53 | $query = ee()->db->select('group_id')
54 | ->where('group_name', $name)
55 | ->where('site_id', ee()->config->item('site_id'))
56 | ->get('category_groups');
57 |
58 | $this->info(sprintf('Category group %s (%s) created.', $name, $query->row('group_id')));
59 |
60 | $query->free_result();
61 | }
62 |
63 | public function getExamples()
64 | {
65 | return array(
66 | 'Create a category group' => '"Art and Science"',
67 | );
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldGridCommand.php:
--------------------------------------------------------------------------------
1 | $this->option('min_rows'),
53 | 'grid_max_rows' => $this->option('max_rows'),
54 | 'grid' => array(
55 | 'cols' => array(),
56 | ),
57 | );
58 | }
59 |
60 | protected function getFieldtypeOptionExamples()
61 | {
62 | return array(
63 | 'max_rows' => '3',
64 | );
65 | }
66 |
67 | public function getExamples()
68 | {
69 | return array(
70 | 'Create a Grid field in field group 1' => '"Your Field Name" your_field_name 1',
71 | 'Create a Grid field with max and min rows' => '--min_rows="1" --max_rows="3" "Name" name 1',
72 | );
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/Command/SyncTemplatesCommand.php:
--------------------------------------------------------------------------------
1 | config->item('save_tmpl_files') !== 'y' || ! ee()->config->item('tmpl_file_basepath')) {
23 | $this->error('The "Save Templates as Files" system configuration must be turned on to use this command.');
24 |
25 | return;
26 | }
27 |
28 | $this->getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\DesignController');
29 |
30 | ee()->sync_templates();
31 |
32 | $vars = ee()->cp->getVariables();
33 |
34 | $toggle = array();
35 |
36 | foreach ($vars['templates'] as $groupName => $templates) {
37 | foreach ($templates as $templateName => $templateData) {
38 | if (isset($templateData['toggle']) && preg_match('#name="toggle\[\]" value="(.*?)"#', $templateData['toggle'], $match)) {
39 | $toggle[] = $match[1];
40 | }
41 | }
42 | }
43 |
44 | if (empty($toggle)) {
45 | $this->error('There are no templates to sync.');
46 |
47 | return;
48 | }
49 |
50 | $_POST = array(
51 | 'confirm' => 'confirm',
52 | 'toggle' => $toggle,
53 | );
54 |
55 | ee()->sync_run();
56 |
57 | if (ee()->functions->getErrorMessage()) {
58 | $this->error(ee()->functions->getErrorMessage());
59 |
60 | return;
61 | }
62 |
63 | if (ee()->functions->getSuccessMessage()) {
64 | $this->info(ee()->functions->getSuccessMessage());
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldMatrixCommand.php:
--------------------------------------------------------------------------------
1 | array(
53 | 'min_rows' => $this->option('min_rows'),
54 | 'max_rows' => $this->option('max_rows'),
55 | 'col_order' => array(),
56 | 'cols' => array(),
57 | ),
58 | );
59 | }
60 |
61 | protected function getFieldtypeOptionExamples()
62 | {
63 | return array(
64 | 'max_rows' => '3',
65 | );
66 | }
67 |
68 | public function getExamples()
69 | {
70 | return array(
71 | 'Create a Matrix field in field group 1' => '"Your Field Name" your_field_name 1',
72 | 'Create a Matrix field with max and min rows' => '--min_rows="1" --max_rows="3" "Name" name 1',
73 | );
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/Command/AbstractCreateFieldNativeOptionsCommand.php:
--------------------------------------------------------------------------------
1 | getFieldtype().'_field_fmt' => $this->option('format'),
50 | $this->getFieldtype().'_field_show_fmt' => $this->option('show_format') ? 'y' : 'n',
51 | $this->getFieldtype().'_field_list_items' => implode("\n", $this->option('option')),
52 | $this->getFieldtype().'_field_pre_populate' => $this->option('pre_populate') ? 'y' : 'n',
53 | $this->getFieldtype().'_field_pre_populate_id' => $this->option('pre_populate'),
54 | );
55 | }
56 |
57 | public function getFieldtypeOptionExamples()
58 | {
59 | return array(
60 | 'option' => 'Foo',
61 | 'pre_populate' => '1',
62 | );
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Db/ConnectionTester.php:
--------------------------------------------------------------------------------
1 | hostname = $hostname;
35 | $this->username = $username;
36 | $this->password = $password;
37 | $this->database = $database;
38 | }
39 |
40 | /**
41 | * Test whether a valid DB connection can
42 | * be made with the specified credentials
43 | * @return bool
44 | */
45 | abstract public function test();
46 |
47 | /**
48 | * Set the error message
49 | * @param string $error
50 | */
51 | public function setError($error)
52 | {
53 | $this->error = $error;
54 | }
55 |
56 | /**
57 | * Get the error message
58 | * @return string|null
59 | */
60 | public function getError()
61 | {
62 | return $this->error;
63 | }
64 |
65 | /**
66 | * Create a new DB tester instance depending
67 | * on the driver specified.
68 | *
69 | * @param string $driver mysql or mysqli
70 | * @param string $hostname
71 | * @param string $username
72 | * @param string $password
73 | * @param string $database
74 | * @return \eecli\Db\ConnectionTester
75 | */
76 | public static function create($driver, $hostname, $username, $password, $database)
77 | {
78 | switch ($driver) {
79 | case 'mysql':
80 | return new MysqlTester($hostname, $username, $password, $database);
81 | case 'mysqli':
82 | return new MysqliTester($hostname, $username, $password, $database);
83 | }
84 |
85 | throw new \Exception(sprintf('Unsupported DB driver %s', $driver));
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/Console/GlobalArgvInput.php:
--------------------------------------------------------------------------------
1 | commandName = current($tokens);
40 |
41 | $this->originalTokens = $tokens;
42 |
43 | parent::__construct($argv, $definition);
44 | }
45 |
46 | /**
47 | * Get the command name
48 | * @return string
49 | */
50 | public function getCommandName()
51 | {
52 | return $this->commandName;
53 | }
54 |
55 | /**
56 | * Get the input definition
57 | * @return \Symfony\Component\Console\Input\InputDefinition
58 | */
59 | public function getDefinition()
60 | {
61 | return $this->definition;
62 | }
63 |
64 | /**
65 | * {@inheritdoc}
66 | */
67 | protected function parse()
68 | {
69 | $parsed = $tokens = $this->originalTokens;
70 |
71 | while (null !== $token = array_shift($parsed)) {
72 | $this->setTokens(array($token));
73 | try {
74 | parent::parse();
75 | } catch (RuntimeException $e) {
76 | // ignore these errors, otherwise re-throw it
77 | if (! preg_match('/^Too many arguments|^No arguments expected|does not exist\.$/', $e->getMessage())) {
78 | throw $e;
79 | }
80 | }
81 | }
82 |
83 | $this->setTokens($tokens);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/Command/ShowFieldGroupsCommand.php:
--------------------------------------------------------------------------------
1 | db->from('field_groups');
40 |
41 | ee()->db->where('field_groups.site_id', ee()->config->item('site_id'));
42 |
43 | $headers = array('Group ID');
44 |
45 | ee()->db->select('field_groups.group_id');
46 |
47 | $headers[] = 'Group Name';
48 |
49 | ee()->db->select('field_groups.group_name');
50 |
51 | $headers[] = 'Channels';
52 |
53 | ee()->db->select('GROUP_CONCAT(channel_name SEPARATOR ";") AS channels');
54 |
55 | ee()->db->join('channels', 'channels.field_group = field_groups.group_id', 'left');
56 | ee()->db->group_by('field_groups.group_id');
57 |
58 | if ($this->option('channel')) {
59 |
60 | ee()->db->where_in('channels.channel_name', $this->option('channel'));
61 | }
62 |
63 | $query = ee()->db->get();
64 |
65 | $results = $query->result_array();
66 |
67 | // alter the results and replace the semicolon with commas as CI driver doesn't like
68 | // commas in DB selects and its best not to deactivate escaping and sanitising functions
69 | $results = array_map(function($a) {
70 | return array_merge($a, array(
71 | 'channels' => str_replace(';', ',', $a['channels']),
72 | ));
73 | }, $results);
74 |
75 | $query->free_result();
76 |
77 | $this->table($headers, $results);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # eecli
2 |
3 | `eecli` is a command line interface for ExpressionEngine 2. It can be used to:
4 |
5 | * aid in development, like creating new channels or generating a custom addon.
6 | * run post-deployment tasks on your staging/production server(s), like clearing cache.
7 | * automate critical tasks, like database backup
8 | * build your own custom CLI commands, like import scripts or cron jobs
9 | * debug using an interactive shell
10 |
11 | 
12 |
13 | ## Installation
14 |
15 | The preferred installation method is to install globally with [Composer](https://getcomposer.org/). Refer the official composer documentation for more information on [installing Composer globally](https://getcomposer.org/doc/00-intro.md#globally). Run this at the command line:
16 |
17 | ```
18 | $ composer global require eecli/eecli
19 | ```
20 |
21 | Make sure your global Composer installation's bin folder is added to your PATH in your `~/.bash_profile` (or `~/.profile` or `~/.bashrc` or `~/.zshrc`) so that you may run the binary `eecli` from the command line:
22 |
23 | ```
24 | export PATH=~/.composer/vendor/bin:$PATH
25 | ```
26 |
27 | For more installation methods, please see the [full Installation guide](https://github.com/rsanchez/eecli/wiki/Installation) in the Wiki.
28 |
29 | ## Usage
30 |
31 | ```
32 | $ eecli [options] [argument1] [argument2]
33 | ```
34 |
35 | To see a list of available commands, simply type eecli at the root of your project installation:
36 |
37 | ```
38 | $ eecli
39 | ```
40 |
41 | For detailed information on a specific command, use the help command:
42 |
43 | ```
44 | $ eecli help
45 | ```
46 |
47 | To generate a new config file, use the init command:
48 |
49 | ```
50 | $ eecli init
51 | ```
52 |
53 | ## Documentation
54 |
55 | For more details on installation, configuration and a command reference, see the [Wiki](https://github.com/rsanchez/eecli/wiki).
56 |
57 | ## Requirements
58 |
59 | * PHP 5.3+
60 | * ExpressionEngine 2.5 - 2.10 (Does *not* work with ExpressionEngine 3).
61 |
62 | ## Contributing
63 |
64 | See [CONTRIBUTING](https://github.com/rsanchez/eecli/blob/master/CONTRIBUTING.md) for more information.
65 |
66 | ## License
67 |
68 | `eecli` is released under the MIT License. See the bundled [LICENSE file](https://github.com/rsanchez/eecli/blob/master/LICENSE.txt).
--------------------------------------------------------------------------------
/src/Handlebars/Loader/FilesystemLoader.php:
--------------------------------------------------------------------------------
1 | normalizePath($match[1]), '/');
26 | }
27 |
28 | return parent::sanitizeDirectory($dir);
29 | }
30 |
31 | /**
32 | * Normalize path.
33 | *
34 | * From https://github.com/thephpleague/flysystem/blob/master/src/Util.php
35 | *
36 | * @param string $path
37 | *
38 | * @throws LogicException
39 | *
40 | * @return string
41 | */
42 | protected function normalizePath($path)
43 | {
44 | // Remove any kind of funky unicode whitespace
45 | $normalized = preg_replace('#\p{C}+|^\./#u', '', $path);
46 | $normalized = $this->normalizeRelativePath($normalized);
47 | if (preg_match('#/\.{2}|^\.{2}/|^\.{2}$#', $normalized)) {
48 | throw new LogicException(
49 | 'Path is outside of the defined root, path: [' . $path . '], resolved: [' . $normalized . ']'
50 | );
51 | }
52 | $normalized = preg_replace('#\\\{2,}#', '\\', trim($normalized, '\\'));
53 | $normalized = preg_replace('#/{2,}#', '/', trim($normalized, '/'));
54 | return $normalized;
55 | }
56 |
57 | /**
58 | * Normalize relative directories in a path.
59 | *
60 | * From https://github.com/thephpleague/flysystem/blob/master/src/Util.php
61 | *
62 | * @param string $path
63 | *
64 | * @return string
65 | */
66 | protected function normalizeRelativePath($path)
67 | {
68 | // Path remove self referring paths ("/./").
69 | $path = preg_replace('#/\.(?=/)|^\./|/\./?$#', '', $path);
70 | // Regex for resolving relative paths
71 | $regex = '#/*[^/\.]+/\.\.#Uu';
72 | while (preg_match($regex, $path)) {
73 | $path = preg_replace($regex, '', $path);
74 | }
75 | return $path;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldWygwamCommand.php:
--------------------------------------------------------------------------------
1 | option('config');
50 |
51 | if (! $config) {
52 | $query = ee()->db->select('config_id')
53 | ->order_by('config_id', 'asc')
54 | ->limit(1)
55 | ->get('wygwam_configs');
56 |
57 | $config = $query->row('config_id');
58 |
59 | $query->free_result();
60 |
61 | if (! $config) {
62 | throw new \RuntimeException('You must first create a Wygwam configuration.');
63 | }
64 | }
65 |
66 | return array(
67 | 'wygwam' => array(
68 | 'config' => $config,
69 | 'defer' => $this->option('defer') ? 'y' : 'n',
70 | ),
71 | );
72 | }
73 |
74 | protected function getFieldtypeOptionExamples()
75 | {
76 | return array(
77 | 'config' => '1',
78 | );
79 | }
80 |
81 | public function getExamples()
82 | {
83 | return array(
84 | 'Create a Wygwam field in field group 1' => '"Your Field Name" your_field_name 1',
85 | 'Create a Wygwam field with Wygwam configuration 1' => '--config=1 "Name" name 1',
86 | 'Create a Wygwam field with deferred initialization' => '--defer "Name" name 1',
87 | );
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/Command/InitCommand.php:
--------------------------------------------------------------------------------
1 | confirm('A configuration file already exists. Do you want to overwrite? y[n]', false);
31 |
32 | if (! $confirmed) {
33 | return;
34 | }
35 | }
36 |
37 | $source = file_get_contents(__DIR__.'/../../sample.eecli.php');
38 |
39 | if ($source === false) {
40 | $this->error('Could not read the sample.eecli.php file.');
41 |
42 | return;
43 | }
44 |
45 | $systemPath = $this->getApplication()->getSystemPath();
46 |
47 | if ($systemPath) {
48 | $cwdLength = strlen($cwd);
49 |
50 | //check if the system path is in the cwd
51 | if (strncmp($cwd, $systemPath, $cwdLength) === 0) {
52 | $systemPath = substr($systemPath, $cwdLength);
53 |
54 | $replacement = "__DIR__.'{$systemPath}'";
55 | } else {
56 | $replacement = "'{$systemPath}'";
57 | }
58 |
59 | $source = str_replace("__DIR__.'/system'", $replacement, $source);
60 | }
61 |
62 | $handle = fopen($destination, 'w');
63 |
64 | if ($handle === false) {
65 | $this->error('Could not open '.$destination.' for writing.');
66 |
67 | return;
68 | }
69 |
70 | $write = fwrite($handle, $source);
71 |
72 | if ($write === false) {
73 | $this->error('Could not write to '.$destination);
74 |
75 | return;
76 | }
77 |
78 | fclose($handle);
79 |
80 | $this->info('Configuration file created.');
81 | }
82 |
83 | /**
84 | * {@inheritdoc}
85 | */
86 | public function getLongDescription()
87 | {
88 | return << array(
73 | 'off_label' => $this->option('off_label'),
74 | 'off_val' => $this->option('off_value'),
75 | 'on_label' => $this->option('on_label'),
76 | 'on_val' => $this->option('on_value'),
77 | 'default' => $this->option('default'),
78 | ),
79 | );
80 | }
81 |
82 | public function getExamples()
83 | {
84 | return array(
85 | 'Create a Fieldpack Switch field in field group 1' => '"Your Field Name" your_field_name 1',
86 | 'Create a Fieldpack Switch field with options' => '--off_label="Nope" --on_label="Yep" "Name" name 1',
87 | );
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldFileCommand.php:
--------------------------------------------------------------------------------
1 | $this->option('content_type'),
66 | 'file_allowed_directories' => $this->option('upload_dir'),
67 | 'file_show_existing' => $this->option('hide_existing') ? 'n' : 'y',
68 | 'file_num_existing' => $this->option('limit'),
69 | );
70 | }
71 |
72 | protected function getFieldtypeOptionExamples()
73 | {
74 | return array(
75 | 'upload_dir' => '1',
76 | );
77 | }
78 |
79 | public function getExamples()
80 | {
81 | return array(
82 | 'Create a File field in field group 1' => '"Your Field Name" your_field_name 1',
83 | 'Create a File field that uploads to directory 1' => '--upload_dir=1 "Your Field Name" your_field_name 1',
84 | 'Create a File field that only allows images' => '--content_type=image "Your Field Name" your_field_name 1',
85 | );
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/Command/ShowConfigCommand.php:
--------------------------------------------------------------------------------
1 | argument('key');
55 |
56 | if ($key) {
57 | $value = $this->dump(ee()->config->item($key));
58 |
59 | $this->line($value);
60 |
61 | return;
62 | }
63 |
64 | $headers = array('Key', 'Value');
65 |
66 | $rows = array();
67 |
68 | $config = ee()->config->config;
69 |
70 | ksort($config);
71 |
72 | foreach ($config as $key => $value) {
73 | if (! is_string($value) && ! is_int($value) && ! is_float($value)) {
74 | $value = $this->dump($value);
75 | }
76 |
77 | $rows[] = array($key, $value);
78 | }
79 |
80 | $this->table($headers, $rows);
81 | }
82 |
83 | /**
84 | * {@inheritdoc}
85 | */
86 | public function getExamples()
87 | {
88 | return array(
89 | 'Show all config items' => '',
90 | 'Show the specified config item' => 'site_label',
91 | );
92 | }
93 |
94 | /**
95 | * {@inheritdoc}
96 | */
97 | public function getLongDescription()
98 | {
99 | return <<db->from('category_groups');
40 |
41 | ee()->db->where('category_groups.site_id', ee()->config->item('site_id'));
42 |
43 | $headers = array('Group ID');
44 |
45 | ee()->db->select('category_groups.group_id');
46 |
47 | $headers[] = 'Group Name';
48 |
49 | ee()->db->select('category_groups.group_name');
50 |
51 | $headers[] = 'Channels';
52 |
53 | ee()->db->select('GROUP_CONCAT(channel_name SEPARATOR ";") AS channels');
54 |
55 | // I know it looks bad but we have to drop the protect identifiers here to get the join working
56 | $existingProtectIdentifiers = ee()->db->_protect_identifiers;
57 | ee()->db->_protect_identifiers = false;
58 | ee()->db->join('channels', 'FIND_IN_SET(group_id, REPLACE(cat_group, "|", ",")) > 0', 'left');
59 | ee()->db->_protect_identifiers = $existingProtectIdentifiers;
60 |
61 | ee()->db->group_by('category_groups.group_id');
62 |
63 | if ($this->option('channel')) {
64 |
65 | ee()->db->where_in('channels.channel_name', $this->option('channel'));
66 | }
67 |
68 | $query = ee()->db->get();
69 |
70 | $results = $query->result_array();
71 |
72 | // alter the results and replace the semicolon with commas as CI driver doesn't like
73 | // commas in DB selects and its best not to deactivate escaping and sanitising functions
74 | $results = array_map(function($a) {
75 | return array_merge($a, array(
76 | 'channels' => str_replace(';', ',', $a['channels']),
77 | ));
78 | }, $results);
79 |
80 | $query->free_result();
81 |
82 | $this->table($headers, $results);
83 | }
84 | }
85 |
86 |
--------------------------------------------------------------------------------
/src/Command/GenerateHtaccessCommand.php:
--------------------------------------------------------------------------------
1 | argument('path') ?: '.';
44 |
45 | // make sure it has a trailing slash
46 | $path = rtrim($path, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
47 |
48 | $handlebars = new Handlebars(array(
49 | 'loader' => new FilesystemLoader(__DIR__.'/../templates/'),
50 | ));
51 |
52 | $destination = $path.'.htaccess';
53 |
54 | if (file_exists($destination)) {
55 | $path = realpath($path).DIRECTORY_SEPARATOR;
56 |
57 | $confirmed = $this->confirm("An .htaccess file already exists in {$path}. Do you want to overwrite? [yN] ", false);
58 |
59 | if (! $confirmed) {
60 | $this->info('Did not create .htaccess file.');
61 |
62 | return;
63 | }
64 | }
65 |
66 | $handle = fopen($destination, 'w');
67 |
68 | $output = $handlebars->render('htaccess', array(
69 | 'systemFolder' => $this->getApplication()->getSystemFolder(),
70 | ));
71 |
72 | fwrite($handle, $output);
73 |
74 | fclose($handle);
75 |
76 | $this->info($destination.' created.');
77 | }
78 |
79 | public function getLongDescription()
80 | {
81 | return 'Generate the official EE .htaccess file (as found in the [EE documentation](https://ellislab.com/expressionengine/user-guide/urls/remove_index.php.html)).';
82 | }
83 |
84 | public function getExamples()
85 | {
86 | return array(
87 | 'Generate .htaccess in the current directory' => '',
88 | );
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/sample.eecli.php:
--------------------------------------------------------------------------------
1 | /system
21 | */
22 | 'system_path' => __DIR__.'/system',
23 |
24 | /**
25 | * Spoof $_SERVER variables
26 | *
27 | * This array will be merged with $_SERVER.
28 | *
29 | * When using php from the command line,
30 | * things like HTTP_HOST and DOCUMENT_ROOT
31 | * do not get set.
32 | *
33 | * Useful if you check for $_SERVER items
34 | * at runtime, like changing DB
35 | * credentials based on HTTP_HOST
36 | * in your config.php.
37 | *
38 | * You can also set these at the command line:
39 | *
40 | * HTTP_HOST="foo.dev" eecli update:addons
41 | */
42 | 'server' => array(
43 | 'HTTP_HOST' => 'localhost',
44 | 'DOCUMENT_ROOT' => __DIR__,
45 | 'REQUEST_URI' => '/',
46 | 'REMOTE_ADDR' => '127.0.0.1',
47 | 'HTTP_USER_AGENT' => 'eecli',
48 | ),
49 |
50 | /**
51 | * Assign variables to config
52 | */
53 | 'assign_to_config' => array(
54 | #'foo' => 'bar',
55 | ),
56 |
57 | /**
58 | * Custom commands
59 | *
60 | * An array of Command class names of
61 | * custom commands.
62 | */
63 | 'commands' => array(
64 | #'\\Your\\Custom\\Command',
65 | ),
66 |
67 | /**
68 | * Custom command directories
69 | *
70 | * An array of directories, keyed by a namespace prefix,
71 | * which will be crawled for Command classes.
72 | */
73 | 'commandDirs' => array(
74 | /*
75 | '\\Your\\Namespace' => '/path/to/commands',
76 | */
77 | ),
78 |
79 | /**
80 | * Event Callbacks
81 | *
82 | * An array of callback functions to be
83 | * invoked on the specified event.
84 | */
85 | 'callbacks' => array(
86 | /*
87 | 'bootstrap.before' => function ($app) {
88 | },
89 | 'bootstrap.after' => function ($app) {
90 | },
91 | */
92 | ),
93 |
94 | /**
95 | * The default addon author name used when generating addons.
96 | */
97 | 'addon_author_name' => '',
98 |
99 | /**
100 | * The default addon author URL used when generating addons.
101 | */
102 | 'addon_author_url' => '',
103 | );
104 |
--------------------------------------------------------------------------------
/src/Command/ShowMembersCommand.php:
--------------------------------------------------------------------------------
1 | db->from('members');
55 |
56 | $headers = array();
57 |
58 | ee()->db->select('members.member_id');
59 | $headers[] = 'ID';
60 |
61 | ee()->db->join('member_groups', 'member_groups.group_id = members.group_id');
62 | $table = ee()->db->dbprefix('member_groups');
63 | ee()->db->select("CONCAT('(', {$table}.group_id, ') ', {$table}.group_title) AS group_name", FALSE);
64 | $headers[] = 'Group';
65 |
66 | ee()->db->select('members.username');
67 | $headers[] = 'Username';
68 |
69 | ee()->db->select('members.screen_name');
70 | $headers[] = 'Screen Name';
71 |
72 | ee()->db->select('members.email');
73 | $headers[] = 'Email';
74 |
75 | if ($this->option('group_id')) {
76 | ee()->db->where_in('members.group_id', $this->option('group_id'));
77 | }
78 |
79 | $search = $this->argument('search');
80 |
81 | if ($search) {
82 | if (is_numeric($search)) {
83 | ee()->db->where('members.member_id', $search);
84 | } else {
85 | ee()->db->like('members.username', $search)
86 | ->or_like('members.screen_name', $search)
87 | ->or_like('members.email', $search);
88 | }
89 | }
90 |
91 | $sql = ee()->db->_compile_select();
92 | ee()->db->_reset_select();
93 | $this->output->writeln($sql);
94 | $query = ee()->db->query($sql);
95 | //$query = ee()->db->get();
96 |
97 | $results = $query->result_array();
98 |
99 | $query->free_result();
100 |
101 | $this->table($headers, $results);
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/Command/DeleteTemplateGroupCommand.php:
--------------------------------------------------------------------------------
1 | argument('template_group');
57 |
58 | $this->getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\DesignController');
59 |
60 | if (! $this->option('force') && ! $this->confirm('Are you sure you want to delete? [Yn]', true)) {
61 | $this->error('Did not delete template group(s): '.implode(' ', $templateGroups));
62 |
63 | return;
64 | }
65 |
66 | foreach ($templateGroups as $groupName) {
67 | $query = ee()->db->select('group_id')
68 | ->where('group_name', $groupName)
69 | ->get('template_groups');
70 |
71 | if ($query->num_rows() === 0) {
72 | $this->error('Template group '.$groupName.' not found.');
73 | } else {
74 | $_POST = array(
75 | 'group_id' => $query->row('group_id'),
76 | );
77 |
78 | ee()->template_group_delete();
79 |
80 | $this->info('Template group '.$groupName.' deleted.');
81 | }
82 |
83 | $query->free_result();
84 | }
85 | }
86 |
87 | public function getLongDescription()
88 | {
89 | return 'Delete one or more template groups. You will be asked to confirm that you want to delete the specified templates(s), unless you use the `--force` option.';
90 | }
91 |
92 | public function getExamples()
93 | {
94 | return array(
95 | 'Delete a template group' => 'site',
96 | 'Delete multiple groups' => 'site news blog',
97 | 'Delete a template group without confirmation' => '--force site',
98 | );
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/CodeIgniter/Functions.php:
--------------------------------------------------------------------------------
1 | output = $output;
47 |
48 | $this->app = $app;
49 |
50 | // for EE 2.5
51 | $this->EE = get_instance();
52 | }
53 |
54 | /**
55 | * Suppress redirections and print any messages
56 | * stored in session flashdata
57 | *
58 | * @param string $location
59 | * @param boolean $method
60 | * @param int|null $statusCode
61 | * @return void
62 | */
63 | public function redirect($location, $method = false, $statusCode = null)
64 | {
65 | $this->successMessage = null;
66 | $this->errorMessage = null;
67 |
68 | $location = str_replace('&', '&', $location);
69 |
70 | if (substr_count($location, '?') > 1) {
71 | $location = substr($location, strpos($location, '?') + 1);
72 | }
73 |
74 | parse_str(parse_url($location, PHP_URL_QUERY), $this->variables);
75 |
76 | $success = ee()->session->flashdata(':new:message_success');
77 | $failure = ee()->session->flashdata(':new:message_failure');
78 |
79 | if ($failure) {
80 | $this->app->addError($failure);
81 |
82 | $this->errorMessage = $failure;
83 | }
84 |
85 | if ($success) {
86 | $this->successMessage = $success;
87 | }
88 | }
89 |
90 | /**
91 | * Reset errorMessage and successMessage to null
92 | * @return void
93 | */
94 | public function resetMessages()
95 | {
96 | $this->errorMessage = null;
97 | $this->successMessage = null;
98 | }
99 |
100 | /**
101 | * Get the flashdata error message
102 | * @return string|null
103 | */
104 | public function getErrorMessage()
105 | {
106 | return $this->errorMessage;
107 | }
108 |
109 | /**
110 | * Get the flashdata success message
111 | * @return string|null
112 | */
113 | public function getSuccessMessage()
114 | {
115 | return $this->successMessage;
116 | }
117 |
118 | /**
119 | * Get the redirect query string variables
120 | * @return array
121 | */
122 | public function getVariables()
123 | {
124 | return $this->variables;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/Command/ShowActionsCommand.php:
--------------------------------------------------------------------------------
1 | argument('action_id')) {
68 | ee()->db->where('action_id', $this->argument('action_id'));
69 | }
70 |
71 | $classes = $this->option('class') ?: [];
72 |
73 | if ($modules = $this->option('module')) {
74 | foreach ($modules as $module) {
75 | $classes[] = ucfirst($module);
76 | $classes[] = ucfirst($module).'_mcp';
77 | }
78 | }
79 |
80 | if ($classes) {
81 | ee()->db->where_in('class', $classes);
82 | }
83 |
84 | if ($methods = $this->option('method')) {
85 | ee()->db->where_in('method', $methods);
86 | }
87 |
88 | $query = ee()->db->order_by('action_id')
89 | ->get('actions');
90 |
91 | if ($query->num_rows() === 0) {
92 | if ($actionId) {
93 | $this->warning('There was no action found with the specified action_id.');
94 | } else {
95 | $this->warning('There were no actions found.');
96 | }
97 | } else {
98 | $results = $query->result_array();
99 |
100 | $headers = array('ID', 'Class', 'Method');
101 |
102 | if (array_key_exists('csrf_exempt', $results[0])) {
103 | $headers[] = 'CSRF Exempt';
104 | }
105 |
106 | $this->table($headers, $results);
107 | }
108 |
109 | $query->free_result();
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldAssetsCommand.php:
--------------------------------------------------------------------------------
1 | option('upload_dir');
70 |
71 | // validate these as ee:1, etc
72 | if ($dirs) {
73 | foreach ($dirs as $dir) {
74 | if (! preg_match('/^(ee|s3|rs|gc):(\d+)$/', $dir)) {
75 | throw new \RuntimeException('Upload dir is not in the proper format. ex. ee:1, sc:2');
76 | }
77 | }
78 | }
79 |
80 | return array(
81 | 'assets' => array(
82 | 'filedirs' => $dirs ?: array('all'),
83 | 'view' => $this->option('view'),
84 | 'thumb_size' => $this->option('thumb_size'),
85 | 'show_cols' => array('folder', 'date', 'size'),
86 | 'show_filenames' => $this->option('show_filenames') ? 'y' : 'n',
87 | 'multi' => $this->option('multiple') ? 'y' : 'n',
88 | ),
89 | );
90 | }
91 |
92 | public function getExamples()
93 | {
94 | return array(
95 | 'Create an Assets field in field group 1' => '"Your Field Name" your_field_name 1',
96 | 'Create an Assets field that uploads to EE directory 1' => '--upload_dir="ee:1" "Your Field Name" your_field_name 1',
97 | 'Create an Assets field that uploads to S3 directory 2' => '--upload_dir="s3:2" "Your Field Name" your_field_name 1',
98 | 'Create an Assets field that allows multiple selections' => '--multiple "Your Field Name" your_field_name 1',
99 | );
100 | }
101 |
102 | protected function getFieldtypeOptionExamples()
103 | {
104 | return array(
105 | 'upload_dir' => '1',
106 | );
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/Command/ShowFieldsCommand.php:
--------------------------------------------------------------------------------
1 | db->from('channel_fields');
52 |
53 | ee()->db->where('channel_fields.site_id', ee()->config->item('site_id'));
54 |
55 | $headers = array('ID');
56 |
57 | ee()->db->select('channel_fields.field_id');
58 |
59 | ee()->db->order_by('channel_fields.group_id', 'asc');
60 |
61 | ee()->db->order_by('channel_fields.field_order', 'asc');
62 |
63 | ee()->db->select('channel_fields.group_id');
64 |
65 | $headers[] = 'Group ID';
66 |
67 | ee()->db->join('field_groups', 'field_groups.group_id = channel_fields.group_id');
68 |
69 | ee()->db->select('field_groups.group_name');
70 |
71 | $headers[] = 'Group';
72 |
73 | if ($this->option('group_id')) {
74 | ee()->db->where_in('channel_fields.group_id', $this->option('group_id'));
75 | }
76 |
77 | if ($this->option('channel')) {
78 | ee()->db->join('channels', 'channels.field_group = channel_fields.group_id');
79 |
80 | ee()->db->where_in('channels.channel_name', $this->option('channel'));
81 | }
82 |
83 | if ($this->option('type')) {
84 | ee()->db->where_in('channel_fields.field_type', $this->option('type'));
85 | }
86 |
87 | ee()->db->select('channel_fields.field_name');
88 | $headers[] = 'Name';
89 |
90 | ee()->db->select('channel_fields.field_label');
91 | $headers[] = 'Label';
92 |
93 | ee()->db->select('channel_fields.field_type');
94 | $headers[] = 'Type';
95 |
96 | ee()->db->select('channel_fields.field_required');
97 | $headers[] = 'R';
98 |
99 | ee()->db->select('channel_fields.field_is_hidden');
100 | $headers[] = 'H';
101 |
102 | ee()->db->select('channel_fields.field_search');
103 | $headers[] = 'S';
104 |
105 | $query = ee()->db->get();
106 |
107 | $results = $query->result_array();
108 |
109 | $query->free_result();
110 |
111 | $this->table($headers, $results);
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/Command/GithubAddonInstallerCommand.php:
--------------------------------------------------------------------------------
1 | getApi()->setOutput($this->output);
55 |
56 | if (class_exists('\Symfony\Component\Console\Helper\ProgressBar')) {
57 | $installerApp->getApi()->setProgressBar(new ProgressBar($this->output));
58 | } else {
59 | $installerApp->getApi()->setProgressHelper($this->getHelperSet()->get('progress'));
60 | }
61 |
62 | $manifest = $installerApp->getManifest();
63 |
64 | $addon = $this->argument('addon');
65 |
66 | if (! $addon) {
67 | $dialog = $this->getHelper('dialog');
68 |
69 | $validation = function ($addon) use ($manifest) {
70 | if (! isset($manifest[$addon])) {
71 | throw new \InvalidArgumentException(sprintf('Addon "%s" is invalid.', $addon));
72 | }
73 |
74 | return $addon;
75 | };
76 |
77 | $addon = $dialog->askAndValidate($this->output, 'Which addon do you want to install? ', $validation, false, null, array_keys($manifest));
78 | }
79 |
80 | $branch = $this->argument('branch') ?: isset($manifest[$addon]['branch']) ? $manifest[$addon]['branch'] : 'master';
81 |
82 | $installerApp->installAddon($addon, $branch);
83 |
84 | $this->info($addon.' installed.');
85 | }
86 |
87 | public function getLongDescription()
88 | {
89 | return <<argument('template');
57 |
58 | $this->getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\DesignController');
59 |
60 | ee()->load->model('template_model');
61 | ee()->template = ee()->TMPL;
62 |
63 | if (! $this->option('force') && ! $this->confirm('Are you sure you want to delete? [Yn]', true)) {
64 | $this->error('Did not delete template(s): '.implode(' ', $templates));
65 |
66 | return;
67 | }
68 |
69 | foreach ($templates as $template) {
70 | if (! preg_match('#^[a-zA-Z0-9_\-]+/[a-zA-Z0-9_\-]+$#', $template)) {
71 | $this->error('Template '.$template.' must be in / format.');
72 |
73 | continue;
74 | }
75 |
76 | list($groupName, $templateName) = explode('/', $template);
77 |
78 | $query = ee()->db->select('template_id')
79 | ->join('template_groups', 'template_groups.group_id = templates.group_id')
80 | ->where('group_name', $groupName)
81 | ->where('template_name', $templateName)
82 | ->get('templates');
83 |
84 | if ($query->num_rows() === 0) {
85 | $this->error('Template '.$template.' not found.');
86 | } else {
87 | $_POST = array(
88 | 'template_id' => $query->row('template_id'),
89 | );
90 |
91 | ee()->template_delete();
92 |
93 | $this->info('Template '.$template.' deleted.');
94 | }
95 |
96 | $query->free_result();
97 | }
98 | }
99 |
100 | public function getLongDescription()
101 | {
102 | return 'Delete one or more templates. You will be asked to confirm that you want to delete the specified templates(s), unless you use the `--force` option.';
103 | }
104 |
105 | public function getExamples()
106 | {
107 | return array(
108 | 'Delete a template' => 'site/index',
109 | 'Delete multiple templates' => 'site/index site/foo',
110 | 'Delete a template without confirmation' => '--force site/index',
111 | );
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/Command/CreateGlobalVariableCommand.php:
--------------------------------------------------------------------------------
1 | argument('name');
63 |
64 | $siteId = ee()->config->item('site_id');
65 | $siteName = ee()->config->item('site_short_name');
66 |
67 | $contents = $this->argument('data');
68 |
69 | if ($this->option('stdin')) {
70 | $contents = '';
71 |
72 | $handle = fopen('php://stdin', 'r');
73 |
74 | while (($buffer = fgets($handle, 4096)) !== false) {
75 | $contents .= $buffer;
76 | }
77 | }
78 |
79 | $tempContents = $contents ? $contents : '{!--TEMP--}';
80 |
81 | $this->getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\DesignController');
82 |
83 | $_POST = array(
84 | 'variable_name' => $name,
85 | 'variable_data' => $tempContents,
86 | );
87 |
88 | ee()->global_variables_create();
89 |
90 | $query = ee()->db->where('variable_name', $name)
91 | ->where('site_id', $siteId)
92 | ->get('global_variables');
93 |
94 | // restore the blank contents
95 | if (! $contents) {
96 | ee()->db->update('global_variables', array('variable_data' => ''), array('variable_id' => $query->row('variable_id')));
97 | }
98 |
99 | ee()->extensions->call('eecli_create_global_variable', $query->row('variable_id'), $query->row('variable_name'), $query->row('variable_data'), $siteId, $siteName);
100 |
101 | $query->free_result();
102 |
103 | $this->info('Global variable '.$name.' created.');
104 | }
105 |
106 | public function getLongDescription()
107 | {
108 | return 'Create a global variable. When you have [Sync Snippets](https://github.com/rsanchez/sync_snippets) installed and configured, this command will write a global variable file as well.';
109 | }
110 |
111 | public function getExamples()
112 | {
113 | return array(
114 | 'Create a blank global variable' => 'your_global_variable_name',
115 | 'Create a global variable with content' => 'your_global_variable_name "your global variable content"',
116 | 'Pipe in content' => '--stdin your_global_variable_name',
117 | );
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/Command/DeleteEntryCommand.php:
--------------------------------------------------------------------------------
1 | argument('entry');
57 |
58 | $siteId = ee()->config->item('site_id');
59 | $siteName = ee()->config->item('site_short_name');
60 |
61 | $type = is_numeric($name) ? 'entry_id' : 'url_title';
62 |
63 | $query = ee()->db->select('entry_id, title')
64 | ->from('channel_titles')
65 | ->where('site_id', $siteId)
66 | ->where($type, $name)
67 | ->get();
68 |
69 | $name = is_numeric($name) ? $name : "“{$name}”";
70 |
71 | if ($query->num_rows() === 0) {
72 | $this->error(sprintf('Entry %s not found.', $name));
73 |
74 | return;
75 | }
76 |
77 | if ($query->num_rows() > 1) {
78 | throw new \RuntimeException("There were multiple entries with $name found");
79 | }
80 |
81 | ee()->load->library(array('api', 'stats'));
82 | ee()->api->instantiate('channel_entries');
83 |
84 | $entry_id = $query->row('entry_id');
85 | $title = $query->row('title');
86 |
87 | $query->free_result();
88 |
89 | //set group id to be a super admin
90 | ee()->session->userdata['group_id'] = '1';
91 | ee()->session->userdata['can_delete_all_entries'] = 'y';
92 |
93 | if (! $this->option('force') && ! $this->confirm('Are you sure you want to delete? [Yn]', true)) {
94 | $this->error(sprintf('Did not delete entry “%s” (%s)', $title, $entry_id));
95 |
96 | return;
97 | }
98 |
99 | $delete = ee()->api_channel_entries->delete_entry((int) $entry_id);
100 |
101 | if ($delete) {
102 | $this->info(sprintf('Entry “%s” (%s) deleted.', $title, $entry_id));
103 | } else {
104 | foreach (ee()->api_channel_entries->errors as $error) {
105 | $this->error($error);
106 | }
107 | }
108 | }
109 |
110 | public function getLongDescription()
111 | {
112 | return 'Delete an entry by entering in an entry_id or url_title. You will be asked to confirm that you want to delete the specified entry, unless you use the `--force` option.';
113 | }
114 |
115 | public function getExamples()
116 | {
117 | return array(
118 | 'Delete an entry by the entry_id' => '123',
119 | 'Delete an entry by the url_title' => 'entry_be_gone',
120 | 'Delete an entry by the entry_id without confirmation' => '--force 123',
121 | );
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/src/Command/DeleteSnippetCommand.php:
--------------------------------------------------------------------------------
1 | argument('name');
64 |
65 | $siteId = $this->option('global') ? 0 : ee()->config->item('site_id');
66 | $siteName = $this->option('global') ? 'global_snippets' : ee()->config->item('site_short_name');
67 |
68 | if (! $this->option('force') && ! $this->confirm('Are you sure you want to delete? [Yn]', true)) {
69 | $this->error('Did not delete snippet(s): '.implode(' ', $names));
70 |
71 | return;
72 | }
73 |
74 | $query = ee()->db->select('snippet_id, snippet_name, snippet_contents')
75 | ->where('site_id', $siteId)
76 | ->where_in('snippet_name', $names)
77 | ->get('snippets');
78 |
79 | $snippets = array();
80 |
81 | foreach ($query->result() as $row) {
82 | $snippets[$row->snippet_name] = $row;
83 | }
84 |
85 | $query->free_result();
86 |
87 | foreach ($names as $name) {
88 | if (! isset($snippets[$name])) {
89 | $this->error('Snippet '.$name.' not found.');
90 |
91 | continue;
92 | }
93 |
94 | $snippet = $snippets[$name];
95 |
96 | ee()->db->delete('snippets', array('snippet_id' => $snippet->snippet_id));
97 |
98 | ee()->extensions->call('eecli_delete_snippet', $snippet->snippet_id, $snippet->snippet_name, $snippet->snippet_contents, $siteId, $siteName);
99 |
100 | $this->info('Snippet '.$name.' deleted.');
101 | }
102 | }
103 |
104 | public function getLongDescription()
105 | {
106 | return "Delete one or more snippets. You will be asked to confirm that you want to delete the specified snippet(s), unless you use the `--force` option.\n\nWhen you have [Sync Snippets](https://github.com/rsanchez/sync_snippets) installed and configured, this command will delete the snippet file as well.";
107 | }
108 |
109 | public function getExamples()
110 | {
111 | return array(
112 | 'Delete a snippet' => 'your_snippet_name',
113 | 'Delete a snippet accessible to all sites' => '--global your_snippet_name',
114 | 'Delete multiple snippets' => 'your_snippet_name your_other_snippet_name',
115 | 'Delete a snippet without confirmation' => '--force your_snippet_name',
116 | );
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/CodeIgniter/ConsoleOutput.php:
--------------------------------------------------------------------------------
1 | app = $app;
35 |
36 | $this->output = $output;
37 |
38 | // you need to load the template library to override the fatal error
39 | ee()->load->library('template', null, 'TMPL');
40 | }
41 |
42 | /**
43 | * Reset errorMessage and successMessage to null
44 | * @return void
45 | */
46 | public function resetMessages()
47 | {
48 | $this->errorMessage = null;
49 | $this->successMessage = null;
50 | }
51 |
52 | /**
53 | * Suppress any header-setting
54 | * @param string $header
55 | * @param boolean $replace
56 | */
57 | public function set_header($header, $replace = true)
58 | {
59 | }
60 |
61 | /**
62 | * {@inheritdoc}
63 | */
64 | public function fatal_error($errorMessage = '', $useLang = true)
65 | {
66 | $errorMessage = str_replace('« Back', '', $errorMessage);
67 |
68 | $errorMessage = strip_tags($errorMessage);
69 |
70 | $this->output->writeln("{$errorMessage}");
71 |
72 | exit;
73 | }
74 |
75 | /**
76 | * Get a success message
77 | * @return string|null
78 | */
79 | public function getSuccessMessage()
80 | {
81 | return $this->successMessage;
82 | }
83 |
84 | /**
85 | * Get an error message
86 | * @return string|null
87 | */
88 | public function getErrorMessage()
89 | {
90 | return $this->errorMessage;
91 | }
92 |
93 | /**
94 | * {@inheritdoc}
95 | */
96 | public function send_ajax_response($data, $error = false)
97 | {
98 | $this->resetMessages();
99 |
100 | $property = $error ? 'errorMessage' : 'successMessage';
101 |
102 | if (is_scalar($data)) {
103 | $this->{$property} = $data;
104 | } elseif (! empty($data['error'])) {
105 | $this->errorMessage = $data['error'];
106 | } elseif (! empty($data['message_failure'])) {
107 | $this->errorMessage = $data['message_failure'];
108 | } elseif (! empty($data['success'])) {
109 | $this->successMessage = $data['success'];
110 | } elseif (! empty($data['message_success'])) {
111 | $this->successMessage = $data['message_success'];
112 | } elseif (is_array($data) && is_string(current($data))) {
113 | $this->{$property} = implode(PHP_EOL, $data);
114 | } else {
115 | $this->{$property} = print_r($data, true);
116 | }
117 | }
118 |
119 | /**
120 | * {@inheritdoc}
121 | */
122 | public function show_message($data, $xhtml = true)
123 | {
124 | $this->resetMessages();
125 |
126 | if (isset($data['content'])) {
127 | $this->successMessage = strip_tags($data['content']);
128 | } else {
129 | $this->successMessage = '';
130 | }
131 | }
132 |
133 | /**
134 | * {@inheritdoc}
135 | */
136 | public function show_user_error($type, $errors, $heading = '')
137 | {
138 | $this->resetMessages();
139 |
140 | if (! is_array($errors)) {
141 | $errors = array($errors);
142 | }
143 |
144 | foreach ($errors as $error) {
145 | $this->app->addError($error);
146 | }
147 |
148 | $this->errorMessage = implode(PHP_EOL, $errors);
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldTextareaCommand.php:
--------------------------------------------------------------------------------
1 | $this->option('rows'),
90 | 'textarea_field_fmt' => $this->option('format'),
91 | 'textarea_field_show_fmt' => $this->option('show_format') ? 'y' : 'n',
92 | 'textarea_field_text_direction' => $this->option('text_direction'),
93 | 'textarea_field_show_smileys' => $this->option('show_smileys') ? 'y' : 'n',
94 | 'textarea_field_show_glossary' => $this->option('show_glossary') ? 'y' : 'n',
95 | 'textarea_field_show_spellcheck' => $this->option('show_spellcheck') ? 'y' : 'n',
96 | 'textarea_field_show_file_selector' => $this->option('show_file_selector') ? 'y' : 'n',
97 | );
98 | }
99 |
100 | public function getExamples()
101 | {
102 | return array(
103 | 'Create a Textarea field in field group 1' => '"Your Field Name" your_field_name 1',
104 | 'Create a Textarea field with 10 rows' => '--rows=10 "Name" name 1',
105 | 'Create a Textarea field with format xhtml (none, br, or xhtml)' => '--format=xhtml "Name" name 1',
106 | 'Create a Textarea field with format selectable on the publish page' => '--show_format "Name" name 1',
107 | 'Create a Textarea field with RTL text direction' => '--text_direction=rtl "Name" name 1',
108 | 'Create a Textarea field with the smileys button' => '--show_smileys "Name" name 1',
109 | 'Create a Textarea field with the glossary button' => '--show_glossary "Name" name 1',
110 | 'Create a Textarea field with the spellcheck button' => '--show_spellcheck "Name" name 1',
111 | 'Create a Textarea field with the file selector button' => '--show_file_selector "Name" name 1',
112 | );
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/Command/DeleteGlobalVariableCommand.php:
--------------------------------------------------------------------------------
1 | argument('name');
57 |
58 | $siteId = ee()->config->item('site_id');
59 | $siteName = ee()->config->item('site_short_name');
60 |
61 | if (! $this->option('force') && ! $this->confirm('Are you sure you want to delete? [Yn]', true)) {
62 | $this->error('Did not delete global variable(s): '.implode(' ', $names));
63 |
64 | return;
65 | }
66 |
67 | $query = ee()->db->select('variable_id, variable_name, variable_data')
68 | ->where('site_id', $siteId)
69 | ->where_in('variable_name', $names)
70 | ->get('global_variables');
71 |
72 | $globalVariables = array();
73 |
74 | foreach ($query->result() as $row) {
75 | $globalVariables[$row->variable_name] = $row;
76 | }
77 |
78 | $query->free_result();
79 |
80 | $hasLowVariables = array_key_exists('Low_variables_ext', ee()->extensions->version_numbers);
81 |
82 | foreach ($names as $name) {
83 | if (! isset($globalVariables[$name])) {
84 | $this->error('Global variable '.$name.' not found.');
85 |
86 | continue;
87 | }
88 |
89 | $globalVariable = $globalVariables[$name];
90 |
91 | if ($hasLowVariables && ee()->db->where('variable_id', $globalVariable->variable_id)->count_all_results('low_variables') > 0) {
92 | $this->error('Could not delete Low Variable '.$name.'.');
93 |
94 | continue;
95 | }
96 |
97 | ee()->db->delete('global_variables', array('variable_id' => $globalVariable->variable_id));
98 |
99 | ee()->extensions->call('eecli_delete_global_variable', $globalVariable->variable_id, $globalVariable->variable_name, $globalVariable->variable_data, $siteId, $siteName);
100 |
101 | $this->info('Global variable '.$name.' deleted.');
102 | }
103 | }
104 |
105 | public function getLongDescription()
106 | {
107 | return "Delete one or more global variables. You will be asked to confirm that you want to delete the specified global variable(s), unless you use the `--force` option.\n\nWhen you have [Sync Snippets](https://github.com/rsanchez/sync_snippets) installed and configured, this command will delete the global variable file as well.";
108 | }
109 |
110 | public function getExamples()
111 | {
112 | return array(
113 | 'Delete a global variable' => 'your_global_variable_name',
114 | 'Delete multiple global variables' => 'your_global_variable_name your_other_global_variable_name',
115 | 'Delete a global variable without confirmation' => '--force your_global_variable_name',
116 | );
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/Command/CreateSnippetCommand.php:
--------------------------------------------------------------------------------
1 | argument('name');
70 |
71 | $siteId = $this->option('global') ? 0 : ee()->config->item('site_id');
72 | $siteName = $this->option('global') ? 'global_snippets' : ee()->config->item('site_short_name');
73 |
74 | $contents = $this->argument('contents');
75 |
76 | if ($this->option('stdin')) {
77 | $contents = '';
78 |
79 | $handle = fopen('php://stdin', 'r');
80 |
81 | while (($buffer = fgets($handle, 4096)) !== false) {
82 | $contents .= $buffer;
83 | }
84 | }
85 |
86 | $tempContents = $contents ? $contents : '{!--TEMP--}';
87 |
88 | $this->getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\DesignController');
89 |
90 | $_POST = array(
91 | 'snippet_name' => $name,
92 | 'snippet_contents' => $tempContents,
93 | 'site_id' => $siteId,
94 | );
95 |
96 | ee()->snippets_update();
97 |
98 | if (ee()->output->getErrorMessage()) {
99 | $this->error(ee()->output->getErrorMessage());
100 |
101 | return;
102 | }
103 |
104 | $query = ee()->db->where('snippet_name', $name)
105 | ->get('snippets');
106 |
107 | // restore the blank contents
108 | if (! $contents) {
109 | ee()->db->update('snippets', array('snippet_contents' => ''), array('snippet_id' => $query->row('snippet_id')));
110 | }
111 |
112 | ee()->extensions->call('eecli_create_snippet', $query->row('snippet_id'), $query->row('snippet_name'), $query->row('snippet_contents'), $siteId, $siteName);
113 |
114 | $query->free_result();
115 |
116 | $this->info('Snippet '.$name.' created.');
117 | }
118 |
119 | public function getLongDescription()
120 | {
121 | return 'Create a new snippet. When you have [Sync Snippets](https://github.com/rsanchez/sync_snippets) installed and configured, this command will write a snippet file as well.';
122 | }
123 |
124 | public function getExamples()
125 | {
126 | return array(
127 | 'Create a blank snippet' => 'your_snippet_name',
128 | 'Create a snippet with content' => 'your_snippet_name "your snippet content"',
129 | 'Pipe in content' => '--stdin your_snippet_name',
130 | 'Create a snippet accessible to all sites' => '--global your_snippet_name',
131 | );
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldTextCommand.php:
--------------------------------------------------------------------------------
1 | $this->option('maxlength'),
96 | 'text_field_fmt' => $this->option('format'),
97 | 'text_field_show_fmt' => $this->option('show_format') ? 'y' : 'n',
98 | 'text_field_text_direction' => $this->option('text_direction'),
99 | 'text_field_content_type' => $this->option('content_type'),
100 | 'text_field_show_smileys' => $this->option('show_smileys') ? 'y' : 'n',
101 | 'text_field_show_glossary' => $this->option('show_glossary') ? 'y' : 'n',
102 | 'text_field_show_spellcheck' => $this->option('show_spellcheck') ? 'y' : 'n',
103 | 'text_field_show_file_selector' => $this->option('show_file_selector') ? 'y' : 'n',
104 | );
105 | }
106 |
107 | public function getExamples()
108 | {
109 | return array(
110 | 'Create a Text field in field group 1' => '"Your Field Name" your_field_name 1',
111 | 'Create a Text field of maxlength 255' => '--max_length=255 "Name" name 1',
112 | 'Create a Text field with format xhtml (none, br, or xhtml)' => '--format=xhtml "Name" name 1',
113 | 'Create a Text field with format selectable on the publish page' => '--show_format "Name" name 1',
114 | 'Create a Text field with RTL text direction' => '--text_direction=rtl "Name" name 1',
115 | 'Create a Text field with a content type (all, numeric, integer, or decimal)' => '--content_type=decimal "Name" name 1',
116 | 'Create a Text field with the smileys button' => '--show_smileys "Name" name 1',
117 | 'Create a Text field with the glossary button' => '--show_glossary "Name" name 1',
118 | 'Create a Text field with the spellcheck button' => '--show_spellcheck "Name" name 1',
119 | 'Create a Text field with the file selector button' => '--show_file_selector "Name" name 1',
120 | );
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/Command/CreateTemplateGroupCommand.php:
--------------------------------------------------------------------------------
1 | argument('name');
58 |
59 | $instance = $this->getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\DesignController');
60 |
61 | $instance->load->model('template_model');
62 |
63 | foreach ($names as $groupName) {
64 | $_POST = array(
65 | 'group_name' => $groupName,
66 | 'is_site_default' => $this->option('default') ? 'y' : 'n',
67 | 'duplicate_group' => false,
68 | );
69 |
70 | $instance->new_template_group();
71 |
72 | if ($this->getApplication()->checkForErrors()) {
73 | continue;
74 | }
75 |
76 | $query = ee()->db->select('group_id')
77 | ->where('site_id', ee()->config->item('site_id'))
78 | ->where('group_name', $groupName)
79 | ->limit(1)
80 | ->get('template_groups');
81 |
82 | $groupId = $query->row('group_id');
83 |
84 | $query->free_result();
85 |
86 | if (ee()->config->item('save_tmpl_files') === 'y' && ee()->config->item('tmpl_file_basepath')) {
87 | // find the newly created index template
88 | $query = ee()->db->select('template_id')
89 | ->where('site_id', ee()->config->item('site_id'))
90 | ->where('group_id', $groupId)
91 | ->where('template_name', 'index')
92 | ->limit(1)
93 | ->get('templates');
94 |
95 | $templateId = $query->row('template_id');
96 |
97 | $query->free_result();
98 |
99 | // create the template file for the index template
100 | $fileCreated = $instance->update_template_file(array(
101 | 'template_group' => $groupName,
102 | 'template_id' => $templateId,
103 | 'template_name' => 'index',
104 | 'template_type' => 'webpage',
105 | 'template_data' => '',
106 | ));
107 |
108 | // set the index template to save to file
109 | ee()->db->update('templates', array('save_template_file' => 'y'), array('template_id' => $templateId));
110 |
111 | if (! $fileCreated) {
112 | $path = ee()->config->slash_item('tmpl_file_basepath').ee()->config->slash_item('site_short_name').$groupName.'.group/';
113 |
114 | $this->error(sprintf('Could not write to %s', $path));
115 | }
116 | }
117 |
118 | $this->comment(sprintf('Template group %s (%s) created.', $groupName, $groupId));
119 | }
120 | }
121 |
122 | public function getLongDescription()
123 | {
124 | return 'Create a new template group. This will also create an index template in the new group(s).';
125 | }
126 |
127 | public function getExamples()
128 | {
129 | return array(
130 | 'Create a template' => 'site',
131 | 'Multiple groups' => 'site news blog',
132 | 'Create the default group' => '--default site',
133 | );
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/Command/GenerateCommandCommand.php:
--------------------------------------------------------------------------------
1 | argument('command_name');
83 | $commandDescription = $this->option('description');
84 | $hasArguments = $this->option('arguments');
85 | $hasOptions = $this->option('options');
86 | $namespace = $this->option('namespace');
87 |
88 | // where to create the file, default to current directory
89 | $path = $this->argument('path') ?: '.';
90 |
91 | // make sure it has a trailing slash
92 | $path = rtrim($path, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
93 |
94 | // split command into individual words
95 | $words = preg_split('/[:-_]/', $commandName);
96 |
97 | // camel case
98 | $words = array_map(function ($word) {
99 | return mb_strtoupper(mb_substr($word, 0, 1)).mb_substr($word, 1);
100 | }, $words);
101 |
102 | $className = implode('', $words);
103 |
104 | $handlebars = new Handlebars(array(
105 | 'loader' => new FilesystemLoader(__DIR__.'/../templates/'),
106 | ));
107 |
108 | $destination = $path.$className.'Command.php';
109 |
110 | $handle = fopen($destination, 'w');
111 |
112 | $output = $handlebars->render('Command.php', array(
113 | 'className' => $className,
114 | 'commandName' => $commandName,
115 | 'commandDescription' => $commandDescription,
116 | 'hasArguments' => $hasArguments,
117 | 'hasOptions' => $hasOptions,
118 | 'namespace' => $namespace,
119 | ));
120 |
121 | fwrite($handle, $output);
122 |
123 | fclose($handle);
124 |
125 | $this->info($destination.' created.');
126 | }
127 |
128 | public function getOptionExamples()
129 | {
130 | return array(
131 | 'namespace' => 'eecli\Command',
132 | 'description' => 'Your description here.',
133 | );
134 | }
135 |
136 | public function getExamples()
137 | {
138 | return array(
139 | 'Generate a file called YourCustomCommand in the current directory' => 'your:custom_comand',
140 | 'Generate in the specified directory' => 'your:custom_comand ./commands/',
141 | 'Generate with a namespace' => '--namespace="YourSite\Command" your:custom_comand ./src/YourSite/Command/',
142 | 'Generate with arguments and options' => '--options --arguments your_command',
143 | 'Generate with a description' => '--description="Clear custom cache" cache:clear:custom',
144 | );
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/Command/CreateUploadPrefCommand.php:
--------------------------------------------------------------------------------
1 | getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\ContentFilesController');
87 |
88 | $instance->load->library('form_validation');
89 | $instance->load->model('file_model');
90 |
91 | $name = $this->argument('name');
92 |
93 | $_POST = array(
94 | 'name' => $name,
95 | 'server_path' => $this->argument('server_path'),
96 | 'url' => $this->argument('url'),
97 | 'allowed_types' => $this->option('images_only') ? 'img' : 'all',
98 | 'max_size' => $this->option('max_size'),
99 | 'max_width' => $this->option('max_width'),
100 | 'max_height' => $this->option('max_height'),
101 | 'properties' => '',
102 | 'pre_format' => '',
103 | 'post_format' => '',
104 | 'file_properties' => '',
105 | 'file_pre_format' => '',
106 | 'file_post_format' => '',
107 | 'size_short_name_2' => '',
108 | 'size_resize_type_2' => 'none',
109 | 'size_width_2' => '',
110 | 'size_height_2' => '',
111 | 'size_watermark_id_2' => '0',
112 | 'submit' => 'Submit',
113 | );
114 |
115 | $query = $instance->db->where('site_id', $instance->config->item('site_id'))
116 | ->where('group_id >', 4)
117 | ->get('member_groups');
118 |
119 | foreach ($query->result() as $row) {
120 | $_POST['access_'.$row->group_id] = 'n';
121 | }
122 |
123 | $query->free_result();
124 |
125 | $instance->edit_upload_preferences();
126 |
127 | $this->getApplication()->checkForErrors(true);
128 |
129 | $this->comment('File upload destination '.$name.' created.');
130 | }
131 |
132 | /**
133 | * {@inheritdoc}
134 | */
135 | public function getExamples()
136 | {
137 | return array(
138 | 'Create a file upload destination with default options' => '"My Files" ./uploads/files /uploads/files/',
139 | 'Create a file upload destination with images only' => '--images_only "My Files" ./uploads/files /uploads/files/',
140 | 'Create a file upload destination with max dimensions' => '--images_only --max_width=1024 --max_height=1024 "My Files" ./uploads/files /uploads/files/',
141 | );
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/src/Command/CreateStatusCommand.php:
--------------------------------------------------------------------------------
1 | getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\AdminContentController');
63 |
64 | $status = $this->argument('status');
65 |
66 | $group = $this->argument('status_group');
67 |
68 | if (is_numeric($group)) {
69 | $query = ee()->db->select('group_id')
70 | ->where('group_id', $group)
71 | ->get('status_groups');
72 |
73 | if ($query->num_rows() === 0) {
74 | throw new \RuntimeException('Invalid group ID.');
75 | }
76 |
77 | $groupId = $query->row('group_id');
78 |
79 | $query->free_result();
80 | } else {
81 | $query = ee()->db->select('group_id')
82 | ->where('group_name', $group)
83 | ->get('status_groups');
84 |
85 | if ($query->num_rows() === 0) {
86 | throw new \RuntimeException('Invalid group name.');
87 | }
88 |
89 | $groupId = $query->row('group_id');
90 |
91 | $query->free_result();
92 | }
93 |
94 | $color = $this->option('color');
95 |
96 | if ($color) {
97 | if (! preg_match('/^(#?)[0-9abcdefABCDEF]{6}$/', $color, $match)) {
98 | throw new \RuntimeException('Color must be a six digit hex string.');
99 | }
100 |
101 | $color = str_replace($match[1], '', $color);
102 | }
103 |
104 | $query = ee()->db->select('status_order')
105 | ->where('group_id', $groupId)
106 | ->order_by('status_order', 'desc')
107 | ->get('statuses');
108 |
109 | $_POST = array(
110 | 'status_id' => '',
111 | 'old_status' => '',
112 | 'group_id' => $groupId,
113 | 'status' => $status,
114 | 'status_order' => $query->row('status_order') + 1,
115 | 'highlight' => $color ?: '000000',
116 | );
117 |
118 | $query = ee()->db->select('group_id')
119 | ->where('group_id >', 4)
120 | ->where('site_id', ee()->config->item('site_id'))
121 | ->get('member_groups');
122 |
123 | foreach ($query->result() as $row) {
124 | $_POST['access_'.$row->group_id] = 'y';
125 | }
126 |
127 | ee()->status_update();
128 |
129 | if (ee()->output->getErrorMessage()) {
130 | $this->error(ee()->output->getErrorMessage());
131 |
132 | return;
133 | }
134 |
135 | $query = ee()->db->select('status_id')
136 | ->where('status', $status)
137 | ->get('statuses');
138 |
139 | $this->info(sprintf('Status %s (%s) created.', $status, $query->row('status_id')));
140 |
141 | $query->free_result();
142 | }
143 |
144 | public function getOptionExamples()
145 | {
146 | return array(
147 | 'color' => '990000',
148 | );
149 | }
150 |
151 | public function getExamples()
152 | {
153 | return array(
154 | 'Create a status in the specfied group (by ID)' => 'featured 1',
155 | 'Create a status in the specified group (by name)' => 'draft your_group_name',
156 | 'Create a status with a red color' => '--color="FF0000" featured 1',
157 | );
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/src/Command/CreateMemberCommand.php:
--------------------------------------------------------------------------------
1 | getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\MembersController');
83 |
84 | $instance->load->helper(array('string', 'security'));
85 | $instance->load->library('stats');
86 |
87 | $username = $this->argument('username_or_email');
88 | $password = $this->option('password') ?: random_string('alnum', 16);
89 | $screenName = $this->option('screen_name');
90 | $email = $this->option('email') ?: $username;
91 | $groupId = $this->option('member_group') ?: $instance->config->item('default_member_group');
92 |
93 | $_POST = array(
94 | 'username' => $username,
95 | 'password' => $password,
96 | 'password_confirm' => $password,
97 | 'screen_name' => $screenName,
98 | 'email' => $email,
99 | 'group_id' => $groupId,
100 | 'bday_y' => '',
101 | 'bday_m' => '',
102 | 'bday_d' => '',
103 | 'url' => 'http://',
104 | 'location' => '',
105 | 'occupation' => '',
106 | 'interests' => '',
107 | 'aol_im' => '',
108 | 'icq' => '',
109 | 'yahoo_im' => '',
110 | 'msn_im' => '',
111 | 'bio' => '',
112 | );
113 |
114 | $instance->new_member_form();
115 |
116 | $this->getApplication()->checkForErrors(true);
117 |
118 | $query = $instance->db->select('member_id')
119 | ->where('username', $username)
120 | ->get('members');
121 |
122 | $memberId = $query->row('member_id');
123 |
124 | $query->free_result();
125 |
126 | $withPassword = $this->option('password') || $this->option('hide_password') ? '' : ' with password '.$password;
127 |
128 | $message = sprintf('Member %s (%s) created%s.', $username, $memberId, $withPassword);
129 |
130 | $this->info($message);
131 | }
132 |
133 | public function getOptionExamples()
134 | {
135 | return array(
136 | 'password' => '997fa90c393a',
137 | 'email' => 'you@yoursite.com',
138 | 'member_group' => '1',
139 | 'screen_name' => 'Your Name',
140 | );
141 | }
142 |
143 | public function getLongDescription()
144 | {
145 | return 'Create a new member. If you omit a password, one will be generated for you. If you omit an email, the username will be used as the email address. If you omit a member group, the default member group for your system will be used.';
146 | }
147 |
148 | public function getExamples()
149 | {
150 | return array(
151 | 'Create a member with same username & email' => 'your.email@site.com',
152 | 'Create a member with different username & email' => '--email="your.email@site.com" your_username',
153 | 'Create a member with the specified screen name' => '--screen_name="Your Name" your.email@site.com',
154 | 'Create a member with the specified password' => '--password="so48jf48jss4sk" your.email@site.com',
155 | 'Create a superadmin' => '--member_group=1 your.email@site.com',
156 | );
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/src/Command/ClearCeCacheCommand.php:
--------------------------------------------------------------------------------
1 | lang->loadfile('ce_cache', 'ce_cache');
76 |
77 | $items = $this->argument('items');
78 | $tags = $this->option('tags');
79 | $drivers = $this->option('driver');
80 | $refresh = $this->option('refresh') ? true : false;
81 | $refresh_time = $this->option('refresh_time');
82 |
83 |
84 | $defaultDrivers = array('file', 'db', 'static', 'apc', 'memcache', 'memcached', 'redis', 'dummy');
85 |
86 | if ($drivers) {
87 | $invalidDrivers = array_diff($drivers, $defaultDrivers);
88 |
89 | if ($invalidDrivers) {
90 | throw new \RuntimeException('Invalid driver(s) specified: '.implode(', ', $invalidDrivers));
91 | }
92 |
93 | $drivers = array_intersect($drivers, $defaultDrivers);
94 | } else {
95 | $drivers = $defaultDrivers;
96 | }
97 |
98 | // if there are no arguments, clear all caches
99 | if (! $items) {
100 | require_once PATH_THIRD.'ce_cache/libraries/Ce_cache_factory.php';
101 |
102 | $drivers = \Ce_cache_factory::factory($drivers);
103 |
104 | foreach ($drivers as $driver) {
105 | $driverName = lang('ce_cache_driver_'.$driver->name());
106 |
107 | if ($driver->clear() === false) {
108 | $this->error(sprintf(lang('ce_cache_error_cleaning_driver_cache'), $driverName));
109 | } else {
110 | $this->comment($driverName.' cache cleared.');
111 | }
112 | }
113 | } else {
114 | require_once PATH_THIRD.'ce_cache/libraries/Ce_cache_break.php';
115 |
116 | $breaker = new \Ce_cache_break();
117 |
118 | $name = $tags ? 'Tag' : 'Item';
119 |
120 | $which = $tags ? 1 : 0;
121 |
122 | $time = $refresh_time ?: 1;
123 |
124 | $defaultArgs = array(array(), array(), $refresh, $time);
125 |
126 | foreach ($items as $item) {
127 | $args = $defaultArgs;
128 |
129 | $args[$which][] = $item;
130 |
131 | call_user_func_array(array($breaker, 'break_cache'), $args);
132 |
133 | $this->comment($name.' '.$item.' cleared.');
134 |
135 | if ($refresh) {
136 | $this->comment($name.' '.$item.' will be refreshed');
137 | }
138 | }
139 | }
140 |
141 | $this->info('CE Cache cleared.');
142 | }
143 |
144 | /**
145 | * {@inheritdoc}
146 | */
147 | public function getExamples()
148 | {
149 | return array(
150 | 'Clear all caches' => '',
151 | 'Clear a specific item' => 'local/foo/item',
152 | 'Clear specific items' => 'local/foo/item local/bar/item',
153 | 'Clear specific tags' => '--tags foo bar',
154 | 'Clear specific driver' => '--driver="file"',
155 | 'Set cache to refresh after clear' => '--refresh',
156 | 'Set the number of seconds to wait before refreshing and deleting items' => '--refresh-time="2"',
157 | );
158 | }
159 |
160 | public function getLongDescription()
161 | {
162 | return "Clears the CE Cache.\n\nBe sure to set your [`http_host`](Global Options) when using the `refresh` option, so `eecli` will know your site's URL.";
163 | }
164 |
165 | public function getOptionExamples()
166 | {
167 | return array(
168 | 'driver' => 'file',
169 | 'refresh-time' => '1',
170 | );
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/src/Command/DbDumpCommand.php:
--------------------------------------------------------------------------------
1 | run();
74 |
75 | if (! $process->isSuccessful()) {
76 | throw new \RuntimeException('mysqldump could not be found in your $PATH.');
77 | }
78 |
79 | ee()->load->helper('security');
80 |
81 | // where to create the file, default to current dir
82 | $path = $this->argument('path') ?: '.';
83 |
84 | $path = rtrim($path, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
85 |
86 | $gzip = $this->option('gzip');
87 |
88 | if ($gzip) {
89 | $process = new Process('gzip --version');
90 |
91 | $process->run();
92 |
93 | if (! $process->isSuccessful()) {
94 | throw new \RuntimeException('gzip could not be found in your $PATH.');
95 | }
96 | }
97 |
98 | $extension = $gzip ? '.sql.gz' : '.sql';
99 |
100 | $name = $this->option('name');
101 |
102 | // set a default name [-]-
103 | if (! $name) {
104 | $name = sanitize_filename(ee()->db->database);
105 |
106 | $env = $this->getApplication()->getEnvironment();
107 |
108 | if ($env) {
109 | $name .= '-'.$env;
110 | }
111 |
112 | $name .= '-'.date('YmdHis');
113 | }
114 |
115 | $file = $path.$name.$extension;
116 |
117 | // compile the mysqldump command using EE's db credentials
118 | $command = sprintf(
119 | 'MYSQL_PWD=%s mysqldump -u %s -h %s %s %s > %s',
120 | escapeshellarg(ee()->db->password),
121 | escapeshellarg(ee()->db->username),
122 | escapeshellarg(ee()->db->hostname),
123 | escapeshellarg(ee()->db->database),
124 | $gzip ? ' | gzip' : '',
125 | escapeshellarg($file)
126 | );
127 |
128 | $process = new Process($command);
129 |
130 | $process->setTimeout(3600);
131 |
132 | $process->run();
133 |
134 | if (! $process->isSuccessful()) {
135 | $this->error('Could not execute mysqldump.');
136 |
137 | return;
138 | }
139 |
140 | $backups = $this->option('backups');
141 |
142 | // check if we need to delete any old backups
143 | if (is_numeric($backups)) {
144 | $finder = new Finder();
145 |
146 | // look for other files in the path that use the
147 | // sql / sql.gz extension
148 | $finder->files()
149 | ->in($path)
150 | ->name('*'.$extension)
151 | ->sortByModifiedTime();
152 |
153 | // omit the X most recent files
154 | $files = array_slice(array_reverse(iterator_to_array($finder)), $backups);
155 |
156 | // if there are backups beyond our limit, delete them
157 | foreach ($files as $file) {
158 | unlink($file->getRealPath());
159 | }
160 | }
161 |
162 | $this->info($file.' created.');
163 | }
164 |
165 | public function getOptionExamples()
166 | {
167 | return array(
168 | 'name' => 'db_backup',
169 | 'backups' => '10',
170 | );
171 | }
172 |
173 | public function getLongDescription()
174 | {
175 | return 'Dump your database using `mysqldump`. NOTE: your PHP installation must be able to call `mysqldump` via the PHP `system` function. If you have an `ENV` or `ENVIRONMENT` constant defined in your config.php, that name will be used in the sql dump file name.';
176 | }
177 |
178 | public function getExamples()
179 | {
180 | return array(
181 | 'Create a sql dump file in the current folder' => '','create a sql dump file in the specified folder' => 'backups/',
182 | 'Create a sql dump file, gzipped' => '--gzip',
183 | 'Create a sql dump file, keep the last X backups and delete the rest' => '--backups=10 --gzip backups/',
184 | );
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldRelationshipCommand.php:
--------------------------------------------------------------------------------
1 | option('author');
107 | $groupIds = $this->option('member_group');
108 |
109 | $authors = array();
110 |
111 | if ($authorIds || $groupIds) {
112 | foreach ($authorIds as $authorId) {
113 | $authors[] = 'm_'.$authorId;
114 | }
115 | foreach ($groupIds as $groupId) {
116 | $authors[] = 'g_'.$groupId;
117 | }
118 | } else {
119 | $authors[] = '--';
120 | }
121 |
122 | $channelIds = array();
123 |
124 | foreach ($this->option('channel') as $channelId) {
125 | if (! is_numeric($channelId)) {
126 | $query = ee()->db->select('channel_id')
127 | ->where('channel_name', $channelId)
128 | ->limit(1)
129 | ->get('channels');
130 |
131 | if ($query->num_rows() > 0) {
132 | $channelId = $query->row('channel_id');
133 | }
134 |
135 | $query->free_result();
136 | }
137 |
138 | $channelIds[] = $channelId;
139 | }
140 |
141 | return array(
142 | 'relationship_channels' => $channelIds ?: array('--'),
143 | 'relationship_expired' => $this->option('expired'),
144 | 'relationship_future' => $this->option('future'),
145 | 'relationship_categories' => $this->option('category') ?: array('--'),
146 | 'relationship_authors' => $authors,
147 | 'relationship_statuses' => $this->option('status') ?: array('--'),
148 | 'relationship_limit' => $this->option('limit'),
149 | 'relationship_order_field' => $this->option('order_by'),
150 | 'relationship_order_dir' => $this->option('sort'),
151 | 'relationship_allow_multiple' => $this->option('multiple'),
152 | );
153 | }
154 |
155 | protected function getFieldtypeOptionExamples()
156 | {
157 | return array(
158 | 'channel' => '1',
159 | 'category' => '1',
160 | 'author' => '1',
161 | 'member_group' => '1',
162 | 'status' => 'open',
163 | );
164 | }
165 |
166 | public function getExamples()
167 | {
168 | return array(
169 | 'Create a Relationships field in field group 1' => '"Your Field Name" your_field_name 1',
170 | 'Create a Relationships field with multiple channels' => '--channel=1 --channel=blogs "Your Field Name" your_field_name 1',
171 | 'Create a Relationships field with multiple statuses' => '--status=closed --status=open "Your Field Name" your_field_name 1',
172 | 'Create a Relationships field with multiple selection' => '--multiple "Your Field Name" your_field_name 1',
173 | );
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/src/Command/CreateFieldPlayaCommand.php:
--------------------------------------------------------------------------------
1 | option('channel') as $channelId) {
121 | if (! is_numeric($channelId)) {
122 | $query = ee()->db->select('channel_id')
123 | ->where('channel_name', $channelId)
124 | ->limit(1)
125 | ->get('channels');
126 |
127 | if ($query->num_rows() > 0) {
128 | $channelId = $query->row('channel_id');
129 | }
130 |
131 | $query->free_result();
132 | }
133 |
134 | $channelIds[] = $channelId;
135 | }
136 |
137 | return array(
138 | 'playa' => array(
139 | 'sites' => $this->option('site') ?: array('any'),
140 | 'channels' => $channelIds ?: array('any'),
141 | 'expired' => $this->option('expired') ? 'y' : 'n',
142 | 'future' => $this->option('future') ? 'y' : 'n',
143 | 'editable' => $this->option('editable') ? 'y' : 'n',
144 | 'cats' => $this->option('category') ?: array('any'),
145 | 'authors' => $this->option('author') ?: array('any'),
146 | 'member_groups' => $this->option('member_group') ?: array('any'),
147 | 'statuses' => $this->option('status') ?: array('any'),
148 | 'limit' => $this->option('limit'),
149 | 'limitby' => 'newest',
150 | 'orderby' => $this->option('order_by'),
151 | 'sort' => strtoupper($this->option('sort')),
152 | 'multi' => $this->option('multiple') ? 'y' : 'n',
153 | ),
154 | );
155 | }
156 |
157 | protected function getFieldtypeOptionExamples()
158 | {
159 | return array(
160 | 'site' => '1',
161 | 'channel' => '1',
162 | 'category' => '1',
163 | 'author' => '1',
164 | 'member_group' => '1',
165 | 'status' => 'open',
166 | );
167 | }
168 |
169 | public function getExamples()
170 | {
171 | return array(
172 | 'Create a Playa field in field group 1' => '"Your Field Name" your_field_name 1',
173 | 'Create a Playa field with multiple channels' => '--channel=1 --channel=blog "Your Field Name" your_field_name 1',
174 | 'Create a Playa field with multiple statuses' => '--status=closed --status=open "Your Field Name" your_field_name 1',
175 | 'Create a Playa field with multiple selection' => '--multiple "Your Field Name" your_field_name 1',
176 | );
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/src/Command/AbstractCreateFieldCommand.php:
--------------------------------------------------------------------------------
1 | db->select('name')
35 | ->get('fieldtypes');
36 |
37 | foreach ($query->result() as $row) {
38 | static::$fieldtypesInstalled[$row->name] = true;
39 | }
40 |
41 | $query->free_result();
42 | }
43 | }
44 |
45 | /**
46 | * {@inheritdoc}
47 | */
48 | public function isApplicable()
49 | {
50 | static::loadInstalledFieldtypes();
51 |
52 | return isset(static::$fieldtypesInstalled[$this->getFieldtype()]);
53 | }
54 |
55 | /**
56 | * Array of InputOption objects for this fieldtype
57 | * @return array of \Symfony\Component\Console\Input\InputOption
58 | */
59 | protected function getFieldtypeOptions()
60 | {
61 | return array();
62 | }
63 |
64 | /**
65 | * Array of fieldtype settings, to be merge into $_POST
66 | * @return array
67 | */
68 | protected function getFieldtypeSettings()
69 | {
70 | return array();
71 | }
72 |
73 | protected function getFieldtypeOptionExamples()
74 | {
75 | return array();
76 | }
77 |
78 | /**
79 | * {@inheritdoc}
80 | */
81 | public function __construct()
82 | {
83 | $this->name = 'create:field:'.$this->getFieldtype();
84 |
85 | parent::__construct();
86 | }
87 |
88 | /**
89 | * {@inheritdoc}
90 | */
91 | protected function getArguments()
92 | {
93 | return array(
94 | array(
95 | 'label', // name
96 | InputArgument::REQUIRED, // mode
97 | 'The label of the field.', // description
98 | ),
99 | array(
100 | 'short_name', // name
101 | InputArgument::REQUIRED, // mode
102 | 'The short name of the field.', // description
103 | ),
104 | array(
105 | 'field_group', // name
106 | InputArgument::REQUIRED, // mode
107 | 'The ID or name of the field group.', // description
108 | ),
109 | );
110 | }
111 |
112 | /**
113 | * {@inheritdoc}
114 | */
115 | protected function getOptions()
116 | {
117 | return array_merge(array(
118 | array(
119 | 'instructions',
120 | null,
121 | InputOption::VALUE_REQUIRED,
122 | 'Instructions for authors on how or what to enter into this field when submitting an entry.',
123 | '',
124 | ),
125 | array(
126 | 'required',
127 | null,
128 | InputOption::VALUE_NONE,
129 | 'Make this field required',
130 | ),
131 | array(
132 | 'searchable',
133 | null,
134 | InputOption::VALUE_NONE,
135 | 'Make this field searchable',
136 | ),
137 | array(
138 | 'hidden',
139 | null,
140 | InputOption::VALUE_NONE,
141 | 'Make this field hidden',
142 | ),
143 | array(
144 | 'order',
145 | null,
146 | InputOption::VALUE_REQUIRED,
147 | 'Set this field\'s order',
148 | ),
149 | ), $this->getFieldtypeOptions());
150 | }
151 |
152 | /**
153 | * {@inheritdoc}
154 | */
155 | protected function fire()
156 | {
157 | $instance = $this->getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\AdminContentController');
158 |
159 | $groupId = $this->argument('field_group');
160 |
161 | if (! is_numeric($groupId)) {
162 | $query = ee()->db->select('group_id')
163 | ->where('group_name', $groupId)
164 | ->limit(1)
165 | ->get('field_groups');
166 |
167 | if ($query->num_rows() > 0) {
168 | $groupId = $query->row('group_id');
169 | }
170 |
171 | $query->free_result();
172 | }
173 |
174 | $name = $this->argument('short_name');
175 |
176 | // get field order
177 | $order = $this->option('order');
178 |
179 | if (! $order && $order !== '0') {
180 | $query = $instance->db->select('field_order')
181 | ->where('group_id', $groupId)
182 | ->order_by('field_order', 'desc')
183 | ->limit(1)
184 | ->get('channel_fields');
185 |
186 | if ($query->num_rows() > 0) {
187 | $order = $query->row('field_order') + 1;
188 | }
189 |
190 | $query->free_result();
191 | }
192 |
193 | $_POST = array(
194 | 'site_id' => $instance->config->item('site_id'),
195 | 'group_id' => $groupId,
196 | 'field_label' => $this->argument('label'),
197 | 'field_name' => $name,
198 | 'field_type' => $this->getFieldtype(),
199 | 'field_instructions' => $this->option('instructions'),
200 | 'field_required' => $this->option('required') ? 'y' : 'n',
201 | 'field_search' => $this->option('searchable') ? 'y' : 'n',
202 | 'field_is_hidden' => $this->option('hidden') ? 'y' : 'n',
203 | 'field_order' => $order,
204 | 'field_maxl' => '128',
205 | 'field_ta_rows' => '6',
206 | );
207 |
208 | $_POST = array_merge($_POST, $this->getFieldtypeSettings());
209 |
210 | $method = version_compare(APP_VER, '2.7', '<') ? 'field_update' : 'field_edit';
211 |
212 | $instance->$method();
213 |
214 | $this->getApplication()->checkForErrors(true);
215 |
216 | $query = ee()->db->select('field_id')
217 | ->where('field_name', $name)
218 | ->where('group_id', $groupId)
219 | ->get('channel_fields');
220 |
221 | $this->info(sprintf('Field %s (%s) created.', $name, $query->row('field_id')));
222 |
223 | $query->free_result();
224 | }
225 |
226 | public function getOptionExamples()
227 | {
228 | $optionExamples = array(
229 | 'instructions' => 'Your instructions here.',
230 | 'order' => '1',
231 | 'content_type' => 'all',
232 | );
233 |
234 | return array_merge($optionExamples, $this->getFieldtypeOptionExamples());
235 | }
236 | }
237 |
--------------------------------------------------------------------------------
/src/Command/CreateCategoryCommand.php:
--------------------------------------------------------------------------------
1 | db->where('group_id', $group);
84 | } else {
85 | ee()->db->where('group_name', $group);
86 | }
87 |
88 | $query = ee()->db->select('group_id')
89 | ->get('category_groups');
90 |
91 | if ($query->num_rows() === 0) {
92 | throw new \RuntimeException('Invalid group.');
93 | }
94 |
95 | $groupId = $query->row('group_id');
96 |
97 | $query->free_result();
98 |
99 | return $groupId;
100 | }
101 |
102 | /**
103 | * Get category fields by group ID
104 | * @param string $groupId
105 | * @return array of \stdClass
106 | */
107 | protected function getCategoryGroupFields($groupId)
108 | {
109 | $query = ee()->db->where('group_id', $groupId)
110 | ->order_by('field_order', 'asc')
111 | ->get('category_fields');
112 |
113 | $fields = $query->result();
114 |
115 | $query->free_result();
116 |
117 | return $fields;
118 | }
119 |
120 | /**
121 | * {@inheritdoc}
122 | */
123 | public function getRuntimeOptions(Application $app, InputInterface $input)
124 | {
125 | $group = $input->getArgument('cat_group');
126 |
127 | $groupId = $this->getCategoryGroupId($group);
128 |
129 | $fields = $this->getCategoryGroupFields($groupId);
130 |
131 | $options = array();
132 |
133 | foreach ($fields as $field) {
134 | $options[] = new InputOption(
135 | $field->field_name,
136 | null,
137 | InputOption::VALUE_REQUIRED,
138 | $field->field_label
139 | );
140 | }
141 |
142 | return $options;
143 | }
144 |
145 | /**
146 | * {@inheritdoc}
147 | */
148 | protected function fire()
149 | {
150 | $instance = $this->getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\AdminContentController');
151 |
152 | $name = $this->argument('name');
153 |
154 | $group = $this->argument('cat_group');
155 |
156 | $groupId = $this->getCategoryGroupId($group);
157 |
158 | $fields = $this->getCategoryGroupFields($groupId);
159 |
160 | $_SERVER['CONTENT_LENGTH'] = 0;
161 |
162 | $_POST = array(
163 | 'group_id' => $groupId,
164 | 'cat_name' => $name,
165 | 'cat_url_title' => $this->option('url_title'),
166 | 'cat_description' => $this->option('description'),
167 | 'cat_image_hidden_file' => '',
168 | 'cat_image_hidden_dir' => '',
169 | 'cat_image_directory' => '',
170 | 'parent_id' => $this->option('parent_id'),
171 | );
172 |
173 | foreach ($fields as $field) {
174 | $_POST['field_ft_'.$field->field_id] = $field->field_default_fmt;
175 |
176 | $value = $this->option($field->field_name);
177 |
178 | if ($field->field_required === 'y' && empty($value)) {
179 | $this->error(sprintf('The --%s option is required for this category group.', $field->field_name));
180 |
181 | return;
182 | }
183 |
184 | $_POST['field_id_'.$field->field_id] = $value;
185 | }
186 |
187 | $instance->category_update();
188 |
189 | $this->getApplication()->checkForErrors(true);
190 |
191 | $query = $instance->db->select('cat_id')
192 | ->where('cat_name', $name)
193 | ->where('group_id', $groupId)
194 | ->order_by('cat_id', 'desc')
195 | ->get('categories');
196 |
197 | $this->info(sprintf('Category %s (%s) created.', $name, $query->row('cat_id')));
198 |
199 | $query->free_result();
200 | }
201 |
202 | /**
203 | * {@inheritdoc}
204 | */
205 | public function getExamples()
206 | {
207 | return array(
208 | 'Create a category in the specfied group (by ID)' => '"16th Century" 1',
209 | 'Create a category in the specified group (by name)' => 'Prehistoric "Time Periods"',
210 | 'Create a category with a custom url title' => '--url_title="16th" "16th Century" 1',
211 | 'Create a category with the specified parent_id' => '--parent_id=12 "1920s" 1',
212 | 'Create a category with the specified description' => '--description="The Roaring 20s" "1920s" 1',
213 | 'Create a category with one (or more) custom category fields' => '--your_category_field="The Roaring 20s" "1920s" 1',
214 | );
215 | }
216 |
217 | public function getOptionExamples()
218 | {
219 | return array(
220 | 'url_title' => 'your_category',
221 | 'description' => 'Your description here.',
222 | 'parent_id' => '1',
223 | );
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/src/Command/CreateTemplateCommand.php:
--------------------------------------------------------------------------------
1 | argument('template');
101 |
102 | $instance = $this->getApplication()->newControllerInstance('\\eecli\\CodeIgniter\\Controller\\DesignController');
103 |
104 | $instance->load->model('template_model');
105 |
106 | $templateData = '';
107 |
108 | if ($this->option('stdin')) {
109 | $handle = fopen('php://stdin', 'r');
110 |
111 | while (($buffer = fgets($handle, 4096)) !== false) {
112 | $templateData .= $buffer;
113 | }
114 | }
115 |
116 | foreach ($templates as $template) {
117 | if (! preg_match('#^[a-zA-Z0-9_\-]+/[a-zA-Z0-9_\-]+$#', $template)) {
118 | $this->error('Template '.$template.' must be in / format.');
119 |
120 | continue;
121 | }
122 |
123 | list($groupName, $templateName) = explode('/', $template);
124 |
125 | $query = $instance->db->select('group_id')
126 | ->where('group_name', $groupName)
127 | ->get('template_groups');
128 |
129 | // create the group if it doesn't exist
130 | if ($query->num_rows() === 0) {
131 | $_POST = array(
132 | 'group_name' => $groupName,
133 | 'is_site_default' => 'n',
134 | 'duplicate_group' => false,
135 | );
136 |
137 | $instance->new_template_group();
138 |
139 | if ($this->getApplication()->checkForErrors()) {
140 | continue;
141 | }
142 |
143 | $this->comment('Template group '.$groupName.' created.');
144 |
145 | $variables = $instance->functions->getVariables();
146 |
147 | $groupId = $variables['tgpref'];
148 |
149 | // it made an index template, update it if it needs
150 |
151 | if ($instance->config->item('save_tmpl_files') === 'y') {
152 | $query = $instance->db->select('template_id')
153 | ->where('group_id', $groupId)
154 | ->where('template_name', 'index')
155 | ->get('templates');
156 |
157 | if ($query->num_rows() > 0) {
158 | $_POST = array(
159 | 'template_id' => $query->row('template_id'),
160 | 'template_data' => '',
161 | 'template_notes' => $this->option('notes'),
162 | 'save_template_file' => 'y',
163 | 'save_template_revision' => $instance->config->item('save_tmpl_revisions'),
164 | );
165 |
166 | $instance->update_template();
167 | }
168 |
169 | $query->free_result();
170 | }
171 | } else {
172 | $groupId = $query->row('group_id');
173 | }
174 |
175 | $query->free_result();
176 |
177 | $templateExists = $instance->db->where('group_id', $groupId)
178 | ->where('template_name', $templateName)
179 | ->where('site_id', $instance->config->item('site_id'))
180 | ->count_all_results('templates') > 0;
181 |
182 | if ($templateExists) {
183 | $this->error('Template '.$template.' already exists.');
184 |
185 | continue;
186 | }
187 |
188 | $templateType = $this->option('type');
189 |
190 | $_POST = array(
191 | 'template_name' => $templateName,
192 | 'group_id' => $groupId,
193 | 'template_type' => $templateType,
194 | 'template_notes' => $this->option('notes'),
195 | );
196 |
197 | $instance->template = $instance->TMPL;
198 |
199 | $instance->create_new_template();
200 |
201 | $variables = $instance->cp->getVariables();
202 |
203 | $templateId = $variables['template_id'];
204 |
205 | $_POST = array(
206 | 'template_id' => $templateId,
207 | 'template_data' => $templateData,
208 | 'template_notes' => $this->option('notes'),
209 | 'save_template_file' => $instance->config->item('save_tmpl_files'),
210 | 'save_template_revision' => $instance->config->item('save_tmpl_revisions'),
211 | );
212 |
213 | $instance->update_template();
214 |
215 | if ($this->getApplication()->checkForErrors()) {
216 | continue;
217 | }
218 |
219 | $_POST = array(
220 | 'template_id' => $templateId,
221 | 'template_name' => $templateName,
222 | 'template_type' => $templateType,
223 | 'template_notes' => $this->option('notes'),
224 | 'cache' => $this->option('cache') ? 'y' : 'n',
225 | 'refresh' => $this->option('cache') ?: 0,
226 | 'allow_php' => $this->option('php') ? 'y' : 'n',
227 | 'protect_javascript' => $this->option('protect_js') ? 'y' : 'n',
228 | 'php_parse_location' => $this->option('input') ? 'i' : 'o',
229 | 'hits' => 0,
230 | );
231 |
232 | $instance->template_edit_ajax();
233 |
234 | if ($this->getApplication()->checkForErrors()) {
235 | continue;
236 | }
237 |
238 | $this->info(sprintf('Template %s (%s) created.', $template, $templateId));
239 | }
240 | }
241 |
242 | public function getOptionExamples()
243 | {
244 | return array(
245 | 'cache' => '300',
246 | 'type' => 'webpage',
247 | );
248 | }
249 |
250 | public function getLongDescription()
251 | {
252 | return 'Create a new template. If the template group does not already exist, it will be created.';
253 | }
254 |
255 | public function getExamples()
256 | {
257 | return array(
258 | 'Create a template' => 'site/index',
259 | 'Multiple templates' => 'site/index site/foo',
260 | 'With php enabled' => '--php site/index',
261 | 'With php enabled on input' => '--php --input site/index',
262 | 'With caching on (for 300 seconds)' => '--cache=300 site/index',
263 | 'Protect javascript' => '--protect_js site/index',
264 | 'Set a type: webpage, feed, css, js, static, xml' => '--type=xml site/index',
265 | );
266 | }
267 | }
268 |
--------------------------------------------------------------------------------