├── src ├── Template │ ├── combustor.yml │ ├── EditPlate.php │ ├── CreatePlate.php │ ├── Fields │ │ ├── DefaultField.php │ │ ├── EmailField.php │ │ ├── BooleanField.php │ │ └── ForeignField.php │ ├── FooterPlate.php │ ├── HeaderPlate.php │ ├── IndexPlate.php │ ├── Repository.php │ ├── TablePlate.php │ ├── Wildfire │ │ └── Model.php │ ├── FormPlate.php │ ├── Doctrine │ │ └── Model.php │ └── Controller.php ├── Commands │ ├── CreateYaml.php │ ├── RemoveWildfire.php │ ├── InstallWildfire.php │ ├── RemoveDoctrine.php │ ├── CreateRepo.php │ ├── InstallDoctrine.php │ ├── CreateLayout.php │ ├── CreateModel.php │ ├── CreateRoute.php │ ├── CreateScaffold.php │ └── CreateView.php ├── Packages │ ├── SparkplugPackage.php │ ├── DescribePackage.php │ └── CombustorPackage.php ├── Colfield.php ├── Combustor.php ├── Console.php ├── Command.php └── Inflector.php ├── .editorconfig ├── bin └── combustor ├── phpstan.neon ├── LICENSE.md ├── .github └── workflows │ └── build.yml ├── composer.json ├── phpstyle.php ├── CHANGELOG.md └── README.md /src/Template/combustor.yml: -------------------------------------------------------------------------------- 1 | app_path: %%CURRENT_DIRECTORY%% 2 | 3 | custom_fields: 4 | - Rougin\Combustor\Template\Fields\BooleanField 5 | - Rougin\Combustor\Template\Fields\EmailField 6 | 7 | excluded_fields: 8 | - created_at 9 | - updated_at 10 | - deleted_at -------------------------------------------------------------------------------- /src/Template/EditPlate.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class EditPlate extends FormPlate 11 | { 12 | /** 13 | * @var boolean 14 | */ 15 | protected $edit = true; 16 | } 17 | -------------------------------------------------------------------------------- /src/Template/CreatePlate.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class CreatePlate extends FormPlate 11 | { 12 | /** 13 | * @var boolean 14 | */ 15 | protected $edit = false; 16 | } 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | ; This file is for unifying the coding style for different editors and IDEs. 2 | ; More information at http://editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | indent_size = 4 9 | indent_style = space 10 | end_of_line = lf 11 | insert_final_newline = true 12 | trim_trailing_whitespace = true 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /bin/combustor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | run(); 22 | // ------------------------------- 23 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | level: 9 3 | paths: 4 | - src 5 | - tests 6 | excludePaths: 7 | analyse: 8 | - tests/Fixture/Plates 9 | - tests/Fixture/Sample/controllers 10 | - tests/Fixture/Sample/models 11 | - tests/Fixture/Sample/repositories 12 | - tests/Fixture/Sample/views 13 | scanDirectories: 14 | - vendor/rougin/codeigniter/src 15 | ignoreErrors: 16 | - '#^Access to property \$database on an unknown class CI_DB\.$#' 17 | - '#^Access to property \$dbdriver on an unknown class CI_DB\.$#' 18 | - '#^Access to property \$dsn on an unknown class CI_DB\.$#' 19 | - '#^Access to property \$hostname on an unknown class CI_DB\.$#' 20 | - '#^Access to property \$password on an unknown class CI_DB\.$#' 21 | - '#^Access to property \$username on an unknown class CI_DB\.$#' 22 | - '#^Constant APPPATH not found\.$#' 23 | - '#^Constant ENVIRONMENT not found\.$#' -------------------------------------------------------------------------------- /src/Template/Fields/DefaultField.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class DefaultField extends Colfield 13 | { 14 | /** 15 | * @var string 16 | */ 17 | protected $class = 'form-control'; 18 | 19 | /** 20 | * @return string[] 21 | */ 22 | public function getPlate() 23 | { 24 | $field = $this->accessor; 25 | 26 | $class = $this->getClass(); 27 | 28 | $name = $this->getName(); 29 | 30 | $html = ''; 31 | 32 | if ($this->edit) 33 | { 34 | $html = ''; 35 | } 36 | 37 | return array($html); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Commands/CreateYaml.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class CreateYaml extends InitializeCommand 13 | { 14 | /** 15 | * @var string 16 | */ 17 | protected $file = 'combustor.yml'; 18 | 19 | /** 20 | * Returns the source directory for the specified file. 21 | * 22 | * @return string 23 | */ 24 | protected function getPlatePath() 25 | { 26 | /** @var string */ 27 | return realpath(__DIR__ . '/../Template'); 28 | } 29 | 30 | /** 31 | * Returns the root directory from the package. 32 | * 33 | * @return string 34 | */ 35 | protected function getRootPath() 36 | { 37 | $root = (string) __DIR__ . '/../../../../../'; 38 | 39 | $exists = file_exists($root . '/vendor/autoload.php'); 40 | 41 | return $exists ? $root : __DIR__ . '/../../'; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Commands/RemoveWildfire.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class RemoveWildfire extends Command 13 | { 14 | /** 15 | * @var string 16 | */ 17 | protected $name = 'remove:wildfire'; 18 | 19 | /** 20 | * @var string 21 | */ 22 | protected $description = 'Remove the Wildfire package'; 23 | 24 | /** 25 | * Checks whether the command is enabled or not in the current environment. 26 | * 27 | * @return boolean 28 | */ 29 | public function isEnabled() 30 | { 31 | return class_exists('Rougin\Wildfire\Wildfire'); 32 | } 33 | 34 | /** 35 | * Executes the command. 36 | * 37 | * @return integer 38 | */ 39 | public function run() 40 | { 41 | system('composer remove rougin/wildfire'); 42 | 43 | $this->showPass('Wildfire removed successfully!'); 44 | 45 | return self::RETURN_SUCCESS; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Commands/InstallWildfire.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class InstallWildfire extends Command 13 | { 14 | /** 15 | * @var string 16 | */ 17 | protected $name = 'install:wildfire'; 18 | 19 | /** 20 | * @var string 21 | */ 22 | protected $description = 'Install the Wildfire package'; 23 | 24 | /** 25 | * Checks whether the command is enabled or not in the current environment. 26 | * 27 | * @return boolean 28 | */ 29 | public function isEnabled() 30 | { 31 | return ! class_exists('Rougin\Wildfire\Wildfire'); 32 | } 33 | 34 | /** 35 | * Executes the command. 36 | * 37 | * @return integer 38 | */ 39 | public function run() 40 | { 41 | system('composer require rougin/wildfire'); 42 | 43 | $this->showPass('Wildfire installed successfully!'); 44 | 45 | return self::RETURN_SUCCESS; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Template/FooterPlate.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class FooterPlate 11 | { 12 | /** 13 | * @var boolean 14 | */ 15 | protected $bootstrap; 16 | 17 | /** 18 | * @param boolean $bootstrap 19 | */ 20 | public function __construct($bootstrap) 21 | { 22 | $this->bootstrap = $bootstrap; 23 | } 24 | 25 | /** 26 | * @param string $tab 27 | * 28 | * @return string 29 | */ 30 | public function make($tab = ' ') 31 | { 32 | $lines = array(); 33 | 34 | if ($this->bootstrap) 35 | { 36 | $lines[] = $tab . ''; 37 | $lines[] = $tab . ''; 38 | } 39 | 40 | $lines[] = ''; 41 | $lines[] = ''; 42 | 43 | return implode("\n", $lines); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Rougin Gutib 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. -------------------------------------------------------------------------------- /src/Template/Fields/EmailField.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class EmailField extends Colfield 13 | { 14 | /** 15 | * @var string 16 | */ 17 | protected $class = 'form-control'; 18 | 19 | /** 20 | * @var string 21 | */ 22 | protected $name = 'email'; 23 | 24 | /** 25 | * @return string[] 26 | */ 27 | public function getPlate() 28 | { 29 | $field = $this->accessor; 30 | 31 | $class = $this->getClass(); 32 | 33 | /** @var string */ 34 | $name = $this->getName(); 35 | 36 | $html = ' \'email\', \'name\' => \'' . $name . '\', \'value\' => set_value(\'' . $name . '\')]) ?>'; 37 | 38 | if ($this->edit) 39 | { 40 | $html = str_replace('set_value(\'' . $name . '\')', 'set_value(\'' . $name . '\', ' . $field . ')', $html); 41 | } 42 | 43 | $html = str_replace(')]) ?>', '), \'class\' => \'' . $class . '\']) ?>', $html); 44 | 45 | return array($html); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: [ 'master' ] 4 | pull_request: 5 | branches: [ 'master' ] 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | run: 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | php-versions: [ '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3' ] 18 | 19 | name: Run Unit Test on PHP ${{ matrix.php-versions }} 20 | 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v3 24 | 25 | - name: Install PHP 26 | uses: shivammathur/setup-php@v2 27 | with: 28 | php-version: ${{ matrix.php-versions }} 29 | 30 | - name: Check the PHP version 31 | run: php -v 32 | 33 | - name: Validate composer.json and composer.lock 34 | run: composer validate --strict 35 | 36 | - name: Install dependencies 37 | run: composer install --prefer-dist --no-progress 38 | 39 | - name: Run test suite 40 | run: vendor/bin/phpunit --coverage-clover=coverage.clover 41 | 42 | - name: Upload coverage to Codecov 43 | uses: codecov/codecov-action@v4-beta 44 | env: 45 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} -------------------------------------------------------------------------------- /src/Template/Fields/BooleanField.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class BooleanField extends Colfield 13 | { 14 | /** 15 | * @var string 16 | */ 17 | protected $class = 'form-check-input'; 18 | 19 | /** 20 | * @var string 21 | */ 22 | protected $type = 'boolean'; 23 | 24 | /** 25 | * @return string[] 26 | */ 27 | public function getPlate() 28 | { 29 | $field = $this->accessor; 30 | 31 | $tab = $this->tab; 32 | 33 | $class = $this->getClass(); 34 | 35 | $name = $this->getName(); 36 | 37 | $lines = array('
'); 38 | 39 | if ($this->edit) 40 | { 41 | $lines[] = $tab . ''; 42 | } 43 | else 44 | { 45 | $lines[] = $tab . ''; 46 | } 47 | 48 | $lines[] = '
'; 49 | 50 | return $lines; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Template/Fields/ForeignField.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class ForeignField extends Colfield 14 | { 15 | /** 16 | * @var string 17 | */ 18 | protected $class = 'form-control'; 19 | 20 | /** 21 | * @var string 22 | */ 23 | protected $table; 24 | 25 | /** 26 | * @return string[] 27 | */ 28 | public function getPlate() 29 | { 30 | $field = $this->accessor; 31 | 32 | $class = $this->getClass(); 33 | 34 | $name = $this->getName(); 35 | 36 | $items = Inflector::plural($this->table); 37 | 38 | $html = ''; 39 | 40 | if ($this->edit) 41 | { 42 | $html = str_replace('set_value(\'' . $name . '\')', 'set_value(\'' . $name . '\', ' . $field . ')', $html); 43 | } 44 | 45 | return array($html); 46 | } 47 | 48 | /** 49 | * @param string $table 50 | * 51 | * @return self 52 | */ 53 | public function setTableName($table) 54 | { 55 | $this->table = $table; 56 | 57 | return $this; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Packages/SparkplugPackage.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class SparkplugPackage implements IntegrationInterface 16 | { 17 | /** 18 | * @var string 19 | */ 20 | protected $root; 21 | 22 | /** 23 | * @param string $root 24 | */ 25 | public function __construct($root) 26 | { 27 | $this->root = $root; 28 | } 29 | 30 | /** 31 | * @param \Rougin\Slytherin\Container\ContainerInterface $container 32 | * @param \Rougin\Slytherin\Integration\Configuration $config 33 | * 34 | * @return \Rougin\Slytherin\Container\ContainerInterface 35 | */ 36 | public function define(ContainerInterface $container, Configuration $config) 37 | { 38 | $class = 'Rougin\SparkPlug\Controller'; 39 | 40 | // If cannot determine APPPATH, ignore --- 41 | $appPath = $this->root . '/application'; 42 | 43 | $root = $this->root . '/config'; 44 | 45 | if (! is_dir($appPath) && ! is_dir($root)) 46 | { 47 | return $container; 48 | } 49 | // --------------------------------------- 50 | 51 | $app = Instance::create($this->root); 52 | 53 | return $container->set($class, $app); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Commands/RemoveDoctrine.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class RemoveDoctrine extends Command 14 | { 15 | /** 16 | * @var string 17 | */ 18 | protected $name = 'remove:doctrine'; 19 | 20 | /** 21 | * @var string 22 | */ 23 | protected $description = 'Remove the Doctrine package'; 24 | 25 | /** 26 | * @var string 27 | */ 28 | protected $path = ''; 29 | 30 | /** 31 | * @param \Rougin\Combustor\Combustor $combustor 32 | */ 33 | public function __construct(Combustor $combustor) 34 | { 35 | $this->path = $combustor->getAppPath(); 36 | } 37 | 38 | /** 39 | * Checks whether the command is enabled or not in the current environment. 40 | * 41 | * @return boolean 42 | */ 43 | public function isEnabled() 44 | { 45 | return class_exists('Rougin\Credo\Credo'); 46 | } 47 | 48 | /** 49 | * Executes the command. 50 | * 51 | * @return integer 52 | */ 53 | public function run() 54 | { 55 | system('composer remove rougin/credo'); 56 | 57 | $file = $this->path . '/core/MY_Loader.php'; 58 | 59 | if (file_exists($file)) 60 | { 61 | unlink($file); 62 | } 63 | 64 | $this->showPass('Doctrine removed successfully!'); 65 | 66 | return self::RETURN_SUCCESS; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Template/HeaderPlate.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class HeaderPlate 11 | { 12 | /** 13 | * @var boolean 14 | */ 15 | protected $bootstrap; 16 | 17 | /** 18 | * @param boolean $bootstrap 19 | */ 20 | public function __construct($bootstrap) 21 | { 22 | $this->bootstrap = $bootstrap; 23 | } 24 | 25 | /** 26 | * @param string $tab 27 | * 28 | * @return string 29 | */ 30 | public function make($tab = ' ') 31 | { 32 | $lines = array(''); 33 | 34 | $lines[] = ''; 35 | $lines[] = ''; 36 | 37 | $lines[] = $tab . ''; 38 | $lines[] = $tab . ''; 39 | $lines[] = $tab . ''; 40 | $lines[] = $tab . 'Welcome to Codeigniter 3'; 41 | 42 | if ($this->bootstrap) 43 | { 44 | $lines[] = $tab . ''; 45 | } 46 | 47 | $lines[] = ''; 48 | $lines[] = ''; 49 | 50 | if ($this->bootstrap) 51 | { 52 | $lines[] = $tab . '
'; 53 | } 54 | else 55 | { 56 | $lines[] = $tab . '
'; 57 | } 58 | 59 | return implode("\n", $lines); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rougin/combustor", 3 | "description": "MVC code generator for Codeigniter 3.", 4 | "keywords": [ "code-generator", "crud-generator" ], 5 | "homepage": "https://roug.in/combustor/", 6 | "license": "MIT", 7 | "authors": 8 | [ 9 | { 10 | "email": "rougingutib@gmail.com", 11 | "homepage": "https://roug.in/", 12 | "name": "Rougin Gutib", 13 | "role": "Software Engineer" 14 | } 15 | ], 16 | "require": 17 | { 18 | "php": ">=5.4.0", 19 | "rougin/blueprint": "~0.7", 20 | "rougin/classidy": "~0.1", 21 | "rougin/describe": "~1.8", 22 | "rougin/spark-plug": "~0.6" 23 | }, 24 | "require-dev": 25 | { 26 | "rougin/codeigniter": "~3.0", 27 | "phpunit/phpunit": "~4.2|~5.7|~6.0|~7.0|~8.0|~9.0", 28 | "sanmai/phpunit-legacy-adapter": "~6.1|~8.0" 29 | }, 30 | "bin": 31 | [ 32 | "bin/combustor" 33 | ], 34 | "autoload": 35 | { 36 | "psr-4": 37 | { 38 | "Rougin\\Combustor\\": "src" 39 | } 40 | }, 41 | "autoload-dev": 42 | { 43 | "psr-4": 44 | { 45 | "Rougin\\Combustor\\": "tests" 46 | } 47 | }, 48 | "scripts": 49 | { 50 | "test": "phpunit" 51 | }, 52 | "extra": 53 | { 54 | "branch-alias": 55 | { 56 | "dev-master": "2.0-dev" 57 | } 58 | }, 59 | "suggest": 60 | { 61 | "rougin/codeigniter": "Packaged \"system\" of Codeigniter 3.", 62 | "rougin/credo": "Doctrine ORM wrapper for Codeigniter 3.", 63 | "rougin/ignite": "Yet another Codeigniter 3 project template.", 64 | "rougin/refinery": "\"Ready-to-eat\" Codeigniter 3 migrations.", 65 | "rougin/spark-plug": "Codeigniter 3 projects as variables.", 66 | "rougin/wildfire": "Query Builder wrapper for Codeigniter 3." 67 | } 68 | } -------------------------------------------------------------------------------- /src/Commands/CreateRepo.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class CreateRepo extends Command 14 | { 15 | /** 16 | * @var string 17 | */ 18 | protected $name = 'create:repository'; 19 | 20 | /** 21 | * @var string 22 | */ 23 | protected $description = 'Create a new entity repository'; 24 | 25 | /** 26 | * Executes the command. 27 | * 28 | * @return integer 29 | */ 30 | public function run() 31 | { 32 | /** @var string */ 33 | $table = $this->getArgument('table'); 34 | 35 | /** @var boolean */ 36 | $force = $this->getOption('force'); 37 | 38 | $name = Inflector::singular($table); 39 | 40 | $name = ucfirst(Inflector::singular($table)); 41 | 42 | $name = $name . '_repository'; 43 | 44 | $path = $this->path . '/repositories/'; 45 | 46 | $file = $path . $name . '.php'; 47 | 48 | if (file_exists($file) && ! $force) 49 | { 50 | $this->showFail('"' . $name . '" already exists. Use --force to overwrite the file.'); 51 | 52 | return self::RETURN_FAILURE; 53 | } 54 | 55 | // Create the repository file ------------------- 56 | if (! is_dir($path)) 57 | { 58 | mkdir($path); 59 | } 60 | 61 | $plate = $this->getTemplate(self::TYPE_DOCTRINE); 62 | 63 | $plate = $this->maker->make($plate); 64 | 65 | file_put_contents($file, $plate); 66 | // ---------------------------------------------- 67 | 68 | $this->showPass('Repository successfully created!'); 69 | 70 | return self::RETURN_SUCCESS; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Commands/InstallDoctrine.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class InstallDoctrine extends Command 16 | { 17 | /** 18 | * @var string 19 | */ 20 | protected $name = 'install:doctrine'; 21 | 22 | /** 23 | * @var string 24 | */ 25 | protected $description = 'Install the Doctrine package'; 26 | 27 | /** 28 | * @var string 29 | */ 30 | protected $path = ''; 31 | 32 | /** 33 | * @param \Rougin\Combustor\Combustor $combustor 34 | */ 35 | public function __construct(Combustor $combustor) 36 | { 37 | $this->path = $combustor->getAppPath(); 38 | } 39 | 40 | /** 41 | * Checks whether the command is enabled or not in the current environment. 42 | * 43 | * @return boolean 44 | */ 45 | public function isEnabled() 46 | { 47 | return ! class_exists('Rougin\Credo\Credo'); 48 | } 49 | 50 | /** 51 | * Executes the command. 52 | * 53 | * @return integer 54 | */ 55 | public function run() 56 | { 57 | system('composer require rougin/credo'); 58 | 59 | $class = new Classidy; 60 | 61 | $class->setName('MY_Loader'); 62 | $class->extendsTo('Rougin\Credo\Loader'); 63 | 64 | $maker = new Generator; 65 | 66 | $result = $maker->make($class); 67 | 68 | $file = $this->path . '/core/MY_Loader.php'; 69 | 70 | if (! file_exists($file)) 71 | { 72 | file_put_contents($file, $result); 73 | } 74 | 75 | $this->showPass('Doctrine installed successfully!'); 76 | 77 | return self::RETURN_SUCCESS; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Packages/DescribePackage.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class DescribePackage implements IntegrationInterface 17 | { 18 | /** 19 | * @param \Rougin\Slytherin\Container\ContainerInterface $container 20 | * @param \Rougin\Slytherin\Integration\Configuration $config 21 | * 22 | * @return \Rougin\Slytherin\Container\ContainerInterface 23 | */ 24 | public function define(ContainerInterface $container, Configuration $config) 25 | { 26 | // Ignore if Spark Plug is not defined --- 27 | $ci3Ctrl = 'Rougin\SparkPlug\Controller'; 28 | 29 | if (! $container->has($ci3Ctrl)) 30 | { 31 | return $container; 32 | } 33 | // --------------------------------------- 34 | 35 | /** @var \Rougin\SparkPlug\Controller */ 36 | $ci3App = $container->get($ci3Ctrl); 37 | 38 | $config = $this->getConfig($ci3App); 39 | 40 | $interface = 'Rougin\Describe\Driver\DriverInterface'; 41 | 42 | $driver = $this->getDriver($config); 43 | 44 | return $container->set($interface, $driver); 45 | } 46 | 47 | /** 48 | * @param \Rougin\SparkPlug\Controller $ci 49 | * 50 | * @return array 51 | */ 52 | protected function getConfig(Controller $ci) 53 | { 54 | $ci->load->database(); 55 | $ci->load->helper('inflector'); 56 | 57 | $config = array(); 58 | 59 | $config['dbdriver'] = $ci->db->dbdriver; 60 | $config['hostname'] = $ci->db->hostname; 61 | $config['username'] = $ci->db->username; 62 | $config['password'] = $ci->db->password; 63 | $config['database'] = $ci->db->database; 64 | 65 | if (empty($config['hostname'])) 66 | { 67 | $config['hostname'] = $ci->db->dsn; 68 | }; 69 | 70 | return $config; 71 | } 72 | 73 | /** 74 | * @param array $config 75 | * 76 | * @return \Rougin\Describe\Driver\DriverInterface 77 | */ 78 | protected function getDriver($config) 79 | { 80 | return new DatabaseDriver($config['dbdriver'], $config); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Commands/CreateLayout.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class CreateLayout extends Command 15 | { 16 | /** 17 | * @var string 18 | */ 19 | protected $name = 'create:layout'; 20 | 21 | /** 22 | * @var string 23 | */ 24 | protected $description = 'Create a new header and footer file'; 25 | 26 | /** 27 | * Configures the current command. 28 | * 29 | * @return void 30 | */ 31 | public function init() 32 | { 33 | $this->addOption('bootstrap', 'adds styling based on Bootstrap'); 34 | 35 | $this->addOption('force', 'generates file/s even they already exists'); 36 | } 37 | 38 | /** 39 | * Executes the command. 40 | * 41 | * @return integer 42 | */ 43 | public function run() 44 | { 45 | /** @var boolean */ 46 | $bootstrap = $this->getOption('bootstrap'); 47 | 48 | /** @var boolean */ 49 | $force = $this->getOption('force'); 50 | 51 | $path = $this->path . '/views/'; 52 | 53 | $file = $path . 'layout/header.php'; 54 | 55 | if (is_dir($path . 'layout') && ! $force) 56 | { 57 | $this->showFail('"header.php", "footer.php" already exists. Use --force to overwrite them.'); 58 | 59 | return self::RETURN_FAILURE; 60 | } 61 | 62 | $this->createDirectory(); 63 | 64 | // Create the "header.php" file ---------- 65 | $header = new HeaderPlate($bootstrap); 66 | 67 | file_put_contents($file, $header->make()); 68 | // --------------------------------------- 69 | 70 | // Create the "footer.php" file ---------- 71 | $footer = new FooterPlate($bootstrap); 72 | 73 | $file = $path . 'layout/footer.php'; 74 | 75 | file_put_contents($file, $footer->make()); 76 | // --------------------------------------- 77 | 78 | $this->showPass('Layout files created!'); 79 | 80 | return self::RETURN_SUCCESS; 81 | } 82 | 83 | /** 84 | * @codeCoverageIgnore 85 | * 86 | * @return void 87 | */ 88 | protected function createDirectory() 89 | { 90 | $path = $this->path . '/views/layout'; 91 | 92 | if (is_dir($path)) 93 | { 94 | return; 95 | } 96 | 97 | mkdir($this->path . '/views/layout'); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /phpstyle.php: -------------------------------------------------------------------------------- 1 | true); 11 | 12 | $cscp = 'control_structure_continuation_position'; 13 | $rules[$cscp] = ['position' => 'next_line']; 14 | 15 | $braces = array(); 16 | $braces['control_structures_opening_brace'] = 'next_line_unless_newline_at_signature_end'; 17 | $braces['functions_opening_brace'] = 'next_line_unless_newline_at_signature_end'; 18 | $braces['anonymous_functions_opening_brace'] = 'next_line_unless_newline_at_signature_end'; 19 | $braces['anonymous_classes_opening_brace'] = 'next_line_unless_newline_at_signature_end'; 20 | $braces['allow_single_line_empty_anonymous_classes'] = false; 21 | $braces['allow_single_line_anonymous_functions'] = false; 22 | $rules['braces_position'] = $braces; 23 | 24 | $visibility = array('elements' => array()); 25 | $visibility['elements'] = array('method', 'property'); 26 | $rules['visibility_required'] = $visibility; 27 | 28 | $rules['phpdoc_var_annotation_correct_order'] = true; 29 | 30 | $rules['single_quote'] = ['strings_containing_single_quote_chars' => true]; 31 | 32 | $rules['no_unused_imports'] = true; 33 | 34 | $rules['align_multiline_comment'] = true; 35 | 36 | $rules['trim_array_spaces'] = true; 37 | 38 | $order = ['case_sensitive' => true]; 39 | $order['null_adjustment'] = 'always_last'; 40 | $rules['phpdoc_types_order'] = $order; 41 | 42 | $rules['new_with_parentheses'] = ['named_class' => false]; 43 | 44 | $rules['concat_space'] = ['spacing' => 'one']; 45 | 46 | $rules['no_empty_phpdoc'] = true; 47 | 48 | $groups = []; 49 | $groups[] = ['template', 'extends']; 50 | $groups[] = ['deprecated', 'link', 'see', 'since', 'codeCoverageIgnore']; 51 | $groups[] = ['ManyToOne', 'JoinColumn']; 52 | $groups[] = ['property', 'property-read', 'property-write']; 53 | $groups[] = ['method']; 54 | $groups[] = ['author', 'copyright', 'license']; 55 | $groups[] = ['category', 'package', 'subpackage']; 56 | $groups[] = ['param']; 57 | $groups[] = ['return', 'throws']; 58 | $rules['phpdoc_separation'] = ['groups' => $groups]; 59 | 60 | $align = ['align' => 'vertical']; 61 | $align['tags'] = ['method', 'param', 'property', 'throws', 'type', 'var']; 62 | $rules['phpdoc_align'] = $align; 63 | 64 | $rules['statement_indentation'] = false; 65 | 66 | $rules['align_multiline_comment'] = true; 67 | // ----------------------------------------------- 68 | 69 | $finder = new \PhpCsFixer\Finder; 70 | 71 | $finder->in((array) $paths); 72 | 73 | $config = new \PhpCsFixer\Config; 74 | 75 | $config->setRules($rules); 76 | 77 | return $config->setFinder($finder); 78 | -------------------------------------------------------------------------------- /src/Packages/CombustorPackage.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class CombustorPackage implements IntegrationInterface 16 | { 17 | /** 18 | * @var \Rougin\Combustor\Colfield[] 19 | */ 20 | protected $customs = array(); 21 | 22 | /** 23 | * @var string[] 24 | */ 25 | protected $excluded = array(); 26 | 27 | /** 28 | * @var string 29 | */ 30 | protected $root; 31 | 32 | /** 33 | * @param string $root 34 | */ 35 | public function __construct($root) 36 | { 37 | $this->root = $root; 38 | } 39 | 40 | /** 41 | * @param \Rougin\Slytherin\Container\ContainerInterface $container 42 | * @param \Rougin\Slytherin\Integration\Configuration $config 43 | * 44 | * @return \Rougin\Slytherin\Container\ContainerInterface 45 | */ 46 | public function define(ContainerInterface $container, Configuration $config) 47 | { 48 | $app = new Combustor($this->root); 49 | 50 | if ($this->customs) 51 | { 52 | $app->setCustomFields($this->customs); 53 | } 54 | 55 | if ($this->excluded) 56 | { 57 | $app->setExcludedFields($this->excluded); 58 | } 59 | 60 | $name = 'Rougin\SparkPlug\Controller'; 61 | 62 | if ($container->has($name)) 63 | { 64 | /** @var \Rougin\SparkPlug\Controller */ 65 | $class = $container->get($name); 66 | 67 | $app->setApp($class); 68 | } 69 | 70 | $name = 'Rougin\Describe\Driver\DriverInterface'; 71 | 72 | if ($container->has($name)) 73 | { 74 | /** @var \Rougin\Describe\Driver\DriverInterface */ 75 | $class = $container->get($name); 76 | 77 | $app->setDriver($class); 78 | } 79 | 80 | return $container->set(get_class($app), $app); 81 | } 82 | 83 | /** 84 | * @param \Rougin\Combustor\Colfield[] $customs 85 | * 86 | * @return self 87 | */ 88 | public function setCustomFields($customs) 89 | { 90 | $this->customs = $customs; 91 | 92 | return $this; 93 | } 94 | 95 | /** 96 | * @param string[] $excluded 97 | * 98 | * @return self 99 | */ 100 | public function setExcludedFields($excluded) 101 | { 102 | $this->excluded = $excluded; 103 | 104 | return $this; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/Commands/CreateModel.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class CreateModel extends Command 14 | { 15 | /** 16 | * @var string 17 | */ 18 | protected $name = 'create:model'; 19 | 20 | /** 21 | * @var string 22 | */ 23 | protected $description = 'Create a new model'; 24 | 25 | /** 26 | * Configures the current command. 27 | * 28 | * @return void 29 | */ 30 | public function init() 31 | { 32 | parent::init(); 33 | 34 | $this->addOption('doctrine', 'generates a Doctrine-based model'); 35 | 36 | $this->addOption('wildfire', 'generates a Wildfire-based model'); 37 | 38 | $this->addOption('empty', 'generates an empty model'); 39 | } 40 | 41 | /** 42 | * Executes the command. 43 | * 44 | * @return integer 45 | */ 46 | public function run() 47 | { 48 | /** @var string */ 49 | $table = $this->getArgument('table'); 50 | 51 | /** @var boolean */ 52 | $doctrine = $this->getOption('doctrine'); 53 | 54 | /** @var boolean */ 55 | $wildfire = $this->getOption('wildfire'); 56 | 57 | /** @var boolean */ 58 | $empty = $this->getOption('empty'); 59 | 60 | /** @var boolean */ 61 | $force = $this->getOption('force'); 62 | 63 | try 64 | { 65 | $type = $this->getInstalled($doctrine, $wildfire); 66 | } 67 | catch (\Exception $e) 68 | { 69 | $this->showFail($e->getMessage()); 70 | 71 | return self::RETURN_FAILURE; 72 | } 73 | 74 | $name = Inflector::singular($table); 75 | 76 | $name = ucfirst(Inflector::singular($table)); 77 | 78 | $path = $this->path . '/models/'; 79 | 80 | $file = $path . $name . '.php'; 81 | 82 | if (file_exists($file) && ! $force) 83 | { 84 | $this->showFail('"' . $name . '" already exists. Use --force to overwrite the file.'); 85 | 86 | return self::RETURN_FAILURE; 87 | } 88 | 89 | // Create the model file -------------------- 90 | $plate = $this->getTemplate($type); 91 | 92 | if ($empty) 93 | { 94 | $plate->setEmpty(); 95 | } 96 | 97 | $plate = $this->maker->make($plate); 98 | 99 | file_put_contents($file, $plate); 100 | // ------------------------------------------ 101 | 102 | $this->showPass('Model successfully created!'); 103 | 104 | return self::RETURN_SUCCESS; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/Colfield.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class Colfield 11 | { 12 | /** 13 | * @var string|null 14 | */ 15 | protected $accessor = null; 16 | 17 | /** 18 | * @var string|null 19 | */ 20 | protected $class = null; 21 | 22 | /** 23 | * @var boolean 24 | */ 25 | protected $edit = false; 26 | 27 | /** 28 | * @var string|null 29 | */ 30 | protected $name = null; 31 | 32 | /** 33 | * @var boolean 34 | */ 35 | protected $styling = false; 36 | 37 | /** 38 | * @var string 39 | */ 40 | protected $tab = ''; 41 | 42 | /** 43 | * @var string|null 44 | */ 45 | protected $type = null; 46 | 47 | /** 48 | * @param boolean $edit 49 | * 50 | * @return self 51 | */ 52 | public function asEdit($edit = true) 53 | { 54 | $this->edit = $edit; 55 | 56 | return $this; 57 | } 58 | 59 | /** 60 | * @return string|null 61 | */ 62 | public function getClass() 63 | { 64 | if ($this->styling) 65 | { 66 | return $this->class; 67 | } 68 | 69 | return null; 70 | } 71 | 72 | /** 73 | * @return string|null 74 | */ 75 | public function getName() 76 | { 77 | return $this->name; 78 | } 79 | 80 | /** 81 | * @codeCoverageIgnore 82 | * 83 | * @return string[] 84 | */ 85 | public function getPlate() 86 | { 87 | return array(); 88 | } 89 | 90 | /** 91 | * @return string|null 92 | */ 93 | public function getType() 94 | { 95 | return $this->type; 96 | } 97 | 98 | /** 99 | * @param string $accessor 100 | * 101 | * @return self 102 | */ 103 | public function setAccessor($accessor) 104 | { 105 | $this->accessor = $accessor; 106 | 107 | return $this; 108 | } 109 | 110 | /** 111 | * @param string $name 112 | * 113 | * @return self 114 | */ 115 | public function setName($name) 116 | { 117 | $this->name = $name; 118 | 119 | return $this; 120 | } 121 | 122 | /** 123 | * @param string $tab 124 | * 125 | * @return self 126 | */ 127 | public function setSpacing($tab = '') 128 | { 129 | $this->tab = $tab; 130 | 131 | return $this; 132 | } 133 | 134 | /** 135 | * @param boolean $styling 136 | * 137 | * @return self 138 | */ 139 | public function useStyling($styling = true) 140 | { 141 | $this->styling = $styling; 142 | 143 | return $this; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/Commands/CreateRoute.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class CreateRoute extends Command 14 | { 15 | /** 16 | * @var string 17 | */ 18 | protected $name = 'create:controller'; 19 | 20 | /** 21 | * @var string 22 | */ 23 | protected $description = 'Create a new HTTP controller'; 24 | 25 | /** 26 | * Configures the current command. 27 | * 28 | * @return void 29 | */ 30 | public function init() 31 | { 32 | parent::init(); 33 | 34 | $this->addOption('doctrine', 'generates a Doctrine-based controller'); 35 | 36 | $this->addOption('wildfire', 'generates a Wildfire-based controller'); 37 | 38 | $this->addOption('empty', 'generates an empty HTTP controller'); 39 | } 40 | 41 | /** 42 | * Executes the command. 43 | * 44 | * @return integer 45 | */ 46 | public function run() 47 | { 48 | /** @var string */ 49 | $table = $this->getArgument('table'); 50 | 51 | /** @var boolean */ 52 | $doctrine = $this->getOption('doctrine'); 53 | 54 | /** @var boolean */ 55 | $wildfire = $this->getOption('wildfire'); 56 | 57 | /** @var boolean */ 58 | $empty = $this->getOption('empty'); 59 | 60 | /** @var boolean */ 61 | $force = $this->getOption('force'); 62 | 63 | try 64 | { 65 | $type = $this->getInstalled($doctrine, $wildfire); 66 | } 67 | catch (\Exception $e) 68 | { 69 | $this->showFail($e->getMessage()); 70 | 71 | return self::RETURN_FAILURE; 72 | } 73 | 74 | $path = $this->path . '/controllers/'; 75 | 76 | $name = Inflector::plural($table); 77 | 78 | $name = ucfirst(Inflector::plural($table)); 79 | 80 | $file = $path . $name . '.php'; 81 | 82 | if (file_exists($file) && ! $force) 83 | { 84 | $this->showFail('"' . $name . '" already exists. Use --force to overwrite the file.'); 85 | 86 | return self::RETURN_FAILURE; 87 | } 88 | 89 | // Create the controller file ------------- 90 | $plate = $this->getTemplate($type); 91 | 92 | if ($empty) 93 | { 94 | $plate->setEmpty(); 95 | } 96 | 97 | $plate = $this->maker->make($plate); 98 | 99 | file_put_contents($file, $plate); 100 | // ---------------------------------------- 101 | 102 | $this->showPass('Controller successfully created!'); 103 | 104 | return self::RETURN_SUCCESS; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/Combustor.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class Combustor 14 | { 15 | /** 16 | * @var \Rougin\SparkPlug\Controller|null 17 | */ 18 | protected $app = null; 19 | 20 | /** 21 | * @var \Rougin\Combustor\Colfield[] 22 | */ 23 | protected $customs = array(); 24 | 25 | /** 26 | * @var \Rougin\Describe\Driver\DriverInterface|null 27 | */ 28 | protected $driver = null; 29 | 30 | /** 31 | * @var string[] 32 | */ 33 | protected $excluded = array(); 34 | 35 | /** 36 | * @var string 37 | */ 38 | protected $root; 39 | 40 | /** 41 | * @param string $root 42 | */ 43 | public function __construct($root) 44 | { 45 | $this->root = $root; 46 | } 47 | 48 | /** 49 | * @return string 50 | */ 51 | public function getAppPath() 52 | { 53 | $app = $this->root . '/application'; 54 | 55 | $root = $this->getRootPath(); 56 | 57 | return is_dir($app) ? $app : $root; 58 | } 59 | 60 | /** 61 | * @return \Rougin\Describe\Driver\DriverInterface|null 62 | */ 63 | public function getDriver() 64 | { 65 | return $this->driver; 66 | } 67 | 68 | /** 69 | * @return string[] 70 | */ 71 | public function getExcludedFields() 72 | { 73 | return $this->excluded; 74 | } 75 | 76 | /** 77 | * @return \Rougin\Combustor\Colfield[] 78 | */ 79 | public function getCustomFields() 80 | { 81 | return $this->customs; 82 | } 83 | 84 | /** 85 | * @return string 86 | */ 87 | public function getRootPath() 88 | { 89 | return $this->root; 90 | } 91 | 92 | /** 93 | * @param \Rougin\SparkPlug\Controller $app 94 | * 95 | * @return self 96 | */ 97 | public function setApp(Controller $app) 98 | { 99 | $this->app = $app; 100 | 101 | return $this; 102 | } 103 | 104 | /** 105 | * @param \Rougin\Describe\Driver\DriverInterface $driver 106 | * 107 | * @return self 108 | */ 109 | public function setDriver(DriverInterface $driver) 110 | { 111 | $this->driver = $driver; 112 | 113 | return $this; 114 | } 115 | 116 | /** 117 | * @param \Rougin\Combustor\Colfield[] $customs 118 | * 119 | * @return self 120 | */ 121 | public function setCustomFields($customs) 122 | { 123 | $this->customs = $customs; 124 | 125 | return $this; 126 | } 127 | 128 | /** 129 | * @param string[] $excluded 130 | * 131 | * @return self 132 | */ 133 | public function setExcludedFields($excluded) 134 | { 135 | $this->excluded = $excluded; 136 | 137 | return $this; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/Template/IndexPlate.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class IndexPlate 13 | { 14 | /** 15 | * @var boolean 16 | */ 17 | protected $bootstrap = false; 18 | 19 | /** 20 | * @var \Rougin\Describe\Column[] 21 | */ 22 | protected $cols; 23 | 24 | /** 25 | * @var string 26 | */ 27 | protected $table; 28 | 29 | /** 30 | * @var integer 31 | */ 32 | protected $type; 33 | 34 | /** 35 | * @param string $table 36 | * @param integer $type 37 | * @param \Rougin\Describe\Column[] $cols 38 | */ 39 | public function __construct($table, $type, $cols) 40 | { 41 | $this->type = $type; 42 | 43 | $this->table = $table; 44 | 45 | $this->cols = $cols; 46 | } 47 | 48 | /** 49 | * @param string $tab 50 | * 51 | * @return string 52 | */ 53 | public function make($tab = '') 54 | { 55 | $model = Inflector::singular($this->table); 56 | 57 | $route = Inflector::plural($this->table); 58 | 59 | $lines = array('

' . ucfirst($route) . '

'); 60 | $lines[] = ''; 61 | 62 | $lines[] = ''; 63 | $class = $this->bootstrap ? 'alert alert-success' : ''; 64 | $lines[] = '
'; 65 | $lines[] = ''; 66 | $lines[] = ''; 67 | 68 | $text = 'Create New ' . ucfirst($model); 69 | $class = $this->bootstrap ? 'my-3' : ''; 70 | $lines[] = '
'; 71 | $class = $this->bootstrap ? 'btn btn-primary' : ''; 72 | $lines[] = ' ' . $text . ''; 73 | $lines[] = '
'; 74 | $lines[] = ''; 75 | 76 | $lines[] = '
'; 77 | 78 | $table = new TablePlate($this->table, $this->cols, $this->type); 79 | 80 | $table->withBootstrap($this->bootstrap); 81 | 82 | foreach ($table->make($tab) as $line) 83 | { 84 | $lines[] = $line; 85 | } 86 | 87 | $lines[] = ' '; 88 | $lines[] = '
'; 89 | $lines[] = ''; 90 | 91 | $lines[] = ''; 102 | 103 | $result = implode("\n", $lines); 104 | 105 | return str_replace(' class=""', '', $result); 106 | } 107 | 108 | /** 109 | * @param boolean $bootstrap 110 | * 111 | * @return self 112 | */ 113 | public function withBootstrap($bootstrap) 114 | { 115 | $this->bootstrap = $bootstrap; 116 | 117 | return $this; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/Commands/CreateScaffold.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class CreateScaffold extends Command 13 | { 14 | const TYPE_WILDFIRE = 0; 15 | 16 | const TYPE_DOCTRINE = 1; 17 | 18 | /** 19 | * @var \Rougin\Describe\Driver\DriverInterface|null 20 | */ 21 | protected $driver = null; 22 | 23 | /** 24 | * @var string 25 | */ 26 | protected $name = 'create:scaffold'; 27 | 28 | /** 29 | * @var string 30 | */ 31 | protected $description = 'Create a new HTTP controller, model, and view templates'; 32 | 33 | /** 34 | * Configures the current command. 35 | * 36 | * @return void 37 | */ 38 | public function init() 39 | { 40 | parent::init(); 41 | 42 | $this->addOption('bootstrap', 'adds styling based on Bootstrap'); 43 | 44 | $this->addOption('doctrine', 'generates a Doctrine-based controller, models, and views'); 45 | 46 | $this->addOption('wildfire', 'generates a Wildfire-based controller, models, and views'); 47 | 48 | $this->addOption('empty', 'generates an empty HTTP controller and model'); 49 | } 50 | 51 | /** 52 | * Executes the command. 53 | * 54 | * @return integer 55 | */ 56 | public function run() 57 | { 58 | /** @var boolean */ 59 | $doctrine = $this->getOption('doctrine'); 60 | 61 | /** @var boolean */ 62 | $empty = $this->getOption('empty'); 63 | 64 | /** @var boolean */ 65 | $wildfire = $this->getOption('wildfire'); 66 | 67 | /** @var boolean */ 68 | $force = $this->getOption('force'); 69 | 70 | try 71 | { 72 | $this->getInstalled($doctrine, $wildfire); 73 | } 74 | catch (\Exception $e) 75 | { 76 | $this->showFail($e->getMessage()); 77 | 78 | return Command::RETURN_FAILURE; 79 | } 80 | 81 | /** @var string */ 82 | $table = $this->getArgument('table'); 83 | 84 | $input = array('table' => $table); 85 | $input['--doctrine'] = $doctrine; 86 | $input['--empty'] = $empty; 87 | $input['--wildfire'] = $wildfire; 88 | $input['--force'] = $force; 89 | 90 | // Execute the "create:controller" command ---- 91 | $this->runCommand('create:controller', $input); 92 | // -------------------------------------------- 93 | 94 | // Execute the "create:model" command ---- 95 | $this->runCommand('create:model', $input); 96 | // --------------------------------------- 97 | 98 | // Execute the "create:views" command ----- 99 | /** @var boolean */ 100 | $bootstrap = $this->getOption('bootstrap'); 101 | 102 | unset($input['--empty']); 103 | 104 | $input['--bootstrap'] = $bootstrap; 105 | 106 | $this->runCommand('create:views', $input); 107 | // ---------------------------------------- 108 | 109 | // Execute the "create:repository" command -------- 110 | if ($doctrine) 111 | { 112 | $input = array('table' => $table); 113 | $input['--force'] = $force; 114 | 115 | $this->runCommand('create:repository', $input); 116 | } 117 | // ------------------------------------------------ 118 | 119 | return Command::RETURN_SUCCESS; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/Commands/CreateView.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class CreateView extends Command 17 | { 18 | /** 19 | * @var string 20 | */ 21 | protected $name = 'create:views'; 22 | 23 | /** 24 | * @var string 25 | */ 26 | protected $description = 'Create view templates'; 27 | 28 | /** 29 | * Configures the current command. 30 | * 31 | * @return void 32 | */ 33 | public function init() 34 | { 35 | parent::init(); 36 | 37 | $this->addOption('bootstrap', 'adds styling based on Bootstrap'); 38 | 39 | $this->addOption('doctrine', 'generates Doctrine-based views'); 40 | 41 | $this->addOption('wildfire', 'generates Wildfire-based views'); 42 | } 43 | 44 | /** 45 | * Executes the command. 46 | * 47 | * @return integer 48 | */ 49 | public function run() 50 | { 51 | /** @var string */ 52 | $table = $this->getArgument('table'); 53 | 54 | /** @var boolean */ 55 | $doctrine = $this->getOption('doctrine'); 56 | 57 | /** @var boolean */ 58 | $wildfire = $this->getOption('wildfire'); 59 | 60 | /** @var boolean */ 61 | $force = $this->getOption('force'); 62 | 63 | try 64 | { 65 | $type = $this->getInstalled($doctrine, $wildfire); 66 | } 67 | catch (\Exception $e) 68 | { 69 | $this->showFail($e->getMessage()); 70 | 71 | return self::RETURN_FAILURE; 72 | } 73 | 74 | /** @var \Rougin\Describe\Driver\DriverInterface */ 75 | $describe = $this->driver; 76 | 77 | $cols = $describe->columns($table); 78 | 79 | $name = Inflector::plural($table); 80 | 81 | $path = $this->path . '/views/'; 82 | 83 | if (is_dir($path . $name) && ! $force) 84 | { 85 | $this->showFail('"' . $name . '" directory already exists. Use --force to overwrite the directory.'); 86 | 87 | return self::RETURN_FAILURE; 88 | } 89 | 90 | if (! is_dir($path . $name)) 91 | { 92 | mkdir($path . $name); 93 | } 94 | 95 | /** @var boolean */ 96 | $bootstrap = $this->getOption('bootstrap'); 97 | 98 | // Create the "create.php" file ---------------- 99 | $create = new CreatePlate($table, $type, $cols); 100 | 101 | $create->withBootstrap($bootstrap); 102 | 103 | $create->withExcludedFields($this->excluded); 104 | 105 | $create->withCustomFields($this->customs); 106 | 107 | $file = $path . $name . '/create.php'; 108 | 109 | file_put_contents($file, $create->make(' ')); 110 | // --------------------------------------------- 111 | 112 | // Create the "edit.php" file -------------- 113 | $edit = new EditPlate($table, $type, $cols); 114 | 115 | $edit->withBootstrap($bootstrap); 116 | 117 | $edit->withExcludedFields($this->excluded); 118 | 119 | $edit->withCustomFields($this->customs); 120 | 121 | $file = $path . $name . '/edit.php'; 122 | 123 | file_put_contents($file, $edit->make(' ')); 124 | // ----------------------------------------- 125 | 126 | // Create the "index.php" file --------------- 127 | $index = new IndexPlate($table, $type, $cols); 128 | 129 | $index->withBootstrap($bootstrap); 130 | 131 | $file = $path . $name . '/index.php'; 132 | 133 | file_put_contents($file, $index->make(' ')); 134 | // ------------------------------------------- 135 | 136 | $this->showPass('Views successfully created!'); 137 | 138 | return self::RETURN_SUCCESS; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `Combustor` will be documented in this file. 4 | 5 | ## [1.3.0](https://github.com/rougin/transcribe/compare/v1.2.4...v1.3.0) - 2024-10-22 6 | 7 | ### Added 8 | - Command for creating `combustor.yml` configuration file 9 | - Custom fields in templates using `custom_fields` 10 | - Fields that can be excluded through `excluded_files` 11 | - Specify customized `application` path using `app_path` 12 | - `create:repository` for creating Entity Repositories 13 | - `--empty` for `create:controller`, `create:model` 14 | - `--force` to overwrite existing files 15 | 16 | ### Changed 17 | - Code coverage provider to `Codecov` 18 | - Code documentation by `php-cs-fixer` 19 | - Improved code quality by `phpstan` 20 | - Main argument `name` to `table` in `Commands` 21 | - Simplified code structure 22 | - Workflow provider to `Github Actions` 23 | 24 | ### Removed 25 | - Options to strictly conform in coding style of `Codeigniter`: 26 | - `--camel` 27 | - `--keep` 28 | - `--lowercase` 29 | - `CONTRIBUTING.md` 30 | 31 | ## [1.2.4](https://github.com/rougin/combustor/compare/v1.2.3...v1.2.4) - 2018-04-18 32 | 33 | ### Fixed 34 | - Bootstrap version in `CreateLayoutCommand` 35 | 36 | ## [1.2.3](https://github.com/rougin/combustor/compare/v1.2.2...v1.2.3) - 2016-09-16 37 | 38 | ### Fixed 39 | - Issues in unit testing 40 | 41 | ## [1.2.2](https://github.com/rougin/combustor/compare/v1.2.1...v1.2.2) - 2016-09-04 42 | 43 | ### Changed 44 | - From `$table` to `$new_table` in `Wildfire.tpl` 45 | 46 | ### Fixed 47 | - Updating configuration files on Windows platform 48 | 49 | ## [1.2.1](https://github.com/rougin/combustor/compare/v1.2.0...v1.2.1) - 2016-05-12 50 | 51 | ### Changed 52 | - Version of `rougin/codeigniter` to `^3.0.0` 53 | 54 | ## [1.2.0](https://github.com/rougin/combustor/compare/v1.1.4...v1.2.0) - 2016-05-11 55 | 56 | ### Added 57 | - Unit tests for other commands 58 | - Contributor Code of Conduct 59 | - `Config` class for handling configurations 60 | 61 | ### Changed 62 | - Can now only install `Wildfire` or `Doctrine` 63 | - Moved redundant functions to base classes (e.g. `BaseValidator`, `InstallCommand`, `RemoveCommand`) 64 | 65 | ### Fixed 66 | - Issues in generating code in `Doctrine` 67 | - Functionalities in `Doctrine.php` 68 | - Issue in changing values in `config` directory 69 | 70 | ## [1.1.4](https://github.com/rougin/combustor/compare/v1.1.3...v1.1.4) - 2015-11-14 71 | 72 | ### Changed 73 | - Whole code structure from scratch 74 | - Conformed to SOLID design approach 75 | 76 | ## [1.1.3](https://github.com/rougin/combustor/compare/v1.1.2...v1.1.3) - 2015-10-15 77 | 78 | ### Added 79 | - Proper form validation rules 80 | - Generation of [Bootstrap](getbootstrap.com)-based views via [Bower](http://bower.io/) 81 | - Special cases for specified fields 82 | - `date` input type in `create.php` and `edit.php` 83 | 84 | ### Changed 85 | - Generation of indexes for [Doctrine](http://www.doctrine-project.org/projects/orm.html) 86 | - Conformed to PSR standards 87 | 88 | ### Fixed 89 | - Wrong generation of date and time data in creating models 90 | 91 | ## [1.1.2](https://github.com/rougin/combustor/compare/v1.1.1...v1.1.2) - 2015-07-01 92 | 93 | ### Changed 94 | - Version number 95 | 96 | ### Fixed 97 | - Errors when generating the codebase 98 | 99 | ## [1.1.1](https://github.com/rougin/combustor/compare/v1.1.0...v1.1.1) - 2015-06-30 100 | 101 | ### Added 102 | - [SparkPlug](https://github.com/rougin/spark-plug) as a dependency 103 | 104 | ### Changed 105 | - File permissions 106 | - Functionalities from scratch to conform [Describe](https://github.com/rougin/spark-)'s latest update 107 | 108 | ### Fixed 109 | - Accessing [SQLite](https://www.sqlite.org/) database 110 | 111 | ## [1.1.0](https://github.com/rougin/combustor/compare/v1.0.0...v1.1.0) - 2015-06-23 112 | 113 | ### Added 114 | - Support for multiple databases in the same database connection 115 | 116 | ### Changed 117 | - Installation process 118 | - Layout views in `create:view` 119 | 120 | ### Fixed 121 | - Issues regarding [Doctrine](http://www.doctrine-project.org/) 122 | 123 | ### Removed 124 | - `Inflect.php` for CodeIgniter's [Inflector Helper](http://www.codeigniter.com/userguide3/helpers/inflector_helper.html) 125 | - `MY_Pagination.php` for CodeIgniter's [Pagination Class](http://www.codeigniter.com/userguide3/libraries/pagination.html) 126 | 127 | ## 1.0.0 - 2015-04-01 128 | 129 | ### Added 130 | - `Combustor` library 131 | -------------------------------------------------------------------------------- /src/Console.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class Console extends Blueprint 19 | { 20 | /** 21 | * @var string 22 | */ 23 | protected $name = 'Combustor'; 24 | 25 | /** 26 | * @var string 27 | */ 28 | protected $file = 'combustor.yml'; 29 | 30 | /** 31 | * @var string 32 | */ 33 | protected $root; 34 | 35 | /** 36 | * @var string 37 | */ 38 | protected $version = '1.3.0'; 39 | 40 | /** 41 | * @param string $root 42 | */ 43 | public function __construct($root) 44 | { 45 | $namespace = __NAMESPACE__ . '\Commands'; 46 | 47 | $this->setCommandNamespace($namespace); 48 | 49 | $this->setCommandPath(__DIR__ . '/Commands'); 50 | 51 | $this->root = $root; 52 | 53 | $this->setPackages(); 54 | } 55 | 56 | /** 57 | * @return string 58 | */ 59 | public function getAppPath() 60 | { 61 | /** @var string */ 62 | $path = realpath($this->root); 63 | 64 | if (! file_exists($path . '/' . $this->file)) 65 | { 66 | return $path; 67 | } 68 | 69 | $parsed = $this->getParsed(); 70 | 71 | if (array_key_exists('app_path', $parsed)) 72 | { 73 | /** @var string */ 74 | $path = $parsed['app_path']; 75 | } 76 | 77 | /** @var string */ 78 | return realpath($path); 79 | } 80 | 81 | /** 82 | * @return \Rougin\Combustor\Colfield[] 83 | */ 84 | public function getCustomFields() 85 | { 86 | $parsed = $this->getParsed(); 87 | 88 | $field = 'custom_fields'; 89 | 90 | if (! array_key_exists($field, $parsed)) 91 | { 92 | return array(); 93 | } 94 | 95 | /** @var class-string[] */ 96 | $items = $parsed[$field]; 97 | 98 | $customs = array(); 99 | 100 | foreach ($items as $item) 101 | { 102 | $ref = new ReflectionClass($item); 103 | 104 | /** @var \Rougin\Combustor\Colfield */ 105 | $custom = $ref->newInstance(); 106 | 107 | $customs[] = $custom; 108 | } 109 | 110 | return $customs; 111 | } 112 | 113 | /** 114 | * @return string[] 115 | */ 116 | public function getExcludedFields() 117 | { 118 | $parsed = $this->getParsed(); 119 | 120 | $field = 'excluded_fields'; 121 | 122 | if (! array_key_exists($field, $parsed)) 123 | { 124 | return array(); 125 | } 126 | 127 | /** @var string[] */ 128 | return $parsed[$field]; 129 | } 130 | 131 | /** 132 | * @return array 133 | */ 134 | protected function getParsed() 135 | { 136 | /** @var string */ 137 | $path = realpath($this->root); 138 | 139 | if (! file_exists($path . '/' . $this->file)) 140 | { 141 | return array(); 142 | } 143 | 144 | $file = $path . '/' . $this->file; 145 | 146 | /** @var string */ 147 | $file = file_get_contents($file); 148 | 149 | // Replace the constant with root path ---- 150 | $search = '%%CURRENT_DIRECTORY%%'; 151 | 152 | $file = str_replace($search, $path, $file); 153 | // ---------------------------------------- 154 | 155 | /** @var array */ 156 | return Yaml::parse($file); 157 | } 158 | 159 | /** 160 | * @return void 161 | */ 162 | protected function setPackages() 163 | { 164 | $container = new Container; 165 | 166 | $path = $this->getAppPath(); 167 | 168 | $sparkPlug = new SparkplugPackage($path); 169 | $container->addPackage($sparkPlug); 170 | 171 | $describe = new DescribePackage; 172 | $container->addPackage($describe); 173 | 174 | $combustor = new CombustorPackage($path); 175 | 176 | $customs = $this->getCustomFields(); 177 | $combustor->setCustomFields($customs); 178 | 179 | $excluded = $this->getExcludedFields(); 180 | $combustor->setExcludedFields($excluded); 181 | 182 | $container->addPackage($combustor); 183 | 184 | $this->setContainer($container); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/Command.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class Command extends Blueprint 18 | { 19 | const TYPE_WILDFIRE = 0; 20 | 21 | const TYPE_DOCTRINE = 1; 22 | 23 | /** 24 | * @var \Rougin\Describe\Driver\DriverInterface|null 25 | */ 26 | protected $driver = null; 27 | 28 | /** 29 | * @var string[] 30 | */ 31 | protected $excluded = array(); 32 | 33 | /** 34 | * @var \Rougin\Combustor\Colfield[] 35 | */ 36 | protected $customs = array(); 37 | 38 | /** 39 | * @var \Rougin\Classidy\Generator 40 | */ 41 | protected $maker; 42 | 43 | /** 44 | * @var string 45 | */ 46 | protected $path; 47 | 48 | /** 49 | * @param \Rougin\Combustor\Combustor $combustor 50 | * @param \Rougin\Classidy\Generator $maker 51 | */ 52 | public function __construct(Combustor $combustor, Generator $maker) 53 | { 54 | $this->driver = $combustor->getDriver(); 55 | 56 | $this->excluded = $combustor->getExcludedFields(); 57 | 58 | $this->customs = $combustor->getCustomFields(); 59 | 60 | $this->maker = $maker; 61 | 62 | $this->path = $combustor->getAppPath(); 63 | } 64 | 65 | /** 66 | * @return void 67 | */ 68 | public function init() 69 | { 70 | $this->addArgument('table', 'Name of the database table'); 71 | 72 | $this->addOption('force', 'generates file/s even they already exists'); 73 | } 74 | 75 | /** 76 | * @return boolean 77 | */ 78 | public function isEnabled() 79 | { 80 | return $this->driver !== null; 81 | } 82 | 83 | /** 84 | * @param boolean $doctrine 85 | * @param boolean $wildfire 86 | * 87 | * @return integer 88 | * @throws \Exception 89 | */ 90 | protected function getInstalled($doctrine, $wildfire) 91 | { 92 | $class = 'Rougin\Credo\Credo'; 93 | $doctrineExists = class_exists($class); 94 | 95 | $class = 'Rougin\Wildfire\Wildfire'; 96 | $wildfireExists = class_exists($class); 97 | 98 | /** 99 | * If --doctrine or --wildfire not specified 100 | */ 101 | if (! $doctrine && ! $wildfire) 102 | { 103 | /** 104 | * If not specified as option and packages are not yet installed 105 | */ 106 | if (! $doctrineExists && ! $wildfireExists) 107 | { 108 | $text = 'Both "rougin/credo" and "rougin/wildfire" are not installed.'; 109 | 110 | throw new \Exception($text . ' Kindly "rougin/credo" or "rougin/wildfire" first.'); 111 | } 112 | 113 | /** 114 | * If both installed and not specified as option 115 | */ 116 | if ($doctrineExists && $wildfireExists) 117 | { 118 | $text = 'Both "rougin/credo" and "rougin/wildfire" are installed.'; 119 | 120 | throw new \Exception($text . ' Kindly select --doctrine or --wildfire first.'); 121 | } 122 | } 123 | 124 | if (! $wildfire && ($doctrine || $doctrineExists)) 125 | { 126 | return self::TYPE_DOCTRINE; 127 | } 128 | 129 | return self::TYPE_WILDFIRE; 130 | } 131 | 132 | /** 133 | * @param integer $type 134 | * 135 | * @return \Rougin\Classidy\Classidy 136 | */ 137 | protected function getTemplate($type) 138 | { 139 | /** @var string */ 140 | $table = $this->getArgument('table'); 141 | 142 | $isModel = $this->name === 'create:model'; 143 | 144 | /** @var \Rougin\Describe\Driver\DriverInterface */ 145 | $driver = $this->driver; 146 | 147 | $cols = $driver->columns($table); 148 | 149 | if ($isModel && $type === self::TYPE_DOCTRINE) 150 | { 151 | return new DoctrineModel($table, $cols, $this->excluded); 152 | } 153 | 154 | if ($isModel && $type === self::TYPE_WILDFIRE) 155 | { 156 | return new WildfireModel($table, $cols, $this->excluded); 157 | } 158 | 159 | if ($this->name === 'create:repository') 160 | { 161 | return new Repository($table, $cols, $this->excluded); 162 | } 163 | 164 | $route = new Controller($table, $cols); 165 | 166 | $route->useLayout($this->hasLayout()); 167 | 168 | return $route->setType($type)->init(); 169 | } 170 | 171 | /** 172 | * @return boolean 173 | */ 174 | protected function hasLayout() 175 | { 176 | return is_dir($this->path . '/views/layout'); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/Inflector.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class Inflector 13 | { 14 | /** 15 | * Takes multiple words separated by the separator and changes them to spaces 16 | * 17 | * @param string $word 18 | * @param string $separator 19 | * 20 | * @return string 21 | */ 22 | public static function humanize($word, $separator = '_') 23 | { 24 | $regex = '/[' . preg_quote($separator) . ']+/'; 25 | 26 | $word = trim(mb_strtolower($word)); 27 | 28 | /** @var string */ 29 | $result = preg_replace($regex, ' ', $word); 30 | 31 | return ucwords($result); 32 | } 33 | 34 | /** 35 | * Takes a singular word and makes it plural. 36 | * 37 | * @param string $word 38 | * 39 | * @return string 40 | */ 41 | public static function plural($word) 42 | { 43 | $result = strval($word); 44 | 45 | $rules = array( 46 | '/(quiz)$/' => '\1zes', // quizzes 47 | '/^(ox)$/' => '\1\2en', // ox 48 | '/([m|l])ouse$/' => '\1ice', // mouse, louse 49 | '/(matr|vert|ind)ix|ex$/' => '\1ices', // matrix, vertex, index 50 | '/(x|ch|ss|sh)$/' => '\1es', // search, switch, fix, box, process, address 51 | '/([^aeiouy]|qu)y$/' => '\1ies', // query, ability, agency 52 | '/(hive)$/' => '\1s', // archive, hive 53 | '/(?:([^f])fe|([lr])f)$/' => '\1\2ves', // half, safe, wife 54 | '/sis$/' => 'ses', // basis, diagnosis 55 | '/([ti])um$/' => '\1a', // datum, medium 56 | '/(p)erson$/' => '\1eople', // person, salesperson 57 | '/(m)an$/' => '\1en', // man, woman, spokesman 58 | '/(c)hild$/' => '\1hildren', // child 59 | '/(buffal|tomat)o$/' => '\1\2oes', // buffalo, tomato 60 | '/(bu|campu)s$/' => '\1\2ses', // bus, campus 61 | '/(alias|status|virus)$/' => '\1es', // alias 62 | '/(octop)us$/' => '\1i', // octopus 63 | '/(ax|cris|test)is$/' => '\1es', // axis, crisis 64 | '/s$/' => 's', // no change (compatibility) 65 | '/$/' => 's', 66 | ); 67 | 68 | foreach ($rules as $rule => $replace) 69 | { 70 | if (preg_match($rule, $result)) 71 | { 72 | /** @var string */ 73 | $result = preg_replace($rule, $replace, $result); 74 | 75 | break; 76 | } 77 | } 78 | 79 | return $result; 80 | } 81 | 82 | /** 83 | * Takes a singular word and makes it singular. 84 | * 85 | * @param string $word 86 | * 87 | * @return string 88 | */ 89 | public static function singular($word) 90 | { 91 | $result = strval($word); 92 | 93 | $rules = array( 94 | '/(matr)ices$/' => '\1ix', 95 | '/(vert|ind)ices$/' => '\1ex', 96 | '/^(ox)en/' => '\1', 97 | '/(alias)es$/' => '\1', 98 | '/([octop|vir])i$/' => '\1us', 99 | '/(cris|ax|test)es$/' => '\1is', 100 | '/(shoe)s$/' => '\1', 101 | '/(o)es$/' => '\1', 102 | '/(bus|campus)es$/' => '\1', 103 | '/([m|l])ice$/' => '\1ouse', 104 | '/(x|ch|ss|sh)es$/' => '\1', 105 | '/(m)ovies$/' => '\1\2ovie', 106 | '/(s)eries$/' => '\1\2eries', 107 | '/([^aeiouy]|qu)ies$/' => '\1y', 108 | '/([lr])ves$/' => '\1f', 109 | '/(tive)s$/' => '\1', 110 | '/(hive)s$/' => '\1', 111 | '/([^f])ves$/' => '\1fe', 112 | '/(^analy)ses$/' => '\1sis', 113 | '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/' => '\1\2sis', 114 | '/([ti])a$/' => '\1um', 115 | '/(p)eople$/' => '\1\2erson', 116 | '/(m)en$/' => '\1an', 117 | '/(s)tatuses$/' => '\1\2tatus', 118 | '/(c)hildren$/' => '\1\2hild', 119 | '/(n)ews$/' => '\1\2ews', 120 | '/(quiz)zes$/' => '\1', 121 | '/([^us])s$/' => '\1' 122 | ); 123 | 124 | foreach ($rules as $rule => $replacement) 125 | { 126 | if (preg_match($rule, $result)) 127 | { 128 | /** @var string */ 129 | $result = preg_replace($rule, $replacement, $result); 130 | 131 | break; 132 | } 133 | } 134 | 135 | return $result; 136 | } 137 | 138 | /** 139 | * Takes multiple words separated by spaces and underscores them. 140 | * 141 | * @param string $word 142 | * 143 | * @return string 144 | */ 145 | public static function snakeCase($word) 146 | { 147 | /** @var string */ 148 | return preg_replace('/[\s]+/', '_', mb_strtolower($word)); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/Template/Repository.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class Repository extends Classidy 15 | { 16 | /** 17 | * @var \Rougin\Describe\Column[] 18 | */ 19 | protected $cols; 20 | 21 | /** 22 | * @var string[] 23 | */ 24 | protected $excluded = array(); 25 | 26 | /** 27 | * @param string $table 28 | * @param \Rougin\Describe\Column[] $cols 29 | * @param string[] $excluded 30 | */ 31 | public function __construct($table, $cols, $excluded = array()) 32 | { 33 | $this->cols = $cols; 34 | 35 | $this->excluded = $excluded; 36 | 37 | $this->init($table); 38 | } 39 | 40 | /** 41 | * @param string $table 42 | * 43 | * @return void 44 | */ 45 | public function init($table) 46 | { 47 | $model = ucfirst(Inflector::singular($table)); 48 | 49 | $this->setName($model . '_repository'); 50 | $this->extendsTo('Rougin\Credo\Repository'); 51 | 52 | $comment = '@extends \Rougin\Credo\Repository<\\' . $model . '>'; 53 | $this->setComment($comment); 54 | 55 | $ci = 'CI_DB_query_builder'; 56 | $this->addClassProperty('db', $ci)->asTag(); 57 | 58 | $em = 'Doctrine\ORM\EntityManagerInterface'; 59 | $this->addClassProperty('_em', $em)->asTag(); 60 | 61 | $method = new Method('create'); 62 | $method->addArrayArgument('data', 'array'); 63 | $method->addClassArgument('entity', '\\' . $model); 64 | $this->addMethod($method->asTag()); 65 | 66 | $method = new Method('delete'); 67 | $method->addClassArgument('entity', '\\' . $model); 68 | $this->addMethod($method->asTag()); 69 | 70 | $method = new Method('find'); 71 | $method->setReturn('\\' . $model . '|null'); 72 | $method->addIntegerArgument('id'); 73 | $this->addMethod($method->asTag()); 74 | 75 | $method = new Method('get'); 76 | $method->setReturn('\\' . $model . '[]'); 77 | $method->addIntegerArgument('limit', true); 78 | $method->addIntegerArgument('offset', true); 79 | $this->addMethod($method->asTag()); 80 | 81 | $method = new Method('set'); 82 | $method->setReturn('\\' . $model); 83 | $method->addArrayArgument('data', 'array'); 84 | $method->addClassArgument('entity', '\\' . $model); 85 | $method->addIntegerArgument('id', true); 86 | $this->addMethod($method->asTag()); 87 | 88 | $method = new Method('update'); 89 | $method->addClassArgument('entity', '\\' . $model); 90 | $method->addArrayArgument('data', 'array'); 91 | $this->addMethod($method->asTag()); 92 | 93 | $this->setExistsMethod(); 94 | 95 | $this->setSetMethod($table); 96 | } 97 | 98 | /** 99 | * @return void 100 | */ 101 | protected function setExistsMethod() 102 | { 103 | $method = new Method('exists'); 104 | 105 | $method->setReturn('boolean'); 106 | 107 | $method->addArrayArgument('data', 'array'); 108 | 109 | $method->addIntegerArgument('id', true); 110 | 111 | $method->setCodeLine(function ($lines) 112 | { 113 | $lines[] = '// Specify logic here if applicable ---'; 114 | $lines[] = '// ------------------------------------'; 115 | $lines[] = ''; 116 | $lines[] = 'return false;'; 117 | 118 | return $lines; 119 | }); 120 | 121 | $this->addMethod($method); 122 | } 123 | 124 | /** 125 | * @param string $table 126 | * 127 | * @return void 128 | */ 129 | protected function setSetMethod($table) 130 | { 131 | $model = ucfirst(Inflector::singular($table)); 132 | 133 | $method = new Method('set'); 134 | 135 | $method->setReturn('\\' . $model); 136 | $method->addArrayArgument('data', 'array'); 137 | $method->addClassArgument('entity', $model) 138 | ->withoutTypeDeclared(); 139 | $method->addIntegerArgument('id', true); 140 | 141 | $cols = $this->cols; 142 | 143 | $method->setCodeLine(function ($lines) use ($cols) 144 | { 145 | $lines[] = '// List editable fields from table ---'; 146 | 147 | foreach ($cols as $index => $col) 148 | { 149 | $name = $col->getField(); 150 | 151 | if ($col->isPrimaryKey() || in_array($name, $this->excluded)) 152 | { 153 | continue; 154 | } 155 | 156 | $type = $col->getDataType(); 157 | 158 | if ($col->isNull()) 159 | { 160 | $type = $type . '|null'; 161 | } 162 | 163 | $isNull = $col->isNull(); 164 | 165 | $isOptional = $isNull || $type === 'boolean'; 166 | 167 | $space = $isOptional ? ' ' : ''; 168 | 169 | if ($isOptional) 170 | { 171 | $default = $isNull ? 'null' : 'false'; 172 | 173 | $field = $name; 174 | 175 | if ($col->isForeignKey()) 176 | { 177 | $field = $col->getReferencedTable(); 178 | $field = Inflector::singular($field); 179 | } 180 | 181 | $lines[] = '$' . $field . ' = ' . $default . ';'; 182 | $lines[] = 'if (array_key_exists(\'' . $name . '\', $data))'; 183 | $lines[] = '{'; 184 | } 185 | 186 | $lines[] = $space . '/** @var ' . $type . ' */'; 187 | $lines[] = $space . '$' . $name . ' = $data[\'' . $name . '\'];'; 188 | 189 | if ($col->isForeignKey()) 190 | { 191 | $foreign = $col->getReferencedTable(); 192 | $foreign = Inflector::singular($foreign); 193 | 194 | $class = ucfirst($foreign); 195 | 196 | $lines[] = $space . '$user = $this->_em->find(\'' . $class . '\', $' . $name . ');'; 197 | 198 | $name = $foreign; 199 | } 200 | 201 | if ($isOptional) 202 | { 203 | $lines[] = '}'; 204 | } 205 | 206 | $lines[] = '$entity->set_' . $name . '($' . $name . ');'; 207 | 208 | if (array_key_exists($index + 1, $cols)) 209 | { 210 | $next = $cols[$index + 1]; 211 | 212 | if (! in_array($next->getField(), $this->excluded)) 213 | { 214 | $lines[] = ''; 215 | } 216 | } 217 | } 218 | 219 | $lines[] = '// -----------------------------------'; 220 | $lines[] = ''; 221 | $lines[] = 'return $entity;'; 222 | 223 | return $lines; 224 | }); 225 | 226 | $this->addMethod($method); 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /src/Template/TablePlate.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class TablePlate 14 | { 15 | const TYPE_WILDFIRE = 0; 16 | 17 | const TYPE_DOCTRINE = 1; 18 | 19 | /** 20 | * @var boolean 21 | */ 22 | protected $bootstrap = false; 23 | 24 | /** 25 | * @var \Rougin\Describe\Column[] 26 | */ 27 | protected $cols; 28 | 29 | /** 30 | * @var string 31 | */ 32 | protected $table; 33 | 34 | /** 35 | * @var integer 36 | */ 37 | protected $type; 38 | 39 | /** 40 | * @param string $table 41 | * @param \Rougin\Describe\Column[] $cols 42 | * @param integer $type 43 | */ 44 | public function __construct($table, $cols, $type) 45 | { 46 | $this->cols = $cols; 47 | 48 | $this->table = $table; 49 | 50 | $this->type = $type; 51 | } 52 | 53 | /** 54 | * @param string $tab 55 | * 56 | * @return string[] 57 | */ 58 | public function make($tab = '') 59 | { 60 | $class = $this->bootstrap ? 'table table-hover' : ''; 61 | 62 | $lines = array(''); 63 | 64 | $lines = $this->setCol($lines, $tab); 65 | 66 | $lines = $this->setRow($lines, $tab); 67 | 68 | $lines[] = '
'; 69 | 70 | return $lines; 71 | } 72 | 73 | /** 74 | * @param \Rougin\Describe\Column $column 75 | * 76 | * @return string 77 | */ 78 | protected function getFieldTitle(Column $column) 79 | { 80 | $name = $column->getField(); 81 | 82 | if ($column->isForeignKey()) 83 | { 84 | $name = $column->getReferencedTable(); 85 | 86 | $name = Inflector::singular($name); 87 | } 88 | 89 | return Inflector::humanize($name); 90 | } 91 | 92 | /** 93 | * @param string[] $lines 94 | * @param string $tab 95 | * 96 | * @return string[] 97 | */ 98 | protected function setCol($lines, $tab = '') 99 | { 100 | $lines[] = $tab . ''; 101 | $lines[] = $tab . $tab . ''; 102 | 103 | $space = $tab . $tab . $tab; 104 | 105 | foreach ($this->cols as $col) 106 | { 107 | if ($col->isPrimaryKey()) 108 | { 109 | continue; 110 | } 111 | 112 | $name = $this->getFieldTitle($col); 113 | 114 | $lines[] = $space . '' . $name . ''; 115 | } 116 | 117 | $lines[] = $space . ''; 118 | 119 | $lines[] = $tab . $tab . ''; 120 | $lines[] = $tab . ''; 121 | 122 | return $lines; 123 | } 124 | 125 | /** 126 | * @param string[] $lines 127 | * @param string $tab 128 | * 129 | * @return string[] 130 | */ 131 | protected function setRow($lines, $tab = '') 132 | { 133 | $lines[] = $tab . ''; 134 | $lines[] = $tab . $tab . ''; 135 | $lines[] = $tab . $tab . $tab . ''; 136 | 137 | $space = $tab . $tab . $tab . $tab; 138 | 139 | $primary = null; 140 | 141 | foreach ($this->cols as $col) 142 | { 143 | if ($col->isPrimaryKey()) 144 | { 145 | $primary = $col; 146 | 147 | continue; 148 | } 149 | 150 | $name = '[FIELD] ?>'; 151 | 152 | $field = $col->getField(); 153 | 154 | if ($this->type === self::TYPE_DOCTRINE) 155 | { 156 | // TODO: Use a single function for this code ------- 157 | $method = 'get_' . $field; 158 | 159 | if ($col->getDataType() === 'boolean') 160 | { 161 | // Remove "is_" from name to get proper name --- 162 | $temp = str_replace('is_', '', $field); 163 | // --------------------------------------------- 164 | 165 | $method = 'is_' . $temp; 166 | } 167 | // ------------------------------------------------- 168 | 169 | $field = Inflector::snakeCase($method); 170 | 171 | $field = $field . '()'; 172 | } 173 | 174 | if ($this->type === self::TYPE_DOCTRINE && $col->isForeignKey()) 175 | { 176 | $foreign = $col->getReferencedField(); 177 | $table = $col->getReferencedTable(); 178 | $table = Inflector::singular($table); 179 | 180 | $method = 'get_' . strtolower($table) . '()'; 181 | $foreign = 'get_' . Inflector::snakeCase($foreign) . '()'; 182 | 183 | $field = $method . '->' . $foreign; 184 | } 185 | 186 | $name = str_replace('[FIELD]', $field, $name); 187 | 188 | $plate = $space . '' . $name . ''; 189 | 190 | $type = $col->getDataType(); 191 | 192 | if ($this->type === self::TYPE_DOCTRINE && ($type === 'date' || $type === 'datetime')) 193 | { 194 | $plate = $space . '' . $field . ' ? $item->' . $field . '->format(\'Y-m-d H:i:s\') : \'\' ?>'; 195 | } 196 | 197 | $lines[] = $plate; 198 | } 199 | 200 | if ($primary) 201 | { 202 | // Set the primary key field ----------- 203 | $id = $primary->getField(); 204 | 205 | if ($this->type === self::TYPE_DOCTRINE) 206 | { 207 | $id = 'get_' . $id . '()'; 208 | } 209 | 210 | $field = '$item->' . $id; 211 | // ------------------------------------- 212 | 213 | $route = Inflector::plural($this->table); 214 | 215 | $class = $this->bootstrap ? 'd-flex' : ''; 216 | $lines[] = $space . ''; 217 | $lines[] = $space . $tab . '
'; 218 | 219 | $lines[] = $space . $tab . $tab . ''; 220 | $class = $this->bootstrap ? 'btn btn-secondary btn-sm' : ''; 221 | $link = ''; 222 | $link = 'Edit'; 223 | $lines[] = $space . $tab . $tab . $tab . $link; 224 | $lines[] = $space . $tab . $tab . ''; 225 | 226 | $lines[] = $space . $tab . $tab . ''; 227 | 228 | $form = ''; 229 | $lines[] = $space . $tab . $tab . $tab . $form; 230 | 231 | $hidden = ''; 232 | $lines[] = $space . $tab . $tab . $tab . $tab . $hidden; 233 | 234 | $class = $this->bootstrap ? 'btn btn-link btn-sm text-danger text-decoration-none' : ''; 235 | $delete = 'Delete'; 236 | $lines[] = $space . $tab . $tab . $tab . $tab . $delete; 237 | 238 | $close = ''; 239 | $lines[] = $space . $tab . $tab . $tab . $close; 240 | 241 | $lines[] = $space . $tab . $tab . ''; 242 | 243 | $lines[] = $space . $tab . '
'; 244 | $lines[] = $space . ''; 245 | } 246 | 247 | $lines[] = $tab . $tab . $tab . ''; 248 | $lines[] = $tab . $tab . ''; 249 | $lines[] = $tab . ''; 250 | 251 | return $lines; 252 | } 253 | 254 | /** 255 | * @param boolean $bootstrap 256 | * 257 | * @return self 258 | */ 259 | public function withBootstrap($bootstrap) 260 | { 261 | $this->bootstrap = $bootstrap; 262 | 263 | return $this; 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /src/Template/Wildfire/Model.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class Model extends Classidy 15 | { 16 | /** 17 | * @var \Rougin\Describe\Column[] 18 | */ 19 | protected $cols; 20 | 21 | /** 22 | * @var string[] 23 | */ 24 | protected $excluded = array(); 25 | 26 | /** 27 | * @param string $table 28 | * @param \Rougin\Describe\Column[] $cols 29 | * @param string[] $excluded 30 | */ 31 | public function __construct($table, $cols, $excluded = array()) 32 | { 33 | $this->cols = $cols; 34 | 35 | $this->excluded = $excluded; 36 | 37 | $this->init($table); 38 | } 39 | 40 | /** 41 | * Configures the current class. 42 | * 43 | * @param string $table 44 | * 45 | * @return void 46 | */ 47 | public function init($table) 48 | { 49 | $name = Inflector::singular($table); 50 | 51 | $this->setName(ucfirst($name)); 52 | $this->extendsTo('Rougin\Wildfire\Model'); 53 | 54 | $this->addTrait('Rougin\Wildfire\Traits\PaginateTrait'); 55 | $this->addTrait('Rougin\Wildfire\Traits\ValidateTrait'); 56 | $this->addTrait('Rougin\Wildfire\Traits\WildfireTrait'); 57 | $this->addTrait('Rougin\Wildfire\Traits\WritableTrait'); 58 | 59 | $this->setProperties(); 60 | 61 | $link = 'https://codeigniter.com/userguide3/libraries'; 62 | 63 | $this->setPagee($link); 64 | 65 | $this->setRules($link); 66 | 67 | $this->addStringProperty('table') 68 | ->withComment('The table associated with the model.') 69 | ->withDefaultValue($table); 70 | 71 | $this->setExistsMethod(); 72 | 73 | $this->setInputMethod(); 74 | } 75 | 76 | /** 77 | * @return void 78 | */ 79 | protected function setExistsMethod() 80 | { 81 | $method = new Method('exists'); 82 | 83 | $method->setReturn('boolean'); 84 | 85 | $method->addArrayArgument('data', 'array'); 86 | 87 | $method->addIntegerArgument('id', true); 88 | 89 | $method->setCodeLine(function ($lines) 90 | { 91 | $lines[] = '// Specify logic here if applicable ---'; 92 | $lines[] = '// ------------------------------------'; 93 | $lines[] = ''; 94 | $lines[] = 'return false;'; 95 | 96 | return $lines; 97 | }); 98 | 99 | $this->addMethod($method); 100 | } 101 | 102 | /** 103 | * @return void 104 | */ 105 | protected function setInputMethod() 106 | { 107 | $method = new Method('input'); 108 | 109 | $method->asProtected(); 110 | 111 | $method->setReturn('array'); 112 | 113 | $method->addArrayArgument('data', 'array'); 114 | 115 | $method->addIntegerArgument('id', true); 116 | 117 | $cols = $this->cols; 118 | 119 | $method->setCodeLine(function ($lines) use ($cols) 120 | { 121 | $lines[] = '$load = array();'; 122 | $lines[] = ''; 123 | $lines[] = '// List editable fields from table ---'; 124 | 125 | foreach ($cols as $index => $col) 126 | { 127 | $name = $col->getField(); 128 | 129 | if ($col->isPrimaryKey() || in_array($name, $this->excluded)) 130 | { 131 | continue; 132 | } 133 | 134 | $type = $col->getDataType(); 135 | 136 | if ($col->isNull()) 137 | { 138 | $type = $type . '|null'; 139 | } 140 | 141 | if ($col->isNull()) 142 | { 143 | $lines[] = 'if (array_key_exists(\'' . $name . '\', $data))'; 144 | $lines[] = '{'; 145 | $lines[] = ' /** @var ' . $type . ' */'; 146 | $lines[] = ' $' . $name . ' = $data[\'' . $name . '\'];'; 147 | $lines[] = ' $load[\'' . $name . '\'] = $' . $name . ';'; 148 | $lines[] = '}'; 149 | } 150 | else 151 | { 152 | 153 | if ($type === 'boolean') 154 | { 155 | $lines[] = '$' . $name . ' = false;'; 156 | $lines[] = 'if (array_key_exists(\'' . $name . '\', $data))'; 157 | $lines[] = '{'; 158 | $lines[] = ' /** @var ' . $type . ' */'; 159 | $lines[] = ' $' . $name . ' = $data[\'' . $name . '\'];'; 160 | $lines[] = '}'; 161 | } 162 | else 163 | { 164 | $lines[] = '/** @var ' . $type . ' */'; 165 | $lines[] = '$' . $name . ' = $data[\'' . $name . '\'];'; 166 | } 167 | 168 | $lines[] = '$load[\'' . $name . '\'] = $' . $name . ';'; 169 | } 170 | 171 | if (array_key_exists($index + 1, $cols)) 172 | { 173 | $next = $cols[$index + 1]; 174 | 175 | if (! in_array($next->getField(), $this->excluded)) 176 | { 177 | $lines[] = ''; 178 | } 179 | } 180 | } 181 | 182 | $lines[] = '// -----------------------------------'; 183 | $lines[] = ''; 184 | $lines[] = 'return $load;'; 185 | 186 | return $lines; 187 | }); 188 | 189 | $this->addMethod($method); 190 | } 191 | 192 | /** 193 | * @param string $link 194 | * 195 | * @return void 196 | */ 197 | protected function setPagee($link) 198 | { 199 | $default = array(); 200 | 201 | $default['page_query_string'] = true; 202 | $default['use_page_numbers'] = true; 203 | $default['query_string_segment'] = 'p'; 204 | $default['reuse_query_string'] = true; 205 | 206 | $this->addArrayProperty('pagee', 'array') 207 | ->withComment('Additional configuration to Pagination Class.') 208 | ->withLink($link . '/pagination.html#customizing-the-pagination') 209 | ->withDefaultValue($default); 210 | } 211 | 212 | /** 213 | * @return void 214 | */ 215 | protected function setProperties() 216 | { 217 | foreach ($this->cols as $col) 218 | { 219 | $type = $col->getDataType(); 220 | 221 | $name = $col->getField(); 222 | 223 | $isNull = $col->isNull(); 224 | 225 | switch ($type) 226 | { 227 | case 'boolean': 228 | $this->addBooleanProperty($name, $isNull)->asTag(); 229 | 230 | break; 231 | case 'integer': 232 | $this->addIntegerProperty($name, $isNull)->asTag(); 233 | 234 | break; 235 | default: 236 | $this->addStringProperty($name, $isNull)->asTag(); 237 | 238 | break; 239 | } 240 | } 241 | } 242 | 243 | /** 244 | * @param string $link 245 | * 246 | * @return void 247 | */ 248 | protected function setRules($link) 249 | { 250 | $rules = array(); 251 | 252 | foreach ($this->cols as $col) 253 | { 254 | $name = $col->getField(); 255 | 256 | $isExcluded = in_array($name, $this->excluded); 257 | 258 | if ($col->isNull() || $col->isPrimaryKey() || $isExcluded) 259 | { 260 | continue; 261 | } 262 | 263 | // Do not include boolean types in validation --- 264 | if ($col->getDataType() === 'boolean') 265 | { 266 | continue; 267 | } 268 | // ---------------------------------------------- 269 | 270 | $rule = array('field' => $name); 271 | 272 | $rule['label'] = ucfirst($name); 273 | 274 | $rule['rules'] = 'required'; 275 | 276 | $rules[] = $rule; 277 | } 278 | 279 | $this->addArrayProperty('rules', 'array[]') 280 | ->withComment('List of validation rules for Form Validation.') 281 | ->withLink($link . '/form_validation.html#setting-rules-using-an-array') 282 | ->withDefaultValue($rules); 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /src/Template/FormPlate.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class FormPlate 16 | { 17 | const TYPE_WILDFIRE = 0; 18 | 19 | const TYPE_DOCTRINE = 1; 20 | 21 | /** 22 | * @var boolean 23 | */ 24 | protected $bootstrap = false; 25 | 26 | /** 27 | * @var \Rougin\Describe\Column[] 28 | */ 29 | protected $cols; 30 | 31 | /** 32 | * @var \Rougin\Combustor\Colfield[] 33 | */ 34 | protected $customs = array(); 35 | 36 | /** 37 | * @var boolean 38 | */ 39 | protected $edit = false; 40 | 41 | /** 42 | * @var string[] 43 | */ 44 | protected $excluded = array(); 45 | 46 | /** 47 | * @var string 48 | */ 49 | protected $table; 50 | 51 | /** 52 | * @var integer 53 | */ 54 | protected $type; 55 | 56 | /** 57 | * @param string $table 58 | * @param integer $type 59 | * @param \Rougin\Describe\Column[] $cols 60 | */ 61 | public function __construct($table, $type, $cols) 62 | { 63 | $this->cols = $cols; 64 | 65 | $this->type = $type; 66 | 67 | $this->table = $table; 68 | } 69 | 70 | /** 71 | * @param string $tab 72 | * 73 | * @return string 74 | */ 75 | public function make($tab = '') 76 | { 77 | $model = Inflector::singular($this->table); 78 | $route = Inflector::plural($this->table); 79 | 80 | $title = $this->edit ? 'Update' : 'Create New'; 81 | $title = $title . ' ' . ucfirst($model); 82 | 83 | $lines = array('

' . $title . '

'); 84 | $lines[] = ''; 85 | 86 | $link = $route . '/create\''; 87 | 88 | if ($this->edit) 89 | { 90 | $primary = $this->getPrimary(); 91 | 92 | $id = $primary ? '/\' . ' . $this->getAccessor($primary) : ''; 93 | 94 | $link = $route . '/edit' . $id; 95 | } 96 | 97 | $lines[] = ''; 98 | 99 | if ($this->edit) 100 | { 101 | $lines[] = $tab . ''; 102 | $lines[] = ''; 103 | } 104 | 105 | foreach ($this->cols as $col) 106 | { 107 | $name = $col->getField(); 108 | 109 | if ($col->isPrimaryKey() || in_array($name, $this->excluded)) 110 | { 111 | continue; 112 | } 113 | 114 | $title = $this->getFieldTitle($col); 115 | 116 | $class = $this->bootstrap ? 'mb-3' : ''; 117 | $lines[] = $tab . '
'; 118 | $class = $this->bootstrap ? 'form-label mb-0' : ''; 119 | $lines[] = $tab . $tab . ' \'' . $class . '\']) ?>'; 120 | 121 | $field = $this->getFieldPlate($col, $tab); 122 | 123 | foreach ($field->getPlate() as $plate) 124 | { 125 | $lines[] = $tab . $tab . $plate; 126 | } 127 | 128 | $class = $this->bootstrap ? 'text-danger small' : ''; 129 | $lines[] = $tab . $tab . '\', \'
\') ?>'; 130 | $lines[] = $tab . '
'; 131 | $lines[] = ''; 132 | } 133 | 134 | $submit = $this->edit ? 'Update' : 'Create'; 135 | 136 | $lines[] = $tab . ''; 137 | $class = $this->bootstrap ? 'alert alert-danger' : ''; 138 | $lines[] = $tab . '
'; 139 | $lines[] = $tab . ''; 140 | $lines[] = ''; 141 | 142 | $class = $this->bootstrap ? 'btn btn-link text-secondary text-decoration-none' : ''; 143 | $lines[] = $tab . ''; 144 | $class = $this->bootstrap ? 'btn btn-primary' : ''; 145 | $lines[] = $tab . ''; 146 | $lines[] = ''; 147 | 148 | $result = implode("\n", $lines); 149 | 150 | // Replace all empty class placeholders ------------------ 151 | $result = str_replace(' class=""', '', $result); 152 | 153 | $result = str_replace(', \'class\' => \'\'', '', $result); 154 | 155 | $result = str_replace(', \'class=""\'', '', $result); 156 | 157 | $search = ', \'\', [\'class\' => \'\']'; 158 | 159 | return str_replace($search, '', $result); 160 | // ------------------------------------------------------- 161 | } 162 | 163 | /** 164 | * @param boolean $bootstrap 165 | * 166 | * @return self 167 | */ 168 | public function withBootstrap($bootstrap) 169 | { 170 | $this->bootstrap = $bootstrap; 171 | 172 | return $this; 173 | } 174 | 175 | /** 176 | * @param \Rougin\Combustor\Colfield[] $customs 177 | * 178 | * @return self 179 | */ 180 | public function withCustomFields($customs) 181 | { 182 | $this->customs = $customs; 183 | 184 | return $this; 185 | } 186 | 187 | /** 188 | * @param string[] $excluded 189 | * 190 | * @return self 191 | */ 192 | public function withExcludedFields($excluded) 193 | { 194 | $this->excluded = $excluded; 195 | 196 | return $this; 197 | } 198 | 199 | /** 200 | * @param \Rougin\Describe\Column $column 201 | * 202 | * @return string 203 | */ 204 | protected function getAccessor(Column $column) 205 | { 206 | $name = $column->getField(); 207 | 208 | if ($this->type === self::TYPE_DOCTRINE) 209 | { 210 | // TODO: Use a single function for this code ------- 211 | $method = 'get_' . $name; 212 | 213 | if ($column->getDataType() === 'boolean') 214 | { 215 | // Remove "is_" from name to get proper name --- 216 | $temp = str_replace('is_', '', $name); 217 | // --------------------------------------------- 218 | 219 | $method = 'is_' . $temp; 220 | } 221 | // ------------------------------------------------- 222 | 223 | $name = $method . '()'; 224 | } 225 | 226 | return '$item->' . $name; 227 | } 228 | 229 | /** 230 | * @param \Rougin\Describe\Column $column 231 | * @param string $tab 232 | * 233 | * @return \Rougin\Combustor\Colfield 234 | */ 235 | protected function getFieldPlate(Column $column, $tab = '') 236 | { 237 | $name = $this->getAccessor($column); 238 | 239 | $field = new DefaultField; 240 | 241 | foreach ($this->customs as $custom) 242 | { 243 | $isField = $custom->getName() === $column->getField(); 244 | 245 | $isType = $custom->getType() === $column->getDataType(); 246 | 247 | if ($isField || $isType) 248 | { 249 | $field = $custom; 250 | } 251 | } 252 | 253 | if ($column->isForeignKey()) 254 | { 255 | $field = new ForeignField; 256 | 257 | $field->setTableName($column->getReferencedTable()); 258 | } 259 | 260 | $field->setName($column->getField()); 261 | 262 | if ($this->bootstrap) 263 | { 264 | $field->useStyling(true); 265 | } 266 | 267 | $field->asEdit($this->edit); 268 | 269 | $field->setSpacing($tab); 270 | 271 | return $field->setAccessor($name); 272 | } 273 | 274 | /** 275 | * @param \Rougin\Describe\Column $column 276 | * 277 | * @return string 278 | */ 279 | protected function getFieldTitle(Column $column) 280 | { 281 | $name = $column->getField(); 282 | 283 | if ($column->isForeignKey()) 284 | { 285 | $name = $column->getReferencedTable(); 286 | 287 | $name = Inflector::singular($name); 288 | } 289 | 290 | return Inflector::humanize($name); 291 | } 292 | 293 | /** 294 | * @return \Rougin\Describe\Column|null 295 | */ 296 | protected function getPrimary() 297 | { 298 | $primary = null; 299 | 300 | foreach ($this->cols as $col) 301 | { 302 | if ($col->isPrimaryKey()) 303 | { 304 | $primary = $col; 305 | } 306 | } 307 | 308 | return $primary; 309 | } 310 | } 311 | -------------------------------------------------------------------------------- /src/Template/Doctrine/Model.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class Model extends Classidy 15 | { 16 | /** 17 | * @var \Rougin\Describe\Column[] 18 | */ 19 | protected $cols; 20 | 21 | /** 22 | * @var string[] 23 | */ 24 | protected $excluded = array(); 25 | 26 | /** 27 | * @param string $table 28 | * @param \Rougin\Describe\Column[] $cols 29 | * @param string[] $excluded 30 | */ 31 | public function __construct($table, $cols, $excluded = array()) 32 | { 33 | $this->cols = $cols; 34 | 35 | $this->excluded = $excluded; 36 | 37 | $this->init($table); 38 | } 39 | 40 | /** 41 | * @param string $table 42 | * 43 | * @return void 44 | */ 45 | public function init($table) 46 | { 47 | $name = Inflector::singular($table); 48 | 49 | $this->setName(ucfirst($name)); 50 | $this->extendsTo('Rougin\Credo\Model'); 51 | 52 | $this->addTrait('Rougin\Credo\Traits\PaginateTrait'); 53 | $this->addTrait('Rougin\Credo\Traits\ValidateTrait'); 54 | 55 | $repo = ucfirst($name) . '_repository'; 56 | 57 | $comment = array('@Entity(repositoryClass="' . $repo . '")'); 58 | $comment[] = ''; 59 | $comment[] = '@Table(name="' . $table . '")'; 60 | $this->setComment($comment); 61 | 62 | $link = 'https://codeigniter.com/userguide3/libraries'; 63 | 64 | // Sort columns by name ------------ 65 | $items = array(); 66 | 67 | foreach ($this->cols as $col) 68 | { 69 | $items[$col->getField()] = $col; 70 | } 71 | 72 | ksort($items); 73 | // --------------------------------- 74 | 75 | $this->setProperties($items); 76 | 77 | $this->setPagee($link); 78 | 79 | $this->setRules($link); 80 | 81 | $this->setMethods($items); 82 | } 83 | 84 | /** 85 | * @param \Rougin\Describe\Column[] $cols 86 | * 87 | * @return void 88 | */ 89 | protected function setMethods($cols) 90 | { 91 | foreach ($cols as $col) 92 | { 93 | // Add additional method for foreign keys -------- 94 | if ($col->isForeignKey()) 95 | { 96 | $name = $col->getReferencedTable(); 97 | $name = Inflector::singular($name); 98 | 99 | $method = 'get_' . $name; 100 | 101 | $method = new Method($method); 102 | 103 | $type = '\\' . ucfirst($name); 104 | 105 | if ($col->isNull()) 106 | { 107 | $type = $type . '|null'; 108 | } 109 | 110 | $method->setReturn($type); 111 | 112 | $fn = function ($lines) use ($name) 113 | { 114 | $lines[] = 'return $this->' . $name . ';'; 115 | 116 | return $lines; 117 | }; 118 | 119 | $method->setCodeLine($fn); 120 | 121 | $this->addMethod($method); 122 | } 123 | // ----------------------------------------------- 124 | 125 | $name = $col->getField(); 126 | 127 | $name = Inflector::snakeCase($name); 128 | 129 | $type = $col->getDataType(); 130 | 131 | if ($col->isNull()) 132 | { 133 | $type = $type . '|null'; 134 | } 135 | 136 | // TODO: Use a single function for this code ------- 137 | $method = 'get_' . $name; 138 | 139 | if ($col->getDataType() === 'boolean') 140 | { 141 | // Remove "is_" from name to get proper name --- 142 | $temp = str_replace('is_', '', $name); 143 | // --------------------------------------------- 144 | 145 | $method = 'is_' . $temp; 146 | } 147 | // ------------------------------------------------- 148 | 149 | $method = new Method($method); 150 | 151 | $method->setReturn($type); 152 | 153 | $fn = function ($lines) use ($name) 154 | { 155 | $lines[] = 'return $this->' . $name . ';'; 156 | 157 | return $lines; 158 | }; 159 | 160 | $method->setCodeLine($fn); 161 | 162 | $this->addMethod($method); 163 | } 164 | 165 | foreach ($cols as $col) 166 | { 167 | if ($col->isPrimaryKey()) 168 | { 169 | continue; 170 | } 171 | 172 | $name = $col->getField(); 173 | 174 | $name = Inflector::snakeCase($name); 175 | 176 | $type = $col->getDataType(); 177 | 178 | if ($col->isForeignKey()) 179 | { 180 | $name = $col->getReferencedTable(); 181 | $name = Inflector::singular($name); 182 | 183 | $type = ucfirst($name); 184 | } 185 | 186 | $method = new Method('set_' . $name); 187 | 188 | $method->setReturn('self'); 189 | 190 | $isNull = $col->isNull(); 191 | 192 | switch ($type) 193 | { 194 | case 'boolean': 195 | $method->addBooleanArgument($name, $isNull); 196 | 197 | break; 198 | case 'integer': 199 | $method->addIntegerArgument($name, $isNull); 200 | 201 | break; 202 | default: 203 | if ($col->isForeignKey()) 204 | { 205 | $method->addClassArgument($name, ucfirst($name), $isNull); 206 | } 207 | else 208 | { 209 | $method->addStringArgument($name, $isNull); 210 | } 211 | 212 | break; 213 | } 214 | 215 | $fn = function ($lines) use ($name) 216 | { 217 | $lines[] = '$this->' . $name . ' = $' . $name . ';'; 218 | $lines[] = ''; 219 | $lines[] = 'return $this;'; 220 | 221 | return $lines; 222 | }; 223 | 224 | $method->setCodeLine($fn); 225 | 226 | $this->addMethod($method); 227 | } 228 | } 229 | 230 | /** 231 | * @param string $link 232 | * 233 | * @return void 234 | */ 235 | protected function setPagee($link) 236 | { 237 | $default = array(); 238 | 239 | $default['page_query_string'] = true; 240 | $default['use_page_numbers'] = true; 241 | $default['query_string_segment'] = 'p'; 242 | $default['reuse_query_string'] = true; 243 | 244 | $this->addArrayProperty('pagee', 'array') 245 | ->withComment('Additional configuration to Pagination Class.') 246 | ->withLink($link . '/pagination.html#customizing-the-pagination') 247 | ->withDefaultValue($default); 248 | } 249 | 250 | /** 251 | * @param \Rougin\Describe\Column[] $cols 252 | * 253 | * @return void 254 | */ 255 | protected function setProperties($cols) 256 | { 257 | foreach ($cols as $col) 258 | { 259 | $isNull = $col->isNull(); 260 | 261 | $isUnique = $col->isUnique(); 262 | 263 | $name = $col->getField(); 264 | 265 | $name = Inflector::snakeCase($name); 266 | 267 | if ($col->isForeignKey()) 268 | { 269 | $foreignTable = $col->getReferencedTable(); 270 | $foreignName = Inflector::singular($foreignTable); 271 | $class = ucfirst($foreignName); 272 | $foreign = $col->getReferencedField(); 273 | 274 | $this->addClassProperty($foreignName, $class, $isNull); 275 | 276 | // Generate Doctrine annotations to foreign key ------- 277 | $lines = array(); 278 | 279 | $keys = array('targetEntity="' . $class . '"'); 280 | $keys[] = 'cascade={"persist"}'; 281 | $lines[] = '@ManyToOne(' . implode(', ', $keys) . ')'; 282 | 283 | $keys = array('name="' . $name . '"'); 284 | $keys[] = 'referencedColumnName="' . $foreign . '"'; 285 | $keys[] = 'nullable=' . ($isNull ? 'true' : 'false'); 286 | $keys[] = 'unique=' . ($isUnique ? 'true' : 'false'); 287 | $lines[] = '@JoinColumn(' . implode(', ', $keys) . ')'; 288 | 289 | $this->withComment($lines); 290 | // ---------------------------------------------------- 291 | } 292 | 293 | $type = $col->getDataType(); 294 | 295 | switch ($type) 296 | { 297 | case 'boolean': 298 | $this->addBooleanProperty($name, $isNull); 299 | 300 | break; 301 | case 'integer': 302 | $this->addIntegerProperty($name, $isNull); 303 | 304 | break; 305 | default: 306 | $this->addStringProperty($name, $isNull); 307 | 308 | break; 309 | } 310 | 311 | // Generate Doctrine annotations to columns --------- 312 | $lines = array(); 313 | 314 | if ($col->isPrimaryKey()) 315 | { 316 | $lines[] = '@Id @GeneratedValue'; 317 | $lines[] = ''; 318 | } 319 | 320 | $keys = array('name="' . $name . '"'); 321 | $keys[] = 'type="' . $type . '"'; 322 | 323 | if ($length = $col->getLength()) 324 | { 325 | $keys[] = 'length=' . $length; 326 | } 327 | 328 | $keys[] = 'nullable=' . ($isNull ? 'true' : 'false'); 329 | $keys[] = 'unique=' . ($isUnique ? 'true' : 'false'); 330 | 331 | $lines[] = '@Column(' . implode(', ', $keys) . ')'; 332 | // -------------------------------------------------- 333 | 334 | $this->withComment($lines); 335 | } 336 | } 337 | 338 | /** 339 | * @param string $link 340 | * 341 | * @return void 342 | */ 343 | protected function setRules($link) 344 | { 345 | $rules = array(); 346 | 347 | foreach ($this->cols as $col) 348 | { 349 | $name = $col->getField(); 350 | 351 | $isExcluded = in_array($name, $this->excluded); 352 | 353 | if ($col->isNull() || $col->isPrimaryKey() || $isExcluded) 354 | { 355 | continue; 356 | } 357 | 358 | // Do not include boolean types in validation --- 359 | if ($col->getDataType() === 'boolean') 360 | { 361 | continue; 362 | } 363 | // ---------------------------------------------- 364 | 365 | $rule = array('field' => $name); 366 | 367 | $rule['label'] = ucfirst($name); 368 | 369 | $rule['rules'] = 'required'; 370 | 371 | $rules[] = $rule; 372 | } 373 | 374 | $this->addArrayProperty('rules', 'array[]') 375 | ->withComment('List of validation rules for Form Validation.') 376 | ->withLink($link . '/form_validation.html#setting-rules-using-an-array') 377 | ->withDefaultValue($rules); 378 | } 379 | } 380 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Combustor 2 | 3 | [![Latest Version on Packagist][ico-version]][link-packagist] 4 | [![Software License][ico-license]][link-license] 5 | [![Build Status][ico-build]][link-build] 6 | [![Coverage Status][ico-coverage]][link-coverage] 7 | [![Total Downloads][ico-downloads]][link-downloads] 8 | 9 | Combustor is a utility package for [Codeigniter 3](https://codeigniter.com/userguide3/) that generates controllers, models, and views based on the provided database tables. It uses the [Describe](https://roug.in/describe/) package for getting columns from a database table and as the basis for code generation. 10 | 11 | ## Features 12 | 13 | * Generates code based on the structure of the `Codeigniter 3` framework; 14 | * Speeds up the code development for prototyping web applications; 15 | * View templates can be based on Bootstrap and are upgradable; and 16 | * Only worry on the database schema, and `Combustor` will do the rest. 17 | 18 | ## Installation 19 | 20 | Extract the contents of the [latest Codeigniter 3 project](https://github.com/bcit-ci/CodeIgniter/archive/3.1.13.zip) first: 21 | 22 | ``` bash 23 | $ wget https://github.com/bcit-ci/CodeIgniter/archive/3.1.13.zip 24 | $ unzip 3.1.13.zip -d ciacme 25 | ``` 26 | 27 | Then configure the project's database connectivity settings: 28 | 29 | ``` 30 | $ cd ciacme 31 | $ nano application/config/database.php 32 | ``` 33 | 34 | ``` php 35 | // ciacme/application/config/database.php 36 | 37 | // ... 38 | 39 | $db['default'] = array( 40 | 'dsn' => '', 41 | 'hostname' => 'localhost', 42 | 'username' => '', 43 | 'password' => '', 44 | 'database' => '', 45 | 'dbdriver' => 'mysqli', 46 | 47 | // ... 48 | ); 49 | ``` 50 | 51 | Next is to proceed in installing `Combustor` via [Composer](https://getcomposer.org/): 52 | 53 | ``` bash 54 | $ composer require rougin/combustor --dev 55 | ``` 56 | 57 | ``` json 58 | // ciacme/composer.json 59 | 60 | { 61 | // ... 62 | 63 | "require-dev": 64 | { 65 | "mikey179/vfsstream": "1.6.*", 66 | "phpunit/phpunit": "4.* || 5.* || 9.*", 67 | "rougin/combustor": "~1.0" 68 | } 69 | } 70 | ``` 71 | 72 | Lastly, install the ORM wrappers like `Wildfire` or `Doctrine`: 73 | 74 | ``` bash 75 | $ vendor/bin/combustor install:wildfire 76 | $ vendor/bin/combustor install:doctrine 77 | ``` 78 | 79 | > [!NOTE] 80 | > Using the `install:wildfire` command installs the [Wildfire](https://roug.in/wildfire/) package while the `install:doctrine` installs the [Credo](https://roug.in/credo/) package. 81 | 82 | ## Reminders 83 | 84 | Prior in executing any commands, kindly ensure that the _**database tables are defined properly**_ (foreign keys, indexes, relationships, normalizations) in order to minimize the modifications after the code structure has been generated. 85 | 86 | Also, please proceed first in generating models, views, or controllers to database tables that are having _**no relationship with other tables**_ in the database. 87 | 88 | > [!TIP] 89 | > `Combustor` will generate controllers, models, or views based on the specified database schema. If there's something wrong in the specified database schema, `Combustor` will generate a bad codebase. 90 | 91 | ## Commands 92 | 93 | ### `create:layout` 94 | 95 | Create a new header and footer file. 96 | 97 | **Options** 98 | 99 | * `--bootstrap` - adds styling based on Bootstrap 100 | * `--force` - generates file/s even they already exists 101 | 102 | **Example** 103 | 104 | ``` bash 105 | $ vendor/bin/combustor create-layout --bootstrap 106 | ``` 107 | 108 | ### `create:controller` 109 | 110 | Create a new HTTP controller. 111 | 112 | **Arguments** 113 | 114 | * `table` - name of the database table 115 | 116 | **Options** 117 | 118 | * `--doctrine` - generates a Doctrine-based controller 119 | * `--wildfire` - generates a Wildfire-based controller 120 | * `--empty` - generates an empty HTTP controller 121 | * `--force` - generates file/s even they already exists 122 | 123 | > [!NOTE] 124 | > If either `Wildfire` or `Doctrine` is installed, no need to specify it as option for executing a specified command (e.g. `--wildfire`). However if both are installed, a command must have a `--wildfire` or `--doctrine` option added. 125 | 126 | **Example** 127 | 128 | ``` bash 129 | $ vendor/bin/combustor create:controller users --wildfire 130 | ``` 131 | 132 | ### `create:model` 133 | 134 | Create a new model. 135 | 136 | **Arguments** 137 | 138 | * `table` - name of the database table 139 | 140 | **Options** 141 | 142 | * `--doctrine` - generates a Doctrine-based model 143 | * `--wildfire` - generates a Wildfire-based model 144 | * `--empty` - generates an empty model 145 | * `--force` - generates file/s even they already exists 146 | 147 | **Example** 148 | 149 | ``` bash 150 | $ vendor/bin/combustor create:model users --wildfire 151 | ``` 152 | 153 | ### `create:repository` 154 | 155 | Create a new entity repository. 156 | 157 | **Arguments** 158 | 159 | * `table` - name of the database table 160 | 161 | **Options** 162 | 163 | * `--force` - generates file/s even they already exists 164 | 165 | **Example** 166 | 167 | ``` bash 168 | $ vendor/bin/combustor create:repository users 169 | ``` 170 | 171 | > [!NOTE] 172 | > This command is only applicable to a [Doctrine](https://roug.in/credo) implementation. 173 | 174 | ### `create:view` 175 | 176 | Create view templates. 177 | 178 | **Arguments** 179 | 180 | * `table` - name of the database table 181 | 182 | **Options** 183 | 184 | * `--bootstrap` - adds styling based on Bootstrap 185 | * `--doctrine` - generates Doctrine-based views 186 | * `--wildfire` - generates Wildfire-based views 187 | * `--force` - generates file/s even they already exists 188 | 189 | **Example** 190 | 191 | ``` bash 192 | $ vendor/bin/combustor create:view users --bootstrap 193 | ``` 194 | 195 | ### `create:scaffold` 196 | 197 | Create a new HTTP controller, model, and view templates. 198 | 199 | **Arguments** 200 | 201 | * `table` - name of the database table 202 | 203 | **Options** 204 | 205 | * `--bootstrap` - adds styling based on Bootstrap 206 | * `--doctrine` - generates a Doctrine-based controller, model, and views 207 | * `--wildfire` - generates a Wildfire-based controller, model, and views 208 | * `--force` - generates file/s even they already exists 209 | 210 | **Example** 211 | 212 | ``` bash 213 | $ vendor/bin/combustor create:scaffold users --bootstrap --wildfire 214 | ``` 215 | 216 | > [!NOTE] 217 | > If `--doctrine` is selected, the command will also execute the `create:repository` command. 218 | 219 | ### `install:doctrine` 220 | 221 | Install the [Doctrine](https://roug.in/credo/) package. 222 | 223 | **Example** 224 | 225 | ``` bash 226 | $ vendor/bin/combustor install:doctrine 227 | ``` 228 | 229 | > [!NOTE] 230 | > * This command will be available if `Doctrine` is not installed in the project. 231 | > * It also adds a `Loader.php` in the `core` directory. The said file is used for loading custom repositories extended to `EntityRepository`. 232 | 233 | ### `install:wildfire` 234 | 235 | Install the [Wildfire](https://roug.in/wildfire/) package. 236 | 237 | **Example** 238 | 239 | ``` bash 240 | $ vendor/bin/combustor install:wildfire 241 | ``` 242 | 243 | > [!NOTE] 244 | > This command will be available if `Wildfire` is not installed in the project. 245 | 246 | ### `remove:doctrine` 247 | 248 | Remove the [Doctrine](https://roug.in/credo/) package. 249 | 250 | **Example** 251 | 252 | ``` bash 253 | $ vendor/bin/combustor remove:doctrine 254 | ``` 255 | 256 | > [!NOTE] 257 | > This command will be available if `Doctrine` is installed in the project. 258 | 259 | ### `remove:wildfire` 260 | 261 | Remove the [Wildfire](https://roug.in/wildfire/) package. 262 | 263 | **Example** 264 | 265 | ``` bash 266 | $ vendor/bin/combustor remove:wildfire 267 | ``` 268 | 269 | > [!NOTE] 270 | > This command will be available if `Wildfire` is installed in the project. 271 | 272 | ## Using `combustor.yml` 273 | 274 | `Combustor` currently works out of the box after the configuration based on `Installation`. However, using a `combustor.yml` can be used for complex setups like specifying the new application path and excluding columns: 275 | 276 | ``` yaml 277 | # combustor.yml 278 | 279 | app_path: %%CURRENT_DIRECTORY%%/Sample 280 | 281 | excluded_fields: 282 | - created_at 283 | - updated_at 284 | - deleted_at 285 | ``` 286 | 287 | To create a `combustor.yml`, simply run the `initialize` command: 288 | 289 | ``` bash 290 | $ vendor/bin/combustor initialize 291 | [PASS] "combustor.yml" added successfully! 292 | ``` 293 | 294 | ### `app_path` 295 | 296 | This property specifies the `application` directory. It may updated to any directory (e.g., `ciacme/application`, `ciacme/config`, etc.) as long it can detect the `config/config.php` file from the defined directory: 297 | 298 | ``` yaml 299 | # combustor.yml 300 | 301 | app_path: %%CURRENT_DIRECTORY%%/Sample 302 | 303 | # ... 304 | ``` 305 | 306 | > [!NOTE] 307 | > `Combustor` will try to check the path specified in `app_path` if it is a valid `Codeigniter 3` project. Then it will perform another check if the `application` directory exists or if the `config` directory can be accessed directly from the directory defined in `app_path`. 308 | 309 | ### `excluded_fields` 310 | 311 | Specified fields in this property are excluded from generation to the following templates: 312 | 313 | * `controllers` 314 | * `models` 315 | * `views` (only for `create` and `edit` templates) 316 | 317 | ``` yaml 318 | # combustor.yml 319 | 320 | # ... 321 | 322 | excluded_fields: 323 | - created_at 324 | - updated_at 325 | - deleted_at 326 | ``` 327 | 328 | > [!NOTE] 329 | > The timestamps are added by default when creating a `combustor.yml` for the first time as they are usually populated automatically by installed ORMs such as `Wildfire` or `Doctrine`. 330 | 331 | ### `custom_fields` 332 | 333 | By default, all of the fields generated by `Combustor` to `create` and `edit` pages will use the `form_input` helper: 334 | 335 | ``` php 336 |
337 | 'form-label mb-0']) ?> 338 | 339 | ', '
') ?> 340 |
341 | ``` 342 | 343 | However, some fields like `email` and `boolean` types may need to use other form helpers: 344 | 345 | ``` php 346 |
347 | 'form-label mb-0']) ?> 348 | // Still using form_input, but the type is "email" instead 349 | 'email', 'name' => 'email', 'value' => set_value('email'), 'class' => 'form-control']) ?> 350 | ', '
') ?> 351 | 352 | ``` 353 | 354 | ``` php 355 |
356 | 'form-label mb-0']) ?> 357 | // Use "form_checkbox" for boolean-based data types 358 |
359 | 360 |
361 | ', '
') ?> 362 | 363 | ``` 364 | 365 | To achieve this, `Combustor` provides a utility for handling specified field names or data types using `custom_fields`: 366 | 367 | ``` yaml 368 | # combustor.yml 369 | 370 | # ... 371 | 372 | custom_fields: 373 | - Rougin\Combustor\Template\Fields\BooleanField 374 | ``` 375 | 376 | When adding a custom field, kindly create a class that extends to the `Colfield` class: 377 | 378 | ``` php 379 | namespace Acme\Fields; 380 | 381 | use Rougin\Combustor\Colfield; 382 | 383 | class EmailField extends Colfield 384 | { 385 | protected $class = 'form-control'; 386 | 387 | /** 388 | * If $name is specified, it will check if the current field 389 | * name matches the in this $name field. 390 | */ 391 | protected $name = 'email'; 392 | 393 | public function getPlate() 394 | { 395 | $field = $this->accessor; 396 | 397 | $class = $this->getClass(); 398 | 399 | /** @var string */ 400 | $name = $this->getName(); 401 | 402 | $html = ' \'email\', \'name\' => \'' . $name . '\', \'value\' => set_value(\'' . $name . '\')]) ?>'; 403 | 404 | if ($this->edit) 405 | { 406 | $html = str_replace('set_value(\'' . $name . '\')', 'set_value(\'' . $name . '\', ' . $field . ')', $html); 407 | } 408 | 409 | $html = str_replace(')]) ?>', '), \'class\' => \'' . $class . '\']) ?>', $html); 410 | 411 | return array($html); 412 | } 413 | } 414 | ``` 415 | 416 | Then after creating the custom field, simply add the class name to the `combustor.yml`: 417 | 418 | ``` yaml 419 | # combustor.yml 420 | 421 | # ... 422 | 423 | custom_fields: 424 | - Rougin\Combustor\Template\Fields\BooleanField 425 | - Acme\Fields\EmailField 426 | ``` 427 | 428 | ## Changelog 429 | 430 | Please see [CHANGELOG][link-changelog] for more information what has changed recently. 431 | 432 | ## Testing 433 | 434 | ``` bash 435 | $ composer test 436 | ``` 437 | 438 | ## Credits 439 | 440 | - [All contributors][link-contributors] 441 | 442 | ## License 443 | 444 | The MIT License (MIT). Please see [LICENSE][link-license] for more information. 445 | 446 | [ico-build]: https://img.shields.io/github/actions/workflow/status/rougin/combustor/build.yml?style=flat-square 447 | [ico-coverage]: https://img.shields.io/codecov/c/github/rougin/combustor?style=flat-square 448 | [ico-downloads]: https://img.shields.io/packagist/dt/rougin/combustor.svg?style=flat-square 449 | [ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square 450 | [ico-version]: https://img.shields.io/packagist/v/rougin/combustor.svg?style=flat-square 451 | 452 | [link-build]: https://github.com/rougin/combustor/actions 453 | [link-changelog]: https://github.com/rougin/combustor/blob/master/CHANGELOG.md 454 | [link-contributors]: https://github.com/rougin/combustor/contributors 455 | [link-coverage]: https://app.codecov.io/gh/rougin/combustor 456 | [link-downloads]: https://packagist.org/packages/rougin/combustor 457 | [link-license]: https://github.com/rougin/combustor/blob/master/LICENSE.md 458 | [link-packagist]: https://packagist.org/packages/rougin/combustor -------------------------------------------------------------------------------- /src/Template/Controller.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class Controller extends Classidy 15 | { 16 | const TYPE_WILDFIRE = 0; 17 | 18 | const TYPE_DOCTRINE = 1; 19 | 20 | /** 21 | * @var \Rougin\Describe\Column[] 22 | */ 23 | protected $cols; 24 | 25 | /** 26 | * @var boolean 27 | */ 28 | protected $layout = false; 29 | 30 | /** 31 | * @var string 32 | */ 33 | protected $table; 34 | 35 | /** 36 | * @var integer 37 | */ 38 | protected $type; 39 | 40 | /** 41 | * @param string $table 42 | * @param \Rougin\Describe\Column[] $cols 43 | */ 44 | public function __construct($table, $cols) 45 | { 46 | $this->cols = $cols; 47 | 48 | $this->table = $table; 49 | } 50 | 51 | /** 52 | * Configures the current class. 53 | * 54 | * @return self 55 | */ 56 | public function init() 57 | { 58 | $name = Inflector::plural($this->table); 59 | 60 | $model = Inflector::singular($this->table); 61 | 62 | /** @var class-string */ 63 | $class = ucfirst($model); 64 | 65 | $type = $this->type; 66 | 67 | $this->addClassProperty('db', 'CI_DB_query_builder')->asTag(); 68 | 69 | $this->addClassProperty('input', 'CI_Input')->asTag(); 70 | 71 | if ($type === self::TYPE_DOCTRINE) 72 | { 73 | $this->imports[] = 'Rougin\Credo\Credo'; 74 | 75 | $this->addClassProperty('load', 'MY_Loader')->asTag(); 76 | } 77 | 78 | $this->addClassProperty('session', 'CI_Session')->asTag(); 79 | 80 | $models = $this->getForeignModels(); 81 | $models[] = $model; 82 | 83 | foreach ($models as $item) 84 | { 85 | $this->addClassProperty($item, ucfirst($item))->asTag(); 86 | } 87 | 88 | if ($type === self::TYPE_DOCTRINE) 89 | { 90 | foreach ($models as $item) 91 | { 92 | $repo = $item . '_repository'; 93 | 94 | $repoName = strtolower($item . '_repo'); 95 | 96 | $class = ucfirst($repo); 97 | 98 | $this->addClassProperty($repoName, $class)->asPrivate(); 99 | } 100 | } 101 | 102 | $this->setName(ucfirst($name)); 103 | 104 | $this->extendsTo('Rougin\SparkPlug\Controller'); 105 | 106 | $this->setConstructor($model, $type); 107 | 108 | $this->setCreateMethod($name, $model, $type); 109 | 110 | $this->setDeleteMethod($name, $model, $type); 111 | 112 | $this->setEditMethod($name, $model, $type); 113 | 114 | $this->setIndexMethod($name, $model, $type); 115 | 116 | return $this; 117 | } 118 | 119 | /** 120 | * @param integer $type 121 | * 122 | * @return self 123 | */ 124 | public function setType($type) 125 | { 126 | $this->type = $type; 127 | 128 | return $this; 129 | } 130 | 131 | /** 132 | * @param boolean $layout 133 | * 134 | * @return self 135 | */ 136 | public function useLayout($layout = true) 137 | { 138 | $this->layout = $layout; 139 | 140 | return $this; 141 | } 142 | 143 | /** 144 | * @return string[] 145 | */ 146 | protected function getForeignModels() 147 | { 148 | $items = array(); 149 | 150 | foreach ($this->cols as $col) 151 | { 152 | if (! $col->isForeignKey()) 153 | { 154 | continue; 155 | } 156 | 157 | $name = $col->getReferencedTable(); 158 | $name = Inflector::singular($name); 159 | 160 | $items[] = $name; 161 | } 162 | 163 | return $items; 164 | } 165 | 166 | /** 167 | * @param string $model 168 | * @param integer $type 169 | * 170 | * @return void 171 | */ 172 | protected function setConstructor($model, $type) 173 | { 174 | $method = new Method('__construct'); 175 | 176 | $method->setComment('Loads the required helpers, libraries, and models.'); 177 | 178 | $method->setCodeLine(function ($lines) use ($model, $type) 179 | { 180 | $lines[] = 'parent::__construct();'; 181 | $lines[] = ''; 182 | 183 | $lines[] = '// Initialize the Database loader ---'; 184 | 185 | if ($type === self::TYPE_WILDFIRE) 186 | { 187 | $lines[] = '$this->load->helper(\'inflector\');'; 188 | } 189 | 190 | $lines[] = '$this->load->database();'; 191 | $lines[] = '// ----------------------------------'; 192 | $lines[] = ''; 193 | 194 | // TODO: Show if --with-view enabled ------------- 195 | $lines[] = '// Load view-related helpers ------'; 196 | $lines[] = '$this->load->helper(\'form\');'; 197 | $lines[] = '$this->load->helper(\'url\');'; 198 | $lines[] = '$this->load->library(\'pagination\');'; 199 | $lines[] = '$this->load->library(\'session\');'; 200 | $lines[] = '// --------------------------------'; 201 | $lines[] = ''; 202 | // ----------------------------------------------- 203 | 204 | $lines[] = '// Load multiple models if required ---'; 205 | 206 | foreach ($this->getForeignModels() as $foreign) 207 | { 208 | $lines[] = '$this->load->model(\'' . $foreign . '\');'; 209 | } 210 | 211 | $lines[] = '$this->load->model(\'' . $model . '\');'; 212 | 213 | $foreigns = $this->getForeignModels(); 214 | 215 | if ($type === self::TYPE_DOCTRINE) 216 | { 217 | $lines[] = ''; 218 | 219 | foreach ($foreigns as $foreign) 220 | { 221 | $lines[] = '$this->load->repository(\'' . $foreign . '\');'; 222 | } 223 | 224 | $lines[] = '$this->load->repository(\'' . $model . '\');'; 225 | } 226 | 227 | $lines[] = '// ------------------------------------'; 228 | 229 | if ($type === self::TYPE_DOCTRINE) 230 | { 231 | $lines[] = ''; 232 | $lines[] = '// Load the required entity repositories ---'; 233 | $lines[] = '$credo = new Credo($this->db);'; 234 | 235 | $foreigns[] = $model; 236 | 237 | foreach ($foreigns as $foreign) 238 | { 239 | $foreign = ucfirst($foreign); 240 | 241 | $lines[] = ''; 242 | $lines[] = '/** @var \\' . $foreign . '_repository */'; 243 | $lines[] = '$repo = $credo->get_repository(\'' . $foreign . '\');'; 244 | $lines[] = '$this->' . strtolower($foreign) . '_repo = $repo;'; 245 | } 246 | 247 | $lines[] = '// -----------------------------------------'; 248 | } 249 | 250 | return $lines; 251 | }); 252 | 253 | $this->addMethod($method); 254 | } 255 | 256 | /** 257 | * @param string $name 258 | * @param string $model 259 | * @param integer $type 260 | * 261 | * @return void 262 | */ 263 | protected function setCreateMethod($name, $model, $type) 264 | { 265 | $method = new Method('create'); 266 | 267 | $texts = array('Returns the form page for creating a ' . $model . '.'); 268 | $texts[] = 'Creates a new ' . $model . ' if receiving payload.'; 269 | $method->setComment($texts); 270 | 271 | $method->setReturn('void'); 272 | 273 | $method->setCodeLine(function ($lines) use ($name, $model, $type) 274 | { 275 | $lines[] = '// Skip if provided empty input ---'; 276 | $lines[] = '/** @var array */'; 277 | $lines[] = '$input = $this->input->post(null, true);'; 278 | $lines[] = ''; 279 | $lines[] = '$data = array();'; 280 | 281 | $lines = $this->setForeigns($lines); 282 | 283 | $lines[] = ''; 284 | $lines[] = 'if (! $input)'; 285 | $lines[] = '{'; 286 | 287 | // TODO: Show if --with-view enabled ------------------------- 288 | if ($this->layout) 289 | { 290 | $lines[] = ' $this->load->view(\'layout/header\');'; 291 | } 292 | 293 | $lines[] = ' $this->load->view(\'' . $name . '/create\', $data);'; 294 | 295 | if ($this->layout) 296 | { 297 | $lines[] = ' $this->load->view(\'layout/footer\');'; 298 | } 299 | 300 | $lines[] = ''; 301 | // ----------------------------------------------------------- 302 | 303 | $lines[] = ' return;'; 304 | $lines[] = '}'; 305 | $lines[] = '// --------------------------------'; 306 | $lines[] = ''; 307 | 308 | $lines[] = '// Specify logic here if applicable ---'; 309 | 310 | if ($type === self::TYPE_WILDFIRE) 311 | { 312 | $lines[] = '$exists = $this->' . $model . '->exists($input);'; 313 | } 314 | else 315 | { 316 | $lines[] = '$exists = $this->' . $model . '_repo->exists($input);'; 317 | } 318 | 319 | $lines[] = ''; 320 | $lines[] = 'if ($exists)'; 321 | $lines[] = '{'; 322 | $lines[] = ' $data[\'error\'] = \'\';'; 323 | $lines[] = '}'; 324 | $lines[] = '// ------------------------------------'; 325 | $lines[] = ''; 326 | 327 | $lines[] = '// Check if provided input is valid ---'; 328 | $lines[] = '$valid = $this->' . $model . '->validate($input);'; 329 | $lines[] = ''; 330 | $lines[] = 'if (! $valid || $exists)'; 331 | $lines[] = '{'; 332 | 333 | // TODO: Show if --with-view enabled -------------------------------- 334 | if ($this->layout) 335 | { 336 | $lines[] = ' $this->load->view(\'layout/header\');'; 337 | } 338 | 339 | $lines[] = ' $this->load->view(\'' . $name . '/create\', $data);'; 340 | 341 | if ($this->layout) 342 | { 343 | $lines[] = ' $this->load->view(\'layout/footer\');'; 344 | } 345 | 346 | $lines[] = ''; 347 | // ------------------------------------------------------------------ 348 | 349 | $lines[] = ' return;'; 350 | $lines[] = '}'; 351 | $lines[] = '// ------------------------------------'; 352 | $lines[] = ''; 353 | 354 | $lines[] = '// Create the item then go back to "index" page ---'; 355 | 356 | if ($type === self::TYPE_WILDFIRE) 357 | { 358 | $lines[] = '$this->' . $model . '->create($input);'; 359 | } 360 | else 361 | { 362 | $class = ucfirst($model); 363 | 364 | $lines[] = '$this->' . $model . '_repo->create($input, new ' . $class . ');'; 365 | $lines[] = ''; 366 | $lines[] = '$this->' . $model . '_repo->flush();'; 367 | } 368 | 369 | $lines[] = ''; 370 | $lines[] = '$text = (string) \'' . ucfirst($model) . ' successfully created!\';'; 371 | $lines[] = ''; 372 | $lines[] = '$this->session->set_flashdata(\'alert\', $text);'; 373 | $lines[] = ''; 374 | $lines[] = 'redirect(\'' . $name . '\');'; 375 | $lines[] = '// ------------------------------------------------'; 376 | 377 | return $lines; 378 | }); 379 | 380 | $this->addMethod($method); 381 | } 382 | 383 | /** 384 | * @param string $name 385 | * @param string $model 386 | * @param integer $type 387 | * 388 | * @return void 389 | */ 390 | protected function setDeleteMethod($name, $model, $type) 391 | { 392 | $method = new Method('delete'); 393 | 394 | $method->setComment('Deletes the specified ' . $model . '.'); 395 | 396 | $method->addIntegerArgument('id'); 397 | 398 | $method->setReturn('void'); 399 | 400 | $method->setCodeLine(function ($lines) use ($name, $model, $type) 401 | { 402 | $lines[] = '// Show 404 page if not using "DELETE" method ---'; 403 | $lines[] = '$method = $this->input->post(\'_method\', true);'; 404 | $lines[] = ''; 405 | 406 | if ($type === self::TYPE_WILDFIRE) 407 | { 408 | $lines[] = '$item = $this->' . $model . '->find($id);'; 409 | } 410 | else 411 | { 412 | $lines[] = '$item = $this->' . $model . '_repo->find($id);'; 413 | } 414 | 415 | $lines[] = ''; 416 | $lines[] = 'if ($method !== \'DELETE\' || ! $item)'; 417 | $lines[] = '{'; 418 | $lines[] = ' show_404();'; 419 | $lines[] = '}'; 420 | $lines[] = '// ----------------------------------------------'; 421 | $lines[] = ''; 422 | 423 | $lines[] = '// Delete the item then go back to "index" page ---'; 424 | 425 | if ($type === self::TYPE_WILDFIRE) 426 | { 427 | $lines[] = '$this->' . $model . '->delete($id);'; 428 | } 429 | else 430 | { 431 | $class = ucfirst($model); 432 | 433 | $lines[] = '/** @var \\' . $class . ' $item */'; 434 | $lines[] = '$this->' . $model . '_repo->delete($item);'; 435 | $lines[] = ''; 436 | $lines[] = '$this->' . $model . '_repo->flush();'; 437 | } 438 | 439 | $lines[] = ''; 440 | $lines[] = '$text = (string) \'' . ucfirst($model) . ' successfully deleted!\';'; 441 | $lines[] = ''; 442 | $lines[] = '$this->session->set_flashdata(\'alert\', $text);'; 443 | $lines[] = ''; 444 | $lines[] = 'redirect(\'' . $name . '\');'; 445 | $lines[] = '// ------------------------------------------------'; 446 | 447 | return $lines; 448 | }); 449 | 450 | $this->addMethod($method); 451 | } 452 | 453 | /** 454 | * @param string $name 455 | * @param string $model 456 | * @param integer $type 457 | * 458 | * @return void 459 | */ 460 | protected function setEditMethod($name, $model, $type) 461 | { 462 | $method = new Method('edit'); 463 | 464 | $texts = array('Returns the form page for updating a ' . $model . '.'); 465 | $texts[] = 'Updates the specified ' . $model . ' if receiving payload.'; 466 | $method->setComment($texts); 467 | 468 | $method->addIntegerArgument('id'); 469 | 470 | $method->setReturn('void'); 471 | 472 | $method->setCodeLine(function ($lines) use ($name, $model, $type) 473 | { 474 | $lines[] = '// Show 404 page if item not found ---'; 475 | 476 | if ($type === self::TYPE_WILDFIRE) 477 | { 478 | $lines[] = 'if (! $item = $this->' . $model . '->find($id))'; 479 | } 480 | else 481 | { 482 | $lines[] = 'if (! $item = $this->' . $model . '_repo->find($id))'; 483 | } 484 | 485 | $lines[] = '{'; 486 | $lines[] = ' show_404();'; 487 | $lines[] = '}'; 488 | $lines[] = ''; 489 | $lines[] = '/** @var \\' . ucfirst($model) . ' $item */'; 490 | $lines[] = '$data = array(\'item\' => $item);'; 491 | $lines[] = '// -----------------------------------'; 492 | 493 | $lines = $this->setForeigns($lines); 494 | 495 | $lines[] = ''; 496 | 497 | $lines[] = '// Skip if provided empty input ---'; 498 | $lines[] = '/** @var array */'; 499 | $lines[] = '$input = $this->input->post(null, true);'; 500 | $lines[] = ''; 501 | $lines[] = 'if (! $input)'; 502 | $lines[] = '{'; 503 | 504 | // TODO: Show if --with-view enabled ------------------------------ 505 | if ($this->layout) 506 | { 507 | $lines[] = ' $this->load->view(\'layout/header\');'; 508 | } 509 | 510 | $lines[] = ' $this->load->view(\'' . $name . '/edit\', $data);'; 511 | 512 | if ($this->layout) 513 | { 514 | $lines[] = ' $this->load->view(\'layout/footer\');'; 515 | } 516 | 517 | $lines[] = ''; 518 | // ---------------------------------------------------------------- 519 | 520 | $lines[] = ' return;'; 521 | $lines[] = '}'; 522 | $lines[] = '// --------------------------------'; 523 | $lines[] = ''; 524 | 525 | $lines[] = '// Show 404 page if not using "PUT" method ---'; 526 | $lines[] = '$method = $this->input->post(\'_method\', true);'; 527 | $lines[] = ''; 528 | $lines[] = 'if ($method !== \'PUT\')'; 529 | $lines[] = '{'; 530 | $lines[] = ' show_404();'; 531 | $lines[] = '}'; 532 | $lines[] = '// -------------------------------------------'; 533 | $lines[] = ''; 534 | 535 | $lines[] = '// Specify logic here if applicable ---'; 536 | 537 | if ($type === self::TYPE_WILDFIRE) 538 | { 539 | $lines[] = '$exists = $this->' . $model . '->exists($input, $id);'; 540 | } 541 | else 542 | { 543 | $lines[] = '$exists = $this->' . $model . '_repo->exists($input, $id);'; 544 | } 545 | 546 | $lines[] = ''; 547 | $lines[] = 'if ($exists)'; 548 | $lines[] = '{'; 549 | $lines[] = ' $data[\'error\'] = \'\';'; 550 | $lines[] = '}'; 551 | $lines[] = '// ------------------------------------'; 552 | $lines[] = ''; 553 | 554 | $lines[] = '// Check if provided input is valid ---'; 555 | $lines[] = '$valid = $this->' . $model . '->validate($input);'; 556 | $lines[] = ''; 557 | $lines[] = 'if (! $valid || $exists)'; 558 | $lines[] = '{'; 559 | 560 | // TODO: Show if --with-view enabled ------------------------------ 561 | if ($this->layout) 562 | { 563 | $lines[] = ' $this->load->view(\'layout/header\');'; 564 | } 565 | 566 | $lines[] = ' $this->load->view(\'' . $name . '/edit\', $data);'; 567 | 568 | if ($this->layout) 569 | { 570 | $lines[] = ' $this->load->view(\'layout/footer\');'; 571 | } 572 | 573 | $lines[] = ''; 574 | // ---------------------------------------------------------------- 575 | 576 | $lines[] = ' return;'; 577 | $lines[] = '}'; 578 | $lines[] = '// ------------------------------------'; 579 | $lines[] = ''; 580 | 581 | $lines[] = '// Update the item then go back to "index" page ---'; 582 | 583 | if ($type === self::TYPE_WILDFIRE) 584 | { 585 | $lines[] = '$this->' . $model . '->update($id, $input);'; 586 | } 587 | else 588 | { 589 | $class = ucfirst($model); 590 | 591 | $lines[] = '/** @var \\' . $class . ' $item */'; 592 | $lines[] = '$this->' . $model . '_repo->update($item, $input);'; 593 | $lines[] = ''; 594 | $lines[] = '$this->' . $model . '_repo->flush();'; 595 | } 596 | 597 | $lines[] = ''; 598 | $lines[] = '$text = (string) \'User successfully updated!\';'; 599 | $lines[] = ''; 600 | $lines[] = '$this->session->set_flashdata(\'alert\', $text);'; 601 | $lines[] = ''; 602 | $lines[] = 'redirect(\'' . $name . '\');'; 603 | $lines[] = '// ------------------------------------------------'; 604 | 605 | return $lines; 606 | }); 607 | 608 | $this->addMethod($method); 609 | } 610 | 611 | /** 612 | * @param string[] $lines 613 | * 614 | * @return string[] 615 | */ 616 | protected function setForeigns($lines) 617 | { 618 | $items = array(); 619 | 620 | foreach ($this->cols as $col) 621 | { 622 | if ($col->isForeignKey()) 623 | { 624 | $items[] = $col; 625 | } 626 | } 627 | 628 | if (count($items) > 0) 629 | { 630 | $lines[] = ''; 631 | } 632 | 633 | foreach ($items as $item) 634 | { 635 | $name = $item->getReferencedTable(); 636 | $name = Inflector::plural($name); 637 | 638 | $model = Inflector::singular($name); 639 | 640 | if ($this->type === self::TYPE_DOCTRINE) 641 | { 642 | $lines[] = '$data[\'' . $name . '\'] = $this->' . $model . '_repo->dropdown(\'id\');'; 643 | } 644 | else 645 | { 646 | $lines[] = '$data[\'' . $name . '\'] = $this->' . $model . '->get()->dropdown(\'id\');'; 647 | } 648 | } 649 | 650 | return $lines; 651 | } 652 | 653 | /** 654 | * @param string $name 655 | * @param string $model 656 | * @param integer $type 657 | * 658 | * @return void 659 | */ 660 | protected function setIndexMethod($name, $model, $type) 661 | { 662 | $method = new Method('index'); 663 | 664 | $method->setComment('Returns the list of paginated ' . $name . '.'); 665 | 666 | $method->setReturn('void'); 667 | 668 | $method->setCodeLine(function ($lines) use ($name, $model, $type) 669 | { 670 | $lines[] = '// Create pagination links and get the offset ---'; 671 | 672 | if ($type === self::TYPE_WILDFIRE) 673 | { 674 | $lines[] = '$total = (int) $this->' . $model . '->total();'; 675 | } 676 | else 677 | { 678 | $lines[] = '$total = (int) $this->' . $model . '_repo->total();'; 679 | } 680 | 681 | $lines[] = ''; 682 | $lines[] = '$result = $this->' . $model . '->paginate(10, $total);'; 683 | $lines[] = ''; 684 | $lines[] = '$data = array(\'links\' => $result[1]);'; 685 | $lines[] = ''; 686 | $lines[] = '/** @var integer */'; 687 | $lines[] = '$offset = $result[0];'; 688 | $lines[] = '// ----------------------------------------------'; 689 | $lines[] = ''; 690 | 691 | if ($type === self::TYPE_WILDFIRE) 692 | { 693 | $lines[] = '$items = $this->' . $model . '->get(10, $offset);'; 694 | } 695 | else 696 | { 697 | $lines[] = '$items = $this->' . $model . '_repo->get(10, $offset);'; 698 | } 699 | 700 | $lines[] = ''; 701 | 702 | if ($type === self::TYPE_WILDFIRE) 703 | { 704 | $lines[] = '$data[\'items\'] = $items->result();'; 705 | } 706 | else 707 | { 708 | $lines[] = '$data[\'items\'] = $items;'; 709 | } 710 | 711 | $lines[] = ''; 712 | $lines[] = 'if ($alert = $this->session->flashdata(\'alert\'))'; 713 | $lines[] = '{'; 714 | $lines[] = ' $data[\'alert\'] = $alert;'; 715 | $lines[] = '}'; 716 | 717 | // TODO: Show if --with-view enabled --------------------------- 718 | $lines[] = ''; 719 | 720 | if ($this->layout) 721 | { 722 | $lines[] = '$this->load->view(\'layout/header\');'; 723 | } 724 | 725 | $lines[] = '$this->load->view(\'' . $name . '/index\', $data);'; 726 | 727 | if ($this->layout) 728 | { 729 | $lines[] = '$this->load->view(\'layout/footer\');'; 730 | } 731 | // ------------------------------------------------------------- 732 | 733 | return $lines; 734 | }); 735 | 736 | $this->addMethod($method); 737 | } 738 | } 739 | --------------------------------------------------------------------------------