diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..550e711 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,45 @@ +on: + push: + branches: [ 'master' ] + pull_request: + branches: [ 'master' ] + +permissions: + contents: read + +jobs: + run: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + 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' ] + + name: Run Unit Test on PHP ${{ matrix.php-versions }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + + - name: Check the PHP version + run: php -v + + - name: Validate composer.json and composer.lock + run: composer validate --strict + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + + - name: Run test suite + run: vendor/bin/phpunit --coverage-clover=coverage.clover + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4-beta + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 52f6cfc..6e17c22 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,11 @@ +.php-cs-fixer.cache .phpintel +.phpunit.result.cache build +combustor.bak +combustor.yml composer.lock -docs +tests/Fixture/Sample/controllers +tests/Fixture/Sample/models +tests/Fixture/Sample/views vendor \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 99f5cb9..0000000 --- a/.travis.yml +++ /dev/null @@ -1,34 +0,0 @@ -dist: xenial -language: php -os: linux - -php: - - 5.6 - - 7.0 - - 7.1 - - 7.2 - - 7.3 - - 7.4 - -jobs: - include: - # - php: 5.3 - # dist: precise - - php: 5.4 - dist: trusty - - php: 5.5 - dist: trusty - -before_install: - - echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini - -before_script: - - npm install -g bower - - travis_retry composer self-update - - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source - -script: - - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover - -after_script: - - if [[ $TRAVIS_PHP_VERSION != 'hhvm' && $TRAVIS_PHP_VERSION != '7.0' ]]; then php vendor/bin/ocular code-coverage:upload --format=php-clover coverage.clover; fi diff --git a/CHANGELOG.md b/CHANGELOG.md index dbed6e7..63780e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,28 @@ All notable changes to `Combustor` will be documented in this file. +## [1.3.0](https://github.com/rougin/transcribe/compare/v1.2.4...v1.3.0) - Unreleased + +### Added +- Command for creating `combustor.yml` configuration file +- Fields that can be excluded through `excluded_files` +- Specify customized `application` path using `app_path` + +### Changed +- Code coverage provider to `Codecov` +- Code documentation by `php-cs-fixer` +- Improved code quality by `phpstan` +- Main argument `name` to `table` in `Commands` +- Simplified code structure +- Workflow provider to `Github Actions` + +### Removed +- Options to strictly conform in coding style of `Codeigniter`: + - `--camel` + - `--keep` + - `--lowercase` +- `CONTRIBUTING.md` + ## [1.2.4](https://github.com/rougin/combustor/compare/v1.2.3...v1.2.4) - 2018-04-18 ### Fixed diff --git a/CONDUCT.md b/CONDUCT.md deleted file mode 100644 index 6ff94ca..0000000 --- a/CONDUCT.md +++ /dev/null @@ -1,22 +0,0 @@ -# Contributor Code of Conduct - -As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. - -We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery -* Personal attacks -* Trolling or insulting/derogatory comments -* Public or private harassment -* Publishing other's private information, such as physical or electronic addresses, without explicit permission -* Other unethical or unprofessional conduct. - -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. - -This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community in a direct capacity. Personal views, beliefs and values of individuals do not necessarily reflect those of the organisation or affiliated individuals and organisations. - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. - -This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index e0d35f4..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,29 +0,0 @@ -# Contributing - -Contributions are **welcome** and will be fully **credited**. - -We accept contributions via Pull Requests on [Github](https://github.com/rougin/combustor). - -## Pull Requests - -- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). - -- **Add tests!** - Your patch won't be accepted if it doesn't have tests. - -- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. - -- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. - -- **Create feature branches** - Don't ask us to pull from your master branch. - -- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. - -- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. - -## Running Tests - -``` bash -$ composer test -``` - -**Happy coding**! diff --git a/LICENSE.md b/LICENSE.md index b867830..10b5cd7 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Rougin Gutib +Copyright (c) Rougin Gutib Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 3c6af5a..428468f 100644 --- a/README.md +++ b/README.md @@ -2,45 +2,103 @@ [![Latest Version on Packagist][ico-version]][link-packagist] [![Software License][ico-license]][link-license] -[![Build Status][ico-travis]][link-travis] -[![Coverage Status][ico-scrutinizer]][link-scrutinizer] -[![Quality Score][ico-code-quality]][link-code-quality] +[![Build Status][ico-build]][link-build] +[![Coverage Status][ico-coverage]][link-coverage] [![Total Downloads][ico-downloads]][link-downloads] -Combustor is a [Codeigniter](https://codeigniter.com/) library that generates controllers, models, and views based from database tables. It uses the [Describe](/describe/) library for retrieving the database tables and as the basis for code generation. +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/) library for getting columns from a database table and as the basis for code generation. ## Features -* Generates code based from the structure of the Codeigniter framework -* Speeds up the code development for prototyping web applications -* View templates are based on Bootstrap which can also be modified later -* Needs to worry only on the database schema, and Combustor will do the rest +* Generates code based on the structure of the `Codeigniter 3` framework; +* Speeds up the code development for prototyping web applications; +* View templates can be based on Bootstrap and are upgradable; and +* Only worry on the database schema, and `Combustor` will do the rest. ## Installation -1. Download the Codeigniter framework [here](https://github.com/bcit-ci/CodeIgniter/archive/3.1.8.zip) and extract it to the web server. -2. Configure the application's database connectivity settings in `application/config/database.php`. -3. Install Combustor through the [Composer](https://getcomposer.org/) package manager: +Extract the contents of the [latest Codeigniter 3 project](https://github.com/bcit-ci/CodeIgniter/archive/3.1.13.zip) first: + +``` bash +$ wget https://github.com/bcit-ci/CodeIgniter/archive/3.1.13.zip +$ unzip 3.1.13.zip -d acme +``` + +Then configure the project's database connectivity settings: + +``` +$ cd acme +$ nano application/config/database.php +``` + +``` php +// acme/application/config/database.php + +// ... + +$db['default'] = array( + 'dsn' => '', + 'hostname' => 'localhost', + 'username' => '', + 'password' => '', + 'database' => '', + 'dbdriver' => 'mysqli', + + // ... +); +``` + +Next is to proceed in installing `Combustor` via [Composer](https://getcomposer.org/): + ``` bash $ composer require rougin/combustor --dev ``` -4. Install the ORM wrappers `Wildfire` and `Doctrine ORM` or both: + +``` json +// acme/composer.json + +{ + // ... + + "require-dev": + { + "mikey179/vfsstream": "1.6.*", + "phpunit/phpunit": "4.* || 5.* || 9.*", + "rougin/combustor": "~1.0" + } +} +``` + +Lastly, install the ORM wrappers like `Wildfire` or `Doctrine`: + ``` bash $ vendor/bin/combustor install:wildfire $ vendor/bin/combustor install:doctrine ``` +> [!NOTE] +> Using the `install:wildfire` command installs [Wildfire](https://roug.in/wildfire/) package while the `install:doctrine` installs [Credo](https://roug.in/credo/) package. + +## Reminders + +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. + +Also, please proceed first in generating models, views, or controllers to database tables that are having _**no relationship with other tables**_ in the database. + +> [!TIP] +> `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. + ## Commands ### `create:layout` -Creates a new header and footer file. +Create a new header and footer file. -#### Options +**Options** -* `--bootstrap` - includes the Bootstrap tags +* `--bootstrap` - adds styling based on Bootstrap -#### Example +**Example** ``` bash $ vendor/bin/combustor create-layout --bootstrap @@ -48,66 +106,60 @@ $ vendor/bin/combustor create-layout --bootstrap ### `create:controller` -Creates a new HTTP controller. +Create a new HTTP controller. + +**Arguments** -#### Arguments +* `table` - name of the database table -* `name` - name of the database table +**Options** -#### Options +* `--doctrine` - generates a Doctrine-based controller +* `--wildfire` - generates a Wildfire-based controller -* `--camel` - uses camel case naming convention for the accessor and mutators -* `--doctrine` - generates a controller based on Doctrine -* `--keep` - keeps the name to be used -* `--lowercase` - keeps the first character of the name to lowercase -* `--wildfire` - generates a controller based from Wildfire +> [!NOTE] +> 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. -#### Example +**Example** ``` bash -$ vendor/bin/combustor create:controller users --camel --wildfire +$ vendor/bin/combustor create:controller users --wildfire ``` ### `create:model` -Creates a new model. +Create a new model. -#### Arguments +**Arguments** -* `name` - name of the database table +* `table` - name of the database table -#### Options +**Options** -* `--camel` - uses camel case naming convention for the accessor and mutators -* `--doctrine` - generates a controller based on Doctrine -* `--keep` - keeps the name to be used -* `--lowercase` - keeps the first character of the name to lowercase -* `--wildfire` - generates a controller based from Wildfire +* `--doctrine` - generates a Doctrine-based model +* `--wildfire` - generates a Wildfire-based model -#### Example +**Example** ``` bash -$ vendor/bin/combustor create:model users --camel --wildfire +$ vendor/bin/combustor create:model users --wildfire ``` ### `create:view` -Creates a new view template. +Create view templates. -#### Arguments +**Arguments** -* `name` - name of the database table +* `table` - name of the database table -#### Options +**Options** -* `--bootstrap` - includes the Bootstrap tags -* `--camel` - uses camel case naming convention for the accessor and mutators -* `--doctrine` - generates a controller based on Doctrine -* `--keep` - keeps the name to be used -* `--lowercase` - keeps the first character of the name to lowercase -* `--wildfire` - generates a controller based from Wildfire +* `--bootstrap` - adds styling based on Bootstrap +* `--doctrine` - generates Doctrine-based views +* `--wildfire` - generates Wildfire-based views -#### Example +**Example** ``` bash $ vendor/bin/combustor create:view users --bootstrap @@ -115,102 +167,135 @@ $ vendor/bin/combustor create:view users --bootstrap ### `create:scaffold` -Creates a new HTTP controller, model, and view template. +Create a new HTTP controller, model, and view templates. -#### Arguments +**Arguments** -* `name` - name of the database table +* `table` - name of the database table -#### Options +**Options** -* `--bootstrap` - includes the Bootstrap tags -* `--camel` - uses camel case naming convention for the accessor and mutators -* `--doctrine` - generates a controller based on Doctrine -* `--keep` - keeps the name to be used -* `--lowercase` - keeps the first character of the name to lowercase -* `--wildfire` - generates a controller based from Wildfire +* `--bootstrap` - adds styling based on Bootstrap +* `--doctrine` - generates a Doctrine-based controller, model, and views +* `--wildfire` - generates a Wildfire-based controller, model, and views -#### Example +**Example** ``` bash $ vendor/bin/combustor create:scaffold users --bootstrap --wildfire ``` -## Wilfire's Methods +### `install:doctrine` -The following methods below are available if `--wildfire` is installed: +Install the [Doctrine](https://roug.in/credo/) package. -### `delete($table, $delimiters = [])` +**Example** -Deletes the specified data from storage. +``` bash +$ vendor/bin/combustor install:doctrine +``` -#### Arguments +> [!NOTE] +> * This command will be available if `Doctrine` is not installed in the project. +> * It also adds a `Loader.php` in the `core` directory. The said file is used for loading custom repositories extended to `EntityRepository`. -* `$table` - name of the database table -* `$delimiters` - delimits the list of rows to be returned +### `install:wildfire` -#### Example +Install the [Wildfire](https://roug.in/wildfire/) package. -``` php -$this->wildfire->delete('users', ['id' => 3]); +**Example** + +``` bash +$ vendor/bin/combustor install:wildfire ``` -### `find($table, $delimiters = [])` +> [!NOTE] +> This command will be available if `Wildfire` is not installed in the project. -Finds the row from the specified ID or with the list of delimiters from the specified table. +### `remove:doctrine` -#### Arguments +Remove the [Doctrine](https://roug.in/credo/) package. -* `$table` - name of the database table -* `$delimiters` - delimits the list of rows to be returned +**Example** -#### Example +``` bash +$ vendor/bin/combustor remove:doctrine +``` -``` php -$this->wildfire->delete('users', ['id' => 3]); +> [!NOTE] +> This command will be available if `Doctrine` is installed in the project. + +### `remove:wildfire` + +Remove the [Wildfire](https://roug.in/wildfire/) package. + +**Example** + +``` bash +$ vendor/bin/combustor remove:wildfire ``` -### `get_all($table, $delimiters = [])` +> [!NOTE] +> This command will be available if `Wildfire` is installed in the project. -Returns all rows from the specified table +## Using `combustor.yml` -#### Arguments +`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: -* `$table` - name of the database table -* `$delimiters` - delimits the list of rows to be returned - * `keyword` - used for searching the data from the storage - * `per_page` - defines the number of rows per page +``` yaml +# combustor.yml -#### Returned methods +app_path: %%CURRENT_DIRECTORY%%/Sample -* `as_dropdown($description)` - returns the list of rows that can be used in `form_dropdown()` - * `description` - the field to be displayed in the result (the default value is `description`) -* `result()` - returns the list of rows from the storage in a model -* `total_rows()` - returns the total number of rows based from the result +excluded_fields: + - created_at + - updated_at + - deleted_at +``` -#### Example +To create a `combustor.yml`, simply run the `initialize` command: -``` php -$delimiters = ['keyword' => 'test', 'per_page' = 3]; +``` bash +$ vendor/bin/combustor initialize +[PASS] "combustor.yml" added successfully! +``` -$result = $this->wildfire->all('users', $delimiters); +### `app_path` -var_dump((array) $result->result()); +This property specifies the `application` directory. It may updated to any directory (e.g., `acme/application`, `acme/config`, etc.) as long it can detect the `config/config.php` file from the defined directory: + +``` yaml +# combustor.yml + +app_path: %%CURRENT_DIRECTORY%%/Sample + +# ... ``` -**NOTE**: This method is also available if `--doctrine` is installed. +> [!NOTE] +> `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`. -## Reminders +### `excluded_fields` + +Specified fields in this property are excluded from generation to the following templates: -* If either Wildfire or Doctrine is installed, no need to specify it as option for executing a specified command (e.g. `vendor/bin/combustor create:controller --wildfire`). However if both are installed, the command to be executed must have a `--wildfire` or `--doctrine` option added. +* `controllers` +* `models` +* `views` (only for `create` and `edit` templates) -* To learn more about Doctrine's functionalities and its concepts, the documentation page can be found [here](http://doctrine-orm.readthedocs.org/en/latest). +``` yaml +# combustor.yml -* Before generating the models, views, and controllers, please make sure that the **database is defined properly** (foreign keys, indexes, relationships, normalizations) in order to minimize the modifications after the codes has been generated. Also, generate the models, views, and controllers first to tables that are having **no relationship with other tables** in the database. +# ... - * The reason for this is that Combustor will generate controllers, models, and views based on the specified database schema. If there's something wrong in the said database, Combustor will definitely generate a bad codebase. +excluded_fields: + - created_at + - updated_at + - deleted_at +``` -* For found bugs or suggestions, feel free to [open an issue](https://github.com/rougin/combustor/issues) or [create a pull request](https://github.com/rougin/combustor/compare). +> [!NOTE] +> By default, the timestamps are added when creating a `combustor.yml` for the first time as they are usually populated automatically by installed ORMs such as `Wildfire` or `Doctrine`. ## Changelog @@ -230,18 +315,16 @@ $ composer test The MIT License (MIT). Please see [LICENSE][link-license] for more information. -[ico-code-quality]: https://img.shields.io/scrutinizer/g/rougin/combustor.svg?style=flat-square +[ico-build]: https://img.shields.io/github/actions/workflow/status/rougin/combustor/build.yml?style=flat-square +[ico-coverage]: https://img.shields.io/codecov/c/github/rougin/combustor?style=flat-square [ico-downloads]: https://img.shields.io/packagist/dt/rougin/combustor.svg?style=flat-square [ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square -[ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/rougin/combustor.svg?style=flat-square -[ico-travis]: https://img.shields.io/travis/rougin/combustor/master.svg?style=flat-square [ico-version]: https://img.shields.io/packagist/v/rougin/combustor.svg?style=flat-square +[link-build]: https://github.com/rougin/combustor/actions [link-changelog]: https://github.com/rougin/combustor/blob/master/CHANGELOG.md -[link-code-quality]: https://scrutinizer-ci.com/g/rougin/combustor [link-contributors]: https://github.com/rougin/combustor/contributors +[link-coverage]: https://app.codecov.io/gh/rougin/combustor [link-downloads]: https://packagist.org/packages/rougin/combustor [link-license]: https://github.com/rougin/combustor/blob/master/LICENSE.md -[link-packagist]: https://packagist.org/packages/rougin/combustor -[link-scrutinizer]: https://scrutinizer-ci.com/g/rougin/combustor/code-structure -[link-travis]: https://travis-ci.org/rougin/combustor \ No newline at end of file +[link-packagist]: https://packagist.org/packages/rougin/combustor \ No newline at end of file diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 0000000..96b23c8 --- /dev/null +++ b/TODO.txt @@ -0,0 +1,7 @@ +[x] bootstrap +- [ ] index pagination +[ ] --empty +[ ] --force +[x] custom fields +- [ ] email +[ ] multi relations \ No newline at end of file diff --git a/bin/combustor b/bin/combustor index 575bce6..69dd143 100644 --- a/bin/combustor +++ b/bin/combustor @@ -1,5 +1,22 @@ #!/usr/bin/env php run(); +// ------------------------------- diff --git a/bin/combustor.php b/bin/combustor.php deleted file mode 100644 index 9848897..0000000 --- a/bin/combustor.php +++ /dev/null @@ -1,50 +0,0 @@ -console->setName('Combustor'); -$app->console->setVersion('1.2.2'); - -$app - ->setTemplatePath(__DIR__ . '/../src/Templates') - ->setCommandPath(__DIR__ . '/../src/Commands') - ->setCommandNamespace('Rougin\Combustor\Commands'); - -$app->injector->delegate('CI_Controller', function () { - return Rougin\SparkPlug\Instance::create(); -}); - -$ci = $app->injector->make('CI_Controller'); - -$app->injector->delegate('Rougin\Describe\Describe', function () use ($ci) { - $ci->load->database(); - $ci->load->helper('inflector'); - - $config = []; - - $config['default'] = [ - 'dbdriver' => $ci->db->dbdriver, - 'hostname' => $ci->db->hostname, - 'username' => $ci->db->username, - 'password' => $ci->db->password, - 'database' => $ci->db->database - ]; - - if (empty($config['default']['hostname'])) { - $config['default']['hostname'] = $ci->db->dsn; - } - - $driver = new Rougin\Describe\Driver\CodeIgniterDriver($config); - - return new Rougin\Describe\Describe($driver); -}); - -// Run the Combustor console application -$app->run(); diff --git a/composer.json b/composer.json index 4756482..7d34a9d 100644 --- a/composer.json +++ b/composer.json @@ -1,67 +1,68 @@ { - "name": "rougin/combustor", - "description": "CRUD generator for the Codeigniter framework.", - "keywords": ["codeigniter", "combustor", "crud", "generator"], - "homepage": "https://roug.in/combustor/", - "license": "MIT", - "authors": - [ - { - "email": "rougingutib@gmail.com", - "homepage": "https://roug.in/", - "name": "Rougin Gutib", - "role": "Software Engineer" - } - ], - "require": + "name": "rougin/combustor", + "description": "MVC code generator for Codeigniter 3.", + "keywords": [ "code-generator", "crud-generator" ], + "homepage": "https://roug.in/combustor/", + "license": "MIT", + "authors": + [ { - "php": ">=5.4.0", - "rougin/blueprint": "~0.1", - "rougin/describe": "~1.4", - "rougin/spark-plug": "~0.4" - }, - "require-dev": - { - "phpunit/phpunit": "~4.2|~5.7", - "rougin/codeigniter": "~3.0", - "scrutinizer/ocular": "~1.1" - }, - "bin": [ - "bin/combustor", - "bin/combustor.php" - ], - "autoload": - { - "psr-4": - { - "Rougin\\Combustor\\": "src" - } - }, - "autoload-dev": - { - "psr-4": - { - "Rougin\\Combustor\\": "tests" - } - }, - "scripts": + "email": "rougingutib@gmail.com", + "homepage": "https://roug.in/", + "name": "Rougin Gutib", + "role": "Software Engineer" + } + ], + "require": + { + "php": ">=5.4.0", + "rougin/blueprint": "dev-master", + "rougin/classidy": "dev-master", + "rougin/describe": "dev-master", + "rougin/spark-plug": "~0.6" + }, + "require-dev": + { + "rougin/codeigniter": "~3.0", + "phpunit/phpunit": "~4.2|~5.7|~6.0|~7.0|~8.0|~9.0", + "sanmai/phpunit-legacy-adapter": "~6.1|~8.0" + }, + "bin": + [ + "bin/combustor" + ], + "autoload": + { + "psr-4": { - "test": "phpunit" - }, - "extra": + "Rougin\\Combustor\\": "src" + } + }, + "autoload-dev": + { + "psr-4": { - "branch-alias": - { - "dev-master": "2.0-dev" - } - }, - "suggest": + "Rougin\\Combustor\\": "tests" + } + }, + "scripts": + { + "test": "phpunit" + }, + "extra": + { + "branch-alias": { - "rougin/codeigniter": "Packaged \"system\" folder of the Codeigniter framework.", - "rougin/credo": "Doctrine ORM integration for the Codeigniter framework.", - "rougin/ignite": "Composer-based project for the Codeigniter framework.", - "rougin/refinery": "\"Ready-to-eat\" migrations for Codeigniter framework", - "rougin/spark-plug": "Codeigniter applications as single variables.", - "rougin/wildfire": "Query Builder wrapper for the Codeigniter framework." + "dev-master": "2.0-dev" } + }, + "suggest": + { + "rougin/codeigniter": "Packaged \"system\" of Codeigniter 3.", + "rougin/credo": "Doctrine ORM wrapper for Codeigniter 3.", + "rougin/ignite": "Yet another Codeigniter 3 project template.", + "rougin/refinery": "\"Ready-to-eat\" Codeigniter 3 migrations.", + "rougin/spark-plug": "Codeigniter 3 projects as variables.", + "rougin/wildfire": "Query Builder wrapper for Codeigniter 3." + } } \ No newline at end of file diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..bd86b33 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,22 @@ +parameters: + level: 9 + paths: + - src + - tests + excludePaths: + analyse: + - tests/Fixture/Plates + - tests/Fixture/Sample/controllers + - tests/Fixture/Sample/models + - tests/Fixture/Sample/views + scanDirectories: + - vendor/rougin/codeigniter/src + ignoreErrors: + - '#^Access to property \$database on an unknown class CI_DB\.$#' + - '#^Access to property \$dbdriver on an unknown class CI_DB\.$#' + - '#^Access to property \$dsn on an unknown class CI_DB\.$#' + - '#^Access to property \$hostname on an unknown class CI_DB\.$#' + - '#^Access to property \$password on an unknown class CI_DB\.$#' + - '#^Access to property \$username on an unknown class CI_DB\.$#' + - '#^Constant APPPATH not found\.$#' + - '#^Constant ENVIRONMENT not found\.$#' \ No newline at end of file diff --git a/phpstyle.php b/phpstyle.php new file mode 100644 index 0000000..a327e31 --- /dev/null +++ b/phpstyle.php @@ -0,0 +1,76 @@ + true); + +$cscp = 'control_structure_continuation_position'; +$rules[$cscp] = ['position' => 'next_line']; + +$braces = array(); +$braces['control_structures_opening_brace'] = 'next_line_unless_newline_at_signature_end'; +$braces['functions_opening_brace'] = 'next_line_unless_newline_at_signature_end'; +$braces['anonymous_functions_opening_brace'] = 'next_line_unless_newline_at_signature_end'; +$braces['anonymous_classes_opening_brace'] = 'next_line_unless_newline_at_signature_end'; +$braces['allow_single_line_empty_anonymous_classes'] = false; +$braces['allow_single_line_anonymous_functions'] = false; +$rules['braces_position'] = $braces; + +$visibility = array('elements' => array()); +$visibility['elements'] = array('method', 'property'); +$rules['visibility_required'] = $visibility; + +$rules['phpdoc_var_annotation_correct_order'] = true; + +$rules['single_quote'] = ['strings_containing_single_quote_chars' => true]; + +$rules['no_unused_imports'] = true; + +$rules['align_multiline_comment'] = true; + +$rules['trim_array_spaces'] = true; + +$order = ['case_sensitive' => true]; +$order['null_adjustment'] = 'always_last'; +$rules['phpdoc_types_order'] = $order; + +$rules['new_with_parentheses'] = ['named_class' => false]; + +$rules['concat_space'] = ['spacing' => 'one']; + +$rules['no_empty_phpdoc'] = true; + +$groups = []; +$groups[] = ['template', 'extends']; +$groups[] = ['deprecated', 'link', 'see', 'since', 'codeCoverageIgnore']; +$groups[] = ['property', 'property-read', 'property-write']; +$groups[] = ['method']; +$groups[] = ['author', 'copyright', 'license']; +$groups[] = ['category', 'package', 'subpackage']; +$groups[] = ['param']; +$groups[] = ['return', 'throws']; +$rules['phpdoc_separation'] = ['groups' => $groups]; + +$align = ['align' => 'vertical']; +$align['tags'] = ['method', 'param', 'property', 'throws', 'type', 'var']; +$rules['phpdoc_align'] = $align; + +$rules['statement_indentation'] = false; + +$rules['align_multiline_comment'] = true; +// ----------------------------------------------- + +$finder = new \PhpCsFixer\Finder; + +$finder->in((array) $paths); + +$config = new \PhpCsFixer\Config; + +$config->setRules($rules); + +return $config->setFinder($finder); diff --git a/src/Combustor.php b/src/Combustor.php new file mode 100644 index 0000000..beef4c2 --- /dev/null +++ b/src/Combustor.php @@ -0,0 +1,114 @@ + + */ +class Combustor +{ + /** + * @var \Rougin\SparkPlug\Controller|null + */ + protected $app = null; + + /** + * @var \Rougin\Describe\Driver\DriverInterface|null + */ + protected $driver = null; + + /** + * @var string[] + */ + protected $excluded = array(); + + /** + * @var string + */ + protected $root; + + /** + * @param string $root + */ + public function __construct($root) + { + $this->root = $root; + } + + /** + * @return string + */ + public function getAppPath() + { + $app = $this->root . '/application'; + + $root = $this->getRootPath(); + + return is_dir($app) ? $app : $root; + } + + /** + * @return \Rougin\Describe\Driver\DriverInterface|null + */ + public function getDriver() + { + return $this->driver; + } + + /** + * @return string[] + */ + public function getExcluded() + { + return $this->excluded; + } + + /** + * @return string + */ + public function getRootPath() + { + return $this->root; + } + + /** + * @param \Rougin\SparkPlug\Controller $app + * + * @return self + */ + public function setApp(Controller $app) + { + $this->app = $app; + + return $this; + } + + /** + * @param \Rougin\Describe\Driver\DriverInterface $driver + * + * @return self + */ + public function setDriver(DriverInterface $driver) + { + $this->driver = $driver; + + return $this; + } + + /** + * @param string[] $excluded + * + * @return self + */ + public function setExcluded($excluded) + { + $this->excluded = $excluded; + + return $this; + } +} diff --git a/src/Command.php b/src/Command.php new file mode 100644 index 0000000..154a2af --- /dev/null +++ b/src/Command.php @@ -0,0 +1,151 @@ + + */ +class Command extends Blueprint +{ + const TYPE_WILDFIRE = 0; + + const TYPE_DOCTRINE = 1; + + /** + * @var \Rougin\Describe\Driver\DriverInterface|null + */ + protected $driver = null; + + /** + * @var string[] + */ + protected $excluded = array(); + + /** + * @var \Rougin\Classidy\Generator + */ + protected $maker; + + /** + * @var string + */ + protected $path; + + /** + * @param \Rougin\Combustor\Combustor $combustor + * @param \Rougin\Classidy\Generator $maker + */ + public function __construct(Combustor $combustor, Generator $maker) + { + $this->driver = $combustor->getDriver(); + + $this->excluded = $combustor->getExcluded(); + + $this->maker = $maker; + + $this->path = $combustor->getAppPath(); + } + + /** + * @return void + */ + public function init() + { + $this->addArgument('table', 'Name of the database table'); + } + + /** + * @return boolean + */ + public function isEnabled() + { + return $this->driver !== null; + } + + /** + * @param boolean $doctrine + * @param boolean $wildfire + * + * @return integer + * @throws \Exception + */ + protected function getInstalled($doctrine, $wildfire) + { + $class = 'Rougin\Credo\Credo'; + $doctrineExists = class_exists($class); + + $class = 'Rougin\Wildfire\Wildfire'; + $wildfireExists = class_exists($class); + + /** + * If --doctrine or --wildfire not specified + */ + if (! $doctrine && ! $wildfire) + { + /** + * If not specified as option and packages are not yet installed + */ + if (! $doctrineExists && ! $wildfireExists) + { + $text = 'Both "rougin/credo" and "rougin/wildfire" are not installed.'; + + throw new \Exception($text . ' Kindly "rougin/credo" or "rougin/wildfire" first.'); + } + + /** + * If both installed and not specified as option + */ + if ($doctrineExists && $wildfireExists) + { + $text = 'Both "rougin/credo" and "rougin/wildfire" are installed.'; + + throw new \Exception($text . ' Kindly select --doctrine or --wildfire first.'); + } + } + + if (! $wildfire && ($doctrine || $doctrineExists)) + { + return self::TYPE_DOCTRINE; + } + + return self::TYPE_WILDFIRE; + } + + /** + * @param integer $type + * + * @return \Rougin\Classidy\Classidy + */ + protected function getTemplate($type) + { + /** @var string */ + $table = $this->getArgument('table'); + + $isModel = $this->name === 'create:model'; + + /** @var \Rougin\Describe\Driver\DriverInterface */ + $driver = $this->driver; + + $cols = $driver->columns($table); + + if ($isModel && $type === self::TYPE_DOCTRINE) + { + return new DoctrineModel($table, $cols, $this->excluded); + } + + if ($isModel && $type === self::TYPE_WILDFIRE) + { + return new WildfireModel($table, $cols, $this->excluded); + } + + return new Controller($table, $type); + } +} diff --git a/src/Commands/AbstractCommand.php b/src/Commands/AbstractCommand.php deleted file mode 100644 index 311f7ce..0000000 --- a/src/Commands/AbstractCommand.php +++ /dev/null @@ -1,99 +0,0 @@ - - */ -abstract class AbstractCommand extends Command -{ - /** - * @var string - */ - protected $command = ''; - - /** - * @var \Rougin\Describe\Describe - */ - protected $describe; - - /** - * @var \Twig_Environment - */ - protected $renderer; - - /** - * @param \Twig_Environment $renderer - * @param \Rougin\Describe\Describe $describe - */ - public function __construct(Describe $describe, Twig_Environment $renderer) - { - parent::__construct(); - - $this->describe = $describe; - $this->renderer = $renderer; - } - - /** - * Set the configurations of the specified command - * - * @return void - */ - protected function configure() - { - $this->setName('create:' . $this->command) - ->setDescription('Create a new ' . $this->command) - ->addArgument( - 'name', - InputArgument::REQUIRED, - 'Name of the table' - )->addOption( - 'bootstrap', - null, - InputOption::VALUE_NONE, - 'Includes the Bootstrap CSS/JS Framework tags' - )->addOption( - 'camel', - null, - InputOption::VALUE_NONE, - 'Uses the camel case naming convention' - )->addOption( - 'keep', - null, - InputOption::VALUE_NONE, - 'Keeps the name to be used' - ); - - if ($this->command == 'controller') { - $this->addOption( - 'lowercase', - null, - InputOption::VALUE_NONE, - 'Keeps the first character of the name to lowercase' - ); - } - } - - /** - * Checks whether the command is enabled or not in the current environment. - * - * @return bool - */ - public function isEnabled() - { - return Tools::isCommandEnabled(); - } -} diff --git a/src/Commands/CreateControllerCommand.php b/src/Commands/CreateControllerCommand.php deleted file mode 100644 index 0ec21f2..0000000 --- a/src/Commands/CreateControllerCommand.php +++ /dev/null @@ -1,80 +0,0 @@ - - */ -class CreateControllerCommand extends AbstractCommand -{ - /** - * @var string - */ - protected $command = 'controller'; - - /** - * Executes the command. - * - * @param \Symfony\Component\Console\Input\InputInterface $input - * @param \Symfony\Component\Console\Output\OutputInterface $output - * @return object|\Symfony\Component\Console\Output\OutputInterface - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $fileName = ucfirst(plural($input->getArgument('name'))); - - if ($input->getOption('keep')) { - $fileName = ucfirst($input->getArgument('name')); - } - - $path = APPPATH . 'controllers' . DIRECTORY_SEPARATOR . $fileName . '.php'; - - $info = [ - 'name' => $fileName, - 'type' => 'controller', - 'path' => $path - ]; - - $validator = new ControllerValidator($input->getOption('camel'), $info); - - if ($validator->fails()) { - $message = $validator->getMessage(); - - return $output->writeln('' . $message . ''); - } - - $data = [ - 'file' => $info, - 'isCamel' => $input->getOption('camel'), - 'name' => $input->getArgument('name'), - 'title' => strtolower($fileName), - 'type' => $validator->getLibrary() - ]; - - $generator = new ControllerGenerator($this->describe, $data); - - $result = $generator->generate(); - $controller = $this->renderer->render('Controller.tpl', $result); - $message = 'The controller "' . $fileName . '" has been created successfully!'; - - $file = new File($path); - - $file->putContents($controller); - $file->close(); - - return $output->writeln('' . $message . ''); - } -} diff --git a/src/Commands/CreateLayout.php b/src/Commands/CreateLayout.php new file mode 100644 index 0000000..fac2599 --- /dev/null +++ b/src/Commands/CreateLayout.php @@ -0,0 +1,71 @@ + + */ +class CreateLayout extends Command +{ + /** + * @var string + */ + protected $name = 'create:layout'; + + /** + * @var string + */ + protected $description = 'Create a new header and footer file'; + + /** + * Configures the current command. + * + * @return void + */ + public function init() + { + $this->addOption('bootstrap', 'adds styling based on Bootstrap'); + } + + /** + * Executes the command. + * + * @return integer + */ + public function run() + { + /** @var boolean */ + $bootstrap = $this->getOption('bootstrap'); + + $path = $this->path . '/views/'; + + if (! is_dir($path . 'layout')) + { + mkdir($path . 'layout'); + } + + // Create the "header.php" file ---------- + $header = new HeaderPlate($bootstrap); + + $file = $path . 'layout/header.php'; + + file_put_contents($file, $header->make()); + // --------------------------------------- + + // Create the "footer.php" file ---------- + $footer = new FooterPlate($bootstrap); + + $file = $path . 'layout/footer.php'; + + file_put_contents($file, $footer->make()); + // --------------------------------------- + + return self::RETURN_SUCCESS; + } +} diff --git a/src/Commands/CreateLayoutCommand.php b/src/Commands/CreateLayoutCommand.php deleted file mode 100644 index c8aa26b..0000000 --- a/src/Commands/CreateLayoutCommand.php +++ /dev/null @@ -1,115 +0,0 @@ - - */ -class CreateLayoutCommand extends AbstractCommand -{ - /** - * Checks whether the command is enabled or not in the current environment. - * - * @return bool - */ - public function isEnabled() - { - return ! Tools::hasLayout(); - } - - /** - * Sets the configurations of the specified command. - * - * @return void - */ - protected function configure() - { - $this->setName('create:layout') - ->setDescription('Creates a new header and footer file') - ->addOption( - 'bootstrap', - null, - InputOption::VALUE_NONE, - 'Includes the Bootstrap CSS/JS Framework tags' - ); - } - - /** - * Executes the command. - * - * @param \Symfony\Component\Console\Input\InputInterface $input - * @param \Symfony\Component\Console\Output\OutputInterface $output - * @return object|\Symfony\Component\Console\Output\OutputInterface - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $layoutPath = APPPATH . 'views/layout'; - - $data = []; - - $data['bootstrapContainer'] = ''; - $data['scripts'] = []; - $data['styleSheets'] = []; - - $css = '//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css'; - - if (! is_dir('bower_components/font-awesome') && system('bower install font-awesome --save')) { - $css = ''; - } - - $data['styleSheets'][0] = $css; - - if ($input->getOption('bootstrap')) { - $data['bootstrapContainer'] = 'container'; - - $css = 'https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'; - $js = 'https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.js'; - $jquery = 'https://code.jquery.com/jquery-2.1.1.min.js'; - - if (! is_dir('bower_components/bootstrap') && system('bower install bootstrap#3.3.7 --save')) { - $css = ''; - $js = ''; - $jquery = ''; - } - - array_push($data['styleSheets'], $css); - array_push($data['scripts'], $jquery); - array_push($data['scripts'], $js); - } - - if (! @mkdir($layoutPath, 0777, true)) { - $message = 'The layout directory already exists!'; - - return $output->writeln('' . $message . ''); - } - - $header = $this->renderer->render('Views/Layout/header.tpl', $data); - $footer = $this->renderer->render('Views/Layout/footer.tpl', $data); - - $headerFile = new File($layoutPath . '/header.php'); - $footerFile = new File($layoutPath . '/footer.php'); - - $headerFile->putContents($header); - $footerFile->putContents($footer); - - $headerFile->close(); - $footerFile->close(); - - $message = 'The layout folder has been created successfully!'; - - return $output->writeln('' . $message . ''); - } -} diff --git a/src/Commands/CreateModel.php b/src/Commands/CreateModel.php new file mode 100644 index 0000000..ca58f8a --- /dev/null +++ b/src/Commands/CreateModel.php @@ -0,0 +1,86 @@ + + */ +class CreateModel extends Command +{ + /** + * @var string + */ + protected $name = 'create:model'; + + /** + * @var string + */ + protected $description = 'Create a new model'; + + /** + * Configures the current command. + * + * @return void + */ + public function init() + { + parent::init(); + + $this->addOption('doctrine', 'generates a Doctrine-based model'); + + $this->addOption('wildfire', 'generates a Wildfire-based model'); + } + + /** + * Executes the command. + * + * @return integer + */ + public function run() + { + /** @var string */ + $table = $this->getArgument('table'); + + /** @var boolean */ + $doctrine = $this->getOption('doctrine'); + + /** @var boolean */ + $wildfire = $this->getOption('wildfire'); + + try + { + $type = $this->getInstalled($doctrine, $wildfire); + } + catch (\Exception $e) + { + $this->showFail($e->getMessage()); + + return self::RETURN_FAILURE; + } + + // Create the model file -------------------- + $name = Inflector::singular($table); + + $name = ucfirst(Inflector::singular($table)); + + $path = $this->path . '/models/'; + + $file = $path . $name . '.php'; + + $plate = $this->getTemplate($type); + + $plate = $this->maker->make($plate); + + file_put_contents($file, $plate); + // ------------------------------------------ + + $this->showPass('Model successfully created!'); + + return self::RETURN_SUCCESS; + } +} diff --git a/src/Commands/CreateModelCommand.php b/src/Commands/CreateModelCommand.php deleted file mode 100644 index 6c73e9e..0000000 --- a/src/Commands/CreateModelCommand.php +++ /dev/null @@ -1,104 +0,0 @@ - - */ -class CreateModelCommand extends AbstractCommand -{ - /** - * @var string - */ - protected $command = 'model'; - - /** - * Sets the configurations of the specified command. - * - * @return void - */ - protected function configure() - { - $this - ->setName('create:model') - ->setDescription('Creates a new model') - ->addArgument( - 'name', - InputArgument::REQUIRED, - 'Name of the table' - )->addOption( - 'camel', - null, - InputOption::VALUE_NONE, - 'Uses the camel case naming convention' - )->addOption( - 'lowercase', - null, - InputOption::VALUE_NONE, - 'Keeps the first character of the name to lowercase' - ); - } - - /** - * Executes the command. - * - * @param \Symfony\Component\Console\Input\InputInterface $input - * @param \Symfony\Component\Console\Output\OutputInterface $output - * @return object|\Symfony\Component\Console\Output\OutputInterface - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $fileName = ucfirst(singular($input->getArgument('name'))); - - $path = APPPATH . 'models' . DIRECTORY_SEPARATOR . $fileName . '.php'; - - $info = [ - 'name' => $fileName, - 'type' => 'model', - 'path' => $path - ]; - - $validator = new ModelValidator($input->getOption('camel'), $info); - - if ($validator->fails()) { - $message = $validator->getMessage(); - - return $output->writeln('' . $message . ''); - } - - $data = [ - 'file' => $info, - 'isCamel' => $input->getOption('camel'), - 'name' => $input->getArgument('name'), - 'type' => $validator->getLibrary() - ]; - - $generator = new ModelGenerator($this->describe, $data); - - $result = $generator->generate(); - $model = $this->renderer->render('Model.tpl', $result); - $message = 'The model "' . $fileName . '" has been created successfully!'; - - $file = new File($path); - - $file->putContents($model); - $file->close(); - - return $output->writeln('' . $message . ''); - } -} diff --git a/src/Commands/CreateRoute.php b/src/Commands/CreateRoute.php new file mode 100644 index 0000000..e7f959c --- /dev/null +++ b/src/Commands/CreateRoute.php @@ -0,0 +1,86 @@ + + */ +class CreateRoute extends Command +{ + /** + * @var string + */ + protected $name = 'create:controller'; + + /** + * @var string + */ + protected $description = 'Create a new HTTP controller'; + + /** + * Configures the current command. + * + * @return void + */ + public function init() + { + parent::init(); + + $this->addOption('doctrine', 'generates a Doctrine-based controller'); + + $this->addOption('wildfire', 'generates a Wildfire-based controller'); + } + + /** + * Executes the command. + * + * @return integer + */ + public function run() + { + /** @var string */ + $table = $this->getArgument('table'); + + /** @var boolean */ + $doctrine = $this->getOption('doctrine'); + + /** @var boolean */ + $wildfire = $this->getOption('wildfire'); + + try + { + $type = $this->getInstalled($doctrine, $wildfire); + } + catch (\Exception $e) + { + $this->showFail($e->getMessage()); + + return self::RETURN_FAILURE; + } + + // Create the controller file ------------- + $path = $this->path . '/controllers/'; + + $name = Inflector::plural($table); + + $name = ucfirst(Inflector::plural($table)); + + $file = $path . $name . '.php'; + + $plate = $this->getTemplate($type); + + $plate = $this->maker->make($plate); + + file_put_contents($file, $plate); + // ---------------------------------------- + + $this->showPass('Controller successfully created!'); + + return self::RETURN_SUCCESS; + } +} diff --git a/src/Commands/CreateScaffold.php b/src/Commands/CreateScaffold.php new file mode 100644 index 0000000..cb92f13 --- /dev/null +++ b/src/Commands/CreateScaffold.php @@ -0,0 +1,99 @@ + + */ +class CreateScaffold extends Command +{ + const TYPE_WILDFIRE = 0; + + const TYPE_DOCTRINE = 1; + + /** + * @var \Rougin\Describe\Driver\DriverInterface|null + */ + protected $driver = null; + + /** + * @var string + */ + protected $name = 'create:scaffold'; + + /** + * @var string + */ + protected $description = 'Create a new HTTP controller, model, and view templates'; + + /** + * Configures the current command. + * + * @return void + */ + public function init() + { + parent::init(); + + $this->addOption('bootstrap', 'adds styling based on Bootstrap'); + + $this->addOption('doctrine', 'generates a Doctrine-based controller, models, and views'); + + $this->addOption('wildfire', 'generates a Wildfire-based controller, models, and views'); + } + + /** + * Executes the command. + * + * @return integer + */ + public function run() + { + /** @var boolean */ + $doctrine = $this->getOption('doctrine'); + + /** @var boolean */ + $wildfire = $this->getOption('wildfire'); + + try + { + $this->getInstalled($doctrine, $wildfire); + } + catch (\Exception $e) + { + $this->showFail($e->getMessage()); + + return Command::RETURN_FAILURE; + } + + /** @var string */ + $table = $this->getArgument('table'); + + $input = array('table' => $table); + $input['--doctrine'] = $doctrine; + $input['--wildfire'] = $wildfire; + + // Execute the "create:controller" command ---- + $this->runCommand('create:controller', $input); + // -------------------------------------------- + + // Execute the "create:model" command ---- + $this->runCommand('create:model', $input); + // --------------------------------------- + + // Execute the "create:views" command ----- + /** @var boolean */ + $bootstrap = $this->getOption('bootstrap'); + + $input['--bootstrap'] = $bootstrap; + + $this->runCommand('create:views', $input); + // ---------------------------------------- + + return Command::RETURN_SUCCESS; + } +} diff --git a/src/Commands/CreateScaffoldCommand.php b/src/Commands/CreateScaffoldCommand.php deleted file mode 100644 index 5313fa8..0000000 --- a/src/Commands/CreateScaffoldCommand.php +++ /dev/null @@ -1,120 +0,0 @@ - - */ -class CreateScaffoldCommand extends AbstractCommand -{ - /** - * Checks whether the command is enabled or not in the current environment. - * - * @return bool - */ - public function isEnabled() - { - return Tools::isCommandEnabled(); - } - - /** - * Sets the configurations of the specified command. - * - * @return void - */ - protected function configure() - { - $this->setName('create:scaffold') - ->setDescription('Creates a new controller, model and view') - ->addArgument( - 'name', - InputArgument::REQUIRED, - 'Name of the table' - )->addOption( - 'bootstrap', - null, - InputOption::VALUE_NONE, - 'Includes the Bootstrap CSS/JS Framework tags' - )->addOption( - 'camel', - null, - InputOption::VALUE_NONE, - 'Uses the camel case naming convention' - )->addOption( - 'keep', - null, - InputOption::VALUE_NONE, - 'Keeps the name to be used' - )->addOption( - 'lowercase', - null, - InputOption::VALUE_NONE, - 'Keeps the first character of the name to lowercase' - ); - } - - /** - * Executes the command. - * - * @param \Symfony\Component\Console\Input\InputInterface $input - * @param \Symfony\Component\Console\Output\OutputInterface $output - * @return object|\Symfony\Component\Console\Output\OutputInterface - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $commands = [ - 'create:controller', - 'create:model', - 'create:view' - ]; - - $bootstrap = $input->getOption('bootstrap'); - $camel = $input->getOption('camel'); - $keep = $input->getOption('keep'); - $lowercase = $input->getOption('lowercase'); - - foreach ($commands as $command) { - $arguments = [ - 'command' => $command, - 'name' => $input->getArgument('name') - ]; - - switch ($command) { - case 'create:controller': - case 'create:model': - $arguments['--camel'] = $camel; - $arguments['--lowercase'] = $lowercase; - - break; - case 'create:view': - $arguments['--bootstrap'] = $bootstrap; - $arguments['--camel'] = $camel; - $arguments['--keep'] = $keep; - - break; - } - - if ($command == 'create:controller') { - $arguments['--keep'] = $keep; - } - - $input = new ArrayInput($arguments); - - $application = $this->getApplication()->find($command); - $application->run($input, $output); - } - } -} diff --git a/src/Commands/CreateView.php b/src/Commands/CreateView.php new file mode 100644 index 0000000..c16dbe4 --- /dev/null +++ b/src/Commands/CreateView.php @@ -0,0 +1,126 @@ + + */ +class CreateView extends Command +{ + /** + * @var string + */ + protected $name = 'create:views'; + + /** + * @var string + */ + protected $description = 'Create view templates'; + + /** + * Configures the current command. + * + * @return void + */ + public function init() + { + parent::init(); + + $this->addOption('bootstrap', 'adds styling based on Bootstrap'); + + $this->addOption('doctrine', 'generates Doctrine-based views'); + + $this->addOption('wildfire', 'generates Wildfire-based views'); + } + + /** + * Executes the command. + * + * @return integer + */ + public function run() + { + /** @var string */ + $table = $this->getArgument('table'); + + /** @var boolean */ + $doctrine = $this->getOption('doctrine'); + + /** @var boolean */ + $wildfire = $this->getOption('wildfire'); + + try + { + $type = $this->getInstalled($doctrine, $wildfire); + } + catch (\Exception $e) + { + $this->showFail($e->getMessage()); + + return self::RETURN_FAILURE; + } + + /** @var \Rougin\Describe\Driver\DriverInterface */ + $describe = $this->driver; + + $cols = $describe->columns($table); + + $name = Inflector::plural($table); + + $path = $this->path . '/views/'; + + if (! is_dir($path . $name)) + { + mkdir($path . $name); + } + + /** @var boolean */ + $bootstrap = $this->getOption('bootstrap'); + + // Create the "create.php" file --------------------------------- + $create = new CreatePlate($table, $type, $cols); + + $create->withBootstrap($bootstrap); + + $create->withExcluded($this->excluded); + + $file = $path . $name . '/create.php'; + + file_put_contents($file, $create->make(' ')); + // -------------------------------------------------------------- + + // Create the "edit.php" file ------------------------------- + $edit = new EditPlate($table, $type, $cols); + + $edit->withBootstrap($bootstrap); + + $edit->withExcluded($this->excluded); + + $file = $path . $name . '/edit.php'; + + file_put_contents($file, $edit->make(' ')); + // ---------------------------------------------------------- + + // Create the "index.php" file --------------- + $index = new IndexPlate($table, $type, $cols); + + $index->withBootstrap($bootstrap); + + $file = $path . $name . '/index.php'; + + file_put_contents($file, $index->make(' ')); + // ------------------------------------------- + + $this->showPass('Views successfully created!'); + + return self::RETURN_SUCCESS; + } +} diff --git a/src/Commands/CreateViewCommand.php b/src/Commands/CreateViewCommand.php deleted file mode 100644 index 72cfc56..0000000 --- a/src/Commands/CreateViewCommand.php +++ /dev/null @@ -1,89 +0,0 @@ - - */ -class CreateViewCommand extends AbstractCommand -{ - /** - * @var string - */ - protected $command = 'view'; - - /** - * Executes the command. - * - * @param \Symfony\Component\Console\Input\InputInterface $input - * @param \Symfony\Component\Console\Output\OutputInterface $output - * @return object|\Symfony\Component\Console\Output\OutputInterface - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $name = Tools::stripTableSchema(plural($input->getArgument('name'))); - - if ($input->getOption('keep')) { - $name = Tools::stripTableSchema($input->getArgument('name')); - } - - $validator = new ViewValidator($name); - - if ($validator->fails()) { - $message = $validator->getMessage(); - - return $output->writeln('' . $message . ''); - } - - $data = [ - 'isBootstrap' => $input->getOption('bootstrap'), - 'isCamel' => $input->getOption('camel'), - 'name' => $input->getArgument('name') - ]; - - $generator = new ViewGenerator($this->describe, $data); - - $result = $generator->generate(); - - $results = [ - 'create' => $this->renderer->render('Views/create.tpl', $result), - 'edit' => $this->renderer->render('Views/edit.tpl', $result), - 'index' => $this->renderer->render('Views/index.tpl', $result), - 'show' => $this->renderer->render('Views/show.tpl', $result) - ]; - - $filePath = APPPATH . 'views/' . $name; - - $create = new File($filePath . '/create.php'); - $edit = new File($filePath . '/edit.php'); - $index = new File($filePath . '/index.php'); - $show = new File($filePath . '/show.php'); - - $create->putContents($results['create']); - $edit->putContents($results['edit']); - $index->putContents($results['index']); - $show->putContents($results['show']); - - $create->close(); - $edit->close(); - $index->close(); - $show->close(); - - $message = 'The views folder "' . $name . '" has been created successfully!'; - - return $output->writeln('' . $message . ''); - } -} diff --git a/src/Commands/CreateYaml.php b/src/Commands/CreateYaml.php new file mode 100644 index 0000000..e2c92a1 --- /dev/null +++ b/src/Commands/CreateYaml.php @@ -0,0 +1,43 @@ + + */ +class CreateYaml extends InitializeCommand +{ + /** + * @var string + */ + protected $file = 'combustor.yml'; + + /** + * Returns the source directory for the specified file. + * + * @return string + */ + protected function getPlatePath() + { + /** @var string */ + return realpath(__DIR__ . '/../Template'); + } + + /** + * Returns the root directory from the package. + * + * @return string + */ + protected function getRootPath() + { + $root = (string) __DIR__ . '/../../../../../'; + + $exists = file_exists($root . '/vendor/autoload.php'); + + return $exists ? $root : __DIR__ . '/../../'; + } +} diff --git a/src/Commands/InstallDoctrine.php b/src/Commands/InstallDoctrine.php new file mode 100644 index 0000000..ab7d6ba --- /dev/null +++ b/src/Commands/InstallDoctrine.php @@ -0,0 +1,79 @@ + + */ +class InstallDoctrine extends Command +{ + /** + * @var string + */ + protected $name = 'install:doctrine'; + + /** + * @var string + */ + protected $description = 'Install the Doctrine package'; + + /** + * @var string + */ + protected $path = ''; + + /** + * @param \Rougin\Combustor\Combustor $combustor + */ + public function __construct(Combustor $combustor) + { + $this->path = $combustor->getAppPath(); + } + + /** + * Checks whether the command is enabled or not in the current environment. + * + * @return boolean + */ + public function isEnabled() + { + return ! class_exists('Rougin\Credo\Credo'); + } + + /** + * Executes the command. + * + * @return integer + */ + public function run() + { + system('composer require rougin/credo'); + + $class = new Classidy; + + $class->setName('MY_Loader'); + $class->extendsTo('Rougin\Credo\Loader'); + + $maker = new Generator; + + $result = $maker->make($class); + + $file = $this->path . '/core/Loader.php'; + + if (! file_exists($file)) + { + file_put_contents($file, $result); + } + + $this->showPass('Doctrine installed successfully!'); + + return self::RETURN_SUCCESS; + } +} diff --git a/src/Commands/InstallDoctrineCommand.php b/src/Commands/InstallDoctrineCommand.php deleted file mode 100644 index 8840330..0000000 --- a/src/Commands/InstallDoctrineCommand.php +++ /dev/null @@ -1,85 +0,0 @@ - - */ -class InstallDoctrineCommand extends InstallCommand -{ - /** - * @var string - */ - protected $library = 'doctrine'; - - /** - * Executes the command. - * - * @param \Symfony\Component\Console\Input\InputInterface $input - * @param \Symfony\Component\Console\Output\OutputInterface $output - * @return object|\Symfony\Component\Console\Output\OutputInterface - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - system('composer require doctrine/orm'); - - $cli = $this->renderer->render('DoctrineCLI.tpl'); - $doctrine = new File(APPPATH . 'libraries/Doctrine.php'); - $template = $this->renderer->render('Libraries/Doctrine.tpl'); - $vendor = realpath('vendor'); - - // Modifies the contents of vendor/bin/doctrine.php, creates the - // Doctrine library and creates a "proxies" directory for lazy loading. - file_put_contents($vendor . '/bin/doctrine.php', $cli); - file_put_contents($vendor . '/doctrine/orm/bin/doctrine.php', $cli); - - $doctrine->putContents($template); - $doctrine->close(); - - $this->addLibrary('doctrine'); - - if (! is_dir(APPPATH . 'models/proxies')) { - mkdir(APPPATH . 'models/proxies'); - chmod(APPPATH . 'models/proxies', 0777); - } - - $abstractCommandPath = $vendor . '/doctrine/orm/lib/Doctrine/ORM/' . - 'Tools/Console/Command/SchemaTool/AbstractCommand.php'; - - // Includes the Base Model class in Doctrine CLI - $abstractCommand = file_get_contents($abstractCommandPath); - - $search = 'use Doctrine\ORM\Tools\SchemaTool;'; - $replace = $search . "\n" . 'include BASEPATH . \'core/Model.php\';'; - - $contents = $abstractCommand; - $schemaTool = 'use Doctrine\ORM\Tools\SchemaTool;'; - $coreModel = 'include BASEPATH . \'core/Model.php\';'; - - if (strpos($abstractCommand, $schemaTool) !== false) { - if (strpos($abstractCommand, $coreModel) === false) { - $contents = str_replace($search, $replace, $abstractCommand); - } - } - - file_put_contents($abstractCommandPath, $contents); - - Tools::ignite(); - - $message = 'Doctrine ORM is now installed successfully!'; - - return $output->writeln('' . $message . ''); - } -} diff --git a/src/Commands/InstallWildfire.php b/src/Commands/InstallWildfire.php new file mode 100644 index 0000000..043f25d --- /dev/null +++ b/src/Commands/InstallWildfire.php @@ -0,0 +1,47 @@ + + */ +class InstallWildfire extends Command +{ + /** + * @var string + */ + protected $name = 'install:wildfire'; + + /** + * @var string + */ + protected $description = 'Install the Wildfire package'; + + /** + * Checks whether the command is enabled or not in the current environment. + * + * @return boolean + */ + public function isEnabled() + { + return ! class_exists('Rougin\Wildfire\Wildfire'); + } + + /** + * Executes the command. + * + * @return integer + */ + public function run() + { + system('composer require rougin/wildfire'); + + $this->showPass('Wildfire installed successfully!'); + + return self::RETURN_SUCCESS; + } +} diff --git a/src/Commands/InstallWildfireCommand.php b/src/Commands/InstallWildfireCommand.php deleted file mode 100644 index 2a1999b..0000000 --- a/src/Commands/InstallWildfireCommand.php +++ /dev/null @@ -1,50 +0,0 @@ - - */ -class InstallWildfireCommand extends InstallCommand -{ - /** - * @var string - */ - protected $library = 'wildfire'; - - /** - * Executes the command. - * - * @param \Symfony\Component\Console\Input\InputInterface $input - * @param \Symfony\Component\Console\Output\OutputInterface $output - * @return object|\Symfony\Component\Console\Output\OutputInterface - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $this->addLibrary('wildfire'); - - $template = $this->renderer->render('Libraries/Wildfire.tpl'); - $wildfire = new File(APPPATH . 'libraries/Wildfire.php'); - - $wildfire->putContents($template); - $wildfire->close(); - - Tools::ignite(); - - $message = 'Wildfire is now installed successfully!'; - - return $output->writeln('' . $message . ''); - } -} diff --git a/src/Commands/RemoveDoctrine.php b/src/Commands/RemoveDoctrine.php new file mode 100644 index 0000000..9849a04 --- /dev/null +++ b/src/Commands/RemoveDoctrine.php @@ -0,0 +1,68 @@ + + */ +class RemoveDoctrine extends Command +{ + /** + * @var string + */ + protected $name = 'remove:doctrine'; + + /** + * @var string + */ + protected $description = 'Remove the Doctrine package'; + + /** + * @var string + */ + protected $path = ''; + + /** + * @param \Rougin\Combustor\Combustor $combustor + */ + public function __construct(Combustor $combustor) + { + $this->path = $combustor->getAppPath(); + } + + /** + * Checks whether the command is enabled or not in the current environment. + * + * @return boolean + */ + public function isEnabled() + { + return class_exists('Rougin\Credo\Credo'); + } + + /** + * Executes the command. + * + * @return integer + */ + public function run() + { + system('composer remove rougin/credo'); + + $file = $this->path . '/core/Loader.php'; + + if (file_exists($file)) + { + unlink($file); + } + + $this->showPass('Doctrine removed successfully!'); + + return self::RETURN_SUCCESS; + } +} diff --git a/src/Commands/RemoveDoctrineCommand.php b/src/Commands/RemoveDoctrineCommand.php deleted file mode 100644 index f9dfd7f..0000000 --- a/src/Commands/RemoveDoctrineCommand.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -class RemoveDoctrineCommand extends RemoveCommand -{ - /** - * @var string - */ - protected $library = 'doctrine'; -} diff --git a/src/Commands/RemoveWildfire.php b/src/Commands/RemoveWildfire.php new file mode 100644 index 0000000..f4c3493 --- /dev/null +++ b/src/Commands/RemoveWildfire.php @@ -0,0 +1,47 @@ + + */ +class RemoveWildfire extends Command +{ + /** + * @var string + */ + protected $name = 'remove:wildfire'; + + /** + * @var string + */ + protected $description = 'Remove the Wildfire package'; + + /** + * Checks whether the command is enabled or not in the current environment. + * + * @return boolean + */ + public function isEnabled() + { + return class_exists('Rougin\Wildfire\Wildfire'); + } + + /** + * Executes the command. + * + * @return integer + */ + public function run() + { + system('composer remove rougin/wildfire'); + + $this->showPass('Wildfire removed successfully!'); + + return self::RETURN_SUCCESS; + } +} diff --git a/src/Commands/RemoveWildfireCommand.php b/src/Commands/RemoveWildfireCommand.php deleted file mode 100644 index b04e035..0000000 --- a/src/Commands/RemoveWildfireCommand.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -class RemoveWildfireCommand extends RemoveCommand -{ - /** - * @var string - */ - protected $library = 'wildfire'; -} diff --git a/src/Common/Commands/InstallCommand.php b/src/Common/Commands/InstallCommand.php deleted file mode 100644 index 68a6ea7..0000000 --- a/src/Common/Commands/InstallCommand.php +++ /dev/null @@ -1,70 +0,0 @@ - - */ -class InstallCommand extends AbstractCommand -{ - /** - * @var string - */ - protected $library = ''; - - /** - * Checks whether the command is enabled or not in the current environment. - * - * @return boolean - */ - public function isEnabled() - { - $library = ($this->library == 'doctrine') ? 'Wildfire' : 'Doctrine'; - - return ! file_exists(APPPATH . 'libraries/' . $library . '.php'); - } - - /** - * Sets the configurations of the specified command. - * - * @return void - */ - protected function configure() - { - $this - ->setName('install:' . $this->library) - ->setDescription('Installs ' . ucfirst($this->library)); - } - - /** - * Adds the specified library in the autoload.php. - * - * @param string $library - * @return void - */ - protected function addLibrary($library) - { - $autoload = new Config('autoload', APPPATH . 'config'); - - $libraries = $autoload->get('libraries', 60, 'array'); - - if (! in_array($library, $libraries)) { - array_push($libraries, $library); - - $autoload->set('libraries', 60, $libraries, 'array'); - $autoload->save(); - } - } -} diff --git a/src/Common/Commands/RemoveCommand.php b/src/Common/Commands/RemoveCommand.php deleted file mode 100644 index f30b5d0..0000000 --- a/src/Common/Commands/RemoveCommand.php +++ /dev/null @@ -1,86 +0,0 @@ - - */ -class RemoveCommand extends AbstractCommand -{ - /** - * @var string - */ - protected $library = ''; - - /** - * Checks whether the command is enabled or not in the current environment. - * - * Override this to check for x or y and return false if the command can not - * run properly under the current conditions. - * - * @return bool - */ - public function isEnabled() - { - $file = APPPATH . 'libraries/' . $this->library . '.php'; - - return file_exists($file); - } - - /** - * Sets the configurations of the specified command. - * - * @return void - */ - protected function configure() - { - $this - ->setName('remove:' . $this->library) - ->setDescription('Removes ' . ucfirst($this->library)); - } - - /** - * Executes the command. - * - * @param \Symfony\Component\Console\Input\InputInterface $input - * @param \Symfony\Component\Console\Output\OutputInterface $output - * @return OutputInterface - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $autoload = new Config('autoload', APPPATH . 'config'); - - $libraries = $autoload->get('libraries', 60, 'array'); - - if (in_array($this->library, $libraries)) { - $position = array_search($this->library, $libraries); - - unset($libraries[$position]); - - $autoload->set('libraries', 60, $libraries, 'array'); - $autoload->save(); - } - - if ($this->library == 'doctrine') { - system('composer remove doctrine/orm'); - } - - unlink(APPPATH . 'libraries/' . ucfirst($this->library) . '.php'); - - $message = ucfirst($this->library) . ' is now successfully removed!'; - - return $output->writeln('' . $message . ''); - } -} diff --git a/src/Common/Config.php b/src/Common/Config.php deleted file mode 100644 index 7300021..0000000 --- a/src/Common/Config.php +++ /dev/null @@ -1,183 +0,0 @@ - - */ -class Config -{ - /** - * @var string - */ - protected $config; - - /** - * @var string - */ - public $fileName; - - /** - * @var array - */ - protected $lines; - - /** - * @param string $config - * @param string $configPath - */ - public function __construct($config, $configPath) - { - $this->config = $config; - $this->fileName = $configPath . '/' . $config . '.php'; - - $content = file_get_contents($this->fileName); - - $this->lines = preg_split("/\\r\\n|\\r|\\n/", $content); - } - - /** - * Returns the specified value from the config item. - * - * @param string $item - * @param integer $line - * @param string $dataType - * @return mixed - */ - public function get($item, $line, $dataType) - { - $result = null; - $value = null; - - switch ($dataType) { - case 'array': - $value = 'array\((.*?)\)'; - - break; - case 'boolean': - $value = '(true|TRUE|false|FALSE)'; - - break; - case 'string': - $value = '(.*?)'; - - break; - } - - $pattern = '/\$' . $this->config . '\[\'' . $item . '\'\] = ' . $value . ';/'; - - preg_match_all($pattern, $this->lines[$line], $match); - - switch ($dataType) { - case 'array': - $result = array_filter($match[1]); - $data = ''; - - if (! empty($result[0])) { - $data = $result[0]; - } - - $result = array_filter(explode(',', $data)); - $length = count($result); - - for ($i = 0; $i < $length; $i++) { - $result[$i] = str_replace(['\'', '"'], '', trim($result[$i])); - } - - break; - case 'boolean': - $result = $match[1][0] == 'TRUE'; - - break; - case 'string': - $result = $match[1][0]; - - if ($result == '\'\'') { - $result = null; - } - - if ($result[0] == '\'' && $result[strlen($result) - 1] == '\'') { - $result = substr($result, 1, strlen($result) - 2); - } - - break; - } - - return $result; - } - - /** - * Sets an value to an item in the config. - * - * @param string $item - * @param integer $line - * @param mixed $value - * @param string $dataType - * @param boolean $exact - */ - public function set($item, $line, $value, $dataType, $exact = false) - { - $data = null; - $format = null; - - switch ($dataType) { - case 'array': - $length = count($value); - - for ($i = 0; $i < $length; $i++) { - $value[$i] = '\'' . $value[$i] . '\''; - } - - $data = 'array(' . implode(', ', $value) . ')'; - $format = 'array\([^)]*\)'; - - break; - case 'boolean': - $data = ($value) ? 'TRUE' : 'FALSE'; - $format = '[^)]*'; - - break; - case 'string': - $data = '\'' . $value . '\''; - $format = '(.*?)'; - - break; - } - - if ($exact) { - $data = $value; - } - - $pattern = '/\$' . $this->config . '\[\'' . $item . '\'\] = ' . $format . ';/'; - $replacement = '$' . $this->config . '[\'' . $item . '\'] = ' . $data . ';'; - - $result = preg_replace($pattern, $replacement, $this->lines[$line]); - - $this->lines[$line] = $result; - } - - /** - * Saves the current config. - * - * @return void - */ - public function save() - { - file_put_contents($this->fileName, (string) $this); - } - - /** - * Returns the whole class into a string. - * - * @return string - */ - public function __toString() - { - return implode(PHP_EOL, $this->lines); - } -} diff --git a/src/Common/File.php b/src/Common/File.php deleted file mode 100644 index c27a580..0000000 --- a/src/Common/File.php +++ /dev/null @@ -1,76 +0,0 @@ - - */ -class File -{ - /** - * @var resource - */ - protected $file; - - /** - * @var string - */ - protected $path; - - /** - * @param string $path - * @param string $mode - */ - public function __construct($path, $mode = 'wb') - { - $this->path = $path; - $this->file = fopen($path, $mode); - } - - /** - * Closes an open file pointer. - * - * @return boolean - */ - public function close() - { - return fclose($this->file); - } - - /** - * Reads entire file into a string. - * - * @return string - */ - public function getContents() - { - return file_get_contents($this->path); - } - - /** - * Writes a string to a file. - * - * @param string $content - * @return integer|boolean - */ - public function putContents($content) - { - return file_put_contents($this->path, $content); - } - - /** - * Changes the file mode of the file. - * - * @param integer $mode - * @return boolean - */ - public function chmod($mode) - { - return chmod($this->path, $mode); - } -} diff --git a/src/Common/Tools.php b/src/Common/Tools.php deleted file mode 100644 index a92b2d4..0000000 --- a/src/Common/Tools.php +++ /dev/null @@ -1,134 +0,0 @@ - - */ -class Tools -{ - /** - * Checks whether the header and footer file exists. - * - * @return bool - */ - public static function hasLayout() - { - $header = APPPATH . 'views/layout/header.php'; - $footer = APPPATH . 'views/layout/footer.php'; - - return file_exists($header) && file_exists($footer); - } - - /** - * "Ignites" the post installation process. - * - * @return void - */ - public static function ignite() - { - $autoloadPath = 'realpath(\'vendor\') . \'/autoload.php\''; - $configPath = APPPATH . 'config'; - $templatePath = __DIR__ . '/../Templates'; - - // Gets data from application/config/config.php - $config = new Config('config', $configPath); - - $config->set('composer_autoload', 138, $autoloadPath, 'string', true); - $config->set('index_page', 37, '', 'string'); - $config->set('encryption_key', 316, md5('rougin'), 'string'); - - $config->save(); - - // Gets data from application/config/autoload.php - $autoload = new Config('autoload', $configPath); - - // Gets the currently included drivers. - $drivers = $autoload->get('drivers', 81, 'array'); - - // Includes "session" driver. - if (! in_array('session', $drivers)) { - array_push($drivers, 'session'); - } - - // Gets the currently included helpers - $defaultHelpers = [ 'form', 'url' ]; - $helpers = $autoload->get('helper', 91, 'array'); - - foreach ($defaultHelpers as $helper) { - if (! in_array($helper, $helpers)) { - array_push($helpers, $helper); - } - } - - $autoload->set('drivers', 81, $drivers, 'array'); - $autoload->set('helper', 91, $helpers, 'array'); - - $autoload->save(); - - $templates = [ - [ - 'file' => '.htaccess', - 'name' => 'Htaccess' - ], - [ - 'file' => APPPATH . 'config/pagination.php', - 'name' => 'Pagination' - ] - ]; - - foreach ($templates as $template) { - $file = new File($template['file']); - $path = $templatePath . '/' . $template['name'] . '.tpl'; - - if ($template['file'] == '.htaccess') { - $file->chmod(0777); - } - - $file->putContents(file_get_contents($path)); - $file->close(); - } - } - - /** - * Checks whether the command is enabled or not in the current environment. - * - * @return bool - */ - public static function isCommandEnabled() - { - $doctrine = APPPATH . 'libraries/Doctrine.php'; - $wildfire = APPPATH . 'libraries/Wildfire.php'; - - return file_exists($doctrine) || file_exists($wildfire); - } - - /** - * Strips the table schema from the table name. - * - * @param string $table - * @return string - */ - public static function stripTableSchema($table) - { - return (strpos($table, '.') !== false) - ? substr($table, strpos($table, '.') + 1) - : $table; - } - - /** - * Strips the table schema from the table name. - * - * @param string $table - * @return string - */ - public static function strip_table_schema($table) - { - return self::stripTableSchema($table); - } -} diff --git a/src/Console.php b/src/Console.php new file mode 100644 index 0000000..65bc202 --- /dev/null +++ b/src/Console.php @@ -0,0 +1,149 @@ + + */ +class Console extends Blueprint +{ + /** + * @var string + */ + protected $name = 'Combustor'; + + /** + * @var string + */ + protected $file = 'combustor.yml'; + + /** + * @var string + */ + protected $root; + + /** + * @var string + */ + protected $version = '1.3.0'; + + /** + * @param string $root + */ + public function __construct($root) + { + $namespace = __NAMESPACE__ . '\Commands'; + + $this->setCommandNamespace($namespace); + + $this->setCommandPath(__DIR__ . '/Commands'); + + $this->root = $root; + + $this->setPackages(); + } + + /** + * @return string + */ + public function getAppPath() + { + /** @var string */ + $path = realpath($this->root); + + if (! file_exists($path . '/combustor.yml')) + { + return $path; + } + + $parsed = $this->getParsed(); + + if (array_key_exists('app_path', $parsed)) + { + /** @var string */ + $path = $parsed['app_path']; + } + + /** @var string */ + return realpath($path); + } + + /** + * @return string[] + */ + public function getExcluded() + { + $parsed = $this->getParsed(); + + $field = 'excluded_fields'; + + if (! array_key_exists($field, $parsed)) + { + return array(); + } + + /** @var string[] */ + return $parsed[$field]; + } + + /** + * @return array + */ + protected function getParsed() + { + /** @var string */ + $path = realpath($this->root); + + if (! file_exists($path . '/' . $this->file)) + { + return array(); + } + + $file = $path . '/' . $this->file; + + /** @var string */ + $file = file_get_contents($file); + + // Replace the constant with root path ---- + $search = '%%CURRENT_DIRECTORY%%'; + + $file = str_replace($search, $path, $file); + // ---------------------------------------- + + /** @var array */ + return Yaml::parse($file); + } + + /** + * @return void + */ + protected function setPackages() + { + $container = new Container; + + $path = $this->getAppPath(); + + $sparkPlug = new SparkplugPackage($path); + $container->addPackage($sparkPlug); + + $describe = new DescribePackage; + $container->addPackage($describe); + + $combustor = new CombustorPackage($path); + $excluded = $this->getExcluded(); + + $combustor->setExcluded($excluded); + $container->addPackage($combustor); + + $this->setContainer($container); + } +} diff --git a/src/Generator/BaseGenerator.php b/src/Generator/BaseGenerator.php deleted file mode 100644 index d7c508c..0000000 --- a/src/Generator/BaseGenerator.php +++ /dev/null @@ -1,81 +0,0 @@ - - */ -class BaseGenerator -{ - /** - * @var \Rougin\Describe\Describe - */ - protected $describe; - - /** - * @var array - */ - protected $data = []; - - /** - * @param \Rougin\Describe\Describe $describe - * @param array $data - */ - public function __construct(Describe $describe, array $data) - { - $this->describe = $describe; - $this->data = $data; - } - - /** - * Gets the primary keys based on specified field. - * - * @param array $data - * @param string $field - * @param string $referencedTable - * @return array - */ - protected function getPrimaryKey(array $data, $field, $referencedTable) - { - $accessor = 'get_' . $this->describe->getPrimaryKey($referencedTable); - - $data['primaryKeys'][$field] = $accessor; - - if ($data['isCamel']) { - $camelized = camelize($data['primaryKeys'][$field]); - - $data['primaryKeys'][$field] = $camelized; - } - - return $data; - } - - /** - * Transforms the field into the template. - * - * @param string $field - * @param string $type - * @return array - */ - protected function transformField($field, $type) - { - if ($type == 'camelize') { - return [ - 'field' => lcfirst(camelize($field)), - 'accessor' => lcfirst(camelize('get_' . $field)), - 'mutator' => lcfirst(camelize('set_' . $field)) - ]; - } - - return [ - 'field' => lcfirst(underscore($field)), - 'accessor' => lcfirst(underscore('get_' . $field)), - 'mutator' => lcfirst(underscore('set_' . $field)) - ]; - } -} diff --git a/src/Generator/ControllerGenerator.php b/src/Generator/ControllerGenerator.php deleted file mode 100644 index 36f842b..0000000 --- a/src/Generator/ControllerGenerator.php +++ /dev/null @@ -1,88 +0,0 @@ - - */ -class ControllerGenerator extends BaseGenerator implements GeneratorInterface -{ - /** - * Prepares the data before generation. - * - * @param array &$data - * @return void - */ - public function prepareData(array &$data) - { - $data['camel'] = []; - $data['columns'] = []; - $data['dropdowns'] = []; - $data['foreignKeys'] = []; - $data['models'] = [$data['name']]; - $data['plural'] = plural($data['name']); - $data['singular'] = singular($data['name']); - $data['underscore'] = []; - } - - /** - * Generates set of code based on data. - * - * @return array - */ - public function generate() - { - $this->prepareData($this->data); - - $columnFields = ['name', 'description', 'label']; - - $table = $this->describe->getTable($this->data['name']); - - foreach ($table as $column) { - if ($column->isAutoIncrement()) { - continue; - } - - $field = strtolower($column->getField()); - $method = 'set_' . $field; - - $this->data['camel'][$field] = lcfirst(camelize($method)); - $this->data['underscore'][$field] = underscore($method); - - array_push($this->data['columns'], $field); - - if ($column->isForeignKey()) { - $referencedTable = Tools::stripTableSchema( - $column->getReferencedTable() - ); - - $this->data['foreignKeys'][$field] = $referencedTable; - - array_push($this->data['models'], $referencedTable); - - $dropdown = [ - 'list' => plural($referencedTable), - 'table' => $referencedTable, - 'field' => $field - ]; - - if (! in_array($field, $columnFields)) { - $field = $this->describe->getPrimaryKey($referencedTable); - - $dropdown['field'] = $field; - } - - array_push($this->data['dropdowns'], $dropdown); - } - } - - return $this->data; - } -} diff --git a/src/Generator/GeneratorInterface.php b/src/Generator/GeneratorInterface.php deleted file mode 100644 index 48f7030..0000000 --- a/src/Generator/GeneratorInterface.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -interface GeneratorInterface -{ - /** - * Generates set of code based on data. - * - * @return array - */ - public function generate(); -} diff --git a/src/Generator/ModelGenerator.php b/src/Generator/ModelGenerator.php deleted file mode 100644 index 4f5997f..0000000 --- a/src/Generator/ModelGenerator.php +++ /dev/null @@ -1,76 +0,0 @@ - - */ -class ModelGenerator extends BaseGenerator implements GeneratorInterface -{ - /** - * Prepares the data before generation. - * - * @param array &$data - * @return void - */ - public function prepareData(array &$data) - { - $data['camel'] = []; - $data['columns'] = []; - $data['indexes'] = []; - $data['primaryKeys'] = []; - $data['underscore'] = []; - $data['columns'] = $this->describe->getTable($data['name']); - $data['primaryKey'] = $this->describe->getPrimaryKey($data['name']); - } - - /** - * Generates set of code based on data. - * - * @return array - */ - public function generate() - { - $this->prepareData($this->data); - - foreach ($this->data['columns'] as $column) { - $field = strtolower($column->getField()); - - $this->data['camel'][$field] = $this->transformField( - $field, - 'camelize' - ); - - $this->data['underscore'][$field] = $this->transformField( - $field, - 'underscore' - ); - - if ($column->isForeignKey()) { - $field = $column->getField(); - $referencedTable = $column->getReferencedTable(); - - array_push($this->data['indexes'], $field); - - $this->data = $this->getPrimaryKey( - $this->data, - $field, - $referencedTable - ); - } - - $column->setReferencedTable( - Tools::stripTableSchema($column->getReferencedTable()) - ); - } - - return $this->data; - } -} diff --git a/src/Generator/ViewGenerator.php b/src/Generator/ViewGenerator.php deleted file mode 100644 index 822abcd..0000000 --- a/src/Generator/ViewGenerator.php +++ /dev/null @@ -1,104 +0,0 @@ - - */ -class ViewGenerator extends BaseGenerator implements GeneratorInterface -{ - /** - * Prepares the data before generation. - * - * @param array $data - * @return void - */ - public function prepareData(array &$data) - { - $bootstrap = [ - 'button' => 'btn btn-default', - 'buttonPrimary' => 'btn btn-primary', - 'formControl' => 'form-control', - 'formGroup' => 'form-group col-lg-12 col-md-12 col-sm-12 col-xs-12', - 'label' => 'control-label', - 'table' => 'table table table-striped table-hover', - 'textRight' => 'text-right' - ]; - - if ($data['isBootstrap']) { - $data['bootstrap'] = $bootstrap; - } - - $data['camel'] = []; - $data['underscore'] = []; - $data['foreignKeys'] = []; - $data['primaryKeys'] = []; - - $data['plural'] = plural($data['name']); - $data['singular'] = singular($data['name']); - - $primaryKey = 'get_' . $this->describe->getPrimaryKey($data['name']); - $data['primaryKey'] = $primaryKey; - - if ($this->data['isCamel']) { - $data['primaryKey'] = camelize($data['primaryKey']); - } - - $data['columns'] = $this->describe->getTable( - $data['name'] - ); - } - - /** - * Generates set of code based on data. - * - * @return array - */ - public function generate() - { - $this->prepareData($this->data); - - foreach ($this->data['columns'] as $column) { - $field = strtolower($column->getField()); - - $this->data['camel'][$field] = $this->transformField( - $field, - 'camelize' - ); - - $this->data['underscore'][$field] = $this->transformField( - $field, - 'underscore' - ); - - if ($column->isForeignKey()) { - $referencedTable = Tools::stripTableSchema( - $column->getReferencedTable() - ); - - $this->data['foreignKeys'][$field] = plural($referencedTable); - - $singular = $field . '_singular'; - - $this->data['foreignKeys'][$singular] = singular( - $referencedTable - ); - - $this->data = $this->getPrimaryKey( - $this->data, - $field, - $referencedTable - ); - } - } - - return $this->data; - } -} diff --git a/src/Inflector.php b/src/Inflector.php new file mode 100644 index 0000000..68f70b4 --- /dev/null +++ b/src/Inflector.php @@ -0,0 +1,150 @@ + + */ +class Inflector +{ + /** + * Takes multiple words separated by the separator and changes them to spaces + * + * @param string $word + * @param string $separator + * + * @return string + */ + public static function humanize($word, $separator = '_') + { + $regex = '/[' . preg_quote($separator) . ']+/'; + + $word = trim(mb_strtolower($word)); + + /** @var string */ + $result = preg_replace($regex, ' ', $word); + + return ucwords($result); + } + + /** + * Takes a singular word and makes it plural. + * + * @param string $word + * + * @return string + */ + public static function plural($word) + { + $result = strval($word); + + $rules = array( + '/(quiz)$/' => '\1zes', // quizzes + '/^(ox)$/' => '\1\2en', // ox + '/([m|l])ouse$/' => '\1ice', // mouse, louse + '/(matr|vert|ind)ix|ex$/' => '\1ices', // matrix, vertex, index + '/(x|ch|ss|sh)$/' => '\1es', // search, switch, fix, box, process, address + '/([^aeiouy]|qu)y$/' => '\1ies', // query, ability, agency + '/(hive)$/' => '\1s', // archive, hive + '/(?:([^f])fe|([lr])f)$/' => '\1\2ves', // half, safe, wife + '/sis$/' => 'ses', // basis, diagnosis + '/([ti])um$/' => '\1a', // datum, medium + '/(p)erson$/' => '\1eople', // person, salesperson + '/(m)an$/' => '\1en', // man, woman, spokesman + '/(c)hild$/' => '\1hildren', // child + '/(buffal|tomat)o$/' => '\1\2oes', // buffalo, tomato + '/(bu|campu)s$/' => '\1\2ses', // bus, campus + '/(alias|status|virus)$/' => '\1es', // alias + '/(octop)us$/' => '\1i', // octopus + '/(ax|cris|test)is$/' => '\1es', // axis, crisis + '/s$/' => 's', // no change (compatibility) + '/$/' => 's', + ); + + foreach ($rules as $rule => $replace) + { + if (preg_match($rule, $result)) + { + /** @var string */ + $result = preg_replace($rule, $replace, $result); + + break; + } + } + + return $result; + } + + /** + * Takes a singular word and makes it singular. + * + * @param string $word + * + * @return string + */ + public static function singular($word) + { + $result = strval($word); + + $rules = array( + '/(matr)ices$/' => '\1ix', + '/(vert|ind)ices$/' => '\1ex', + '/^(ox)en/' => '\1', + '/(alias)es$/' => '\1', + '/([octop|vir])i$/' => '\1us', + '/(cris|ax|test)es$/' => '\1is', + '/(shoe)s$/' => '\1', + '/(o)es$/' => '\1', + '/(bus|campus)es$/' => '\1', + '/([m|l])ice$/' => '\1ouse', + '/(x|ch|ss|sh)es$/' => '\1', + '/(m)ovies$/' => '\1\2ovie', + '/(s)eries$/' => '\1\2eries', + '/([^aeiouy]|qu)ies$/' => '\1y', + '/([lr])ves$/' => '\1f', + '/(tive)s$/' => '\1', + '/(hive)s$/' => '\1', + '/([^f])ves$/' => '\1fe', + '/(^analy)ses$/' => '\1sis', + '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/' => '\1\2sis', + '/([ti])a$/' => '\1um', + '/(p)eople$/' => '\1\2erson', + '/(m)en$/' => '\1an', + '/(s)tatuses$/' => '\1\2tatus', + '/(c)hildren$/' => '\1\2hild', + '/(n)ews$/' => '\1\2ews', + '/(quiz)zes$/' => '\1', + '/([^us])s$/' => '\1' + ); + + foreach ($rules as $rule => $replacement) + { + if (preg_match($rule, $result)) + { + /** @var string */ + $result = preg_replace($rule, $replacement, $result); + + break; + } + } + + return $result; + } + + /** + * Takes multiple words separated by spaces and underscores them. + * + * @param string $word + * + * @return string + */ + public static function snakeCase($word) + { + /** @var string */ + return preg_replace('/[\s]+/', '_', mb_strtolower($word)); + } +} diff --git a/src/Packages/CombustorPackage.php b/src/Packages/CombustorPackage.php new file mode 100644 index 0000000..0e4ff5a --- /dev/null +++ b/src/Packages/CombustorPackage.php @@ -0,0 +1,84 @@ + + */ +class CombustorPackage implements IntegrationInterface +{ + /** + * @var string[] + */ + protected $excluded = array(); + + /** + * @var string + */ + protected $root; + + /** + * @param string $root + */ + public function __construct($root) + { + $this->root = $root; + } + + /** + * @param \Rougin\Slytherin\Container\ContainerInterface $container + * @param \Rougin\Slytherin\Integration\Configuration $config + * + * @return \Rougin\Slytherin\Container\ContainerInterface + */ + public function define(ContainerInterface $container, Configuration $config) + { + $app = new Combustor($this->root); + + if ($this->excluded) + { + $app->setExcluded($this->excluded); + } + + $name = 'Rougin\SparkPlug\Controller'; + + if ($container->has($name)) + { + /** @var \Rougin\SparkPlug\Controller */ + $class = $container->get($name); + + $app->setApp($class); + } + + $name = 'Rougin\Describe\Driver\DriverInterface'; + + if ($container->has($name)) + { + /** @var \Rougin\Describe\Driver\DriverInterface */ + $class = $container->get($name); + + $app->setDriver($class); + } + + return $container->set(get_class($app), $app); + } + + /** + * @param string[] $excluded + * + * @return self + */ + public function setExcluded($excluded) + { + $this->excluded = $excluded; + + return $this; + } +} diff --git a/src/Packages/DescribePackage.php b/src/Packages/DescribePackage.php new file mode 100644 index 0000000..6ffea5e --- /dev/null +++ b/src/Packages/DescribePackage.php @@ -0,0 +1,82 @@ + + */ +class DescribePackage implements IntegrationInterface +{ + /** + * @param \Rougin\Slytherin\Container\ContainerInterface $container + * @param \Rougin\Slytherin\Integration\Configuration $config + * + * @return \Rougin\Slytherin\Container\ContainerInterface + */ + public function define(ContainerInterface $container, Configuration $config) + { + // Ignore if Spark Plug is not defined --- + $ci3Ctrl = 'Rougin\SparkPlug\Controller'; + + if (! $container->has($ci3Ctrl)) + { + return $container; + } + // --------------------------------------- + + /** @var \Rougin\SparkPlug\Controller */ + $ci3App = $container->get($ci3Ctrl); + + $config = $this->getConfig($ci3App); + + $interface = 'Rougin\Describe\Driver\DriverInterface'; + + $driver = $this->getDriver($config); + + return $container->set($interface, $driver); + } + + /** + * @param \Rougin\SparkPlug\Controller $ci + * + * @return array + */ + protected function getConfig(Controller $ci) + { + $ci->load->database(); + $ci->load->helper('inflector'); + + $config = array(); + + $config['dbdriver'] = $ci->db->dbdriver; + $config['hostname'] = $ci->db->hostname; + $config['username'] = $ci->db->username; + $config['password'] = $ci->db->password; + $config['database'] = $ci->db->database; + + if (empty($config['hostname'])) + { + $config['hostname'] = $ci->db->dsn; + }; + + return $config; + } + + /** + * @param array $config + * + * @return \Rougin\Describe\Driver\DriverInterface + */ + protected function getDriver($config) + { + return new DatabaseDriver($config['dbdriver'], $config); + } +} diff --git a/src/Packages/SparkplugPackage.php b/src/Packages/SparkplugPackage.php new file mode 100644 index 0000000..20755cc --- /dev/null +++ b/src/Packages/SparkplugPackage.php @@ -0,0 +1,55 @@ + + */ +class SparkplugPackage implements IntegrationInterface +{ + /** + * @var string + */ + protected $root; + + /** + * @param string $root + */ + public function __construct($root) + { + $this->root = $root; + } + + /** + * @param \Rougin\Slytherin\Container\ContainerInterface $container + * @param \Rougin\Slytherin\Integration\Configuration $config + * + * @return \Rougin\Slytherin\Container\ContainerInterface + */ + public function define(ContainerInterface $container, Configuration $config) + { + $class = 'Rougin\SparkPlug\Controller'; + + // If cannot determine APPPATH, ignore --- + $appPath = $this->root . '/application'; + + $root = $this->root . '/config'; + + if (! is_dir($appPath) && ! is_dir($root)) + { + return $container; + } + // --------------------------------------- + + $app = Instance::create($this->root); + + return $container->set($class, $app); + } +} diff --git a/src/Template/Controller.php b/src/Template/Controller.php new file mode 100644 index 0000000..cabc50f --- /dev/null +++ b/src/Template/Controller.php @@ -0,0 +1,538 @@ + + */ +class Controller extends Classidy +{ + const TYPE_WILDFIRE = 0; + + const TYPE_DOCTRINE = 1; + + /** + * @var integer + */ + protected $type; + + /** + * @param string $table + * @param integer $type + */ + public function __construct($table, $type) + { + $this->type = $type; + + $this->init($table); + } + + /** + * Configures the current class. + * + * @param string $table + * + * @return void + */ + public function init($table) + { + $name = Inflector::plural($table); + + $model = Inflector::singular($table); + + /** @var class-string */ + $class = ucfirst($model); + + $type = $this->type; + + $this->addClassProperty('db', 'CI_DB_query_builder')->asTag(); + + $this->addClassProperty('input', 'CI_Input')->asTag(); + + if ($type === self::TYPE_DOCTRINE) + { + $this->imports[] = 'Rougin\Credo\Credo'; + + $this->addClassProperty('load', 'MY_Loader')->asTag(); + } + + $this->addClassProperty('session', 'CI_Session')->asTag(); + + $this->addClassProperty($model, $class)->asTag(); + + if ($type === self::TYPE_DOCTRINE) + { + $repo = $model . '_repository'; + + $class = ucfirst($repo); + + $this->addClassProperty($repo, $class)->asTag(); + + $this->addClassProperty('repo', $class)->asPrivate(); + } + + $this->setName(ucfirst($name)); + + $this->extendsTo('Rougin\SparkPlug\Controller'); + + $this->setConstructor($model, $type); + + $this->setCreateMethod($name, $model, $type); + + $this->setDeleteMethod($name, $model, $type); + + $this->setEditMethod($name, $model, $type); + + $this->setIndexMethod($name, $model, $type); + } + + /** + * @param string $model + * @param integer $type + * + * @return void + */ + protected function setConstructor($model, $type) + { + $method = new Method('__construct'); + + $method->setComment('Loads the required helpers, libraries, and models.'); + + $method->setCodeLine(function ($lines) use ($model, $type) + { + $lines[] = 'parent::__construct();'; + $lines[] = ''; + + $lines[] = '// Initialize the Database loader ---'; + + if ($type === self::TYPE_WILDFIRE) + { + $lines[] = '$this->load->helper(\'inflector\');'; + } + + $lines[] = '$this->load->database();'; + $lines[] = '// ----------------------------------'; + $lines[] = ''; + + // TODO: Show if --with-view enabled ------------- + $lines[] = '// Load view-related helpers ------'; + $lines[] = '$this->load->helper(\'form\');'; + $lines[] = '$this->load->helper(\'url\');'; + $lines[] = '$this->load->library(\'pagination\');'; + $lines[] = '$this->load->library(\'session\');'; + $lines[] = '// --------------------------------'; + $lines[] = ''; + // ----------------------------------------------- + + $lines[] = '// Load multiple models if required ---'; + $lines[] = '$this->load->model(\'' . $model . '\');'; + + if ($type === self::TYPE_DOCTRINE) + { + $lines[] = ''; + $lines[] = '$this->load->repository(\'' . $model . '\');'; + } + + $lines[] = '// ------------------------------------'; + + $model = ucfirst($model); + + if ($type === self::TYPE_DOCTRINE) + { + $lines[] = ''; + $lines[] = '// Load the main repository of the model ---'; + $lines[] = '$credo = new Credo($this->db);'; + $lines[] = ''; + $lines[] = '/** @var \\' . $model . '_repository */'; + $lines[] = '$repo = $credo->get_repository(\'' . $model . '\');'; + $lines[] = ''; + $lines[] = '$this->repo = $repo;'; + $lines[] = '// -----------------------------------------'; + } + + return $lines; + }); + + $this->addMethod($method); + } + + /** + * @param string $name + * @param string $model + * @param integer $type + * + * @return void + */ + protected function setCreateMethod($name, $model, $type) + { + $method = new Method('create'); + + $texts = array('Returns the form page for creating a ' . $model . '.'); + $texts[] = 'Creates a new ' . $model . ' if receiving payload.'; + $method->setComment($texts); + + $method->setReturn('void'); + + $method->setCodeLine(function ($lines) use ($name, $model, $type) + { + $lines[] = '// Skip if provided empty input ---'; + $lines[] = '/** @var array */'; + $lines[] = '$input = $this->input->post(null, true);'; + $lines[] = ''; + $lines[] = 'if (! $input)'; + $lines[] = '{'; + + // TODO: Show if --with-view enabled ------------------------- + $lines[] = ' $this->load->view(\'' . $name . '/create\');'; + $lines[] = ''; + // ----------------------------------------------------------- + + $lines[] = ' return;'; + $lines[] = '}'; + $lines[] = '// --------------------------------'; + $lines[] = ''; + + $lines[] = '// Specify logic here if applicable ---'; + + if ($type === self::TYPE_WILDFIRE) + { + $lines[] = '$exists = $this->' . $model . '->exists($input);'; + } + else + { + $lines[] = '$exists = $this->repo->exists($input);'; + } + + $lines[] = ''; + $lines[] = '$data = array();'; + $lines[] = ''; + $lines[] = 'if ($exists)'; + $lines[] = '{'; + $lines[] = ' $data[\'error\'] = \'\';'; + $lines[] = '}'; + $lines[] = '// ------------------------------------'; + $lines[] = ''; + + $lines[] = '// Check if provided input is valid ---'; + $lines[] = '$valid = $this->' . $model . '->validate($input);'; + $lines[] = ''; + $lines[] = 'if (! $valid || $exists)'; + $lines[] = '{'; + + // TODO: Show if --with-view enabled ---------------------------- + $lines[] = ' $this->load->view(\'' . $name . '/create\', $data);'; + $lines[] = ''; + // -------------------------------------------------------------- + + $lines[] = ' return;'; + $lines[] = '}'; + $lines[] = '// ------------------------------------'; + $lines[] = ''; + + $lines[] = '// Create the item then go back to "index" page ---'; + + if ($type === self::TYPE_WILDFIRE) + { + $lines[] = '$this->' . $model . '->create($input);'; + } + else + { + $class = ucfirst($model); + + $lines[] = '$this->repo->create($input, new ' . $class . ');'; + } + + $lines[] = ''; + $lines[] = '$text = (string) \'' . ucfirst($model) . ' successfully created!\';'; + $lines[] = ''; + $lines[] = '$this->session->set_flashdata(\'alert\', $text);'; + $lines[] = ''; + $lines[] = 'redirect(\'' . $name . '\');'; + $lines[] = '// ------------------------------------------------'; + + return $lines; + }); + + $this->addMethod($method); + } + + /** + * @param string $name + * @param string $model + * @param integer $type + * + * @return void + */ + protected function setDeleteMethod($name, $model, $type) + { + $method = new Method('delete'); + + $method->setComment('Deletes the specified ' . $model . '.'); + + $method->addIntegerArgument('id'); + + $method->setReturn('void'); + + $method->setCodeLine(function ($lines) use ($name, $model, $type) + { + $lines[] = '// Show 404 page if not using "DELETE" method ---'; + $lines[] = '$method = $this->input->post(\'_method\', true);'; + $lines[] = ''; + + if ($type === self::TYPE_WILDFIRE) + { + $lines[] = '$item = $this->' . $model . '->find($id);'; + } + else + { + $lines[] = '$item = $this->repo->find($id);'; + } + + $lines[] = ''; + $lines[] = 'if ($method !== \'DELETE\' || ! $item)'; + $lines[] = '{'; + $lines[] = ' show_404();'; + $lines[] = '}'; + $lines[] = '// ----------------------------------------------'; + $lines[] = ''; + + $lines[] = '// Delete the item then go back to "index" page ---'; + + if ($type === self::TYPE_WILDFIRE) + { + $lines[] = '$this->' . $model . '->delete($id);'; + } + else + { + $class = ucfirst($model); + + $lines[] = '/** @var \\' . $class . ' $item */'; + $lines[] = '$this->repo->delete($item);'; + } + + $lines[] = ''; + $lines[] = '$text = (string) \'' . ucfirst($model) . ' successfully deleted!\';'; + $lines[] = ''; + $lines[] = '$this->session->set_flashdata(\'alert\', $text);'; + $lines[] = ''; + $lines[] = 'redirect(\'' . $name . '\');'; + $lines[] = '// ------------------------------------------------'; + + return $lines; + }); + + $this->addMethod($method); + } + + /** + * @param string $name + * @param string $model + * @param integer $type + * + * @return void + */ + protected function setEditMethod($name, $model, $type) + { + $method = new Method('edit'); + + $texts = array('Returns the form page for updating a ' . $model . '.'); + $texts[] = 'Updates the specified ' . $model . ' if receiving payload.'; + $method->setComment($texts); + + $method->addIntegerArgument('id'); + + $method->setReturn('void'); + + $method->setCodeLine(function ($lines) use ($name, $model, $type) + { + $lines[] = '// Show 404 page if item not found ---'; + + if ($type === self::TYPE_WILDFIRE) + { + $lines[] = 'if (! $item = $this->' . $model . '->find($id))'; + } + else + { + $lines[] = 'if (! $item = $this->repo->find($id))'; + } + + $lines[] = '{'; + $lines[] = ' show_404();'; + $lines[] = '}'; + $lines[] = ''; + $lines[] = '/** @var \\' . ucfirst($model) . ' $item */'; + $lines[] = '$data = array(\'item\' => $item);'; + $lines[] = '// -----------------------------------'; + $lines[] = ''; + + $lines[] = '// Skip if provided empty input ---'; + $lines[] = '/** @var array */'; + $lines[] = '$input = $this->input->post(null, true);'; + $lines[] = ''; + $lines[] = 'if (! $input)'; + $lines[] = '{'; + + // TODO: Show if --with-view enabled ---------------------------- + $lines[] = ' $this->load->view(\'' . $name . '/edit\', $data);'; + $lines[] = ''; + // -------------------------------------------------------------- + + $lines[] = ' return;'; + $lines[] = '}'; + $lines[] = '// --------------------------------'; + $lines[] = ''; + + $lines[] = '// Show 404 page if not using "PUT" method ---'; + $lines[] = '$method = $this->input->post(\'_method\', true);'; + $lines[] = ''; + $lines[] = 'if ($method !== \'PUT\')'; + $lines[] = '{'; + $lines[] = ' show_404();'; + $lines[] = '}'; + $lines[] = '// -------------------------------------------'; + $lines[] = ''; + + $lines[] = '// Specify logic here if applicable ---'; + + if ($type === self::TYPE_WILDFIRE) + { + $lines[] = '$exists = $this->' . $model . '->exists($input, $id);'; + } + else + { + $lines[] = '$exists = $this->repo->exists($input, $id);'; + } + + $lines[] = ''; + $lines[] = 'if ($exists)'; + $lines[] = '{'; + $lines[] = ' $data[\'error\'] = \'\';'; + $lines[] = '}'; + $lines[] = '// ------------------------------------'; + $lines[] = ''; + + $lines[] = '// Check if provided input is valid ---'; + $lines[] = '$valid = $this->' . $model . '->validate($input);'; + $lines[] = ''; + $lines[] = 'if (! $valid || $exists)'; + $lines[] = '{'; + + // TODO: Show if --with-view enabled ---------------------------- + $lines[] = ' $this->load->view(\'' . $name . '/edit\', $data);'; + $lines[] = ''; + // -------------------------------------------------------------- + + $lines[] = ' return;'; + $lines[] = '}'; + $lines[] = '// ------------------------------------'; + $lines[] = ''; + + $lines[] = '// Update the item then go back to "index" page ---'; + + if ($type === self::TYPE_WILDFIRE) + { + $lines[] = '$this->' . $model . '->update($id, $input);'; + } + else + { + $class = ucfirst($model); + + $lines[] = '/** @var \\' . $class . ' $item */'; + $lines[] = '$this->repo->update($item, $input);'; + } + + $lines[] = ''; + $lines[] = '$text = (string) \'User successfully updated!\';'; + $lines[] = ''; + $lines[] = '$this->session->set_flashdata(\'alert\', $text);'; + $lines[] = ''; + $lines[] = 'redirect(\'' . $name . '\');'; + $lines[] = '// ------------------------------------------------'; + + return $lines; + }); + + $this->addMethod($method); + } + + /** + * @param string $name + * @param string $model + * @param integer $type + * + * @return void + */ + protected function setIndexMethod($name, $model, $type) + { + $method = new Method('index'); + + $method->setComment('Returns the list of paginated ' . $name . '.'); + + $method->setReturn('void'); + + $method->setCodeLine(function ($lines) use ($name, $model, $type) + { + $lines[] = '// Create pagination links and get the offset ---'; + + if ($type === self::TYPE_WILDFIRE) + { + $lines[] = '$total = (int) $this->' . $model . '->total();'; + } + else + { + $lines[] = '$total = (int) $this->repo->total();'; + } + + $lines[] = ''; + $lines[] = '$result = $this->' . $model . '->paginate(10, $total);'; + $lines[] = ''; + $lines[] = '$data = array(\'links\' => $result[1]);'; + $lines[] = ''; + $lines[] = '/** @var integer */'; + $lines[] = '$offset = $result[0];'; + $lines[] = '// ----------------------------------------------'; + $lines[] = ''; + + if ($type === self::TYPE_WILDFIRE) + { + $lines[] = '$items = $this->' . $model . '->get(10, $offset);'; + } + else + { + $lines[] = '$items = $this->repo->get(10, $offset);'; + } + + $lines[] = ''; + + if ($type === self::TYPE_WILDFIRE) + { + $lines[] = '$data[\'items\'] = $items->result();'; + } + else + { + $lines[] = '$data[\'items\'] = $items;'; + } + + $lines[] = ''; + $lines[] = 'if ($alert = $this->session->flashdata(\'alert\'))'; + $lines[] = '{'; + $lines[] = ' $data[\'alert\'] = $alert;'; + $lines[] = '}'; + + // TODO: Show if --with-view enabled --------------------------- + $lines[] = ''; + $lines[] = '$this->load->view(\'' . $name . '/index\', $data);'; + // ------------------------------------------------------------- + + return $lines; + }); + + $this->addMethod($method); + } +} diff --git a/src/Template/CreatePlate.php b/src/Template/CreatePlate.php new file mode 100644 index 0000000..95f29d8 --- /dev/null +++ b/src/Template/CreatePlate.php @@ -0,0 +1,16 @@ + + */ +class CreatePlate extends FormPlate +{ + /** + * @var boolean + */ + protected $edit = false; +} diff --git a/src/Template/Doctrine/Model.php b/src/Template/Doctrine/Model.php new file mode 100644 index 0000000..0c98cfd --- /dev/null +++ b/src/Template/Doctrine/Model.php @@ -0,0 +1,300 @@ + + */ +class Model extends Classidy +{ + /** + * @var \Rougin\Describe\Column[] + */ + protected $cols; + + /** + * @var string[] + */ + protected $excluded = array(); + + /** + * @param string $table + * @param \Rougin\Describe\Column[] $cols + * @param string[] $excluded + */ + public function __construct($table, $cols, $excluded = array()) + { + $this->cols = $cols; + + $this->excluded = $excluded; + + $this->init($table); + } + + /** + * @param string $table + * + * @return void + */ + public function init($table) + { + $name = Inflector::singular($table); + + $this->setName(ucfirst($name)); + $this->extendsTo('Rougin\Credo\Model'); + + $this->addTrait('Rougin\Credo\Traits\PaginateTrait'); + $this->addTrait('Rougin\Credo\Traits\ValidateTrait'); + + $repo = ucfirst($name) . '_repository'; + + $comment = array('@Entity(repositoryClass="' . $repo . '")'); + $comment[] = ''; + $comment[] = '@Table(name="' . $table . '")'; + $this->setComment($comment); + + $link = 'https://codeigniter.com/userguide3/libraries'; + + // Sort columns by name ------------ + $items = array(); + + foreach ($this->cols as $col) + { + $items[$col->getField()] = $col; + } + + ksort($items); + // --------------------------------- + + $this->setProperties($items); + + $this->setPagee($link); + + $this->setRules($link); + + $this->setMethods($items); + } + + /** + * @param \Rougin\Describe\Column[] $cols + * + * @return void + */ + protected function setMethods($cols) + { + foreach ($cols as $col) + { + $name = $col->getField(); + + $name = Inflector::snakeCase($name); + + $type = $col->getDataType(); + + if ($col->isNull()) + { + $type = $type . '|null'; + } + + $method = 'get_' . $name; + + if ($col->getDataType() === 'boolean') + { + // Remove "is_" from name to get proper name --- + $temp = str_replace('is_', '', $name); + // --------------------------------------------- + + $method = 'is_' . $temp; + } + + $method = new Method($method); + + $method->setReturn($type); + + $method->setCodeLine(function ($lines) use ($name) + { + $lines[] = 'return $this->' . $name . ';'; + + return $lines; + }); + + $this->addMethod($method); + } + + foreach ($cols as $col) + { + if ($col->isPrimaryKey()) + { + continue; + } + + $name = $col->getField(); + + $name = Inflector::snakeCase($name); + + $type = $col->getDataType(); + + if ($col->isNull()) + { + $type = $type . '|null'; + } + + $method = new Method('set_' . $name); + + $method->setReturn('self'); + + $type = $col->getDataType(); + + $isNull = $col->isNull(); + + switch ($type) + { + case 'boolean': + $method->addBooleanArgument($name, $isNull); + + break; + case 'integer': + $method->addIntegerArgument($name, $isNull); + + break; + default: + $method->addStringArgument($name, $isNull); + + break; + } + + $method->setCodeLine(function ($lines) use ($name) + { + $lines[] = '$this->' . $name . ' = $' . $name . ';'; + $lines[] = ''; + $lines[] = 'return $this;'; + + return $lines; + }); + + $this->addMethod($method); + } + } + + /** + * @param string $link + * + * @return void + */ + protected function setPagee($link) + { + $default = array(); + + $default['page_query_string'] = true; + $default['use_page_numbers'] = true; + $default['query_string_segment'] = 'p'; + $default['reuse_query_string'] = true; + + $this->addArrayProperty('pagee', 'array') + ->withComment('Additional configuration to Pagination Class.') + ->withLink($link . '/pagination.html#customizing-the-pagination') + ->withDefaultValue($default); + } + + /** + * @param \Rougin\Describe\Column[] $cols + * + * @return void + */ + protected function setProperties($cols) + { + foreach ($cols as $col) + { + $isNull = $col->isNull(); + + $isUnique = $col->isUnique(); + + $name = $col->getField(); + + $name = Inflector::snakeCase($name); + + $type = $col->getDataType(); + + switch ($type) + { + case 'boolean': + $this->addBooleanProperty($name, $isNull); + + break; + case 'integer': + $this->addIntegerProperty($name, $isNull); + + break; + default: + $this->addStringProperty($name, $isNull); + + break; + } + + // Generate Doctrine annotations to columns --------- + $lines = array(); + + if ($col->isPrimaryKey()) + { + $lines[] = '@Id @GeneratedValue'; + $lines[] = ''; + } + + $keys = array('name="' . $name . '"'); + $keys[] = 'type="' . $type . '"'; + + if ($length = $col->getLength()) + { + $keys[] = 'length=' . $length; + } + + $keys[] = 'nullable=' . ($isNull ? 'true' : 'false'); + $keys[] = 'unique=' . ($isUnique ? 'true' : 'false'); + + $lines[] = '@Column(' . implode(', ', $keys) . ')'; + // -------------------------------------------------- + + $this->withComment($lines); + } + } + + /** + * @param string $link + * + * @return void + */ + protected function setRules($link) + { + $rules = array(); + + foreach ($this->cols as $col) + { + $name = $col->getField(); + + $isExcluded = in_array($name, $this->excluded); + + if ($col->isNull() || $col->isPrimaryKey() || $isExcluded) + { + continue; + } + + $rule = array('field' => $name); + + $rule['label'] = ucfirst($name); + + $rule['rules'] = 'required'; + + $rules[] = $rule; + } + + $this->addArrayProperty('rules', 'array[]') + ->withComment('List of validation rules for Form Validation.') + ->withLink($link . '/form_validation.html#setting-rules-using-an-array') + ->withDefaultValue($rules); + } +} diff --git a/src/Template/EditPlate.php b/src/Template/EditPlate.php new file mode 100644 index 0000000..891e533 --- /dev/null +++ b/src/Template/EditPlate.php @@ -0,0 +1,16 @@ + + */ +class EditPlate extends FormPlate +{ + /** + * @var boolean + */ + protected $edit = true; +} diff --git a/src/Template/FooterPlate.php b/src/Template/FooterPlate.php new file mode 100644 index 0000000..8b7d3bc --- /dev/null +++ b/src/Template/FooterPlate.php @@ -0,0 +1,45 @@ + + */ +class FooterPlate +{ + /** + * @var boolean + */ + protected $bootstrap; + + /** + * @param boolean $bootstrap + */ + public function __construct($bootstrap) + { + $this->bootstrap = $bootstrap; + } + + /** + * @param string $tab + * + * @return string + */ + public function make($tab = ' ') + { + $lines = array(); + + if ($this->bootstrap) + { + $lines[] = $tab . ''; + $lines[] = $tab . ''; + } + + $lines[] = ''; + $lines[] = ''; + + return implode("\n", $lines); + } +} diff --git a/src/Template/FormPlate.php b/src/Template/FormPlate.php new file mode 100644 index 0000000..86eee83 --- /dev/null +++ b/src/Template/FormPlate.php @@ -0,0 +1,233 @@ + + */ +class FormPlate +{ + const TYPE_WILDFIRE = 0; + + const TYPE_DOCTRINE = 1; + + /** + * @var boolean + */ + protected $bootstrap = false; + + /** + * @var \Rougin\Describe\Column[] + */ + protected $cols; + + /** + * @var boolean + */ + protected $edit = false; + + /** + * @var string[] + */ + protected $excluded = array(); + + /** + * @var string + */ + protected $table; + + /** + * @var integer + */ + protected $type; + + /** + * @param string $table + * @param integer $type + * @param \Rougin\Describe\Column[] $cols + */ + public function __construct($table, $type, $cols) + { + $this->cols = $cols; + + $this->type = $type; + + $this->table = $table; + } + + /** + * @param string $tab + * + * @return string + */ + public function make($tab = '') + { + $model = Inflector::singular($this->table); + + $route = Inflector::plural($this->table); + + $title = 'Create New ' . ucfirst($model); + + if ($this->edit) + { + $title = 'Update ' . ucfirst($model); + } + + $lines = array('

' . $title . '

'); + $lines[] = ''; + + $link = $route . '/create\''; + + if ($this->edit) + { + $primary = $this->getPrimary(); + + $id = null; + + if ($primary) + { + $id = '/\' . ' . $this->getField($primary); + } + + $link = $route . '/edit' . $id; + } + + $lines[] = ''; + + if ($this->edit) + { + $lines[] = $tab . ''; + $lines[] = ''; + } + + foreach ($this->cols as $col) + { + $name = $col->getField(); + + if ($col->isPrimaryKey() || in_array($name, $this->excluded)) + { + continue; + } + + $title = Inflector::humanize($name); + + $field = $this->getField($col); + + $class = $this->bootstrap ? 'mb-3' : ''; + $lines[] = $tab . '
'; + $class = $this->bootstrap ? 'form-label mb-0' : ''; + $lines[] = $tab . $tab . ' \'' . $class . '\']) ?>'; + + $class = $this->bootstrap ? 'form-control' : ''; + + if ($this->edit) + { + $lines[] = $tab . $tab . ''; + } + else + { + $lines[] = $tab . $tab . ''; + } + + $class = $this->bootstrap ? 'text-danger small' : ''; + $lines[] = $tab . $tab . '\', \'
\') ?>'; + $lines[] = $tab . ''; + $lines[] = ''; + } + + $submit = 'Create'; + + if ($this->edit) + { + $submit = 'Update'; + } + + $lines[] = $tab . ''; + $class = $this->bootstrap ? 'alert alert-danger' : ''; + $lines[] = $tab . '
'; + $lines[] = $tab . ''; + $lines[] = ''; + + $class = $this->bootstrap ? 'btn btn-link text-secondary text-decoration-none' : ''; + $lines[] = $tab . ''; + $class = $this->bootstrap ? 'btn btn-primary' : ''; + $lines[] = $tab . ''; + $lines[] = ''; + + $result = implode("\n", $lines); + + // Replace all empty class placeholders ------------- + $result = str_replace(' class=""', '', $result); + + $result = str_replace(', \'class=""\'', '', $result); + + $search = ', \'\', [\'class\' => \'\']'; + + return str_replace($search, '', $result); + // -------------------------------------------------- + } + + /** + * @param boolean $bootstrap + * + * @return self + */ + public function withBootstrap($bootstrap) + { + $this->bootstrap = $bootstrap; + + return $this; + } + + /** + * @param string[] $excluded + * + * @return self + */ + public function withExcluded($excluded) + { + $this->excluded = $excluded; + + return $this; + } + + /** + * @param \Rougin\Describe\Column $column + * + * @return string + */ + protected function getField(Column $column) + { + $name = $column->getField(); + + if ($this->type === self::TYPE_DOCTRINE) + { + $name = 'get_' . $name . '()'; + } + + return '$item->' . $name; + } + + /** + * @return \Rougin\Describe\Column|null + */ + protected function getPrimary() + { + $primary = null; + + foreach ($this->cols as $col) + { + if ($col->isPrimaryKey()) + { + $primary = $col; + } + } + + return $primary; + } +} diff --git a/src/Template/HeaderPlate.php b/src/Template/HeaderPlate.php new file mode 100644 index 0000000..b5d3794 --- /dev/null +++ b/src/Template/HeaderPlate.php @@ -0,0 +1,61 @@ + + */ +class HeaderPlate +{ + /** + * @var boolean + */ + protected $bootstrap; + + /** + * @param boolean $bootstrap + */ + public function __construct($bootstrap) + { + $this->bootstrap = $bootstrap; + } + + /** + * @param string $tab + * + * @return string + */ + public function make($tab = ' ') + { + $lines = array(''); + + $lines[] = ''; + $lines[] = ''; + + $lines[] = $tab . ''; + $lines[] = $tab . ''; + $lines[] = $tab . ''; + $lines[] = $tab . 'Welcome to Codeigniter 3'; + + if ($this->bootstrap) + { + $lines[] = $tab . ''; + } + + $lines[] = ''; + $lines[] = ''; + + if ($this->bootstrap) + { + $lines[] = $tab . '
'; + } + else + { + $lines[] = $tab . '
'; + } + + return implode("\n", $lines); + } +} diff --git a/src/Template/IndexPlate.php b/src/Template/IndexPlate.php new file mode 100644 index 0000000..98d6ce3 --- /dev/null +++ b/src/Template/IndexPlate.php @@ -0,0 +1,119 @@ + + */ +class IndexPlate +{ + /** + * @var boolean + */ + protected $bootstrap = false; + + /** + * @var \Rougin\Describe\Column[] + */ + protected $cols; + + /** + * @var string + */ + protected $table; + + /** + * @var integer + */ + protected $type; + + /** + * @param string $table + * @param integer $type + * @param \Rougin\Describe\Column[] $cols + */ + public function __construct($table, $type, $cols) + { + $this->type = $type; + + $this->table = $table; + + $this->cols = $cols; + } + + /** + * @param string $tab + * + * @return string + */ + public function make($tab = '') + { + $model = Inflector::singular($this->table); + + $route = Inflector::plural($this->table); + + $lines = array('

' . ucfirst($route) . '

'); + $lines[] = ''; + + $lines[] = ''; + $class = $this->bootstrap ? 'alert alert-success' : ''; + $lines[] = '
'; + $lines[] = ''; + $lines[] = ''; + + $text = 'Create New ' . ucfirst($model); + $class = $this->bootstrap ? 'my-3' : ''; + $lines[] = '
'; + $class = $this->bootstrap ? 'btn btn-primary' : ''; + $lines[] = ' ' . $text . ''; + $lines[] = '
'; + $lines[] = ''; + + $lines[] = '
'; + + $table = new TablePlate($this->table, $this->cols, $this->type); + + $table->withBootstrap($this->bootstrap); + + foreach ($table->make($tab) as $line) + { + $lines[] = $line; + } + + $lines[] = ' '; + $lines[] = '
'; + $lines[] = ''; + + $lines[] = ''; + + $result = implode("\n", $lines); + + return str_replace(' class=""', '', $result); + } + + /** + * @param boolean $bootstrap + * + * @return self + */ + public function withBootstrap($bootstrap) + { + $this->bootstrap = $bootstrap; + + return $this; + } +} diff --git a/src/Template/TablePlate.php b/src/Template/TablePlate.php new file mode 100644 index 0000000..f548996 --- /dev/null +++ b/src/Template/TablePlate.php @@ -0,0 +1,209 @@ + + */ +class TablePlate +{ + const TYPE_WILDFIRE = 0; + + const TYPE_DOCTRINE = 1; + + /** + * @var boolean + */ + protected $bootstrap = false; + + /** + * @var \Rougin\Describe\Column[] + */ + protected $cols; + + /** + * @var string + */ + protected $table; + + /** + * @var integer + */ + protected $type; + + /** + * @param string $table + * @param \Rougin\Describe\Column[] $cols + * @param integer $type + */ + public function __construct($table, $cols, $type) + { + $this->cols = $cols; + + $this->table = $table; + + $this->type = $type; + } + + /** + * @param string $tab + * + * @return string[] + */ + public function make($tab = '') + { + $class = $this->bootstrap ? 'table table-hover' : ''; + + $lines = array(''); + + $lines = $this->setCol($lines, $tab); + + $lines = $this->setRow($lines, $tab); + + $lines[] = '
'; + + return $lines; + } + + /** + * @param string[] $lines + * @param string $tab + * + * @return string[] + */ + protected function setCol($lines, $tab = '') + { + $lines[] = $tab . ''; + $lines[] = $tab . $tab . ''; + + $space = $tab . $tab . $tab; + + foreach ($this->cols as $col) + { + if ($col->isPrimaryKey()) + { + continue; + } + + $name = Inflector::humanize($col->getField()); + + $lines[] = $space . '' . $name . ''; + } + + $lines[] = $tab . $tab . ''; + $lines[] = $tab . ''; + + return $lines; + } + + /** + * @param string[] $lines + * @param string $tab + * + * @return string[] + */ + protected function setRow($lines, $tab = '') + { + $lines[] = $tab . ''; + $lines[] = $tab . $tab . ''; + $lines[] = $tab . $tab . $tab . ''; + + $space = $tab . $tab . $tab . $tab; + + $primary = null; + + foreach ($this->cols as $col) + { + if ($col->isPrimaryKey()) + { + $primary = $col; + + continue; + } + + $name = '[FIELD] ?>'; + + $field = $col->getField(); + + if ($this->type === self::TYPE_DOCTRINE) + { + $field = 'get_' . $col->getField(); + + $field = Inflector::snakeCase($field); + + $field = $field . '()'; + } + + $name = str_replace('[FIELD]', $field, $name); + + $lines[] = $space . '' . $name . ''; + } + + if ($primary) + { + // Set the primary key field ----------- + $id = $primary->getField(); + + if ($this->type === self::TYPE_DOCTRINE) + { + $id = 'get_' . $id . '()'; + } + + $field = '$item->' . $id; + // ------------------------------------- + + $route = Inflector::plural($this->table); + + $class = $this->bootstrap ? 'd-flex' : ''; + $lines[] = $space . ''; + + $lines[] = $space . $tab . ''; + $class = $this->bootstrap ? 'btn btn-secondary' : ''; + $link = ''; + $link = 'Edit'; + $lines[] = $space . $tab . $tab . $link; + $lines[] = $space . $tab . ''; + + $lines[] = $space . $tab . ''; + + $form = ''; + $lines[] = $space . $tab . $tab . $form; + + $hidden = ''; + $lines[] = $space . $tab . $tab . $tab . $hidden; + + $class = $this->bootstrap ? 'btn btn-link text-danger text-decoration-none' : ''; + $delete = 'Delete'; + $lines[] = $space . $tab . $tab . $tab . $delete; + + $close = ''; + $lines[] = $space . $tab . $tab . $close; + + $lines[] = $space . $tab . ''; + + $lines[] = $space . ''; + } + + $lines[] = $tab . $tab . $tab . ''; + $lines[] = $tab . $tab . ''; + $lines[] = $tab . ''; + + return $lines; + } + + /** + * @param boolean $bootstrap + * + * @return self + */ + public function withBootstrap($bootstrap) + { + $this->bootstrap = $bootstrap; + + return $this; + } +} diff --git a/src/Template/Wildfire/Model.php b/src/Template/Wildfire/Model.php new file mode 100644 index 0000000..d27654b --- /dev/null +++ b/src/Template/Wildfire/Model.php @@ -0,0 +1,262 @@ + + */ +class Model extends Classidy +{ + /** + * @var \Rougin\Describe\Column[] + */ + protected $cols; + + /** + * @var string[] + */ + protected $excluded = array(); + + /** + * @param string $table + * @param \Rougin\Describe\Column[] $cols + * @param string[] $excluded + */ + public function __construct($table, $cols, $excluded = array()) + { + $this->cols = $cols; + + $this->excluded = $excluded; + + $this->init($table); + } + + /** + * Configures the current class. + * + * @param string $table + * + * @return void + */ + public function init($table) + { + $name = Inflector::singular($table); + + $this->setName(ucfirst($name)); + $this->extendsTo('Rougin\Wildfire\Model'); + + $this->addTrait('Rougin\Wildfire\Traits\PaginateTrait'); + $this->addTrait('Rougin\Wildfire\Traits\ValidateTrait'); + $this->addTrait('Rougin\Wildfire\Traits\WildfireTrait'); + $this->addTrait('Rougin\Wildfire\Traits\WritableTrait'); + + $this->setProperties(); + + $link = 'https://codeigniter.com/userguide3/libraries'; + + $this->setPagee($link); + + $this->setRules($link); + + $this->addStringProperty('table') + ->withComment('The table associated with the model.') + ->withDefaultValue($table); + + $this->setExistsMethod(); + + $this->setInputMethod(); + } + + /** + * @return void + */ + protected function setExistsMethod() + { + $method = new Method('exists'); + + $method->setReturn('boolean'); + + $method->addArrayArgument('data', 'array'); + + $method->addIntegerArgument('id', true); + + $method->setCodeLine(function ($lines) + { + $lines[] = '// Specify logic here if applicable ---'; + $lines[] = '// ------------------------------------'; + $lines[] = ''; + $lines[] = 'return false;'; + + return $lines; + }); + + $this->addMethod($method); + } + + /** + * @return void + */ + protected function setInputMethod() + { + $method = new Method('input'); + + $method->asProtected(); + + $method->setReturn('array'); + + $method->addArrayArgument('data', 'array'); + + $method->addIntegerArgument('id', true); + + $cols = $this->cols; + + $method->setCodeLine(function ($lines) use ($cols) + { + $lines[] = '$load = array();'; + $lines[] = ''; + $lines[] = '// List editable fields from table ---'; + + foreach ($cols as $index => $col) + { + $name = $col->getField(); + + if ($col->isPrimaryKey() || in_array($name, $this->excluded)) + { + continue; + } + + $type = $col->getDataType(); + + if ($col->isNull()) + { + $type = $type . '|null'; + } + + $lines[] = '/** @var ' . $type . ' */'; + $lines[] = '$' . $name . ' = $data[\'' . $name . '\'];'; + + if ($col->isNull()) + { + $lines[] = 'if ($' . $name . ')'; + $lines[] = '{'; + $lines[] = ' $load[\'' . $name . '\'] = $' . $name . ';'; + $lines[] = '}'; + } + else + { + $lines[] = '$load[\'' . $name . '\'] = $' . $name . ';'; + } + + if (array_key_exists($index + 1, $cols)) + { + $next = $cols[$index + 1]; + + if (! in_array($next->getField(), $this->excluded)) + { + $lines[] = ''; + } + } + } + + $lines[] = '// -----------------------------------'; + $lines[] = ''; + $lines[] = 'return $load;'; + + return $lines; + }); + + $this->addMethod($method); + } + + /** + * @param string $link + * + * @return void + */ + protected function setPagee($link) + { + $default = array(); + + $default['page_query_string'] = true; + $default['use_page_numbers'] = true; + $default['query_string_segment'] = 'p'; + $default['reuse_query_string'] = true; + + $this->addArrayProperty('pagee', 'array') + ->withComment('Additional configuration to Pagination Class.') + ->withLink($link . '/pagination.html#customizing-the-pagination') + ->withDefaultValue($default); + } + + /** + * @return void + */ + protected function setProperties() + { + foreach ($this->cols as $col) + { + $type = $col->getDataType(); + + $name = $col->getField(); + + $isNull = $col->isNull(); + + switch ($type) + { + case 'boolean': + $this->addBooleanProperty($name, $isNull)->asTag(); + + break; + case 'integer': + $this->addIntegerProperty($name, $isNull)->asTag(); + + break; + default: + $this->addStringProperty($name, $isNull)->asTag(); + + break; + } + } + } + + /** + * @param string $link + * + * @return void + */ + protected function setRules($link) + { + $rules = array(); + + foreach ($this->cols as $col) + { + $name = $col->getField(); + + $isExcluded = in_array($name, $this->excluded); + + if ($col->isNull() || $col->isPrimaryKey() || $isExcluded) + { + continue; + } + + $rule = array('field' => $name); + + $rule['label'] = ucfirst($name); + + $rule['rules'] = 'required'; + + $rules[] = $rule; + } + + $this->addArrayProperty('rules', 'array[]') + ->withComment('List of validation rules for Form Validation.') + ->withLink($link . '/form_validation.html#setting-rules-using-an-array') + ->withDefaultValue($rules); + } +} diff --git a/src/Template/combustor.yml b/src/Template/combustor.yml new file mode 100644 index 0000000..976f6df --- /dev/null +++ b/src/Template/combustor.yml @@ -0,0 +1,6 @@ +app_path: %%CURRENT_DIRECTORY%% + +excluded_fields: + - created_at + - updated_at + - deleted_at \ No newline at end of file diff --git a/src/Templates/Controller.tpl b/src/Templates/Controller.tpl deleted file mode 100644 index eabaa11..0000000 --- a/src/Templates/Controller.tpl +++ /dev/null @@ -1,245 +0,0 @@ -load->model('{{ model }}'); -{% endfor %} - } - - /** - * Shows the form for creating a new {{ singular | lower | replace({'_': ' '}) }}. - * - * @return void - */ - public function create() - { - $data = array(); - $this->_set_form_validation(); - - if ($this->form_validation->run()) - { -{% for column in columns if column != 'datetime_updated' %} -{% set hasGenders = (column.field == 'gender') ? TRUE : FALSE %} -{% set hasMaritalStatus = (column.field == 'marital_status') ? TRUE : FALSE %} -{% if column == 'datetime_created' %} - $this->{{ singular }}->{{ isCamel ? camel[column] : underscore[column] }}('now'); -{% else %} -{% if column in foreignKeys|keys %} - - ${{ foreignKeys[column] }} = $this->{{ type }}->find('{{ foreignKeys[column] }}', $this->input->post('{{ column }}')); - $this->{{ singular }}->{{ isCamel ? camel[column] : underscore[column] }}(${{ foreignKeys[column] }});{{ columns[loop.index0 + 1] in foreignKeys|keys ? '' : "\n"}} -{% else %} - $this->{{ singular }}->{{ isCamel ? camel[column] : underscore[column] }}($this->input->post('{{ column }}')); -{% endif %} -{% endif %} -{% endfor %} - -{% if type == 'doctrine' %} - $this->doctrine->entity_manager->persist($this->{{ singular }}); - $this->doctrine->entity_manager->flush(); -{% else %} - $this->{{ singular }}->save(); -{% endif %} - - $this->session->set_flashdata('notification', 'The {{ singular | lower | replace({'_': ' '}) }} has been created successfully!'); - $this->session->set_flashdata('alert', 'success'); - - redirect('{{ plural }}'); - } -{% if dropdowns | length > 0 %} - -{% for dropdown in dropdowns %} - $data['{{ dropdown.list }}'] = $this->{{ type }}->get_all('{{ dropdown.table }}')->as_dropdown('{{ dropdown.field }}'); -{% endfor %} -{% endif %} -{% if hasGenders %} - $data['genders'] = array('male' => 'Male', 'female' => 'Female'); -{% elseif hasMaritalStatus %} - $data['marital_statuses'] = array( - 'single' => 'Single', - 'married' => 'Married', - 'widowed' => 'Widowed', - 'seperated' => 'Seperated', - 'divorced' => 'Divorced' - ); -{% endif %} - - $this->load->view('{{ plural }}/create', $data); - } - - /** - * Deletes the specified {{ singular | lower | replace({'_': ' '}) }} from storage. - * - * @param int $id - * @return void - */ - public function delete($id) - { - if ( ! isset($id)) - { - show_404(); - } - -{% if type == 'doctrine' %} - ${{ singular }} = $this->doctrine->entity_manager->find('{{ singular }}', $id); - - $this->doctrine->entity_manager->remove(${{ singular }}); - $this->doctrine->entity_manager->flush(); -{% else %} - $this->wildfire->delete('{{ singular }}', $id); -{% endif %} - - $this->session->set_flashdata('notification', 'The {{ singular | lower | replace({'_': ' '}) }} has been deleted successfully!'); - $this->session->set_flashdata('alert', 'success'); - - redirect('{{ plural }}'); - } - - /** - * Shows the form for editing the specified {{ singular | lower | replace({'_': ' '}) }}. - * - * @param int $id - * @return void - */ - public function edit($id) - { - if ( ! isset($id)) - { - show_404(); - } - - $this->_set_form_validation(); - - if ($this->form_validation->run()) - { - ${{ singular }} = $this->{{ type }}->find('{{ singular }}', $id); - -{% for column in columns if column != 'datetime_updated' %} -{% if column == 'datetime_created' %} - ${{ singular }}->{{ isCamel ? camel[column] : underscore[column] }}('now'); -{% else %} -{% if column in foreignKeys|keys %} - - ${{ foreignKeys[column] }} = $this->{{ type }}->find('{{ foreignKeys[column] }}', $this->input->post('{{ column }}')); - ${{ singular }}->{{ isCamel ? camel[column] : underscore[column] }}(${{ foreignKeys[column] }});{{ columns[loop.index0 + 1] in foreignKeys|keys ? '' : "\n"}} -{% else %} - ${{ singular }}->{{ isCamel ? camel[column] : underscore[column] }}($this->input->post('{{ column }}')); -{% endif %} -{% endif %} -{% endfor %} - -{% if type == 'doctrine' %} - $this->doctrine->entity_manager->persist(${{ singular }}); - $this->doctrine->entity_manager->flush(); -{% else %} - ${{ singular }}->save(); -{% endif %} - - $this->session->set_flashdata('notification', 'The {{ singular | lower | replace({'_': ' '}) }} has been updated successfully!'); - $this->session->set_flashdata('alert', 'success'); - - redirect('{{ plural }}'); - } - - $data['{{ singular }}'] = $this->{{ type }}->find('{{ singular }}', $id); -{% for dropdown in dropdowns %} - $data['{{ dropdown.list }}'] = $this->{{ type }}->get_all('{{ dropdown.table }}')->as_dropdown('{{ dropdown.field }}'); -{% endfor %} -{% if hasGenders %} - $data['genders'] = array('male' => 'Male', 'female' => 'Female'); -{% elseif hasMaritalStatus %} - $data['marital_statuses'] = array( - 'single' => 'Single', - 'married' => 'Married', - 'widowed' => 'Widowed', - 'seperated' => 'Seperated', - 'divorced' => 'Divorced' - ); -{% endif %} - - $this->load->view('{{ plural }}/edit', $data); - } - - /** - * Displays a listing of {{ plural | lower | replace({'_': ' '}) }}. - * - * @return void - */ - public function index() - { - $this->load->library('pagination'); - - include APPPATH . 'config/pagination.php'; - - $delimiters = array(); - $delimiters['keyword'] = $this->input->get('keyword'); - - $config['base_url'] = base_url('{{ plural }}'); - $config['suffix'] = '&keyword=' . $delimiters['keyword']; - $config['total_rows'] = $this->{{ type }}->get_all('{{ singular }}', $delimiters)->total_rows(); - - $delimiters['page'] = $this->input->get($config['query_string_segment']); - $delimiters['per_page'] = $config['per_page']; - - $this->pagination->initialize($config); - - $data['{{ plural }}'] = $this->{{ type }}->get_all('{{ singular }}', $delimiters)->result(); - $data['links'] = $this->pagination->create_links(); - - $this->load->view('{{ plural }}/index', $data); - } - - /** - * Displays the specified {{ singular | lower | replace({'_': ' '}) }}. - * - * @param int $id - * @return void - */ - public function show($id) - { - if ( ! isset($id)) - { - show_404(); - } - - $data['{{ singular }}'] = $this->{{ type }}->find('{{ singular }}', $id); - - $this->load->view('{{ plural }}/show', $data); - } - - /** - * Validates the input retrieved from the view. - * - * @return void - */ - private function _set_form_validation() - { - $this->load->library('form_validation'); - -{% for column in columns %} -{% if column in foreignKeys|keys %} - $this->form_validation->set_rules('{{ column }}', '{{ foreignKeys[column] | lower | capitalize | replace({'_': ' '}) }}', 'required|greater_than[0]'); -{% elseif column != 'datetime_created' and column != 'datetime_updated' %} - $this->form_validation->set_rules('{{ column }}', '{{ column | capitalize | replace({'_': ' '}) }}', 'required'); -{% endif %} -{% endfor %} - } - -} \ No newline at end of file diff --git a/src/Templates/DoctrineCLI.tpl b/src/Templates/DoctrineCLI.tpl deleted file mode 100644 index a53178e..0000000 --- a/src/Templates/DoctrineCLI.tpl +++ /dev/null @@ -1,62 +0,0 @@ -. - */ - -use Symfony\Component\Console\Helper\HelperSet; -use Doctrine\ORM\Tools\Console\ConsoleRunner; - -(@include_once __DIR__ . '/../vendor/autoload.php') || @include_once __DIR__ . '/../../../autoload.php'; - -/** - * Path to the root folder - */ - -define('ROOT', __DIR__ . '/../../../../'); - -/** - * Path to the "system" folder - */ - -define('BASEPATH', str_replace('\\\\', '/', ROOT . 'system/')); - -/** - * The path to the "application" folder - */ - -define('APPPATH', ROOT . 'application/'); - -/** - * Load the Doctrine Library - */ - -require APPPATH . '/libraries/Doctrine.php'; - -$doctrine = new Doctrine(); - -$helperSet = require $doctrine->cli(); - -if ( ! ($helperSet instanceof HelperSet)) { - foreach ($GLOBALS as $helperSetCandidate) { - if ($helperSetCandidate instanceof HelperSet) { - $helperSet = $helperSetCandidate; - break; - } - } -} - -\Doctrine\ORM\Tools\Console\ConsoleRunner::run($helperSet, $commands); \ No newline at end of file diff --git a/src/Templates/Htaccess.tpl b/src/Templates/Htaccess.tpl deleted file mode 100644 index 1b5ab03..0000000 --- a/src/Templates/Htaccess.tpl +++ /dev/null @@ -1,6 +0,0 @@ -RewriteEngine on -Options +FollowSymLinks -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d -RewriteCond %{REQUEST_FILENAME} !-l -RewriteRule .* index.php/$0 [PT,L] \ No newline at end of file diff --git a/src/Templates/Libraries/Doctrine.tpl b/src/Templates/Libraries/Doctrine.tpl deleted file mode 100644 index 6326141..0000000 --- a/src/Templates/Libraries/Doctrine.tpl +++ /dev/null @@ -1,303 +0,0 @@ - - * @author Rougin Gutib - * - * stackoverflow.com/questions/17121997/integrating-doctrine-with-codeigniter - */ -class Doctrine { - - /** - * The variable for handling the entity manager - */ - public $entity_manager; - - private $_describe; - private $_query; - private $_query_builder; - private $_table; - private $_tables = array(); - - /** - * Setup the CLI and load the specified classes - * - * @return void - */ - public function __construct() - { - /** - * Load the database configuration from CodeIgniter - */ - - require APPPATH . 'config/database.php'; - - $driver = $db['default']['dbdriver']; - $hostname = $db['default']['hostname']; - - if ($driver == 'pdo' && strpos($hostname, ':') !== FALSE) - { - $keys = explode(':', $hostname); - $driver .= '_' . $keys[0]; - } - - $connection_options = array( - 'driver' => $driver, - 'user' => $db['default']['username'], - 'password' => $db['default']['password'], - 'host' => $db['default']['hostname'], - 'dbname' => $db['default']['database'], - 'charset' => $db['default']['char_set'], - ); - - if ($driver == 'pdo_sqlite') - { - $keys = explode(':', $db['default']['hostname']); - $connection_options['path'] = $keys[1]; - } - - /** - * With this configuration, your model files need to be in application/models/ - * e.g. Creating a new \User loads the class from application/models/User.php - */ - - $metadata_paths = array(APPPATH . 'models'); - $models = APPPATH . 'models'; - $models_namespace = ''; - $proxies = APPPATH . 'models/proxies'; - - /** - * Set $dev_mode to TRUE to disable caching while you develop - */ - - $config = Setup::createAnnotationMetadataConfiguration($metadata_paths, $dev_mode = true, $proxies); - $this->entity_manager = EntityManager::create($connection_options, $config); - - $loader = new ClassLoader($models_namespace, $models); - $loader->register(); - - /** - * Load the Query Builder - */ - - $this->_query_builder = $this->entity_manager->createQueryBuilder(); - - /** - * Load Describe - */ - - $this->_describe = new Describe(new CodeIgniterDriver($db)); - } - - /** - * List all data in dropdown format - * - * @param string $description - * @return array - */ - public function as_dropdown($description = 'description') - { - $table_information = $this->_describe->get_table($this->_table); - - $data = array(''); - $description = 'get_' . $description; - $id = 'get_' . $this->_describe->get_primary_key($this->_table); - - if ( ! method_exists($this->_table, $id)) - { - $id = camelize($id); - } - - if ( ! method_exists($this->_table, $description)) - { - $description = camelize($description); - } - - $result = $this->_query->getResult(); - - foreach ($result as $row) { - $data[$row->$id()] = ucwords($row->$description()); - } - - return $data; - } - - /** - * The Command Line Interface (CLI) configuration for Doctrine - * - * @return object - */ - public function cli() - { - foreach ($GLOBALS as $helper_set_candidate) - { - if ($helper_set_candidate instanceof HelperSet) - { - $helperSet = $helper_set_candidate; - break; - } - } - - $helperSet = new HelperSet(array( - 'db' => new ConnectionHelper($this->entity_manager->getConnection()), - 'em' => new EntityManagerHelper($this->entity_manager) - )); - - return ConsoleRunner::run($helperSet); - } - - /** - * Retrieve a listing of data from the specified table - * - * @param string $table - * @param array $delimiters - * @return Doctrine - */ - public function get_all($table, $delimiters = array()) - { - $alias = $this->_get_alias($table); - $this->_table = $table; - - $this->_query_builder->resetDQLParts(); - $this->_query_builder->select($alias)->from($table, $alias); - - if (isset($delimiters['keyword']) && $delimiters['keyword'] != NULL) - { - $this->_find_by_keyword($delimiters['keyword']); - } - - if (isset($delimiters['per_page']) && $delimiters['per_page'] != NULL) - { - $page = $delimiters['per_page'] * $delimiters['page'] - $delimiters['per_page']; - - if ($page == NULL || $page < 0) - { - $page = 0; - } - - $this->_query_builder->setFirstResult($page); - $this->_query_builder->setMaxResults($delimiters['per_page']); - } - - $this->_query = $this->_query_builder->getQuery(); - - return $this; - } - - /** - * Return the result - * - * @return object - */ - public function result() - { - $result = $this->_query->getResult(); - - return $result; - } - - /** - * Return the number of rows from the result - * - * @return int - */ - public function total_rows() - { - $result = $this->_query->getResult(); - - return count($result); - } - - /** - * Search for keywords based on the list of columns in the storage - * - * @param string $keyword - * @param string $table - * @param array $tables - * @param string $table_alias - */ - private function _find_by_keyword($keyword, $table = NULL, $tables = array(), $table_alias = NULL) - { - if ($table == NULL) - { - $table = $this->_table; - } - - if ($table_alias == NULL) - { - $table_alias = $this->_get_alias($table); - } - - if ( ! array_key_exists($table, $this->_tables)) - { - $table_information = $this->_describe->get_table($table); - $this->_tables[$table] = $table_information; - } - else - { - $table_information = $this->_tables[$table]; - } - - array_push($tables, $table); - - foreach ($table_information as $column) - { - if ($column->isForeignKey()) - { - if ( ! in_array($column->get_referenced_table(), $tables)) - { - $foreign_table_alias = $this->_get_alias($column->get_referenced_table()); - - $this->_query_builder->leftJoin($table_alias . '.' . $column->get_field(), $foreign_table_alias); - - array_push($tables, $column->get_referenced_table()); - $tables = array_unique($tables); - $this->_find_by_keyword($keyword, $column->get_referenced_table(), $tables, $foreign_table_alias); - } - } - else if ( ! $column->isPrimaryKey()) - { - $this->_query_builder->orWhere( - $this->_query_builder->expr()->like($table_alias . '.' . $column->get_field(), - $this->_query_builder->expr()->literal('%' . $keyword . '%')) - ); - } - } - } - - /** - * Get the corresponding alias of the specified table - * - * @param string $table - * @return string - */ - private function _get_alias($table) - { - $alias = ''; - $words = explode('_', $table); - - foreach ($words as $word) - { - $alias .= $word[0]; - } - - return $alias; - } - -} \ No newline at end of file diff --git a/src/Templates/Libraries/Wildfire.tpl b/src/Templates/Libraries/Wildfire.tpl deleted file mode 100644 index ee1892a..0000000 --- a/src/Templates/Libraries/Wildfire.tpl +++ /dev/null @@ -1,320 +0,0 @@ -_ci =& get_instance(); - $this->_ci->load->database(); - $this->_ci->load->helper('inflector'); - - require APPPATH . 'config/database.php'; - - $this->_describe = new Describe(new CodeIgniterDriver($db)); - } - - /** - * List all data in dropdown format - * - * @param string $description - * @return array - */ - public function as_dropdown($description = 'description') - { - $table_information = $this->_describe->get_table($this->_table); - - $data = array(); - $description = 'get_' . $description; - $id = 'get_' . $this->_describe->get_primary_key($this->_table); - - $result = $this->result(); - - foreach ($result as $row) { - $data[$row->$id()] = ucwords($row->$description()); - } - - return $data; - } - - /** - * Delete the specified data from storage - * - * @param string $table - * @param array|integer $delimiters - * @return boolean - */ - public function delete($table, $delimiters = array()) - { - if ( ! is_array($delimiters)) - { - $id = $delimiters; - $primary_key = $this->_describe->get_primary_key($table); - - $delimiters = array($primary_key => $id); - } - - $this->_ci->db->where($delimiters); - return ($this->_ci->db->delete($table)) ? TRUE : FALSE; - } - - /** - * Find the row from the specified ID or with the list of delimiters from the specified table - * - * @param string $table - * @param array|integer delimiters - * @return object|boolean - */ - public function find($table, $delimiters = array()) - { - if ( ! is_array($delimiters)) - { - $id = $delimiters; - $primary_key = $this->_describe->get_primary_key($table); - - $delimiters = array($primary_key => $id); - } - - $this->_ci->db->where($delimiters); - $query = $this->_ci->db->get($table); - - if ($query->num_rows() > 0) - { - return $this->_create_object($table, $query->row()); - } - - return FALSE; - } - - /** - * Return all rows from the specified table - * - * @param array $delimiters - * @return object|boolean - */ - public function get_all($table, $delimiters = array()) - { - $this->_rows = array(); - $this->_table = $table; - - if (isset($delimiters['keyword']) && $delimiters['keyword'] != NULL) - { - $this->_find_by_keyword($delimiters['keyword']); - } - - if (isset($delimiters['per_page']) && $delimiters['per_page'] != NULL) - { - $page = $delimiters['page']; - - if ($page != NULL) - { - $page = $delimiters['per_page'] * $page - $delimiters['per_page']; - } - - $this->_ci->db->limit($delimiters['per_page'], $page); - } - - $this->_query = $this->_ci->db->get($table); - - return $this; - } - - /** - * Join a specified model into the result - * - * @param string $table - * @param string $referenced_field - * @param string $column - * @return object - */ - public function join($table, $referenced_field, $column) - { - $this->_joined_tables[$column] = array( - 'table' => $table, - 'referenced_field' => $referenced_field - ); - - return $this; - } - - /** - * Return the result - * - * @return object - */ - public function result() - { - foreach ($this->_query->result() as $row) - { - $this->_rows[] = $this->_create_object($this->_table, $row); - } - - return $this->_rows; - } - - /** - * Return the number of rows from the result - * - * @return int - */ - public function total_rows() - { - return $this->_query->num_rows(); - } - - /** - * Create an object from the specified data - * - * @param string $table - * @param object $row - * @return array - */ - protected function _create_object($table, $row) - { - $new_table = singular(Tools::strip_table_schema($table)); - $model = new $new_table(); - - if ( ! array_key_exists($new_table, $this->_tables)) - { - $main_table_information = $this->_describe->get_table($new_table); - $this->_tables[$new_table] = $main_table_information; - } - else - { - $main_table_information = $this->_tables[$new_table]; - } - - foreach ($row as $column => $value) - { - $mutator = 'set_' . $column; - - foreach ($main_table_information as $table_column) - { - if ($table_column->get_field() != $column) - { - continue; - } - - $data = $value; - - if ($table_column->is_foreign_key()) - { - $delimiters = array($table_column->get_referenced_field() => $data); - $data = $this->find($table_column->get_referenced_table(), $delimiters); - } - - if ($data && method_exists($model, $mutator)) - { - $model->$mutator($data); - } - } - - if (isset($this->_joined_tables[$column])) - { - $delimiters = array($this->_joined_tables[$column]['referenced_field'] => $value); - $data = $this->find($this->_joined_tables[$column]['table'], $delimiters); - - $model->$mutator($data); - } - } - - foreach ($main_table_information as $table_column) - { - $method = $table_column->get_field(); - $mutator = 'set_' . $table_column->get_field(); - - $data = $row->$method; - - if ($table_column->is_foreign_key()) - { - $delimiters = array($table_column->get_referenced_field() => $data); - $data = $this->find($table_column->get_referenced_table(), $delimiters); - } - - if ($data && method_exists($model, $mutator)) - { - $model->$mutator($data); - } - } - - return $model; - } - - /** - * Search for keywords based on the list of columns in the storage - * - * @param string $keyword - * @param string $table - * @param array $tables - * @param string $table_alias - */ - protected function _find_by_keyword($keyword, $table = NULL, $tables = array(), $table_alias = NULL) - { - if ($table == NULL) - { - $table = $this->_table; - } - - if ($table_alias == NULL) - { - $table_alias = $table; - } - - if ( ! array_key_exists($table, $this->_tables)) - { - $table_information = $this->_describe->get_table($table); - $this->_tables[$table] = $table_information; - } - else - { - $table_information = $this->_tables[$table]; - } - - array_push($tables, $table); - - foreach ($table_information as $column) - { - if ($column->is_foreign_key()) - { - if ( ! in_array($column->get_referenced_table(), $tables)) - { - $foreign_primary_key = $this->_describe->get_primary_key($column->get_referenced_table()); - $foreign_table_alias = rand(0, 100) . '_' . Tools::strip_table_schema($table) . '_' . Tools::strip_table_schema($column->get_referenced_table()); - $condition = $foreign_table_alias . '.' . $foreign_primary_key . ' = ' . $table_alias . '.' . $column->get_field(); - - $this->_ci->db->join($column->get_referenced_table() . ' as ' . $foreign_table_alias, $condition, 'left'); - - array_push($tables, $column->get_referenced_table()); - $tables = array_unique($tables); - $this->_find_by_keyword($keyword, $column->get_referenced_table(), $tables, $foreign_table_alias); - } - } - else if ( ! $column->is_primary_key()) - { - $this->_ci->db->or_like($table_alias . '.' . $column->get_field(), $keyword); - } - } - } - -} \ No newline at end of file diff --git a/src/Templates/Model.tpl b/src/Templates/Model.tpl deleted file mode 100644 index 9d60096..0000000 --- a/src/Templates/Model.tpl +++ /dev/null @@ -1,124 +0,0 @@ -_{{ column.field }}; - } - - /** - * Gets {{ column.field | lower | replace({'_': ' '}) }} - * - * @param {{ column.dataType }} - * @return {{ name | capitalize }} - */ - public function {{ mutator }}({{ column.isForeignKey ? '\\' ~ column.referencedTable | capitalize ~ ' ' : '' }}${{ field }}) - { -{% if column.dataType == 'datetime' %} - $this->_{{ column.field }} = new \DateTime(${{ field }}); -{% else %} - $this->_{{ column.field }} = ${{ field }}; -{% endif %} - - return $this; - } - -{% endfor %} -{% if type == 'wildfire' %} - /** - * Saves the data to storage - * - * @return boolean - */ - public function save() - { - $data = array( -{% for column in columns if column.field != 'datetime_created' and column.field != 'datetime_updated' %} -{% set field = isCamel ? camel[column.field].field : underscore[column.field].field %} -{% set accessor = isCamel ? camel[column.field]['accessor'] : underscore[column.field]['accessor'] %} -{% if column.field in primaryKeys|keys %} - '{{ column.field }}' => $this->{{ accessor }}()->{{ primaryKeys[column.field] }}(), -{% else %} - '{{ column.field }}' => $this->{{ accessor }}(), -{% endif %} -{% endfor %} - ); -{% for column in columns if column.field == 'datetime_created' or column.field == 'datetime_updated' %} -{% set field = isCamel ? camel[column.field].field : underscore[column.field].field %} -{% set accessor = isCamel ? camel[column.field]['accessor'] : underscore[column.field]['accessor'] %} - - if ($this->_{{ column.field }}) - { - $data['{{ column.field }}'] = $this->{{ accessor }}()->format('Y-m-d H:i:s'); - } -{% endfor %} - - if ($this->_{{ primaryKey }} > 0) - { - $this->db->where('{{ primaryKey }}', $this->_{{ primaryKey }}); - - if ($this->db->get('{{ name }}')->num_rows()) - { - if ($this->db->update('{{ name }}', $data, array('{{ primaryKey }}' => $this->_{{ primaryKey }}))) - { - return TRUE; - } - } - else if ($this->db->insert('{{ name }}', $data)) - { - return TRUE; - } - } - else if ($this->db->insert('{{ name }}', $data)) - { - $this->_{{ primaryKey }} = $this->db->insert_id(); - - return TRUE; - } - - return FALSE; - } - -{% endif %} -} \ No newline at end of file diff --git a/src/Templates/Pagination.tpl b/src/Templates/Pagination.tpl deleted file mode 100644 index 3674e2b..0000000 --- a/src/Templates/Pagination.tpl +++ /dev/null @@ -1,33 +0,0 @@ -'; -// $config['full_tag_close'] = ''; -// $config['num_tag_open'] = '
  • '; -// $config['num_tag_close'] = '
  • '; -// $config['cur_tag_open'] = '
  • '; -// $config['cur_tag_close'] = '
  • '; -// $config['next_tag_open'] = '
  • '; -// $config['next_tagl_close'] = '
  • '; -// $config['prev_tag_open'] = '
  • '; -// $config['prev_tagl_close'] = '
  • '; -// $config['first_tag_open'] = '
  • '; -// $config['first_tagl_close'] = '
  • '; -// $config['last_tag_open'] = '
  • '; -// $config['last_tagl_close'] = '
  • '; \ No newline at end of file diff --git a/src/Templates/Views/Layout/footer.tpl b/src/Templates/Views/Layout/footer.tpl deleted file mode 100644 index 62f4a6b..0000000 --- a/src/Templates/Views/Layout/footer.tpl +++ /dev/null @@ -1,10 +0,0 @@ -{% for script in scripts %} - -{% endfor %} - session->flashdata('notification')): ?> - - - - \ No newline at end of file diff --git a/src/Templates/Views/Layout/header.tpl b/src/Templates/Views/Layout/header.tpl deleted file mode 100644 index 00dfbf5..0000000 --- a/src/Templates/Views/Layout/header.tpl +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - Document <?php echo ($this->uri->segment(1)) ? ' - ' . ucwords(str_replace('_', ' ', $this->uri->segment(1))) : NULL; ?> -{% for styleSheet in styleSheets %} - -{% endfor %} - - -
    diff --git a/src/Templates/Views/create.tpl b/src/Templates/Views/create.tpl deleted file mode 100644 index 6f7bf56..0000000 --- a/src/Templates/Views/create.tpl +++ /dev/null @@ -1,37 +0,0 @@ -load->view('layout/header'); ?> -

    - - {{ plural | title }} -

    - -
    - - - Cancel - -
    -{% for column in columns if not column.isPrimaryKey and column.field != 'datetime_created' and column.field != 'datetime_updated' %} -
    -{% if column.field in foreignKeys|keys %} -{% set field = foreignKeys[column.field ~ '_singular'] | lower | capitalize | replace({'_': ' '}) %} -{% elseif column.field != 'datetime_created' and column.field != 'datetime_updated' %} -{% set field = column.field | capitalize | replace({'_': ' '}) %} -{% endif %} - '{{ bootstrap.label }}')); ?> -
    -{% if column.field in foreignKeys|keys %} - -{% elseif column.dataType == 'date' or column.dataType == 'datetime' %} - -{% else %} - -{% endif %} - -
    -
    -{% endfor %} - -load->view('layout/footer'); ?> \ No newline at end of file diff --git a/src/Templates/Views/edit.tpl b/src/Templates/Views/edit.tpl deleted file mode 100644 index c7fdd8f..0000000 --- a/src/Templates/Views/edit.tpl +++ /dev/null @@ -1,38 +0,0 @@ -load->view('layout/header'); ?> -

    - - {{ plural | title }} -

    - {{ primaryKey }}(), 'class=""'); ?> -
    - - - Cancel - -
    -{% for column in columns if not column.isPrimaryKey and column.field != 'datetime_created' and column.field != 'datetime_updated' %} -{% set accessor = isCamel ? camel[column.field]['accessor'] : underscore[column.field]['accessor'] %} -
    -{% if column.field in foreignKeys|keys %} -{% set field = foreignKeys[column.field ~ '_singular'] | lower | capitalize | replace({'_': ' '}) %} -{% elseif column.field != 'datetime_created' and column.field != 'datetime_updated' %} -{% set field = column.field | capitalize | replace({'_': ' '}) %} -{% endif %} - '{{ bootstrap.label }}')); ?> -
    -{% if column.field in foreignKeys|keys %} - {{ accessor }}()->{{ primaryKeys[column.field] }}()), 'class="{{ bootstrap - .formControl }}" {{ column.isNull ? '' : 'required' }}'); ?> -{% elseif column.dataType == 'date' or column.dataType == 'datetime' %} - -{% else %} - {{ accessor }}()), 'class="{{ bootstrap.formControl }}" {{ column.isNull ? '' : 'required' }}'); ?> -{% endif %} - -
    -
    -{% endfor %} - -load->view('layout/footer'); ?> \ No newline at end of file diff --git a/src/Templates/Views/index.tpl b/src/Templates/Views/index.tpl deleted file mode 100644 index d8240de..0000000 --- a/src/Templates/Views/index.tpl +++ /dev/null @@ -1,49 +0,0 @@ -load->view('layout/header'); ?> -

    - - {{ plural | title }} -

    - - - - - -{% for column in columns if not column.isPrimaryKey and column.field != 'datetime_created' and column.field != 'datetime_updated' %} - -{% endfor %} - - - - - -{% for column in columns if not column.isPrimaryKey and column.field != 'datetime_created' and column.field != 'datetime_updated' %} -{% set accessor = isCamel ? camel[column.field]['accessor'] : underscore[column.field]['accessor'] %} -{% if column.field in foreignKeys|keys %} - -{% else %} - -{% endif %} -{% endfor %} - - - - -
    {{ column.field | replace({'_id': '', '_': ' '}) | title }}
    {{ accessor }}()->{{ primaryKeys[column.field] }}(); ?>{{ accessor }}(); ?> - - - - - - -
    - - input->get('keyword')): ?> - Your search - input->get('keyword') ?> - did not match any {{ plural | lower | replace({'_': ' '}) }}. - - There are no {{ plural | lower | replace({'_': ' '}) }} that are currently available. - -load->view('layout/footer'); ?> \ No newline at end of file diff --git a/src/Templates/Views/show.tpl b/src/Templates/Views/show.tpl deleted file mode 100644 index 6039b41..0000000 --- a/src/Templates/Views/show.tpl +++ /dev/null @@ -1,29 +0,0 @@ -load->view('layout/header'); ?> -

    - - {{ plural | title }} -

    - -{% for column in columns if not column.isPrimaryKey and column.field != 'datetime_created' and column.field != 'datetime_updated' %} -{% set accessor = isCamel ? camel[column.field]['accessor'] : underscore[column.field]['accessor'] %} -
    -{% if column.field in foreignKeys|keys %} -{% set field = foreignKeys[column.field] | lower | capitalize | replace({'_': ' '}) %} -{% elseif column.field != 'datetime_created' and column.field != 'datetime_updated' %} -{% set field = column.field | capitalize | replace({'_': ' '}) %} -{% endif %} - '{{ bootstrap.label }}')); ?> -
    -{% if column.field in foreignKeys|keys %} - -{% else %} - -{% endif %} -
    -
    -{% endfor %} -load->view('layout/footer'); ?> \ No newline at end of file diff --git a/src/Validator/BaseValidator.php b/src/Validator/BaseValidator.php deleted file mode 100644 index 2df20fb..0000000 --- a/src/Validator/BaseValidator.php +++ /dev/null @@ -1,110 +0,0 @@ - - */ -class BaseValidator implements ValidatorInterface -{ - /** - * @var array - */ - protected $file = []; - - /** - * @var boolean - */ - protected $isCamel = false; - - /** - * @var string - */ - protected $library = ''; - - /** - * @var string - */ - protected $message = ''; - - /** - * @param boolean $isCamel - * @param array $file - */ - public function __construct($isCamel, $file) - { - $this->file = $file; - $this->isCamel = $isCamel; - } - - /** - * Checks if the validator fails. - * - * @return boolean - */ - public function fails() - { - $hasDoctrine = file_exists(APPPATH . 'libraries/Doctrine.php'); - $hasWildfire = file_exists(APPPATH . 'libraries/Wildfire.php'); - - if (! $hasWildfire && ! $hasDoctrine) { - $this->message = 'Please install Wildfire or Doctrine!'; - - return true; - } - - if ($hasWildfire && $hasDoctrine) { - $this->message = 'Both Wildfire and Doctrine exists! Choose only one.'; - - return true; - } - - if ($hasWildfire && $this->isCamel) { - $this->message = 'Wildfire does not support camel casing!'; - - return true; - } - - if (file_exists($this->file['path'])) { - $name = $this->file['name']; - $type = $this->file['type']; - - $this->message = 'The "' . $name . '" ' . $type . ' already exists!'; - - return true; - } - - if ($hasDoctrine) { - $this->library = 'doctrine'; - } else { - $this->library = 'wildfire'; - } - - return false; - } - - /** - * Gets the rendered message. - * - * @return string - */ - public function getMessage() - { - return $this->message; - } - - /** - * Gets the selected library. - * - * @return string - */ - public function getLibrary() - { - return $this->library; - } -} diff --git a/src/Validator/ControllerValidator.php b/src/Validator/ControllerValidator.php deleted file mode 100644 index 7561238..0000000 --- a/src/Validator/ControllerValidator.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -class ControllerValidator extends BaseValidator -{ -} diff --git a/src/Validator/ModelValidator.php b/src/Validator/ModelValidator.php deleted file mode 100644 index 2c42abb..0000000 --- a/src/Validator/ModelValidator.php +++ /dev/null @@ -1,15 +0,0 @@ - - */ -class ModelValidator extends BaseValidator -{ -} diff --git a/src/Validator/ValidatorInterface.php b/src/Validator/ValidatorInterface.php deleted file mode 100644 index 6585fcc..0000000 --- a/src/Validator/ValidatorInterface.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ -interface ValidatorInterface -{ - /** - * Checks if the validator fails. - * - * @return boolean - */ - public function fails(); - - /** - * Gets the rendered message. - * - * @return string - */ - public function getMessage(); -} diff --git a/src/Validator/ViewValidator.php b/src/Validator/ViewValidator.php deleted file mode 100644 index 0e815df..0000000 --- a/src/Validator/ViewValidator.php +++ /dev/null @@ -1,60 +0,0 @@ - - */ -class ViewValidator implements ValidatorInterface -{ - /** - * @var string - */ - protected $name = ''; - - /** - * @var string - */ - protected $message = ''; - - public function __construct($name) - { - $this->name = $name; - } - - /** - * Checks if the validator fails. - * - * @return boolean - */ - public function fails() - { - $filePath = APPPATH . 'views/' . $this->name; - - if (! @mkdir($filePath, 0775, true)) { - $this->message = 'The "' . $this->name . '" views folder already exists!'; - - return true; - } - - return false; - } - - /** - * Gets the rendered message. - * - * @return string - */ - public function getMessage() - { - return $this->message; - } -} diff --git a/tests/AppTest.php b/tests/AppTest.php new file mode 100644 index 0000000..0fa6149 --- /dev/null +++ b/tests/AppTest.php @@ -0,0 +1,41 @@ + + */ +class AppTest extends Testcase +{ + /** + * @return void + */ + public function test_combustor_yml_file() + { + $app = new Console(__DIR__ . '/Fixture'); + + $expected = 'Rougin\Blueprint\Wrapper'; + + $actual = $app->make()->find('create:controller'); + + $this->assertInstanceOf($expected, $actual); + } + + /** + * @return void + */ + public function test_without_combustor_yml() + { + $app = new Console(__DIR__ . '/../'); + + $expected = 'Rougin\Blueprint\Wrapper'; + + $actual = $app->make()->find('initialize'); + + $this->assertInstanceOf($expected, $actual); + } +} diff --git a/tests/CheckTest.php b/tests/CheckTest.php new file mode 100644 index 0000000..7de3af8 --- /dev/null +++ b/tests/CheckTest.php @@ -0,0 +1,127 @@ + + */ +class CheckTest extends Testcase +{ + /** + * @return void + */ + public function test_with_packages_absent() + { + $app = new Console(__DIR__ . '/Fixture'); + + $command = $app->make()->find('create:controller'); + + $test = new CommandTester($command); + + $input = array('table' => 'users'); + + $test->execute($input); + + $expected = '[FAIL] Both "rougin/credo" and "rougin/wildfire" are not installed. Kindly "rougin/credo" or "rougin/wildfire" first.'; + + $actual = $this->getActualDisplay($test); + + $this->assertEquals($expected, $actual); + } + + /** + * @return void + */ + public function test_with_packages_absent_as_scaffold() + { + $app = new Console(__DIR__ . '/Fixture'); + + $command = $app->make()->find('create:scaffold'); + + $test = new CommandTester($command); + + $input = array('table' => 'users'); + + $test->execute($input); + + $expected = '[FAIL] Both "rougin/credo" and "rougin/wildfire" are not installed. Kindly "rougin/credo" or "rougin/wildfire" first.'; + + $actual = $this->getActualDisplay($test); + + $this->assertEquals($expected, $actual); + } + + /** + * @return void + */ + public function test_with_packages_absent_view() + { + $app = new Console(__DIR__ . '/Fixture'); + + $command = $app->make()->find('create:view'); + + $test = new CommandTester($command); + + $input = array('table' => 'users'); + + $test->execute($input); + + $expected = '[FAIL] Both "rougin/credo" and "rougin/wildfire" are not installed. Kindly "rougin/credo" or "rougin/wildfire" first.'; + + $actual = $this->getActualDisplay($test); + + $this->assertEquals($expected, $actual); + } + + /** + * @return void + */ + public function test_with_packages_present() + { + // Mock class of specified packages --- + $test = 'Rougin\Combustor\Inflector'; + + $doctrine = 'Rougin\Credo\Credo'; + class_alias($test, $doctrine); + + $wildfire = 'Rougin\Wildfire\Wildfire'; + class_alias($test, $wildfire); + // ------------------------------------ + + $app = new Console(__DIR__ . '/Fixture'); + + $command = $app->make()->find('create:model'); + + $test = new CommandTester($command); + + $input = array('table' => 'users'); + + $test->execute($input); + + $expected = '[FAIL] Both "rougin/credo" and "rougin/wildfire" are installed. Kindly select --doctrine or --wildfire first.'; + + $actual = $this->getActualDisplay($test); + + $this->assertEquals($expected, $actual); + } + + /** + * @param \Symfony\Component\Console\Tester\CommandTester $tester + * + * @return string + */ + protected function getActualDisplay(CommandTester $tester) + { + $actual = $tester->getDisplay(); + + $actual = str_replace("\r\n", '', $actual); + + return str_replace("\n", '', $actual); + } +} diff --git a/tests/CombustorTest.php b/tests/CombustorTest.php deleted file mode 100644 index 53422b5..0000000 --- a/tests/CombustorTest.php +++ /dev/null @@ -1,78 +0,0 @@ -appPath = __DIR__ . '/TestApp/application'; - } - - /** - * Tests if the initial commands exists. - * - * @return void - */ - public function testCommandsExist() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $application = $this->getApplication(); - - $this->assertTrue($application->has('create:layout')); - $this->assertTrue($application->has('install:doctrine')); - $this->assertTrue($application->has('install:wildfire')); - } - - /** - * Gets the application with the loaded classes. - * - * @return \Symfony\Component\Console\Application - */ - protected function getApplication() - { - $application = new Application; - - foreach ($this->commands as $commandName) { - $command = CommandBuilder::create($commandName); - - $application->add($command); - } - - return $application; - } -} diff --git a/tests/Commands/CreateControllerCommandTest.php b/tests/Commands/CreateControllerCommandTest.php deleted file mode 100644 index 83e85df..0000000 --- a/tests/Commands/CreateControllerCommandTest.php +++ /dev/null @@ -1,100 +0,0 @@ -appPath = __DIR__ . '/../TestApp/application'; - - $createCommand = 'Rougin\Combustor\Commands\CreateControllerCommand'; - - $this->createCommand = CommandBuilder::create($createCommand); - } - - /** - * Tests if the expected Wildfire controller is created. - * - * @return void - */ - public function testWildfireControllerIsCreated() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $wildfireCommand = 'Rougin\Combustor\Commands\InstallWildfireCommand'; - $wildfire = CommandBuilder::create($wildfireCommand); - - $installCommand = new CommandTester($wildfire); - $installCommand->execute([]); - - $createCommand = new CommandTester($this->createCommand); - $createCommand->execute([ - 'name' => $this->table, - '--camel' => false, - '--keep' => false - ]); - - $file = $this->appPath . '/controllers/' . ucfirst(plural($this->table)) . '.php'; - - $this->assertFileExists($file); - - CodeIgniterHelper::setDefaults($this->appPath); - } - - /** - * Tests if the expected Doctrine controller is created. - * - * @return void - */ - public function testDoctrineControllerIsCreated() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $doctrineCommand = 'Rougin\Combustor\Commands\InstallDoctrineCommand'; - $doctrine = CommandBuilder::create($doctrineCommand); - - $installCommand = new CommandTester($doctrine); - $installCommand->execute([]); - - $createCommand = new CommandTester($this->createCommand); - $createCommand->execute([ - 'name' => $this->table, - '--camel' => false, - '--keep' => true - ]); - - $file = $this->appPath . '/controllers/' . ucfirst($this->table) . '.php'; - - $this->assertFileExists($file); - - CodeIgniterHelper::setDefaults($this->appPath); - } -} diff --git a/tests/Commands/CreateLayoutCommandTest.php b/tests/Commands/CreateLayoutCommandTest.php deleted file mode 100644 index 59dab9a..0000000 --- a/tests/Commands/CreateLayoutCommandTest.php +++ /dev/null @@ -1,74 +0,0 @@ -appPath = __DIR__ . '/../TestApp/application'; - $command = 'Rougin\Combustor\Commands\CreateLayoutCommand'; - - $this->command = CommandBuilder::create($command); - } - - /** - * Tests if the expected file exists after executing the command. - * - * @return void - */ - public function testFilesExist() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $command = new CommandTester($this->command); - $command->execute([ '--bootstrap' => true ]); - - $header = $this->appPath . '/views/layout/header.php'; - $footer = $this->appPath . '/views/layout/footer.php'; - - $this->assertFileExists($header); - $this->assertFileExists($footer); - - CodeIgniterHelper::setDefaults($this->appPath); - } - - /** - * Tests if the folder already exists. - * - * @return void - */ - public function testFolderExists() - { - $command = new CommandTester($this->command); - - $command->execute([ '--bootstrap' => true ]); - $command->execute([ '--bootstrap' => true ]); - - $this->assertRegExp('/layout directory already exists/', $command->getDisplay()); - - CodeIgniterHelper::setDefaults($this->appPath); - } -} diff --git a/tests/Commands/CreateModelCommandTest.php b/tests/Commands/CreateModelCommandTest.php deleted file mode 100644 index d8468fa..0000000 --- a/tests/Commands/CreateModelCommandTest.php +++ /dev/null @@ -1,120 +0,0 @@ -appPath = __DIR__ . '/../TestApp/application'; - - $createCommand = 'Rougin\Combustor\Commands\CreateModelCommand'; - - $this->createCommand = CommandBuilder::create($createCommand); - } - - /** - * Tests if the expected Wildfire model is created. - * - * @return void - */ - public function testWildfireModelIsCreated() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $wildfireCommand = 'Rougin\Combustor\Commands\InstallWildfireCommand'; - $wildfire = CommandBuilder::create($wildfireCommand); - - $installCommand = new CommandTester($wildfire); - $installCommand->execute([]); - - $createCommand = new CommandTester($this->createCommand); - $createCommand->execute([ - 'name' => $this->table, - '--camel' => false - ]); - - $file = $this->appPath . '/models/' . ucfirst(singular($this->table)) . '.php'; - - $this->assertFileExists($file); - - CodeIgniterHelper::setDefaults($this->appPath); - } - - /** - * Tests if the expected Doctrine model is created. - * - * @return void - */ - public function testDoctrineModelIsCreated() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $doctrineCommand = 'Rougin\Combustor\Commands\InstallDoctrineCommand'; - $doctrine = CommandBuilder::create($doctrineCommand); - - $installCommand = new CommandTester($doctrine); - $installCommand->execute([]); - - $createCommand = new CommandTester($this->createCommand); - $createCommand->execute([ - 'name' => $this->table, - '--camel' => false - ]); - - $file = $this->appPath . '/models/' . ucfirst(singular($this->table)) . '.php'; - - $this->assertFileExists($file); - - CodeIgniterHelper::setDefaults($this->appPath); - } - - /** - * Tests if command prompts an error if there is no library installed. - * - * @return void - */ - public function testNoLibraryInstalled() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $createCommand = new CommandTester($this->createCommand); - $createCommand->execute([ - 'name' => $this->table, - '--camel' => false - ]); - - $expected = 'Please install Wildfire or Doctrine!' . PHP_EOL; - - $this->assertRegExp('/Please install Wildfire or Doctrine/', $createCommand->getDisplay()); - - CodeIgniterHelper::setDefaults($this->appPath); - } -} diff --git a/tests/Commands/CreateScaffoldCommandTest.php b/tests/Commands/CreateScaffoldCommandTest.php deleted file mode 100644 index d80510a..0000000 --- a/tests/Commands/CreateScaffoldCommandTest.php +++ /dev/null @@ -1,114 +0,0 @@ -appPath = __DIR__ . '/../TestApp/application'; - } - - /** - * Tests if the initial commands exists. - * - * @return void - */ - public function testCommandsExist() - { - CodeIgniterHelper::setDefaults($this->appPath); - - mkdir($this->appPath . '/views/layout'); - - $files = [ - __DIR__ . '/../../src/Templates/Libraries/Wildfire.tpl' => - $this->appPath . '/libraries/Wildfire.php', - __DIR__ . '/../../src/Templates/Views/Layout/header.tpl' => - $this->appPath . '/views/layout/header.php', - __DIR__ . '/../../src/Templates/Views/Layout/footer.tpl' => - $this->appPath . '/views/layout/footer.php' - ]; - - foreach ($files as $source => $destination) { - copy($source, $destination); - } - - $application = $this->getApplication(); - - $command = $application->find('create:scaffold'); - $commandTester = new CommandTester($command); - $commandTester->execute([ - 'name' => $this->table, - '--bootstrap' => true - ]); - - $controller = $this->appPath . '/controllers/' . ucfirst(plural($this->table)) . '.php'; - $model = $this->appPath . '/models/' . ucfirst(singular($this->table)) . '.php'; - - $this->assertFileExists($controller); - $this->assertFileExists($model); - - $create = $this->appPath . '/views/' . plural($this->table) . '/create.php'; - $edit = $this->appPath . '/views/' . plural($this->table) . '/edit.php'; - $index = $this->appPath . '/views/' . plural($this->table) . '/index.php'; - $show = $this->appPath . '/views/' . plural($this->table) . '/show.php'; - - $this->assertFileExists($create); - $this->assertFileExists($edit); - $this->assertFileExists($index); - $this->assertFileExists($show); - - CodeIgniterHelper::setDefaults($this->appPath); - } - - /** - * Gets the application with the loaded classes. - * - * @return \Symfony\Component\Console\Application - */ - protected function getApplication() - { - $application = new Application; - - foreach ($this->commands as $commandName) { - $command = CommandBuilder::create($commandName); - - $application->add($command); - } - - return $application; - } -} diff --git a/tests/Commands/CreateViewCommandTest.php b/tests/Commands/CreateViewCommandTest.php deleted file mode 100644 index cde86eb..0000000 --- a/tests/Commands/CreateViewCommandTest.php +++ /dev/null @@ -1,99 +0,0 @@ -appPath = __DIR__ . '/../TestApp/application'; - - $createCommand = 'Rougin\Combustor\Commands\CreateViewCommand'; - - $this->createCommand = CommandBuilder::create($createCommand); - } - - /** - * Tests if the expected views are created. - * - * @return void - */ - public function testViewsAreCreated() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $createCommand = new CommandTester($this->createCommand); - $createCommand->execute([ - 'name' => $this->table, - '--camel' => true, - '--bootstrap' => true, - '--keep' => true - ]); - - $create = $this->appPath . '/views/' . $this->table . '/create.php'; - $edit = $this->appPath . '/views/' . $this->table . '/edit.php'; - $index = $this->appPath . '/views/' . $this->table . '/index.php'; - $show = $this->appPath . '/views/' . $this->table . '/show.php'; - - $this->assertFileExists($create); - $this->assertFileExists($edit); - $this->assertFileExists($index); - $this->assertFileExists($show); - - CodeIgniterHelper::setDefaults($this->appPath); - } - - /** - * Tests if the command prompts an error if the folder already exists. - * - * @return void - */ - public function testFolderAlreadyExists() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $options = [ - 'name' => $this->table, - '--camel' => true, - '--bootstrap' => true, - '--keep' => false - ]; - - $createCommand = new CommandTester($this->createCommand); - $createCommand->execute($options); - - $createCommand = new CommandTester($this->createCommand); - $createCommand->execute($options); - - $this->assertRegExp('/views folder already exists/', $createCommand->getDisplay()); - - CodeIgniterHelper::setDefaults($this->appPath); - } -} diff --git a/tests/Commands/InstallDoctrineCommandTest.php b/tests/Commands/InstallDoctrineCommandTest.php deleted file mode 100644 index d6e140f..0000000 --- a/tests/Commands/InstallDoctrineCommandTest.php +++ /dev/null @@ -1,72 +0,0 @@ -appPath = __DIR__ . '/../TestApp/application'; - $command = 'Rougin\Combustor\Commands\InstallDoctrineCommand'; - - $this->command = CommandBuilder::create($command); - } - - /** - * Tests if the expected file exists after executing the command. - * - * @return void - */ - public function testFileExists() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $command = new CommandTester($this->command); - $command->execute([]); - - $file = $this->appPath . '/libraries/Doctrine.php'; - - $this->assertFileExists($file); - - $autoload = new Config('autoload', $this->appPath . '/config'); - - $drivers = [ 'session' ]; - $helpers = [ 'form', 'url' ]; - - $this->assertEquals($drivers, $autoload->get('drivers', 81, 'array')); - $this->assertEquals($helpers, $autoload->get('helper', 91, 'array')); - - $config = new Config('config', $this->appPath . '/config'); - - $composerAutoload = 'realpath(\'vendor\') . \'/autoload.php\''; - - $this->assertEquals($composerAutoload, $config->get('composer_autoload', 138, 'string')); - $this->assertEmpty($config->get('index_page', 37, 'string')); - $this->assertEquals(md5('rougin'), $config->get('encryption_key', 316, 'string')); - - CodeIgniterHelper::setDefaults($this->appPath); - } -} diff --git a/tests/Commands/InstallWildfireCommandTest.php b/tests/Commands/InstallWildfireCommandTest.php deleted file mode 100644 index 42ab187..0000000 --- a/tests/Commands/InstallWildfireCommandTest.php +++ /dev/null @@ -1,73 +0,0 @@ -appPath = __DIR__ . '/../TestApp/application'; - $command = 'Rougin\Combustor\Commands\InstallWildfireCommand'; - - $this->command = CommandBuilder::create($command); - } - - /** - * Tests if the expected file exists after executing the command. - * - * @return void - */ - public function testFileExists() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $command = new CommandTester($this->command); - $command->execute([]); - - $file = $this->appPath . '/libraries/Wildfire.php'; - - $this->assertFileExists($file); - - $autoload = new Config('autoload', $this->appPath . '/config'); - - $drivers = [ 'session' ]; - $helpers = [ 'form', 'url' ]; - - $this->assertEquals($drivers, $autoload->get('drivers', 81, 'array')); - $this->assertEquals($helpers, $autoload->get('helper', 91, 'array')); - - $config = new Config('config', $this->appPath . '/config'); - - $composerAutoload = 'realpath(\'vendor\') . \'/autoload.php\''; - - $this->assertEquals($composerAutoload, $config->get('composer_autoload', 138, 'string')); - $this->assertEmpty($config->get('index_page', 37, 'string')); - $this->assertEquals(md5('rougin'), $config->get('encryption_key', 316, 'string')); - - CodeIgniterHelper::setDefaults($this->appPath); - } -} diff --git a/tests/Commands/RemoveDoctrineCommandTest.php b/tests/Commands/RemoveDoctrineCommandTest.php deleted file mode 100644 index 3987d63..0000000 --- a/tests/Commands/RemoveDoctrineCommandTest.php +++ /dev/null @@ -1,66 +0,0 @@ -appPath = __DIR__ . '/../TestApp/application'; - - $installCommand = 'Rougin\Combustor\Commands\InstallDoctrineCommand'; - $removeCommand = 'Rougin\Combustor\Commands\RemoveDoctrineCommand'; - - CodeIgniterHelper::setDefaults($this->appPath); - - $this->installCommand = CommandBuilder::create($installCommand); - $this->removeCommand = CommandBuilder::create($removeCommand); - } - - /** - * Tests if the expected file exists after executing the command. - * - * @return void - */ - public function testFileExists() - { - $installCommand = new CommandTester($this->installCommand); - $installCommand->execute([]); - - $removeCommand = new CommandTester($this->removeCommand); - $removeCommand->execute([]); - - $file = $this->appPath . '/libraries/Doctrine.php'; - - $this->assertTrue(! file_exists($file)); - - CodeIgniterHelper::setDefaults($this->appPath); - } -} diff --git a/tests/Commands/RemoveWildfireCommandTest.php b/tests/Commands/RemoveWildfireCommandTest.php deleted file mode 100644 index 2b3d348..0000000 --- a/tests/Commands/RemoveWildfireCommandTest.php +++ /dev/null @@ -1,66 +0,0 @@ -appPath = __DIR__ . '/../TestApp/application'; - - $installCommand = 'Rougin\Combustor\Commands\InstallWildfireCommand'; - $removeCommand = 'Rougin\Combustor\Commands\RemoveWildfireCommand'; - - CodeIgniterHelper::setDefaults($this->appPath); - - $this->installCommand = CommandBuilder::create($installCommand); - $this->removeCommand = CommandBuilder::create($removeCommand); - } - - /** - * Tests if the expected file exists after executing the command. - * - * @return void - */ - public function testFileExists() - { - $installCommand = new CommandTester($this->installCommand); - $installCommand->execute([]); - - $removeCommand = new CommandTester($this->removeCommand); - $removeCommand->execute([]); - - $file = $this->appPath . '/libraries/Wildfire.php'; - - $this->assertTrue(! file_exists($file)); - - CodeIgniterHelper::setDefaults($this->appPath); - } -} diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php deleted file mode 100644 index 4c4c06e..0000000 --- a/tests/ConfigTest.php +++ /dev/null @@ -1,78 +0,0 @@ -appPath = __DIR__ . '/TestApp/application'; - $this->configPath = $this->appPath . '/config'; - } - - /** - * Tests Config::get. - * - * @return void - */ - public function testGet() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $config = new Config('config', $this->configPath); - - $this->assertFalse($config->get('enable_hooks', 102, 'boolean')); - $this->assertEquals('index.php', $config->get('index_page', 37, 'string')); - $this->assertEmpty($config->get('csrf_exclude_uris', 445, 'array')); - - CodeIgniterHelper::setDefaults($this->appPath); - } - - /** - * Tests Config::set. - * - * @return void - */ - public function testSet() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $expected = [ - 'http://localhost/', - true, - ['foo', 'bar'] - ]; - - $config = new Config('config', $this->configPath); - - $config->set('base_url', 25, $expected[0], 'string'); - $config->set('csrf_protection', 440, $expected[1], 'boolean'); - $config->set('csrf_exclude_uris', 445, $expected[2], 'array'); - - $config->save(); - - $this->assertEquals($expected[0], $config->get('base_url', 25, 'string')); - $this->assertEquals($expected[1], $config->get('csrf_protection', 440, 'boolean')); - $this->assertEquals($expected[2], $config->get('csrf_exclude_uris', 445, 'array')); - - CodeIgniterHelper::setDefaults($this->appPath); - } -} diff --git a/tests/Fixture/CodeIgniterHelper.php b/tests/Fixture/CodeIgniterHelper.php deleted file mode 100644 index 3885b5e..0000000 --- a/tests/Fixture/CodeIgniterHelper.php +++ /dev/null @@ -1,105 +0,0 @@ - - */ -class CodeIgniterHelper -{ - /** - * Sets default configurations. - * - * @param string $appPath - * @return void - */ - public static function setDefaults($appPath) - { - $files = [ - [ - 'source' => $appPath . '/config/default/autoload.php', - 'destination' => $appPath . '/config/autoload.php' - ], - [ - 'source' => $appPath . '/config/default/config.php', - 'destination' => $appPath . '/config/config.php' - ], - ]; - - foreach ($files as $file) { - $contents = file_get_contents($file['source']); - - file_put_contents($file['destination'], $contents); - } - - self::emptyDirectory($appPath . '/controllers'); - self::emptyDirectory($appPath . '/models'); - self::emptyDirectory($appPath . '/views'); - - $files = [ - $appPath . '/config/pagination.php', - $appPath . '/libraries/Doctrine.php', - $appPath . '/libraries/Wildfire.php', - $appPath . '/views/layout/header.php', - $appPath . '/views/layout/footer.php', - '.htaccess', - ]; - - foreach ($files as $file) { - if (file_exists($file)) { - unlink($file); - } - } - - $directories = [ - $appPath . '/views/layout', - $appPath . '/models/proxies', - 'bower_components', - 'vendor/doctrine/orm' - ]; - - foreach ($directories as $directory) { - if (is_dir($directory)) { - self::emptyDirectory($directory, true); - } - } - } - - /** - * Deletes files in the specified directory. - * - * @param string $directory - * @param boolean $delete - * @return void - */ - protected static function emptyDirectory($directory, $delete = false) - { - $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS); - $files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST); - - foreach ($files as $file) { - $isErrorDirectory = strpos($file->getRealPath(), 'errors'); - $isIndexHtml = strpos($file->getRealPath(), 'index.html'); - - if ($isErrorDirectory !== false || $isIndexHtml !== false) { - continue; - } - - if ($file->isDir()) { - rmdir($file->getRealPath()); - } else { - unlink($file->getRealPath()); - } - } - - if ($delete) { - rmdir($directory); - } - } -} diff --git a/tests/Fixture/CommandBuilder.php b/tests/Fixture/CommandBuilder.php deleted file mode 100644 index 2d5afeb..0000000 --- a/tests/Fixture/CommandBuilder.php +++ /dev/null @@ -1,76 +0,0 @@ - - */ -class CommandBuilder -{ - /** - * Injects a command with its dependencies. - * - * @param string $command - * @param string $app - * @param string $templates - * @return \Symfony\Component\Console\Command\Command - */ - public static function create($command, $app = '', $templates = '') - { - $injector = new Injector; - - if (empty($app)) - { - $app = __DIR__ . '/../TestApp'; - } - - if (empty($templates)) - { - $templates = __DIR__ . '/../../src/Templates'; - } - - $injector->delegate('Twig\Environment', function () use ($templates) { - $loader = new FilesystemLoader($templates); - - return new Environment($loader); - }); - - $injector->delegate('Rougin\Describe\Describe', function () use ($app) { - $ci = Instance::create($app); - - $ci->load->database(); - $ci->load->helper('inflector'); - - $config['default'] = - [ - 'dbdriver' => $ci->db->dbdriver, - 'hostname' => $ci->db->hostname, - 'username' => $ci->db->username, - 'password' => $ci->db->password, - 'database' => $ci->db->database - ]; - - if (empty($config['default']['hostname'])) - { - $config['default']['hostname'] = $ci->db->dsn; - } - - $driver = new CodeIgniterDriver($config); - - return new Describe($driver); - }); - - return $injector->make($command); - } -} diff --git a/tests/Fixture/Plates/Doctrine/Common/CreateView.php b/tests/Fixture/Plates/Doctrine/Common/CreateView.php new file mode 100644 index 0000000..9e419be --- /dev/null +++ b/tests/Fixture/Plates/Doctrine/Common/CreateView.php @@ -0,0 +1,40 @@ +

    Create New User

    + + +
    + + + ', '
    ') ?> +
    + +
    + + + ', '
    ') ?> +
    + +
    + + + ', '
    ') ?> +
    + +
    + + + ', '
    ') ?> + + +
    + + + ', '
    ') ?> + + + +
    + + + + + \ No newline at end of file diff --git a/tests/Fixture/Plates/Doctrine/Common/EditView.php b/tests/Fixture/Plates/Doctrine/Common/EditView.php new file mode 100644 index 0000000..3d19f44 --- /dev/null +++ b/tests/Fixture/Plates/Doctrine/Common/EditView.php @@ -0,0 +1,42 @@ +

    Update User

    + +get_id()) ?> + + +
    + + get_email())) ?> + ', '
    ') ?> + + +
    + + get_name())) ?> + ', '
    ') ?> + + +
    + + get_year())) ?> + ', '
    ') ?> + + +
    + + get_admin())) ?> + ', '
    ') ?> + + +
    + + get_remarks())) ?> + ', '
    ') ?> + + + +
    + + + + + \ No newline at end of file diff --git a/tests/Fixture/Plates/Doctrine/Common/IndexView.php b/tests/Fixture/Plates/Doctrine/Common/IndexView.php new file mode 100644 index 0000000..68464a4 --- /dev/null +++ b/tests/Fixture/Plates/Doctrine/Common/IndexView.php @@ -0,0 +1,64 @@ +

    Users

    + + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    EmailNameYearAdminRemarksCreated AtUpdated AtDeleted At
    get_email() ?>get_name() ?>get_year() ?>get_admin() ?>get_remarks() ?>get_created_at() ?>get_updated_at() ?>get_deleted_at() ?> + + Edit + + + get_id()) ?> + + Delete + + +
    + +
    + + \ No newline at end of file diff --git a/tests/Fixture/Plates/Doctrine/Controller.php b/tests/Fixture/Plates/Doctrine/Controller.php new file mode 100644 index 0000000..7f86695 --- /dev/null +++ b/tests/Fixture/Plates/Doctrine/Controller.php @@ -0,0 +1,242 @@ +load->database(); + // ---------------------------------- + + // Load view-related helpers ------ + $this->load->helper('form'); + $this->load->helper('url'); + $this->load->library('pagination'); + $this->load->library('session'); + // -------------------------------- + + // Load multiple models if required --- + $this->load->model('user'); + + $this->load->repository('user'); + // ------------------------------------ + + // Load the main repository of the model --- + $credo = new Credo($this->db); + + /** @var \User_repository */ + $repo = $credo->get_repository('User'); + + $this->repo = $repo; + // ----------------------------------------- + } + + /** + * Returns the form page for creating a user. + * Creates a new user if receiving payload. + * + * @return void + */ + public function create() + { + // Skip if provided empty input --- + /** @var array */ + $input = $this->input->post(null, true); + + if (! $input) + { + $this->load->view('users/create'); + + return; + } + // -------------------------------- + + // Specify logic here if applicable --- + $exists = $this->repo->exists($input); + + $data = array(); + + if ($exists) + { + $data['error'] = ''; + } + // ------------------------------------ + + // Check if provided input is valid --- + $valid = $this->user->validate($input); + + if (! $valid || $exists) + { + $this->load->view('users/create', $data); + + return; + } + // ------------------------------------ + + // Create the item then go back to "index" page --- + $this->repo->create($input, new User); + + $text = (string) 'User successfully created!'; + + $this->session->set_flashdata('alert', $text); + + redirect('users'); + // ------------------------------------------------ + } + + /** + * Deletes the specified user. + * + * @param integer $id + * + * @return void + */ + public function delete($id) + { + // Show 404 page if not using "DELETE" method --- + $method = $this->input->post('_method', true); + + $item = $this->repo->find($id); + + if ($method !== 'DELETE' || ! $item) + { + show_404(); + } + // ---------------------------------------------- + + // Delete the item then go back to "index" page --- + /** @var \User $item */ + $this->repo->delete($item); + + $text = (string) 'User successfully deleted!'; + + $this->session->set_flashdata('alert', $text); + + redirect('users'); + // ------------------------------------------------ + } + + /** + * Returns the form page for updating a user. + * Updates the specified user if receiving payload. + * + * @param integer $id + * + * @return void + */ + public function edit($id) + { + // Show 404 page if item not found --- + if (! $item = $this->repo->find($id)) + { + show_404(); + } + + /** @var \User $item */ + $data = array('item' => $item); + // ----------------------------------- + + // Skip if provided empty input --- + /** @var array */ + $input = $this->input->post(null, true); + + if (! $input) + { + $this->load->view('users/edit', $data); + + return; + } + // -------------------------------- + + // Show 404 page if not using "PUT" method --- + $method = $this->input->post('_method', true); + + if ($method !== 'PUT') + { + show_404(); + } + // ------------------------------------------- + + // Specify logic here if applicable --- + $exists = $this->repo->exists($input, $id); + + if ($exists) + { + $data['error'] = ''; + } + // ------------------------------------ + + // Check if provided input is valid --- + $valid = $this->user->validate($input); + + if (! $valid || $exists) + { + $this->load->view('users/edit', $data); + + return; + } + // ------------------------------------ + + // Update the item then go back to "index" page --- + /** @var \User $item */ + $this->repo->update($item, $input); + + $text = (string) 'User successfully updated!'; + + $this->session->set_flashdata('alert', $text); + + redirect('users'); + // ------------------------------------------------ + } + + /** + * Returns the list of paginated users. + * + * @return void + */ + public function index() + { + // Create pagination links and get the offset --- + $total = (int) $this->repo->total(); + + $result = $this->user->paginate(10, $total); + + $data = array('links' => $result[1]); + + /** @var integer */ + $offset = $result[0]; + // ---------------------------------------------- + + $items = $this->repo->get(10, $offset); + + $data['items'] = $items; + + if ($alert = $this->session->flashdata('alert')) + { + $data['alert'] = $alert; + } + + $this->load->view('users/index', $data); + } +} diff --git a/tests/Fixture/Plates/Doctrine/Model.php b/tests/Fixture/Plates/Doctrine/Model.php new file mode 100644 index 0000000..c5af70c --- /dev/null +++ b/tests/Fixture/Plates/Doctrine/Model.php @@ -0,0 +1,277 @@ + + */ + protected $pagee = array( + 'page_query_string' => true, + 'use_page_numbers' => true, + 'query_string_segment' => 'p', + 'reuse_query_string' => true, + ); + + /** + * List of validation rules for Form Validation. + * + * @link https://codeigniter.com/userguide3/libraries/form_validation.html#setting-rules-using-an-array + * + * @var array[] + */ + protected $rules = array( + array('field' => 'email', 'label' => 'Email', 'rules' => 'required'), + array('field' => 'name', 'label' => 'Name', 'rules' => 'required'), + array('field' => 'year', 'label' => 'Year', 'rules' => 'required'), + array('field' => 'admin', 'label' => 'Admin', 'rules' => 'required'), + ); + + /** + * @return boolean + */ + public function is_admin() + { + return $this->admin; + } + + /** + * @return datetime + */ + public function get_created_at() + { + return $this->created_at; + } + + /** + * @return datetime|null + */ + public function get_deleted_at() + { + return $this->deleted_at; + } + + /** + * @return string + */ + public function get_email() + { + return $this->email; + } + + /** + * @return integer + */ + public function get_id() + { + return $this->id; + } + + /** + * @return string + */ + public function get_name() + { + return $this->name; + } + + /** + * @return string|null + */ + public function get_remarks() + { + return $this->remarks; + } + + /** + * @return datetime|null + */ + public function get_updated_at() + { + return $this->updated_at; + } + + /** + * @return integer + */ + public function get_year() + { + return $this->year; + } + + /** + * @param boolean $admin + * + * @return self + */ + public function set_admin($admin) + { + $this->admin = $admin; + + return $this; + } + + /** + * @param string $created_at + * + * @return self + */ + public function set_created_at($created_at) + { + $this->created_at = $created_at; + + return $this; + } + + /** + * @param string|null $deleted_at + * + * @return self + */ + public function set_deleted_at($deleted_at = null) + { + $this->deleted_at = $deleted_at; + + return $this; + } + + /** + * @param string $email + * + * @return self + */ + public function set_email($email) + { + $this->email = $email; + + return $this; + } + + /** + * @param string $name + * + * @return self + */ + public function set_name($name) + { + $this->name = $name; + + return $this; + } + + /** + * @param string|null $remarks + * + * @return self + */ + public function set_remarks($remarks = null) + { + $this->remarks = $remarks; + + return $this; + } + + /** + * @param string|null $updated_at + * + * @return self + */ + public function set_updated_at($updated_at = null) + { + $this->updated_at = $updated_at; + + return $this; + } + + /** + * @param integer $year + * + * @return self + */ + public function set_year($year) + { + $this->year = $year; + + return $this; + } +} diff --git a/tests/Fixture/Plates/Doctrine/Styled/CreateView.php b/tests/Fixture/Plates/Doctrine/Styled/CreateView.php new file mode 100644 index 0000000..919e1e6 --- /dev/null +++ b/tests/Fixture/Plates/Doctrine/Styled/CreateView.php @@ -0,0 +1,40 @@ +

    Create New User

    + + +
    + 'form-label mb-0']) ?> + + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + + ', '
    ') ?> + + + +
    + + + + + \ No newline at end of file diff --git a/tests/Fixture/Plates/Doctrine/Styled/EditView.php b/tests/Fixture/Plates/Doctrine/Styled/EditView.php new file mode 100644 index 0000000..1476b22 --- /dev/null +++ b/tests/Fixture/Plates/Doctrine/Styled/EditView.php @@ -0,0 +1,42 @@ +

    Update User

    + +get_id()) ?> + + +
    + 'form-label mb-0']) ?> + get_email()), 'class="form-control"') ?> + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + get_name()), 'class="form-control"') ?> + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + get_year()), 'class="form-control"') ?> + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + get_admin()), 'class="form-control"') ?> + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + get_remarks()), 'class="form-control"') ?> + ', '
    ') ?> + + + +
    + + + + + \ No newline at end of file diff --git a/tests/Fixture/Plates/Doctrine/Styled/IndexView.php b/tests/Fixture/Plates/Doctrine/Styled/IndexView.php new file mode 100644 index 0000000..cfba5d4 --- /dev/null +++ b/tests/Fixture/Plates/Doctrine/Styled/IndexView.php @@ -0,0 +1,64 @@ +

    Users

    + + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    EmailNameYearAdminRemarksCreated AtUpdated AtDeleted At
    get_email() ?>get_name() ?>get_year() ?>get_admin() ?>get_remarks() ?>get_created_at() ?>get_updated_at() ?>get_deleted_at() ?> + + Edit + + + get_id()) ?> + + Delete + + +
    + +
    + + \ No newline at end of file diff --git a/tests/Fixture/Plates/Layout/CommonFooter.php b/tests/Fixture/Plates/Layout/CommonFooter.php new file mode 100644 index 0000000..691287b --- /dev/null +++ b/tests/Fixture/Plates/Layout/CommonFooter.php @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/tests/Fixture/Plates/Layout/CommonHeader.php b/tests/Fixture/Plates/Layout/CommonHeader.php new file mode 100644 index 0000000..826dc8f --- /dev/null +++ b/tests/Fixture/Plates/Layout/CommonHeader.php @@ -0,0 +1,10 @@ + + + + + + + Welcome to Codeigniter 3 + + +
    \ No newline at end of file diff --git a/tests/Fixture/Plates/Layout/StyledFooter.php b/tests/Fixture/Plates/Layout/StyledFooter.php new file mode 100644 index 0000000..0ddd64f --- /dev/null +++ b/tests/Fixture/Plates/Layout/StyledFooter.php @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/tests/Fixture/Plates/Layout/StyledHeader.php b/tests/Fixture/Plates/Layout/StyledHeader.php new file mode 100644 index 0000000..523e738 --- /dev/null +++ b/tests/Fixture/Plates/Layout/StyledHeader.php @@ -0,0 +1,11 @@ + + + + + + + Welcome to Codeigniter 3 + + + +
    \ No newline at end of file diff --git a/tests/Fixture/Plates/Wildfire/Common/CreateView.php b/tests/Fixture/Plates/Wildfire/Common/CreateView.php new file mode 100644 index 0000000..9e419be --- /dev/null +++ b/tests/Fixture/Plates/Wildfire/Common/CreateView.php @@ -0,0 +1,40 @@ +

    Create New User

    + + +
    + + + ', '
    ') ?> +
    + +
    + + + ', '
    ') ?> +
    + +
    + + + ', '
    ') ?> + + +
    + + + ', '
    ') ?> + + +
    + + + ', '
    ') ?> + + + +
    + + + + + \ No newline at end of file diff --git a/tests/Fixture/Plates/Wildfire/Common/EditView.php b/tests/Fixture/Plates/Wildfire/Common/EditView.php new file mode 100644 index 0000000..86d2269 --- /dev/null +++ b/tests/Fixture/Plates/Wildfire/Common/EditView.php @@ -0,0 +1,42 @@ +

    Update User

    + +id) ?> + + +
    + + email)) ?> + ', '
    ') ?> + + +
    + + name)) ?> + ', '
    ') ?> + + +
    + + year)) ?> + ', '
    ') ?> + + +
    + + admin)) ?> + ', '
    ') ?> + + +
    + + remarks)) ?> + ', '
    ') ?> + + + +
    + + + + + \ No newline at end of file diff --git a/tests/Fixture/Plates/Wildfire/Common/IndexView.php b/tests/Fixture/Plates/Wildfire/Common/IndexView.php new file mode 100644 index 0000000..ddbc9c5 --- /dev/null +++ b/tests/Fixture/Plates/Wildfire/Common/IndexView.php @@ -0,0 +1,64 @@ +

    Users

    + + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    EmailNameYearAdminRemarksCreated AtUpdated AtDeleted At
    email ?>name ?>year ?>admin ?>remarks ?>created_at ?>updated_at ?>deleted_at ?> + + Edit + + + id) ?> + + Delete + + +
    + +
    + + \ No newline at end of file diff --git a/tests/Fixture/Plates/Wildfire/Controller.php b/tests/Fixture/Plates/Wildfire/Controller.php new file mode 100644 index 0000000..30af6ad --- /dev/null +++ b/tests/Fixture/Plates/Wildfire/Controller.php @@ -0,0 +1,222 @@ +load->helper('inflector'); + $this->load->database(); + // ---------------------------------- + + // Load view-related helpers ------ + $this->load->helper('form'); + $this->load->helper('url'); + $this->load->library('pagination'); + $this->load->library('session'); + // -------------------------------- + + // Load multiple models if required --- + $this->load->model('user'); + // ------------------------------------ + } + + /** + * Returns the form page for creating a user. + * Creates a new user if receiving payload. + * + * @return void + */ + public function create() + { + // Skip if provided empty input --- + /** @var array */ + $input = $this->input->post(null, true); + + if (! $input) + { + $this->load->view('users/create'); + + return; + } + // -------------------------------- + + // Specify logic here if applicable --- + $exists = $this->user->exists($input); + + $data = array(); + + if ($exists) + { + $data['error'] = ''; + } + // ------------------------------------ + + // Check if provided input is valid --- + $valid = $this->user->validate($input); + + if (! $valid || $exists) + { + $this->load->view('users/create', $data); + + return; + } + // ------------------------------------ + + // Create the item then go back to "index" page --- + $this->user->create($input); + + $text = (string) 'User successfully created!'; + + $this->session->set_flashdata('alert', $text); + + redirect('users'); + // ------------------------------------------------ + } + + /** + * Deletes the specified user. + * + * @param integer $id + * + * @return void + */ + public function delete($id) + { + // Show 404 page if not using "DELETE" method --- + $method = $this->input->post('_method', true); + + $item = $this->user->find($id); + + if ($method !== 'DELETE' || ! $item) + { + show_404(); + } + // ---------------------------------------------- + + // Delete the item then go back to "index" page --- + $this->user->delete($id); + + $text = (string) 'User successfully deleted!'; + + $this->session->set_flashdata('alert', $text); + + redirect('users'); + // ------------------------------------------------ + } + + /** + * Returns the form page for updating a user. + * Updates the specified user if receiving payload. + * + * @param integer $id + * + * @return void + */ + public function edit($id) + { + // Show 404 page if item not found --- + if (! $item = $this->user->find($id)) + { + show_404(); + } + + /** @var \User $item */ + $data = array('item' => $item); + // ----------------------------------- + + // Skip if provided empty input --- + /** @var array */ + $input = $this->input->post(null, true); + + if (! $input) + { + $this->load->view('users/edit', $data); + + return; + } + // -------------------------------- + + // Show 404 page if not using "PUT" method --- + $method = $this->input->post('_method', true); + + if ($method !== 'PUT') + { + show_404(); + } + // ------------------------------------------- + + // Specify logic here if applicable --- + $exists = $this->user->exists($input, $id); + + if ($exists) + { + $data['error'] = ''; + } + // ------------------------------------ + + // Check if provided input is valid --- + $valid = $this->user->validate($input); + + if (! $valid || $exists) + { + $this->load->view('users/edit', $data); + + return; + } + // ------------------------------------ + + // Update the item then go back to "index" page --- + $this->user->update($id, $input); + + $text = (string) 'User successfully updated!'; + + $this->session->set_flashdata('alert', $text); + + redirect('users'); + // ------------------------------------------------ + } + + /** + * Returns the list of paginated users. + * + * @return void + */ + public function index() + { + // Create pagination links and get the offset --- + $total = (int) $this->user->total(); + + $result = $this->user->paginate(10, $total); + + $data = array('links' => $result[1]); + + /** @var integer */ + $offset = $result[0]; + // ---------------------------------------------- + + $items = $this->user->get(10, $offset); + + $data['items'] = $items->result(); + + if ($alert = $this->session->flashdata('alert')) + { + $data['alert'] = $alert; + } + + $this->load->view('users/index', $data); + } +} diff --git a/tests/Fixture/Plates/Wildfire/Model.php b/tests/Fixture/Plates/Wildfire/Model.php new file mode 100644 index 0000000..4893952 --- /dev/null +++ b/tests/Fixture/Plates/Wildfire/Model.php @@ -0,0 +1,113 @@ + + */ + protected $pagee = array( + 'page_query_string' => true, + 'use_page_numbers' => true, + 'query_string_segment' => 'p', + 'reuse_query_string' => true, + ); + + /** + * List of validation rules for Form Validation. + * + * @link https://codeigniter.com/userguide3/libraries/form_validation.html#setting-rules-using-an-array + * + * @var array[] + */ + protected $rules = array( + array('field' => 'email', 'label' => 'Email', 'rules' => 'required'), + array('field' => 'name', 'label' => 'Name', 'rules' => 'required'), + array('field' => 'year', 'label' => 'Year', 'rules' => 'required'), + array('field' => 'admin', 'label' => 'Admin', 'rules' => 'required'), + ); + + /** + * The table associated with the model. + * + * @var string + */ + protected $table = 'users'; + + /** + * @param array $data + * @param integer|null $id + * + * @return boolean + */ + public function exists($data, $id = null) + { + // Specify logic here if applicable --- + // ------------------------------------ + + return false; + } + + /** + * @param array $data + * @param integer|null $id + * + * @return array + */ + protected function input($data, $id = null) + { + $load = array(); + + // List editable fields from table --- + /** @var string */ + $email = $data['email']; + $load['email'] = $email; + + /** @var string */ + $name = $data['name']; + $load['name'] = $name; + + /** @var integer */ + $year = $data['year']; + $load['year'] = $year; + + /** @var boolean */ + $admin = $data['admin']; + $load['admin'] = $admin; + + /** @var string|null */ + $remarks = $data['remarks']; + if ($remarks) + { + $load['remarks'] = $remarks; + } + // ----------------------------------- + + return $load; + } +} diff --git a/tests/Fixture/Plates/Wildfire/Styled/CreateView.php b/tests/Fixture/Plates/Wildfire/Styled/CreateView.php new file mode 100644 index 0000000..919e1e6 --- /dev/null +++ b/tests/Fixture/Plates/Wildfire/Styled/CreateView.php @@ -0,0 +1,40 @@ +

    Create New User

    + + +
    + 'form-label mb-0']) ?> + + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + + ', '
    ') ?> + + + +
    + + + + + \ No newline at end of file diff --git a/tests/Fixture/Plates/Wildfire/Styled/EditView.php b/tests/Fixture/Plates/Wildfire/Styled/EditView.php new file mode 100644 index 0000000..1137f2d --- /dev/null +++ b/tests/Fixture/Plates/Wildfire/Styled/EditView.php @@ -0,0 +1,42 @@ +

    Update User

    + +id) ?> + + +
    + 'form-label mb-0']) ?> + email), 'class="form-control"') ?> + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + name), 'class="form-control"') ?> + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + year), 'class="form-control"') ?> + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + admin), 'class="form-control"') ?> + ', '
    ') ?> + + +
    + 'form-label mb-0']) ?> + remarks), 'class="form-control"') ?> + ', '
    ') ?> + + + +
    + + + + + \ No newline at end of file diff --git a/tests/Fixture/Plates/Wildfire/Styled/IndexView.php b/tests/Fixture/Plates/Wildfire/Styled/IndexView.php new file mode 100644 index 0000000..65819e2 --- /dev/null +++ b/tests/Fixture/Plates/Wildfire/Styled/IndexView.php @@ -0,0 +1,64 @@ +

    Users

    + + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    EmailNameYearAdminRemarksCreated AtUpdated AtDeleted At
    email ?>name ?>year ?>admin ?>remarks ?>created_at ?>updated_at ?>deleted_at ?> + + Edit + + + id) ?> + + Delete + + +
    + +
    + + \ No newline at end of file diff --git a/tests/TestApp/application/config/autoload.php b/tests/Fixture/Sample/config/autoload.php similarity index 99% rename from tests/TestApp/application/config/autoload.php rename to tests/Fixture/Sample/config/autoload.php index 355dd75..d07684a 100644 --- a/tests/TestApp/application/config/autoload.php +++ b/tests/Fixture/Sample/config/autoload.php @@ -1,4 +1,5 @@ + */ +class InstallTest extends Testcase +{ + /** + * @return void + */ + public function test_install_doctrine() + { + $test = $this->findCommand('install:doctrine'); + + $test->execute(array()); + + $expected = '[PASS] Doctrine installed successfully!'; + + $actual = $this->getActualDisplay($test); + + $this->assertEquals($expected, $actual); + } + + /** + * @return void + */ + public function test_install_wildfire() + { + $test = $this->findCommand('install:wildfire'); + + $test->execute(array()); + + $expected = '[PASS] Wildfire installed successfully!'; + + $actual = $this->getActualDisplay($test); + + $this->assertEquals($expected, $actual); + } + + /** + * @depends test_install_doctrine + * + * @return void + */ + public function test_remove_doctrine() + { + // Mock class of specified packages ----- + $test = 'Rougin\Combustor\Inflector'; + class_alias($test, 'Rougin\Credo\Credo'); + // -------------------------------------- + + $test = $this->findCommand('remove:doctrine'); + + $test->execute(array()); + + $expected = '[PASS] Doctrine removed successfully!'; + + $actual = $this->getActualDisplay($test); + + $this->assertEquals($expected, $actual); + } + + /** + * @depends test_install_wildfire + * + * @return void + */ + public function test_remove_wildfire() + { + // Mock class of specified packages ----------- + $test = 'Rougin\Combustor\Inflector'; + class_alias($test, 'Rougin\Wildfire\Wildfire'); + // -------------------------------------------- + + $test = $this->findCommand('remove:wildfire'); + + $test->execute(array()); + + $expected = '[PASS] Wildfire removed successfully!'; + + $actual = $this->getActualDisplay($test); + + $this->assertEquals($expected, $actual); + } + + /** + * @param string $name + * + * @return \Symfony\Component\Console\Tester\CommandTester + */ + protected function findCommand($name) + { + $app = new Console(__DIR__ . '/Fixture'); + + $command = $app->make()->find($name); + + return new CommandTester($command); + } + + /** + * @param \Symfony\Component\Console\Tester\CommandTester $tester + * + * @return string + */ + protected function getActualDisplay(CommandTester $tester) + { + $actual = $tester->getDisplay(); + + $actual = str_replace("\r\n", '', $actual); + + return str_replace("\n", '', $actual); + } +} diff --git a/tests/PlateTest.php b/tests/PlateTest.php new file mode 100644 index 0000000..4776949 --- /dev/null +++ b/tests/PlateTest.php @@ -0,0 +1,500 @@ + + */ +class PlateTest extends Testcase +{ + const TYPE_CONTROLLER = 0; + + const TYPE_MODEL = 1; + + const TYPE_VIEW = 2; + + const VIEW_COMMON = 0; + + const VIEW_STYLED = 1; + + /** + * @var \Rougin\Combustor\Console + */ + protected $app; + + /** + * @return void + */ + public function doSetUp() + { + $this->app = new Console(__DIR__ . '/Fixture'); + } + + /** + * @return void + */ + public function test_creating_layout() + { + $test = $this->findCommand('create:layout'); + + $test->execute(array()); + + $type = self::VIEW_COMMON; + + $expected = $this->getLayoutView($type); + + $actual = $this->getActualLayout(); + + $this->assertEquals($expected, $actual); + } + + /** + * @return void + */ + public function test_creating_layout_with_bootstrap() + { + $test = $this->findCommand('create:layout'); + + $test->execute(array('--bootstrap' => true)); + + $type = self::VIEW_STYLED; + + $expected = $this->getLayoutView($type); + + $actual = $this->getActualLayout(); + + $this->assertEquals($expected, $actual); + } + + /** + * @return void + */ + public function test_doctrine_controller() + { + $test = $this->findCommand('create:controller'); + + $input = array('table' => 'users'); + $input['--doctrine'] = true; + + $test->execute($input); + + $expected = $this->getDoctrineCtrl(); + + $actual = $this->getActualCtrl('Users'); + + $this->assertEquals($expected, $actual); + } + + /** + * @return void + */ + public function test_doctrine_model() + { + $test = $this->findCommand('create:model'); + + $input = array('table' => 'users'); + $input['--doctrine'] = true; + + $test->execute($input); + + $expected = $this->getDoctrineModel(); + + $actual = $this->getActualModel('User'); + + $this->assertEquals($expected, $actual); + } + + /** + * @return void + */ + public function test_doctrine_view() + { + $test = $this->findCommand('create:view'); + + $input = array('table' => 'users'); + $input['--doctrine'] = true; + + $test->execute($input); + + $expected = $this->getDoctrineView(); + + $actual = $this->getActualView('User'); + + $this->assertEquals($expected, $actual); + } + + /** + * @return void + */ + public function test_doctrine_view_with_bootstrap() + { + $test = $this->findCommand('create:view'); + + $input = array('table' => 'users'); + $input['--doctrine'] = true; + $input['--bootstrap'] = true; + + $test->execute($input); + + $expected = $this->getDoctrineView(self::VIEW_STYLED); + + $actual = $this->getActualView('User'); + + $this->assertEquals($expected, $actual); + } + + /** + * @return void + */ + public function test_scaffold_on_doctrine() + { + $test = $this->findCommand('create:scaffold'); + + $input = array('table' => 'users'); + $input['--doctrine'] = true; + $input['--bootstrap'] = true; + + $test->execute($input); + + // Return the controller, model, and views -------- + $route = $this->getDoctrineCtrl(); + + $model = $this->getDoctrineModel(); + + $views = $this->getDoctrineView(self::VIEW_STYLED); + + $expected = $route . "\n" . $model . "\n" . $views; + // ------------------------------------------------ + + // Return the actual results -------------------- + $route = $this->getActualCtrl('Users'); + + $model = $this->getActualModel('User'); + + $views = $this->getActualView('User'); + + $actual = $route . "\n" . $model . "\n" . $views; + // ---------------------------------------------- + + $this->assertEquals($expected, $actual); + } + + /** + * @return void + */ + public function test_wildfire_controller() + { + $test = $this->findCommand('create:controller'); + + $input = array('table' => 'users'); + $input['--wildfire'] = true; + + $test->execute($input); + + $expected = $this->getWildfireCtrl(); + + $actual = $this->getActualCtrl('Users'); + + $this->assertEquals($expected, $actual); + } + + /** + * @return void + */ + public function test_wildfire_model() + { + $test = $this->findCommand('create:model'); + + $input = array('table' => 'users'); + $input['--wildfire'] = true; + + $test->execute($input); + + $expected = $this->getWildfireModel(); + + $actual = $this->getActualModel('User'); + + $this->assertEquals($expected, $actual); + } + + /** + * @return void + */ + public function test_wildfire_view() + { + $test = $this->findCommand('create:view'); + + $input = array('table' => 'users'); + $input['--wildfire'] = true; + + $test->execute($input); + + $expected = $this->getWildfireView(); + + $actual = $this->getActualView('User'); + + $this->assertEquals($expected, $actual); + } + + /** + * @return void + */ + public function test_wildfire_view_with_bootstrap() + { + $test = $this->findCommand('create:view'); + + $input = array('table' => 'users'); + $input['--wildfire'] = true; + $input['--bootstrap'] = true; + + $test->execute($input); + + $expected = $this->getWildfireView(self::VIEW_STYLED); + + $actual = $this->getActualView('User'); + + $this->assertEquals($expected, $actual); + } + + /** + * @param string $name + * + * @return void + */ + protected function deleteView($name) + { + $path = $this->app->getAppPath(); + + $source = $path . '/views/' . $name; + + /** @var string[] */ + $files = glob($source . '/*.*'); + + array_map('unlink', $files); + + rmdir($path . '/views/' . $name); + } + + /** + * @param string $name + * + * @return \Symfony\Component\Console\Tester\CommandTester + */ + protected function findCommand($name) + { + return new CommandTester($this->app->make()->find($name)); + } + + /** + * @param string $name + * + * @return string + */ + protected function getActualCtrl($name) + { + return $this->getActualFile($name, self::TYPE_CONTROLLER); + } + + /** + * @param string $name + * @param integer $type + * + * @return string + */ + protected function getActualFile($name, $type = self::TYPE_CONTROLLER) + { + $path = $this->app->getAppPath(); + + if ($type === self::TYPE_VIEW) + { + $path .= '/views'; + } + + if ($type === self::TYPE_CONTROLLER) + { + $path .= '/controllers'; + } + + if ($type === self::TYPE_MODEL) + { + $path .= '/models'; + } + + $file = $path . '/' . $name . '.php'; + + /** @var string */ + + + $result = file_get_contents($file); + + return str_replace("\r\n", "\n", $result); + } + + /** + * @return string + */ + protected function getActualLayout() + { + $name = 'layout'; + + $header = $this->getActualFile($name . '/header', self::TYPE_VIEW); + + $footer = $this->getActualFile($name . '/footer', self::TYPE_VIEW); + + // Delete directory after getting the files --- + $this->deleteView($name); + // -------------------------------------------- + + return $header . "\n" . $footer; + } + + /** + * @param string $name + * + * @return string + */ + protected function getActualModel($name) + { + return $this->getActualFile($name, self::TYPE_MODEL); + } + + /** + * @param string $name + * + * @return string + */ + protected function getActualView($name) + { + $name = strtolower(Inflector::plural($name)); + + $create = $this->getActualFile($name . '/create', self::TYPE_VIEW); + + $edit = $this->getActualFile($name . '/edit', self::TYPE_VIEW); + + $index = $this->getActualFile($name . '/index', self::TYPE_VIEW); + + // Delete directory after getting the files --- + $this->deleteView($name); + // -------------------------------------------- + + return $create . "\n" . $edit . "\n" . $index; + } + + /** + * @return string + */ + protected function getDoctrineCtrl() + { + return $this->getTemplate('Doctrine/Controller'); + } + + /** + * @return string + */ + protected function getDoctrineModel() + { + return $this->getTemplate('Doctrine/Model'); + } + + /** + * @param integer $type + * + * @return string + */ + protected function getDoctrineView($type = self::VIEW_COMMON) + { + $name = 'Common'; + + if ($type === self::VIEW_STYLED) + { + $name = 'Styled'; + } + + $create = $this->getTemplate('Doctrine/' . $name . '/CreateView'); + + $edit = $this->getTemplate('Doctrine/' . $name . '/EditView'); + + $index = $this->getTemplate('Doctrine/' . $name . '/IndexView'); + + return $create . "\n" . $edit . "\n" . $index; + } + + /** + * @param integer $type + * + * @return string + */ + protected function getLayoutView($type = self::VIEW_COMMON) + { + $name = 'Common'; + + if ($type === self::VIEW_STYLED) + { + $name = 'Styled'; + } + + $header = $this->getTemplate('Layout/' . $name . 'Header'); + + $footer = $this->getTemplate('Layout/' . $name . 'Footer'); + + return $header . "\n" . $footer; + } + + /** + * @param string $name + * + * @return string + */ + protected function getTemplate($name) + { + $path = __DIR__ . '/Fixture/Plates/' . $name . '.php'; + + /** @var string */ + $file = file_get_contents($path); + + return str_replace("\r\n", "\n", $file); + } + + /** + * @return string + */ + protected function getWildfireCtrl() + { + return $this->getTemplate('Wildfire/Controller'); + } + + /** + * @return string + */ + protected function getWildfireModel() + { + return $this->getTemplate('Wildfire/Model'); + } + + /** + * @param integer $type + * + * @return string + */ + protected function getWildfireView($type = self::VIEW_COMMON) + { + $name = 'Common'; + + if ($type === self::VIEW_STYLED) + { + $name = 'Styled'; + } + + $create = $this->getTemplate('Wildfire/' . $name . '/CreateView'); + + $edit = $this->getTemplate('Wildfire/' . $name . '/EditView'); + + $index = $this->getTemplate('Wildfire/' . $name . '/IndexView'); + + return $create . "\n" . $edit . "\n" . $index; + } +} diff --git a/tests/Testcase.php b/tests/Testcase.php new file mode 100644 index 0000000..03088dd --- /dev/null +++ b/tests/Testcase.php @@ -0,0 +1,29 @@ + + */ +class Testcase extends Legacy +{ + /** @phpstan-ignore-next-line */ + public function setExpectedException($exception) + { + if (method_exists($this, 'expectException')) + { + $this->expectException($exception); + + return; + } + + /** @phpstan-ignore-next-line */ + parent::setExpectedException($exception); + } +} diff --git a/tests/ToolsTest.php b/tests/ToolsTest.php deleted file mode 100644 index 10da995..0000000 --- a/tests/ToolsTest.php +++ /dev/null @@ -1,25 +0,0 @@ -assertEquals('post', $table); - $this->assertEmpty($file->getContents()); - } -} diff --git a/tests/ValidatorTest.php b/tests/ValidatorTest.php deleted file mode 100644 index 876daed..0000000 --- a/tests/ValidatorTest.php +++ /dev/null @@ -1,158 +0,0 @@ -appPath = __DIR__ . '/TestApp/application'; - - $createCommand = 'Rougin\Combustor\Commands\CreateControllerCommand'; - - $this->createCommand = CommandBuilder::create($createCommand); - } - - /** - * Tests if command prompts an error if there is no library installed. - * - * @return void - */ - public function testNoLibraryInstalled() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $createCommand = new CommandTester($this->createCommand); - $createCommand->execute([ - 'name' => $this->table, - '--camel' => false, - '--keep' => true - ]); - - $this->assertRegExp('/Please install Wildfire or Doctrine/', $createCommand->getDisplay()); - - CodeIgniterHelper::setDefaults($this->appPath); - } - - /** - * Tests if command prompts an error if user does not select a library. - * - * @return void - */ - public function testNoLibrarySelected() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $templatesPath = __DIR__ . '/../src/Templates'; - - $files = [ - $templatesPath . '/Libraries/Wildfire.tpl' => - $this->appPath . '/libraries/Wildfire.php', - $templatesPath . '/Libraries/Doctrine.tpl' => - $this->appPath . '/libraries/Doctrine.php', - ]; - - foreach ($files as $source => $destination) { - copy($source, $destination); - } - - $createCommand = new CommandTester($this->createCommand); - $createCommand->execute([ - 'name' => $this->table, - '--camel' => false, - '--keep' => false - ]); - - $this->assertRegExp('/Choose only one/', $createCommand->getDisplay()); - - CodeIgniterHelper::setDefaults($this->appPath); - } - - /** - * Tests if the generated file already exists. - * - * @return void - */ - public function testFileExists() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $wildfireCommand = 'Rougin\Combustor\Commands\InstallWildfireCommand'; - $wildfire = CommandBuilder::create($wildfireCommand); - - $installCommand = new CommandTester($wildfire); - $installCommand->execute([]); - - $createCommand = new CommandTester($this->createCommand); - $createCommand->execute([ - 'name' => $this->table, - '--camel' => false, - '--keep' => true - ]); - - $createCommand = new CommandTester($this->createCommand); - $createCommand->execute([ - 'name' => $this->table, - '--camel' => false, - '--keep' => true - ]); - - $this->assertRegExp('/controller already exists/', $createCommand->getDisplay()); - - CodeIgniterHelper::setDefaults($this->appPath); - } - - /** - * Tests if the command prompts an error if camel is used in Wildfire. - * - * @return void - */ - public function testWildfireCamelCasing() - { - CodeIgniterHelper::setDefaults($this->appPath); - - $wildfireCommand = 'Rougin\Combustor\Commands\InstallWildfireCommand'; - $wildfire = CommandBuilder::create($wildfireCommand); - - $installCommand = new CommandTester($wildfire); - $installCommand->execute([]); - - $createCommand = new CommandTester($this->createCommand); - $createCommand->execute([ - 'name' => $this->table, - '--camel' => true, - '--keep' => true - ]); - - $this->assertRegExp('/not support camel casing/', $createCommand->getDisplay()); - - CodeIgniterHelper::setDefaults($this->appPath); - } -}