├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── .travis.yml ├── LICENSE ├── README.md ├── app ├── index.js └── templates │ ├── _bower.json │ ├── _build.xml │ ├── _composer.json │ ├── _package.json │ ├── build │ ├── phpcs.xml │ ├── phpdox.xml │ └── phpmd.xml │ ├── editorconfig │ ├── jshintrc │ ├── phalcon │ ├── _htaccess │ ├── private │ │ ├── common │ │ │ └── lib │ │ │ │ └── application │ │ │ │ ├── Application.php │ │ │ │ ├── ApplicationModule.php │ │ │ │ ├── RoutedModule.php │ │ │ │ ├── controllers │ │ │ │ ├── ApplicationApiController.php │ │ │ │ ├── ApplicationController.php │ │ │ │ └── ApplicationViewController.php │ │ │ │ ├── models │ │ │ │ ├── ApplicationCollection.php │ │ │ │ └── ApplicationModel.php │ │ │ │ └── router │ │ │ │ └── ApplicationRouter.php │ │ └── config │ │ │ ├── config.php │ │ │ └── modules.php │ ├── public │ │ ├── .htaccess │ │ ├── index.php │ │ └── src │ │ │ └── app │ │ │ ├── layouts │ │ │ └── main.html │ │ │ └── partials │ │ │ └── index.html │ └── test │ │ ├── application │ │ ├── ApplicationTest.php │ │ └── phpunit.xml │ │ ├── helpers │ │ ├── TestHelper.php │ │ └── UnitTestCase.php │ │ └── phalcon │ │ ├── FunctionalTestCase.php │ │ ├── ModelTestCase.php │ │ └── UnitTestCase.php │ └── travis.yml ├── controller-api ├── index.js └── templates │ ├── controllers │ └── api │ │ └── IndexController.php │ └── test │ └── ControllerTest.php ├── controller-view ├── index.js └── templates │ ├── controllers │ └── view │ │ └── IndexController.php │ └── views │ └── index │ └── index.html ├── module ├── index.js └── templates │ ├── module │ ├── Module.php │ ├── ModuleRoutes.php │ ├── config │ │ └── config.php │ ├── controllers │ │ └── .gitignore │ ├── lib │ │ ├── controllers │ │ │ ├── ModuleApiController.php │ │ │ ├── ModuleController.php │ │ │ └── ModuleViewController.php │ │ └── models │ │ │ ├── ModuleCollection.php │ │ │ └── ModuleModel.php │ └── models │ │ └── .gitignore │ └── test │ ├── ModuleTest.php │ ├── helpers │ ├── ModuleTestHelper.php │ └── ModuleUnitTestCase.php │ └── phpunit.xml ├── package.json └── test ├── test-creation.js └── test-load.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | temp/ 3 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 4, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "regexp": true, 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "white": true 21 | } 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.8' 4 | - '0.10' 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # generator-phalcon 2 | 3 | A generator for [Yeoman](http://yeoman.io). Let Yeoman generate a multi module [Phalcon PHP Framework](http://phalconphp.com) application. 4 | 5 | 6 | ## Getting Started 7 | 8 | Since this is a Yeoman generator you have to install him first: 9 | 10 | ``` 11 | $ npm install -g yo 12 | ``` 13 | 14 | ### Phalcon Generator 15 | 16 | To install generator-phalcon from npm, run: 17 | 18 | ``` 19 | $ npm install -g generator-phalcon 20 | ``` 21 | 22 | Finally, initiate the generator: 23 | 24 | ``` 25 | $ yo phalcon 26 | ``` 27 | 28 | You will be asked some questions about your application. You can specify the main namespace where all generated classes will live in. This will also be used to generate the project name. You can specify the folder name this project lives in (if it differs from the project name). Finally you have a working multi-module application set up: 29 | 30 | ``` 31 | I welcome you to the Phalcon project generator. 32 | 33 | I will create a new Phalcon multi module application 34 | Please answer some questions first: 35 | 36 | [?] How would you like to call the new Project? (Enter the global namespace of the project, eg. MyApplication) 37 | [?] How would you like to name the main module? (Enter the namespace of the default module, eg. MyMainModule) 38 | [?] Please enter the name of the folder this project lives in (defaults to the slugified project name). 39 | 40 | ``` 41 | 42 | ### Module Subgenerator 43 | 44 | If you would like to add another module to your project, just issue the module subgenerator like this: 45 | 46 | ``` 47 | $ yo phalcon:module 48 | ``` 49 | 50 | This will kickstart the module generator which will include a new module in your project. This works for every project created by the generator-phalcon generator. 51 | 52 | The subgenerator will ask you about the project namespace and the namespace of the new module: 53 | 54 | ``` 55 | I will create a new Phalcon module for your application. 56 | 57 | Please answer these simple questions: 58 | 59 | [?] What is the namespace of the project this module should belong to? (Enter the global namespace of the project, eg. MyApplication) 60 | [?] How would you like to name your module? (Enter the namespace of your new module, eg. MyNewModule) 61 | ``` 62 | 63 | ### Controller Subgenerator 64 | 65 | If you would like to add another controller to your project, just issue the module subgenerator like this: 66 | 67 | ``` 68 | $ yo phalcon:controller 69 | ``` 70 | 71 | This will kickstart the controller generator which will include a new controller in one of your projects modules. 72 | 73 | The subgenerator will ask you about the project namespace, the namespace of the new module and the controller name: 74 | 75 | ``` 76 | I will create a new Phalcon controller for your application. 77 | 78 | Please answer these simple questions: 79 | 80 | [?] What is the namespace of the project this controller should belong to? (Enter the global namespace of the project, eg. MyApplication) 81 | [?] How is the namespace of the module your controller should belong to? (Enter the namespace of your new module, eg. MyNewModule) 82 | [?] What is the name of your controller (Without "Controller" suffix)? (Enter the simple controller name, eg. Auth) 83 | 84 | ``` 85 | 86 | ### Build the project 87 | 88 | By now the project can be build with Ant. The build directory contains some PHP specific configurations for PHP MessDetector, PHPDox and CodeSniffer. 89 | 90 | ### About the generated project 91 | 92 | As every Yeoman generator, this generator is opinionated about how you should manage your application, be it directory structure, class inheritance or every other detail of your application. 93 | As Phalcon is a very flexible framework feel free to adjust the project to your needs. 94 | The project generated with the generator-phalcon generator will have the following structure: 95 | 96 | ``` 97 | . 98 | ├── bower.json 99 | ├── build 100 | │   ├── phpcs.xml 101 | │   ├── phpdox.xml 102 | │   └── phpmd.xml 103 | ├── build.xml 104 | ├── composer.json 105 | ├── package.json 106 | ├── private 107 | │   ├── common 108 | │   │   └── lib 109 | │   │   └── application 110 | │   │   ├── ApplicationModule.php 111 | │   │   ├── Application.php 112 | │   │   ├── controllers 113 | │   │   │   ├── ApplicationApiController.php 114 | │   │   │   └── ApplicationController.php 115 | │   │   ├── models 116 | │   │   │   └── ApplicationModel.php 117 | │   │   ├── RoutedModule.php 118 | │   │   └── router 119 | │   │   └── ApplicationRouter.php 120 | │   ├── config 121 | │   │   ├── config.php 122 | │   │   └── modules.php 123 | │   └── modules 124 | │   └── mainmodule 125 | │   ├── config 126 | │   │   └── config.php 127 | │   ├── controllers 128 | │   │   ├── api 129 | │   │   │   └── IndexController.php 130 | │   │   ├── ModuleApiController.php 131 | │   │   └── ModuleController.php 132 | │   ├── lib 133 | │   ├── models 134 | │   │   └── ModuleModel.php 135 | │   ├── Module.php 136 | │   └── ModuleRoutes.php 137 | ├── public 138 | │   ├── assets 139 | │   ├── common 140 | │   ├── index.php 141 | │   ├── src 142 | │   │   └── app 143 | │   │   ├── layouts 144 | │   │   │   └── main.html 145 | │   │   ├── modules 146 | │   │   │   └── mainmodule 147 | │   │   │   └── views 148 | │   │   │   └── index 149 | │   │   │   └── index.html 150 | │   │   └── partials 151 | │   │   └── index.html 152 | │   └── styles 153 | └── test 154 | ├── application 155 | │   ├── ApplicationTest.php 156 | │   └── phpunit.xml 157 | ├── helpers 158 | │   ├── TestHelper.php 159 | │   └── UnitTestCase.php 160 | ├── modules 161 | │   └── mainmodule 162 | │   ├── helpers 163 | │   │   ├── ModuleTestHelper.php 164 | │   │   └── ModuleUnitTestCase.php 165 | │   ├── IndexControllerTest.php 166 | │   ├── ModuleTest.php 167 | │   └── phpunit.xml 168 | └── phalcon 169 | ├── FunctionalTestCase.php 170 | ├── ModelTestCase.php 171 | └── UnitTestCase.php 172 | 173 | ``` 174 | 175 | ### Todo 176 | 177 | * Documentation 178 | * Subgenerators for models, routes 179 | * Generators for client side scripts 180 | 181 | ### Getting To Know Yeoman 182 | 183 | Yeoman has a heart of gold. He's a person with feelings and opinions, but he's very easy to work with. If you think he's too opinionated, he can be easily convinced. 184 | 185 | If you'd like to get to know Yeoman better and meet some of his friends, [Grunt](http://gruntjs.com) and [Bower](http://bower.io), check out the complete [Getting Started Guide](https://github.com/yeoman/yeoman/wiki/Getting-Started). 186 | 187 | 188 | ## License 189 | 190 | [MIT License](http://en.wikipedia.org/wiki/MIT_License) 191 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var util = require('util'); 4 | var path = require('path'); 5 | var colors = require('colors'); 6 | var yeoman = require('yeoman-generator'); 7 | 8 | var PhalconGenerator = module.exports = function PhalconGenerator(args, options, config) { 9 | yeoman.generators.Base.apply(this, arguments); 10 | 11 | this.on('end', function () { 12 | this.installDependencies({ skipInstall: options['skip-install'] }); 13 | 14 | // we assume project slug as root folder, inform the user about this fact 15 | console.log( 16 | 'Please make sure this project is located in the ' + 17 | (this.project.rewritePath).yellow.bold + 18 | ' directory under your webserver root!' 19 | ); 20 | 21 | // call module generator 22 | this.invoke('phalcon:module', { 23 | options: { 24 | 'skip-install': true, 25 | 'moduleName': this.module.name, 26 | 'projectName': this.project.name 27 | } 28 | }); 29 | }); 30 | 31 | this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json'))); 32 | }; 33 | 34 | util.inherits(PhalconGenerator, yeoman.generators.Base); 35 | 36 | PhalconGenerator.prototype.askFor = function askFor() 37 | { 38 | var cb = this.async(); 39 | 40 | console.log('\nI welcome you to the ' + 'Phalcon project generator'.bold + '.\n\n' + 41 | 'I will create a new ' + 'Phalcon multi module application'.yellow + '\n' + 42 | 'Please answer some questions first:\n' 43 | ); 44 | 45 | var prompts = [ 46 | { 47 | type: 'input', 48 | name: 'projectName', 49 | message: 'How would you like to call the new Project?', 50 | validate: function (input) { 51 | if (!input) { 52 | return 'I think your ' + 'project'.red + ' deserves an awesome ' + 'name'.red + '!'; 53 | } 54 | return true; 55 | } 56 | }, 57 | 58 | { 59 | type: 'input', 60 | name: 'moduleName', 61 | message: 'How would you like to name the main module?', 62 | validate: function (input) { 63 | if (!input) { 64 | return 'Please specify a valid ' + 'module name'.red + ' - this is not too difficult since it may be any string ...'; 65 | } 66 | return true; 67 | } 68 | }, 69 | 70 | { 71 | type: 'input', 72 | name: 'rewritePath', 73 | message: 'Please enter the name of the folder this project lives in (defaults to the slugified project name).' 74 | } 75 | ]; 76 | 77 | this.prompt(prompts, function (props) { 78 | this.project = this.getProjectObject(props.projectName, props.rewritePath); 79 | this.module = this.getModuleObject(props.moduleName); 80 | cb(); 81 | }.bind(this)); 82 | }; 83 | 84 | PhalconGenerator.prototype.app = function app() 85 | { 86 | this.publicDirs(); 87 | this.privateDirs(); 88 | this.testDirs(); 89 | this.buildDirs(); 90 | 91 | /* copy .htaccess file as template */ 92 | this.template('phalcon/_htaccess', '.htaccess'); 93 | 94 | /* build related files */ 95 | this.copy('_package.json', 'package.json'); 96 | this.copy('_bower.json', 'bower.json'); 97 | this.copy('_composer.json', 'composer.json'); 98 | this.copy('_build.xml', 'build.xml'); 99 | }; 100 | 101 | /* 102 | * Create public directory structure 103 | */ 104 | PhalconGenerator.prototype.publicDirs = function publicDirs() 105 | { 106 | var dir = 'public'; 107 | this.mkdir(dir); 108 | this.mkdir(dir + '/assets'); 109 | this.mkdir(dir + '/common'); 110 | this.mkdir(dir + '/styles'); 111 | this.directory('phalcon/public', dir); 112 | }; 113 | 114 | /* 115 | * Create private directory structure 116 | */ 117 | PhalconGenerator.prototype.privateDirs = function privateDirs() 118 | { 119 | var dir = 'private'; 120 | this.mkdir(dir); 121 | this.directory('phalcon/private', dir); 122 | }; 123 | 124 | /* 125 | * Create private directory structure 126 | */ 127 | PhalconGenerator.prototype.testDirs = function testDirs() 128 | { 129 | var dir = 'test'; 130 | this.mkdir(dir); 131 | this.directory('phalcon/test', dir); 132 | }; 133 | 134 | /* 135 | * Create private directory structure 136 | */ 137 | PhalconGenerator.prototype.buildDirs = function buildDirs() 138 | { 139 | var dir = 'build'; 140 | this.mkdir(dir); 141 | this.directory('build', dir); 142 | }; 143 | 144 | PhalconGenerator.prototype.projectfiles = function projectfiles() 145 | { 146 | this.copy('editorconfig', '.editorconfig'); 147 | this.copy('jshintrc', '.jshintrc'); 148 | }; 149 | 150 | PhalconGenerator.prototype.getModuleObject = function getModuleObject(moduleName) 151 | { 152 | return { 153 | name: moduleName, 154 | namespace: this._.camelize(this._.capitalize(moduleName)), 155 | slug: this._.slugify(moduleName), 156 | camelCase: this._.camelize(moduleName), 157 | viewsDir: "__DIR__ . '/../../../public/src/app/modules/" + this._.slugify(moduleName) + "/views/'" 158 | }; 159 | }; 160 | 161 | PhalconGenerator.prototype.getProjectObject = function getProjectObject(projectName, rewritePath) 162 | { 163 | return { 164 | name: projectName, 165 | namespace: this._.camelize(this._.capitalize(projectName)), 166 | slug: this._.slugify(projectName), 167 | camelCase: this._.camelize(projectName), 168 | rewritePath: '/' + this._.slugify(rewritePath || projectName) + '/', 169 | layoutsDir: "__DIR__ . '/../../../public/src/app/layouts/'" 170 | }; 171 | }; -------------------------------------------------------------------------------- /app/templates/_bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package", 3 | "version": "0.0.0", 4 | "dependencies": {} 5 | } 6 | 7 | -------------------------------------------------------------------------------- /app/templates/_build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /app/templates/_composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "phpunit/phpunit": "3.8.*" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /app/templates/_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package", 3 | "version": "0.0.0", 4 | "dependencies": {} 5 | } 6 | -------------------------------------------------------------------------------- /app/templates/build/phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | The PSR-2 coding standard. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 0 45 | 46 | 47 | 0 48 | 49 | 50 | 0 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 91 | 92 | 93 | 94 | 95 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 0 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 136 | 137 | 138 | 139 | 140 | 142 | 143 | 148 | 149 | 150 | 151 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 191 | 192 | -------------------------------------------------------------------------------- /app/templates/build/phpdox.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/templates/build/phpmd.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | My custom rule set that checks my code... 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | 1 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/templates/editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = tabs 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | -------------------------------------------------------------------------------- /app/templates/jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 4, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "regexp": true, 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "white": true 21 | } 22 | -------------------------------------------------------------------------------- /app/templates/phalcon/_htaccess: -------------------------------------------------------------------------------- 1 | 2 | RewriteEngine on 3 | RewriteBase <%= project.rewritePath %> 4 | RewriteRule ^$ public/ [L] 5 | RewriteRule (.*) public/$1 [L] 6 | -------------------------------------------------------------------------------- /app/templates/phalcon/private/common/lib/application/Application.php: -------------------------------------------------------------------------------- 1 | \Application; 4 | 5 | use \Phalcon\Mvc\Url as UrlResolver, 6 | \Phalcon\DiInterface, 7 | \Phalcon\Mvc\View, 8 | \Phalcon\Loader, 9 | \Phalcon\Http\ResponseInterface, 10 | \Phalcon\Events\Manager as EventsManager, 11 | \Phalcon\Session\Adapter\Files as SessionAdapter, 12 | \Phalcon\Mvc\Collection\Manager, 13 | \<%= project.namespace %>\Application\Router\ApplicationRouter; 14 | 15 | /** 16 | * Application class for multi module applications 17 | * including HMVC internal requests. 18 | */ 19 | class Application extends \Phalcon\Mvc\Application 20 | { 21 | /** 22 | * Application Constructor 23 | * 24 | * @param \Phalcon\DiInterface $di 25 | */ 26 | public function __construct(DiInterface $di) 27 | { 28 | /** 29 | * Sets the parent DI and register the app itself as a service, 30 | * necessary for redirecting HMVC requests 31 | */ 32 | parent::setDI($di); 33 | $di->set('app', $this); 34 | 35 | /** 36 | * Register application wide accessible services 37 | */ 38 | $this->registerServices(); 39 | 40 | /** 41 | * Register the installed/configured modules 42 | */ 43 | $this->registerModules(require __DIR__ . '/../../../config/modules.php'); 44 | } 45 | 46 | /** 47 | * Register the services here to make them general or register in the 48 | * ModuleDefinition to make them module-specific 49 | */ 50 | protected function registerServices() 51 | { 52 | /** 53 | * The application wide configuration 54 | */ 55 | $config = include __DIR__ . '/../../../config/config.php'; 56 | $this->di->set('config', $config); 57 | 58 | /** 59 | * Setup an events manager with priorities enabled 60 | */ 61 | $eventsManager = new EventsManager(); 62 | $eventsManager->enablePriorities(true); 63 | $this->setEventsManager($eventsManager); 64 | 65 | /** 66 | * Register namespaces for application classes 67 | */ 68 | $loader = new Loader(); 69 | $loader->registerNamespaces( 70 | [ 71 | '<%=project.namespace %>\Application' => __DIR__, 72 | '<%=project.namespace %>\Application\Controllers' => __DIR__ . '/controllers/', 73 | '<%=project.namespace %>\Application\Models' => __DIR__ . '/models/', 74 | '<%=project.namespace %>\Application\Router' => __DIR__ . '/router/' 75 | ], 76 | true 77 | )->register(); 78 | 79 | /** 80 | * Start the session the first time some component request the session service 81 | */ 82 | $this->di->set( 83 | 'session', 84 | function () { 85 | $session = new SessionAdapter(); 86 | $session->start(); 87 | return $session; 88 | } 89 | ); 90 | 91 | /** 92 | * Registering the application wide router with the standard routes set 93 | */ 94 | $this->di->set('router', new ApplicationRouter()); 95 | 96 | /** 97 | * Specify the use of metadata adapter 98 | */ 99 | $this->di->set( 100 | 'modelsMetadata', 101 | '\Phalcon\Mvc\Model\Metadata\\' . $config->application->models->metadata->adapter 102 | ); 103 | 104 | /** 105 | * Specify the annotations cache adapter 106 | */ 107 | $this->di->set( 108 | 'annotations', 109 | '\Phalcon\Annotations\Adapter\\' . $config->application->annotations->adapter 110 | ); 111 | 112 | //Collection manager 113 | $this->di->set( 114 | 'collectionManager', 115 | function () { 116 | return new Manager(); 117 | } 118 | ); 119 | } 120 | 121 | /** 122 | * Register the given modules in the parent and prepare to load 123 | * the module routes by triggering the init routes method 124 | */ 125 | public function registerModules($modules, $merge = null) 126 | { 127 | parent::registerModules($modules, $merge); 128 | 129 | $loader = new Loader(); 130 | $modules = $this->getModules(); 131 | 132 | /** 133 | * Iterate the application modules and register the routes 134 | * by calling the initRoutes method of the Module class. 135 | * We need to auto load the class 136 | */ 137 | foreach ($modules as $module) { 138 | $className = $module['className']; 139 | 140 | if (!class_exists($className, false)) { 141 | $loader->registerClasses([$className => $module['path']], true)->register()->autoLoad($className); 142 | } 143 | 144 | /** @var \<%= project.namespace %>\Application\ApplicationModule $className */ 145 | $className::initRoutes($this->di); 146 | } 147 | } 148 | 149 | /** 150 | * Handles the request and echoes its content to the output stream. 151 | */ 152 | public function main() 153 | { 154 | echo $this->handle()->getContent(); 155 | } 156 | 157 | /** 158 | * Does a HMVC request inside the application 159 | * 160 | * Inside a controller we might do 161 | * 162 | * $this->app->request([ 'controller' => 'do', 'action' => 'something' ], 'param'); 163 | * 164 | * 165 | * @param array $location Array with the route information: 'namespace', 'module', 'controller', 'action', 'params' 166 | * @return mixed 167 | */ 168 | public function request(array $location) 169 | { 170 | /** @var \Phalcon\Mvc\Dispatcher $dispatcher */ 171 | $dispatcher = clone $this->di->get('dispatcher'); 172 | $defaults = [ 173 | 'controller' => 'index', 174 | 'action' => 'index', 175 | 'params' => [] 176 | ] + $location; 177 | 178 | if (isset($location['module'])) { 179 | $dispatcher->setModuleName($location['module']); 180 | } 181 | 182 | if (isset($location['namespace'])) { 183 | $dispatcher->setNamespaceName($location['namespace']); 184 | } 185 | 186 | $dispatcher->setControllerName($defaults['controller']); 187 | $dispatcher->setActionName($defaults['action']); 188 | $dispatcher->setParams((array)$defaults['params']); 189 | $dispatcher->dispatch(); 190 | 191 | $response = $dispatcher->getReturnedValue(); 192 | 193 | if ($response instanceof ResponseInterface) { 194 | return $response->getContent(); 195 | } 196 | 197 | return $response; 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /app/templates/phalcon/private/common/lib/application/ApplicationModule.php: -------------------------------------------------------------------------------- 1 | \Application; 4 | 5 | use \Phalcon\Mvc\ModuleDefinitionInterface, 6 | \Phalcon\Mvc\User\Module as UserModule, 7 | \<%= project.namespace %>\Application\RoutedModule; 8 | 9 | /** 10 | * Abstract application module base class 11 | */ 12 | abstract class ApplicationModule 13 | extends UserModule 14 | implements ModuleDefinitionInterface, RoutedModule 15 | { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /app/templates/phalcon/private/common/lib/application/RoutedModule.php: -------------------------------------------------------------------------------- 1 | \Application; 4 | 5 | use \Phalcon\DiInterface; 6 | 7 | /** 8 | * Abstract application module base class 9 | */ 10 | interface RoutedModule 11 | { 12 | /** 13 | * Load the module specific routes and mount them to the router 14 | * before the whole module gets loaded and add routing annotated 15 | * controllers 16 | * 17 | * @param \Phalcon\DiInterface $di 18 | */ 19 | static function initRoutes(DiInterface $di); 20 | } 21 | -------------------------------------------------------------------------------- /app/templates/phalcon/private/common/lib/application/controllers/ApplicationApiController.php: -------------------------------------------------------------------------------- 1 | \Application\Controllers; 4 | 5 | 6 | /** 7 | * Controller base class for all application API controllers 8 | */ 9 | class ApplicationApiController extends ApplicationController 10 | { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /app/templates/phalcon/private/common/lib/application/controllers/ApplicationController.php: -------------------------------------------------------------------------------- 1 | \Application\Controllers; 4 | 5 | use Phalcon\Mvc\Controller; 6 | 7 | /** 8 | * Controller base class for all application controllers 9 | */ 10 | class ApplicationController extends Controller 11 | { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /app/templates/phalcon/private/common/lib/application/controllers/ApplicationViewController.php: -------------------------------------------------------------------------------- 1 | \Application\Controllers; 4 | 5 | use Phalcon\Mvc\Controller; 6 | 7 | /** 8 | * Controller base class for all application controllers 9 | */ 10 | class ApplicationViewController extends ApplicationController 11 | { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /app/templates/phalcon/private/common/lib/application/models/ApplicationCollection.php: -------------------------------------------------------------------------------- 1 | \Application\Models; 4 | 5 | use \Phalcon\Mvc\Collection; 6 | 7 | class ApplicationCollection extends Collection 8 | { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /app/templates/phalcon/private/common/lib/application/models/ApplicationModel.php: -------------------------------------------------------------------------------- 1 | \Application\Models; 4 | 5 | use \Phalcon\Mvc\Model; 6 | 7 | /** 8 | * Application model base class 9 | */ 10 | class ApplicationModel extends Model 11 | { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /app/templates/phalcon/private/common/lib/application/router/ApplicationRouter.php: -------------------------------------------------------------------------------- 1 | \Application\Router; 4 | 5 | use \Phalcon\Mvc\Router\Annotations as Router; 6 | 7 | /** 8 | * This class acts as the application router and defines global application routes. 9 | * Module specific routes are defined inside the ModuleRoutes classes. Since this 10 | * class extends the \Phalcon\Mvc\Router\Annotations class annotations are also allowed 11 | * for routing. Therefore add the Controllers as resources in the ModuleRoutes by invoking 12 | * addModuleResource on an instance of this class. Remember to register the controllers to the 13 | * autoloader. 14 | */ 15 | class ApplicationRouter extends Router 16 | { 17 | /** 18 | * Creates a new instance of ApplicationRouter class and defines standard application routes 19 | * @param boolean $defaultRoutes 20 | */ 21 | public function __construct($defaultRoutes = false) 22 | { 23 | parent::__construct($defaultRoutes); 24 | 25 | $this->removeExtraSlashes(true); 26 | 27 | /** 28 | * Controller and action always default to 'index' 29 | */ 30 | $this->setDefaults([ 31 | 'controller' => 'index', 32 | 'action' => 'index' 33 | ]); 34 | 35 | /** 36 | * Add global matching route for the default module '<%= module.namespace %>': 'default-route' 37 | */ 38 | $this->add('/', [ 39 | 'module' => '<%= module.slug %>', 40 | 'namespace' => '<%= project.namespace %>\<%= module.namespace %>\Controllers\API\\' 41 | ])->setName('default-route'); 42 | 43 | /** 44 | * Add default not found route 45 | */ 46 | $this->notFound([ 47 | 'controller' => 'index', 48 | 'action' => 'route404' 49 | ]); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/templates/phalcon/private/config/config.php: -------------------------------------------------------------------------------- 1 | [ 8 | 'baseUri' => '<%= project.rewritePath %>', 9 | 'annotations' => ['adapter' => 'Apc'], 10 | 'models' => [ 11 | 'metadata' => ['adapter' => 'Apc'] 12 | ] 13 | ] 14 | ]); 15 | -------------------------------------------------------------------------------- /app/templates/phalcon/private/config/modules.php: -------------------------------------------------------------------------------- 1 | project 6 | */ 7 | return []; 8 | -------------------------------------------------------------------------------- /app/templates/phalcon/public/.htaccess: -------------------------------------------------------------------------------- 1 | AddDefaultCharset UTF-8 2 | 3 | 4 | RewriteEngine On 5 | RewriteCond %{REQUEST_FILENAME} !-d 6 | RewriteCond %{REQUEST_FILENAME} !-f 7 | RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L] 8 | -------------------------------------------------------------------------------- /app/templates/phalcon/public/index.php: -------------------------------------------------------------------------------- 1 | \Application\Application(new FactoryDefault()); 16 | $application->main(); 17 | } catch (\Phalcon\Exception $e) { 18 | echo 'A Phalcon\Exception occurred: ', $e->getMessage(), $e->getTraceAsString(); 19 | } catch (\PDOException $e) { 20 | echo 'A PDOException occurred: ', $e->getMessage(), $e->getTraceAsString(); 21 | } catch (\Exception $e) { 22 | echo 'An Exception occurred: ', $e->getMessage(), $e->getTraceAsString(); 23 | } 24 | -------------------------------------------------------------------------------- /app/templates/phalcon/public/src/app/layouts/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | GastroKey generated by Yeoman 5 | 6 | 7 | 8 |

Application wide layout file

9 | getContent(); ?> 10 | 11 | -------------------------------------------------------------------------------- /app/templates/phalcon/public/src/app/partials/index.html: -------------------------------------------------------------------------------- 1 |
2 | partial content 3 |
4 | -------------------------------------------------------------------------------- /app/templates/phalcon/test/application/ApplicationTest.php: -------------------------------------------------------------------------------- 1 | \Test; 4 | 5 | use \Phalcon\DI, 6 | \Phalcon\Loader, 7 | <%= project.namespace %>\Test\Helper\UnitTestCase; 8 | 9 | /** 10 | * Test class for <%= project.namespace %> Application class 11 | */ 12 | class ApplicationTest extends UnitTestCase 13 | { 14 | /** 15 | * Test application instance matches the app service 16 | * 17 | * @covers \<%= project.namespace %>\Application\Application::__construct 18 | */ 19 | public function testInternalApplicationService() 20 | { 21 | $this->assertEquals($this->application, $this->application->di->get('app')); 22 | } 23 | 24 | /** 25 | * Test service registration 26 | * 27 | * @covers \<%= project.namespace %>\Application\Application::_registerServices 28 | */ 29 | public function testServiceRegistration() 30 | { 31 | $this->assertInstanceOf('\Phalcon\Mvc\Router', $this->application->di->get('router')); 32 | $this->assertInstanceOf('\Phalcon\Session\Adapter', $this->application->di->get('session')); 33 | $this->assertInstanceOf('\Phalcon\Mvc\Model\MetaData', $this->application->di->get('modelsMetadata')); 34 | $this->assertInstanceOf('\Phalcon\Annotations\Adapter', $this->application->di->get('annotations')); 35 | $this->assertInstanceOf('\Phalcon\Mvc\Collection\Manager', $this->application->di->get('collectionManager')); 36 | $this->assertInstanceOf('\Phalcon\Events\Manager', $this->application->getEventsManager()); 37 | } 38 | 39 | /** 40 | * Simple test for registerModules method 41 | * 42 | * @covers \<%= project.namespace %>\Application\Application::registerModules 43 | */ 44 | public function testModuleIsRegistered() 45 | { 46 | $this->assertArrayHasKey('<%= module.slug %>', $this->application->getModules()); 47 | } 48 | 49 | /** 50 | * Test applicaton HMVC request 51 | * 52 | * @covers \<%= project.namespace %>\Application\Application::request 53 | */ 54 | public function testHMVCApplicationRequest() 55 | { 56 | $controllerName = 'index'; 57 | $indexCntrl = $this->getController($controllerName); 58 | 59 | $this->assertInstanceOf( 60 | '\Phalcon\Mvc\Controller', 61 | $indexCntrl, 62 | sprintf('Make sure the %sController matches the internal HMVC request.', ucfirst($controllerName)) 63 | ); 64 | 65 | $this->assertEquals( 66 | $indexCntrl->indexAction(), 67 | $this->application->request( 68 | [ 69 | 'namespace' => '<%= project.namespace %>\<%= module.namespace %>\Controllers\API', 70 | 'module' => '<%= module.slug %>', 71 | 'controller' => $controllerName, 72 | 'action' => 'index' 73 | ] 74 | ), 75 | sprintf( 76 | 'Assert that calling the %s action of the %sController matches the internal HMVC request.', 77 | $controllerName, 78 | ucfirst($controllerName) 79 | ) 80 | ); 81 | } 82 | 83 | /** 84 | * Helper to load the a controller 85 | * 86 | * @coversNothing 87 | */ 88 | public function getController($name) 89 | { 90 | $loader = new Loader(); 91 | $loader->registerClasses( 92 | [ 93 | '\<%= project.namespace %>\<%= module.namespace %>\Controllers\API\\' . ucfirst($name) . 'Controller' => ROOT_PATH . 'modules/<%= module.slug %>/controller/api/' 94 | ] 95 | )->register(); 96 | 97 | $indexCntrl = new \<%= project.namespace %>\<%= module.namespace %>\Controllers\API\IndexController(); 98 | $this->assertNotNull($indexCntrl, 'Make sure the index controller could be loaded'); 99 | 100 | return $indexCntrl; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /app/templates/phalcon/test/application/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./ 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/templates/phalcon/test/helpers/TestHelper.php: -------------------------------------------------------------------------------- 1 | registerNamespaces([ 21 | 'Phalcon\Test' => ROOT_PATH . '../test/phalcon/', 22 | '<%= project.namespace %>\Test\Helper' => ROOT_PATH . '../test/helpers/', 23 | '<%= project.namespace %>\Application' => ROOT_PATH . 'common/lib/application/' 24 | ])->register(); 25 | 26 | $di = new FactoryDefault(); 27 | DI::reset(); 28 | 29 | // add any needed services to the DI here 30 | 31 | DI::setDefault($di); -------------------------------------------------------------------------------- /app/templates/phalcon/test/helpers/UnitTestCase.php: -------------------------------------------------------------------------------- 1 | \Test\Helper; 3 | 4 | use Phalcon\DI, 5 | \Phalcon\Test\UnitTestCase as PhalconTestCase, 6 | \<%= project.namespace %>\Application\Application; 7 | 8 | abstract class UnitTestCase extends PhalconTestCase 9 | { 10 | /** 11 | * @var \Voice\Cache 12 | */ 13 | protected $_cache; 14 | 15 | /** 16 | * @var \Phalcon\Config 17 | */ 18 | protected $_config; 19 | 20 | protected $application; 21 | 22 | /** 23 | * @var bool 24 | */ 25 | private $_loaded = false; 26 | 27 | public function setUp(\Phalcon\DiInterface $di = null, \Phalcon\Config $config = null) 28 | { 29 | // Load any additional services that might be required during testing 30 | $di = DI::getDefault(); 31 | 32 | // get any DI components here. If you have a config, be sure to pass it to the parent 33 | $this->application = new Application($di); 34 | 35 | parent::setUp($this->application->di, $this->application->config); 36 | 37 | $this->_loaded = true; 38 | } 39 | 40 | public function tearDown() { 41 | $this->application = null; 42 | } 43 | 44 | /** 45 | * Check if the test case is setup properly 46 | * @throws \PHPUnit_Framework_IncompleteTestError; 47 | */ 48 | public function __destruct() { 49 | if(!$this->_loaded) { 50 | throw new \PHPUnit_Framework_IncompleteTestError('Please run parent::setUp().'); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /app/templates/phalcon/test/phalcon/FunctionalTestCase.php: -------------------------------------------------------------------------------- 1 | 13 | * @author Nikolaos Dimopoulos 14 | * 15 | * The contents of this file are subject to the New BSD License that is 16 | * bundled with this package in the file docs/LICENSE.txt 17 | * 18 | * If you did not receive a copy of the license and are unable to obtain it 19 | * through the world-wide-web, please send an email to license@phalconphp.com 20 | * so that we can send you a copy immediately. 21 | */ 22 | 23 | namespace Phalcon\Test; 24 | 25 | use \Phalcon\Mvc\Dispatcher as PhDispatcher; 26 | use \Phalcon\Escaper as PhEscaper; 27 | 28 | abstract class FunctionalTestCase extends ModelTestCase 29 | { 30 | protected $application; 31 | 32 | /** 33 | * Sets the test up by loading the DI container and other stuff 34 | * 35 | * @return void 36 | */ 37 | protected function setUp() 38 | { 39 | parent::setUp(); 40 | 41 | // Set the dispatcher 42 | $this->di->setShared( 43 | 'dispatcher', 44 | function () { 45 | $dispatcher = new PhDispatcher(); 46 | $dispatcher->setControllerName('test'); 47 | $dispatcher->setActionName('empty'); 48 | $dispatcher->setParams(array()); 49 | return $dispatcher; 50 | } 51 | ); 52 | 53 | $this->di->set( 54 | 'escaper', 55 | function () { 56 | return new PhEscaper(); 57 | } 58 | ); 59 | 60 | if ($this->di instanceof DiInterface) { 61 | $this->application = new PhApplication($this->di); 62 | } 63 | 64 | } 65 | 66 | /** 67 | * Ensures that each test has it's own DI and all globals are purged 68 | * 69 | * @return void 70 | */ 71 | protected function tearDown() 72 | { 73 | $this->di->reset(); 74 | $this->application = null; 75 | 76 | $_SESSION = array(); 77 | $_GET = array(); 78 | $_POST = array(); 79 | $_COOKIE = array(); 80 | } 81 | 82 | /** 83 | * Dispatches a given url and sets the response object accordingly 84 | * 85 | * @param string $url The request url 86 | * 87 | * @return void 88 | */ 89 | protected function dispatch($url) 90 | { 91 | $this->di->setShared('response', $this->application->handle($url)); 92 | } 93 | 94 | /** 95 | * Assert that the last dispatched controller matches the given controller class name 96 | * 97 | * @param string $expected The expected controller name 98 | * 99 | * @return void 100 | */ 101 | public function assertController($expected) 102 | { 103 | $actual = $this->di->getShared('dispatcher')->getControllerName(); 104 | if ($actual != $expected) { 105 | throw new \PHPUnit_Framework_ExpectationFailedException( 106 | sprintf( 107 | 'Failed asserting Controller name "%s", actual Controller name is "%s"', 108 | $expected, 109 | $actual 110 | ) 111 | ); 112 | } 113 | $this->assertEquals($expected, $actual); 114 | } 115 | 116 | /** 117 | * Assert that the last dispatched action matches the given action name 118 | * 119 | * @param string $expected The expected action name 120 | * 121 | * @return void 122 | */ 123 | public function assertAction($expected) 124 | { 125 | $actual = $this->di->getShared('dispatcher')->getActionName(); 126 | if ($actual != $expected) { 127 | throw new \PHPUnit_Framework_ExpectationFailedException( 128 | sprintf( 129 | 'Failed asserting Action name "%s", actual Action name is "%s"', 130 | $expected, 131 | $actual 132 | ) 133 | ); 134 | } 135 | $this->assertEquals($expected, $actual); 136 | } 137 | 138 | /** 139 | * Assert that the response headers contains the given array 140 | * 141 | * $expected = array('Content-Type' => 'application/json') 142 | * 143 | * 144 | * @param string $expected The expected headers 145 | * 146 | * @return void 147 | */ 148 | public function assertHeader(array $expected) 149 | { 150 | foreach ($expected as $expectedField => $expectedValue) { 151 | $actualValue = $this->di->getShared('response')->getHeaders()->get($expectedField); 152 | if ($actualValue != $expectedValue) { 153 | throw new \PHPUnit_Framework_ExpectationFailedException( 154 | sprintf( 155 | 'Failed asserting "%s" has a value of "%s", actual "%s" header value is "%s"', 156 | $expectedField, 157 | $expectedValue, 158 | $expectedField, 159 | $actualValue 160 | ) 161 | ); 162 | } 163 | $this->assertEquals($expectedValue, $actualValue); 164 | } 165 | } 166 | 167 | /** 168 | * Asserts that the response code matches the given one 169 | * 170 | * @param string $expected the expected response code 171 | * 172 | * @return void 173 | */ 174 | public function assertResponseCode($expected) 175 | { 176 | $actualValue = $this->di->getShared('response')->getHeaders()->get('Status'); 177 | if (empty($actualValue) || stristr($actualValue, $expected)) { 178 | throw new \PHPUnit_Framework_ExpectationFailedException( 179 | sprintf( 180 | 'Failed asserting response code "%s", actual response code is "%s"', 181 | $expected, 182 | $actualValue 183 | ) 184 | ); 185 | } 186 | $this->assertContains($expected, $actualValue); 187 | } 188 | 189 | /** 190 | * Asserts that the dispatched url resulted in a redirection 191 | * 192 | * @return void 193 | */ 194 | public function assertRedirection() 195 | { 196 | $actual = $this->di->getShared('dispatcher')->wasForwarded(); 197 | if (!$actual) { 198 | throw new \PHPUnit_Framework_ExpectationFailedException( 199 | 'Failed asserting response caused a redirect' 200 | ); 201 | } 202 | $this->assertTrue($actual); 203 | } 204 | } -------------------------------------------------------------------------------- /app/templates/phalcon/test/phalcon/ModelTestCase.php: -------------------------------------------------------------------------------- 1 | 13 | * @author Nikolaos Dimopoulos 14 | * 15 | * The contents of this file are subject to the New BSD License that is 16 | * bundled with this package in the file docs/LICENSE.txt 17 | * 18 | * If you did not receive a copy of the license and are unable to obtain it 19 | * through the world-wide-web, please send an email to license@phalconphp.com 20 | * so that we can send you a copy immediately. 21 | */ 22 | 23 | namespace Phalcon\Test; 24 | 25 | use \Phalcon\Mvc\Model\Manager as PhModelManager; 26 | use \Phalcon\Events\Manager as PhEventsManager; 27 | use \Phalcon\Logger\Adapter\File as PhLogger; 28 | use \Phalcon\Db\Adapter\Pdo\Mysql as PhMysql; 29 | use \Phalcon\Session\Adapter\Files as PhSession; 30 | use \Phalcon\Cache\Frontend\Data as PhCacheFront; 31 | use \Phalcon\Cache\Backend\File as PhCacheBack; 32 | use \Phalcon\Mvc\Application as PhApplication; 33 | use \Phalcon\Mvc\Dispatcher as PhDispatcher; 34 | use \Phalcon\Mvc\Url as PhUrl; 35 | use \Phalcon\Mvc\View as PhView; 36 | use \Phalcon\Mvc\View\Engine\Volt as PhVolt; 37 | use \Phalcon\Mvc\Model\Metadata\Memory as PhMetadataMemory; 38 | use \Phalcon\Mvc\Model\Metadata\Files as PhMetadataFiles; 39 | use \Phalcon\Exception as PhException; 40 | 41 | abstract class ModelTestCase extends UnitTestCase 42 | { 43 | /** 44 | * Sets the test up by loading the DI container and other stuff 45 | * 46 | * @author Nikos Dimopoulos 47 | * @since 2012-09-20 48 | */ 49 | protected function setUp() 50 | { 51 | parent::setUp(); 52 | 53 | // Set Models manager 54 | $this->di->set( 55 | 'modelsManager', 56 | function () { 57 | return new PhModelManager(); 58 | } 59 | ); 60 | 61 | // Set Models metadata 62 | $this->di->set( 63 | 'modelsMetadata', 64 | function () { 65 | return new PhMetadataMemory(); 66 | } 67 | ); 68 | 69 | // Set the connection to the db (defaults to mysql) 70 | $this->setDb(); 71 | } 72 | 73 | /** 74 | * Sets the database adapter in the DI container 75 | * 76 | * @param string $dbType Sets the database type for the test 77 | * 78 | * @author Nikos Dimopoulos 79 | * @since 2012-09-20 80 | */ 81 | protected function setDb($dbType = 'mysql') 82 | { 83 | $config = $this->config; 84 | 85 | if ($this->di->has('db')) { 86 | $db = $this->di->get('db'); 87 | $class = '\Phalcon\Db\Adapter\Pdo\\' . ucfirst($dbType); 88 | if (get_class($db) == $class) { 89 | return $db; 90 | } 91 | } 92 | 93 | // Set the connection to whatever we chose 94 | $this->di->set( 95 | 'db', 96 | function () use ($dbType, $config) { 97 | $params = $config['db'][$dbType]; 98 | $class = '\Phalcon\Db\Adapter\Pdo\\' . ucfirst($dbType); 99 | 100 | $conn = new $class($params); 101 | return $conn; 102 | } 103 | ); 104 | } 105 | 106 | /** 107 | * Empties a table in the database. 108 | * 109 | * @param $table 110 | * 111 | * @return boolean 112 | * 113 | * @author Nikos Dimopoulos 114 | * @since 2012-11-08 115 | */ 116 | public function emptyTable($table) 117 | { 118 | $connection = $this->di->get('db'); 119 | 120 | $success = $connection->delete($table); 121 | 122 | return $success; 123 | } 124 | 125 | /** 126 | * Populates a table with default data 127 | * 128 | * @param $table 129 | * @param null $records 130 | * 131 | * @author Nikos Dimopoulos 132 | * @since 2012-11-08 133 | */ 134 | public function populateTable($table, $records = null) 135 | { 136 | // Empty the table first 137 | $this->emptyTable($table); 138 | 139 | $connection = $this->di->get('db'); 140 | $parts = explode('_', $table); 141 | $suffix = ''; 142 | 143 | foreach ($parts as $part) { 144 | $suffix .= ucfirst($part); 145 | } 146 | 147 | $class = 'Phalcon\Test\Fixtures\\' . $suffix; 148 | 149 | $data = $class::get($records); 150 | 151 | foreach ($data as $record) { 152 | $sql = "INSERT INTO {$table} VALUES " . $record; 153 | $connection->execute($sql); 154 | } 155 | } 156 | } -------------------------------------------------------------------------------- /app/templates/phalcon/test/phalcon/UnitTestCase.php: -------------------------------------------------------------------------------- 1 | 13 | * @author Nikolaos Dimopoulos 14 | * @author Stephen Hoogendijk 15 | * 16 | * The contents of this file are subject to the New BSD License that is 17 | * bundled with this package in the file docs/LICENSE.txt 18 | * 19 | * If you did not receive a copy of the license and are unable to obtain it 20 | * through the world-wide-web, please send an email to license@phalconphp.com 21 | * so that we can send you a copy immediately. 22 | */ 23 | 24 | namespace Phalcon\Test; 25 | 26 | use Phalcon\DI\FactoryDefault; 27 | use Phalcon\Config; 28 | use Phalcon\DI; 29 | use Phalcon\DiInterface; 30 | use Phalcon\Mvc\Url; 31 | 32 | /** 33 | * Class UnitTestCase 34 | * @package Phalcon\Test 35 | */ 36 | abstract class UnitTestCase extends \PHPUnit_Framework_TestCase 37 | { 38 | // Holds the configuration variables and other stuff 39 | // I can use the DI container but for tests like the Translate 40 | // we do not need the overhead 41 | protected $config = array(); 42 | 43 | /** 44 | * @var 45 | */ 46 | protected $di; 47 | 48 | /** 49 | * Sets the test up by loading the DI container and other stuff 50 | * 51 | * @author Nikos Dimopoulos 52 | * @since 2012-09-30 53 | * 54 | * @param \Phalcon\DiInterface $di 55 | * @param \Phalcon\Config $config 56 | * @return DI 57 | */ 58 | protected function setUp(DiInterface $di = null, Config $config = null) 59 | { 60 | $this->checkExtension('phalcon'); 61 | 62 | if(!is_null($config)){ 63 | $this->config = $config; 64 | } 65 | 66 | if(is_null($di)){ 67 | 68 | // Reset the DI container 69 | DI::reset(); 70 | 71 | // Instantiate a new DI container 72 | $di = new FactoryDefault(); 73 | 74 | // Set the URL 75 | $di->set( 76 | 'url', 77 | function () { 78 | $url = new Url(); 79 | $url->setBaseUri('/'); 80 | return $url; 81 | } 82 | ); 83 | 84 | $di->set( 85 | 'escaper', 86 | function () { 87 | return new \Phalcon\Escaper(); 88 | } 89 | ); 90 | } 91 | $this->di = $di; 92 | } 93 | 94 | /** 95 | * Checks if a particular extension is loaded and if not it marks 96 | * the tests skipped 97 | * 98 | * @param $extension 99 | */ 100 | public function checkExtension($extension) 101 | { 102 | if (!extension_loaded($extension)) { 103 | $this->markTestSkipped("Warning: {$extension} extension is not loaded"); 104 | } 105 | } 106 | 107 | /** 108 | * Returns a unique file name 109 | * 110 | * @author Nikos Dimopoulos 111 | * @since 2012-09-30 112 | * 113 | * @param string $prefix A prefix for the file 114 | * @param string $suffix A suffix for the file 115 | * 116 | * @return string 117 | * 118 | */ 119 | protected function getFileName($prefix = '', $suffix = 'log') 120 | { 121 | $prefix = ($prefix) ? $prefix . '_' : ''; 122 | $suffix = ($suffix) ? $suffix : 'log'; 123 | 124 | return uniqid($prefix, true) . '.' . $suffix; 125 | } 126 | 127 | /** 128 | * Removes a file from the system 129 | * 130 | * @author Nikos Dimopoulos 131 | * @since 2012-09-30 132 | * 133 | * @param $path 134 | * @param $fileName 135 | */ 136 | protected function cleanFile($path, $fileName) 137 | { 138 | $file = (substr($path, -1, 1) != "/") ? ($path . '/') : $path; 139 | $file .= $fileName; 140 | 141 | $actual = file_exists($file); 142 | 143 | if ($actual) { 144 | unlink($file); 145 | } 146 | } 147 | } -------------------------------------------------------------------------------- /app/templates/travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.8' 4 | - '0.10' 5 | -------------------------------------------------------------------------------- /controller-api/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var util = require('util'); 4 | var path = require('path'); 5 | var yeoman = require('yeoman-generator'); 6 | var colors = require('colors'); 7 | var fs = require('fs') 8 | 9 | var ControllerGenerator = module.exports = function ControllerGenerator(args, options, config) { 10 | yeoman.generators.Base.apply(this, arguments); 11 | 12 | this.on('end', function () { 13 | this.installDependencies({ skipInstall: options['skip-install'] }); 14 | console.log('The controller ' + (this.controller.fullName).yellow.bold + ' has been created.'); 15 | }); 16 | 17 | console.log( 18 | '\nWelcome to the ' + 'Phalcon controller generator'.bold + '.\n\n' + 19 | 'I will create a new ' + 'Phalcon controller'.yellow + ' for your application.\n' 20 | ); 21 | 22 | this.controller = false; 23 | this.module = false; 24 | this.project = false; 25 | 26 | if (options.controllerName) { 27 | this.controller = this.getControllerObject(options.controllerName); 28 | } 29 | 30 | if (options.moduleName) { 31 | this.module = this.getModuleObject(options.moduleName); 32 | } 33 | 34 | if (options.projectName) { 35 | this.project = this.getProjectObject(options.projectName); 36 | } 37 | }; 38 | 39 | util.inherits(ControllerGenerator, yeoman.generators.Base); 40 | 41 | ControllerGenerator.prototype.askFor = function askFor() 42 | { 43 | var prompts, 44 | cb = this.async(); 45 | 46 | if (!this.module || !this.project) { 47 | console.log('Please answer these simple questions:\n'); 48 | prompts = [ 49 | { 50 | type: 'input', 51 | name: 'projectName', 52 | message: 'What is the namespace of the project this controller should belong to?', 53 | validate: function (input) { 54 | if (!input) { 55 | return 'I think your ' + 56 | 'project'.red + 57 | ' deserves an awesome ' + 58 | 'namespace'.red + '!'; 59 | } 60 | return true; 61 | } 62 | }, 63 | { 64 | type: 'input', 65 | name: 'moduleName', 66 | message: 'How is the namespace of the module your controller should belong to?', 67 | validate: function (input) { 68 | if (!input) { 69 | return 'Please specify a valid ' + 70 | 'module name'.red + 71 | ' - this is not too difficult since it may be any string ...'; 72 | } 73 | return true; 74 | } 75 | }, 76 | { 77 | type: 'input', 78 | name: 'controllerName', 79 | message: 'What is the name of your controller (Without "Controller" suffix)?', 80 | validate: function (input) { 81 | if (!input) { 82 | return 'Please specify a valid ' + 83 | 'controller name'.red + 84 | ' - this is not too difficult since it may be any string ...'; 85 | } 86 | return true; 87 | } 88 | } 89 | ]; 90 | 91 | this.prompt(prompts, function (props) { 92 | this.controller = this.getControllerObject(props.controllerName); 93 | this.project = this.getProjectObject(props.projectName); 94 | this.module = this.getModuleObject(props.moduleName); 95 | this.files(); 96 | cb(); 97 | }.bind(this)); 98 | } else { 99 | this.files(); 100 | cb(); 101 | } 102 | }; 103 | 104 | /* 105 | * Create module directory structure and module specific files, 106 | * copy the view files to the public resources 107 | */ 108 | ControllerGenerator.prototype.files = function files() 109 | { 110 | this.controllerFiles(); 111 | }; 112 | 113 | /* 114 | * Create module directory structure and module specific files 115 | */ 116 | ControllerGenerator.prototype.controllerFiles = function controllerFiles() 117 | { 118 | var dir = 'private/modules/' + this.module.slug + '/controllers/api/'; 119 | this.mkdir(dir); 120 | this.template('controllers/api/IndexController.php', dir + this.controller.fileName); 121 | 122 | dir = 'test/modules/' + this.module.slug + '/'; 123 | this.mkdir(dir); 124 | this.template('test/ControllerTest.php', dir + this.controller.name + 'ControllerTest.php'); 125 | 126 | }; 127 | 128 | /* 129 | * Add a controller config entry to the module routed controller configuration. 130 | */ 131 | ControllerGenerator.prototype.addModuleConfig = function addModuleConfig() 132 | { 133 | var file = 'private/modules/' + this.module.slug + '/config/config.php', 134 | replaceString = "'annotationRouted' => [", 135 | ctrlString = "'annotationRouted' => [\n\t\t\t" + 136 | "'\\" + this.project.namespace + "\\" + this.module.namespace + "\\Controllers\\API\\" + this.controller.name + "',"; 137 | 138 | fs.readFile(file, 'utf8', function (err, data) { 139 | if (err) { 140 | return console.log(err); 141 | } else { 142 | var result = data.replace(replaceString, ctrlString); 143 | fs.writeFile(file, result, 'utf8', function (err) { 144 | if (err) { 145 | return console.log(err); 146 | } 147 | }); 148 | } 149 | }); 150 | }; 151 | 152 | ControllerGenerator.prototype.getProjectObject = function getProjectObject(projectName) 153 | { 154 | return { 155 | name: projectName, 156 | namespace: this._.camelize(this._.capitalize(projectName)), 157 | slug: this._.slugify(projectName), 158 | camelCase: this._.camelize(projectName), 159 | rewritePath: '/' + this._.slugify(projectName) + '/', 160 | layoutsDir: "__DIR__ . '/../../../public/src/app/layouts/'" 161 | }; 162 | }; 163 | 164 | ControllerGenerator.prototype.getModuleObject = function getModuleObject(moduleName) 165 | { 166 | return { 167 | name: moduleName, 168 | namespace: this._.camelize(this._.capitalize(moduleName)), 169 | slug: this._.slugify(moduleName), 170 | camelCase: this._.camelize(moduleName), 171 | viewsDir: "__DIR__ . '/../../../public/src/app/modules/" + this._.slugify(moduleName) + "/views/'" 172 | }; 173 | }; 174 | 175 | ControllerGenerator.prototype.getControllerObject = function getControllerObject(controllerName) 176 | { 177 | return { 178 | name: controllerName, 179 | fullName: controllerName + 'Controller', 180 | fileName: controllerName + 'Controller.php', 181 | namespace: this._.camelize(this._.capitalize(controllerName)), 182 | slug: this._.slugify(controllerName), 183 | camelCase: this._.camelize(controllerName) 184 | }; 185 | }; 186 | -------------------------------------------------------------------------------- /controller-api/templates/controllers/api/IndexController.php: -------------------------------------------------------------------------------- 1 | \<%= module.namespace %>\Controllers\API; 4 | 5 | use \<%= project.namespace %>\<%= module.namespace %>\Library\Controllers\ModuleApiController; 6 | 7 | /** 8 | * Concrete implementation of <%= module.namespace %> module controller 9 | * 10 | * @RoutePrefix("/<%= module.slug %>/api") 11 | */ 12 | class <%= controller.name %>Controller extends ModuleApiController 13 | { 14 | /** 15 | * @Route("/<%= controller.slug %>", paths={module="<%= module.slug %>"}, methods={"GET"}, name="<%= module.slug %>-<%= controller.slug %>-index") 16 | */ 17 | public function indexAction() 18 | { 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /controller-api/templates/test/ControllerTest.php: -------------------------------------------------------------------------------- 1 | \<%= module.namespace %>\Test; 4 | 5 | use <%= project.namespace %>\<%= module.namespace %>\Test\Helper\ModuleUnitTestCase; 6 | 7 | /** 8 | * Test class for Application class 9 | * 10 | * @coversDefaultClass \<%= project.namespace %>\<%= module.namespace %>\Controllers\API\<%= controller.fullName %> 11 | */ 12 | class <%= controller.name %>ControllerTest extends ModuleUnitTestCase 13 | { 14 | public function testController() 15 | { 16 | $this->assertTrue(false); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /controller-view/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var util = require('util'); 4 | var path = require('path'); 5 | var yeoman = require('yeoman-generator'); 6 | var colors = require('colors'); 7 | var fs = require('fs') 8 | 9 | var ControllerGenerator = module.exports = function ControllerGenerator(args, options, config) { 10 | yeoman.generators.Base.apply(this, arguments); 11 | 12 | this.on('end', function () { 13 | this.installDependencies({ skipInstall: options['skip-install'] }); 14 | console.log('The controller ' + (this.controller.fullName).yellow.bold + ' has been created.'); 15 | }); 16 | 17 | console.log( 18 | '\nWelcome to the ' + 'Phalcon controller generator'.bold + '.\n\n' + 19 | 'I will create a new ' + 'Phalcon controller'.yellow + ' for your application.\n' 20 | ); 21 | 22 | this.controller = false; 23 | this.module = false; 24 | this.project = false; 25 | 26 | if (options.controllerName) { 27 | this.controller = this.getControllerObject(options.controllerName); 28 | } 29 | 30 | if (options.moduleName) { 31 | this.module = this.getModuleObject(options.moduleName); 32 | } 33 | 34 | if (options.projectName) { 35 | this.project = this.getProjectObject(options.projectName); 36 | } 37 | }; 38 | 39 | util.inherits(ControllerGenerator, yeoman.generators.Base); 40 | 41 | ControllerGenerator.prototype.askFor = function askFor() 42 | { 43 | var prompts, 44 | cb = this.async(); 45 | 46 | if (!this.module || !this.project) { 47 | console.log('Please answer these simple questions:\n'); 48 | prompts = [ 49 | { 50 | type: 'input', 51 | name: 'projectName', 52 | message: 'What is the namespace of the project this controller should belong to?', 53 | validate: function (input) { 54 | if (!input) { 55 | return 'I think your ' + 56 | 'project'.red + 57 | ' deserves an awesome ' + 58 | 'namespace'.red + '!'; 59 | } 60 | return true; 61 | } 62 | }, 63 | { 64 | type: 'input', 65 | name: 'moduleName', 66 | message: 'How is the namespace of the module your controller should belong to?', 67 | validate: function (input) { 68 | if (!input) { 69 | return 'Please specify a valid ' + 70 | 'module name'.red + 71 | ' - this is not too difficult since it may be any string ...'; 72 | } 73 | return true; 74 | } 75 | }, 76 | { 77 | type: 'input', 78 | name: 'controllerName', 79 | message: 'What is the name of your controller (Without "Controller" suffix)?', 80 | validate: function (input) { 81 | if (!input) { 82 | return 'Please specify a valid ' + 83 | 'controller name'.red + 84 | ' - this is not too difficult since it may be any string ...'; 85 | } 86 | return true; 87 | } 88 | } 89 | ]; 90 | 91 | this.prompt(prompts, function (props) { 92 | this.controller = this.getControllerObject(props.controllerName); 93 | this.project = this.getProjectObject(props.projectName); 94 | this.module = this.getModuleObject(props.moduleName); 95 | this.files(); 96 | cb(); 97 | }.bind(this)); 98 | } else { 99 | this.files(); 100 | cb(); 101 | } 102 | }; 103 | 104 | /* 105 | * Create module directory structure and module specific files, 106 | * copy the view files to the public resources 107 | */ 108 | ControllerGenerator.prototype.files = function files() 109 | { 110 | this.controllerFiles(); 111 | this.viewFiles(); 112 | }; 113 | 114 | /* 115 | * Create module directory structure and module specific files 116 | */ 117 | ControllerGenerator.prototype.controllerFiles = function controllerFiles() 118 | { 119 | var dir = 'private/modules/' + this.module.slug + '/controllers/view/'; 120 | this.mkdir(dir); 121 | this.template('controllers/view/IndexController.php', dir + this.controller.fileName); 122 | 123 | }; 124 | 125 | /* 126 | * Create module directory structure and module specific files, 127 | * copy the view files to the public resources 128 | */ 129 | ControllerGenerator.prototype.viewFiles = function viewFiles() 130 | { 131 | var dir = 'public/src/app/modules/' + this.module.slug + '/views/' + this.controller.slug; 132 | this.mkdir(dir); 133 | this.template('views/index/index.html', dir + '/index.html'); 134 | }; 135 | 136 | /* 137 | * Add a controller config entry to the module routed controller configuration. 138 | */ 139 | ControllerGenerator.prototype.addModuleConfig = function addModuleConfig() 140 | { 141 | var file = 'private/modules/' + this.module.slug + '/config/config.php', 142 | replaceString = "'annotationRouted' => [", 143 | ctrlString = "'annotationRouted' => [\n\t\t\t" + 144 | "'\\" + this.project.namespace + "\\" + this.module.namespace + "\\Controllers\\API\\" + this.controller.name + "',"; 145 | 146 | fs.readFile(file, 'utf8', function (err, data) { 147 | if (err) { 148 | return console.log(err); 149 | } else { 150 | var result = data.replace(replaceString, ctrlString); 151 | fs.writeFile(file, result, 'utf8', function (err) { 152 | if (err) { 153 | return console.log(err); 154 | } 155 | }); 156 | } 157 | }); 158 | }; 159 | 160 | ControllerGenerator.prototype.getProjectObject = function getProjectObject(projectName) 161 | { 162 | return { 163 | name: projectName, 164 | namespace: this._.camelize(this._.capitalize(projectName)), 165 | slug: this._.slugify(projectName), 166 | camelCase: this._.camelize(projectName), 167 | rewritePath: '/' + this._.slugify(projectName) + '/', 168 | layoutsDir: "__DIR__ . '/../../../public/src/app/layouts/'" 169 | }; 170 | }; 171 | 172 | ControllerGenerator.prototype.getModuleObject = function getModuleObject(moduleName) 173 | { 174 | return { 175 | name: moduleName, 176 | namespace: this._.camelize(this._.capitalize(moduleName)), 177 | slug: this._.slugify(moduleName), 178 | camelCase: this._.camelize(moduleName), 179 | viewsDir: "__DIR__ . '/../../../public/src/app/modules/" + this._.slugify(moduleName) + "/views/'" 180 | }; 181 | }; 182 | 183 | ControllerGenerator.prototype.getControllerObject = function getControllerObject(controllerName) 184 | { 185 | return { 186 | name: controllerName, 187 | fullName: controllerName + 'Controller', 188 | fileName: controllerName + 'Controller.php', 189 | namespace: this._.camelize(this._.capitalize(controllerName)), 190 | slug: this._.slugify(controllerName), 191 | camelCase: this._.camelize(controllerName) 192 | }; 193 | }; 194 | -------------------------------------------------------------------------------- /controller-view/templates/controllers/view/IndexController.php: -------------------------------------------------------------------------------- 1 | \<%= module.namespace %>\Controllers\View; 4 | 5 | use \<%= project.namespace %>\<%= module.namespace %>\Library\Controllers\ModuleViewController; 6 | 7 | /** 8 | * Concrete implementation of <%= module.namespace %> module controller 9 | * 10 | * @RoutePrefix("/<%= module.slug %>/view") 11 | */ 12 | class <%= controller.name %>Controller extends ModuleViewController 13 | { 14 | /** 15 | * @Route("/<%= controller.slug %>", paths={module="<%= module.slug %>"}, methods={"GET"}, name="<%= module.slug %>-<%= controller.slug %>-index") 16 | */ 17 | public function indexAction() 18 | { 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /controller-view/templates/views/index/index.html: -------------------------------------------------------------------------------- 1 |

Index file of <%= project.namespace %>\<%= module.namespace %>\<%= controller.fullName %>

2 | 3 | partial('index'); ?> 4 | 5 |

You're now flying with Phalcon. Great things are about to happen!

-------------------------------------------------------------------------------- /module/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var util = require('util'); 4 | var path = require('path'); 5 | var yeoman = require('yeoman-generator'); 6 | var colors = require('colors'); 7 | var fs = require('fs') 8 | 9 | var ModuleGenerator = module.exports = function ModuleGenerator(args, options, config) { 10 | yeoman.generators.Base.apply(this, arguments); 11 | 12 | this.on('end', function () { 13 | this.installDependencies({ skipInstall: options['skip-install'] }); 14 | console.log('The module ' + (this.module.slug).yellow.bold + ' has been created.'); 15 | 16 | // call controller generator 17 | this.invoke('phalcon:controller-view', { 18 | options: { 19 | 'skip-install': true, 20 | 'moduleName': this.module.name, 21 | 'projectName': this.project.name, 22 | 'controllerName': 'Index' 23 | } 24 | }); 25 | 26 | // call controller generator 27 | this.invoke('phalcon:controller-api', { 28 | options: { 29 | 'skip-install': true, 30 | 'moduleName': this.module.name, 31 | 'projectName': this.project.name, 32 | 'controllerName': 'Index' 33 | } 34 | }); 35 | }); 36 | 37 | console.log( 38 | '\nWelcome to the ' + 'Phalcon module generator'.bold + '.\n\n' + 39 | 'I will create a new ' + 'Phalcon module'.yellow + ' for your application.\n' 40 | ); 41 | 42 | this.module = false; 43 | this.project = false; 44 | 45 | if (options.moduleName) { 46 | this.module = this.getModuleObject(options.moduleName); 47 | } 48 | 49 | if (options.projectName) { 50 | this.project = this.getProjectObject(options.projectName); 51 | } 52 | }; 53 | 54 | util.inherits(ModuleGenerator, yeoman.generators.Base); 55 | 56 | ModuleGenerator.prototype.askFor = function askFor() 57 | { 58 | var prompts, 59 | cb = this.async(); 60 | 61 | if (!this.module || !this.project) { 62 | console.log('Please answer these simple questions:\n'); 63 | prompts = [ 64 | { 65 | type: 'input', 66 | name: 'projectName', 67 | message: 'What is the namespace of the project this module should belong to?', 68 | validate: function (input) { 69 | if (!input) { 70 | return 'I think your ' + 71 | 'project'.red + 72 | ' deserves an awesome ' + 73 | 'namespace'.red + '!'; 74 | } 75 | return true; 76 | } 77 | }, 78 | { 79 | type: 'input', 80 | name: 'moduleName', 81 | message: 'How would you like to name your module?', 82 | validate: function (input) { 83 | if (!input) { 84 | return 'Please specify a valid ' + 85 | 'module name'.red + 86 | ' - this is not too difficult since it may be any string ...'; 87 | } 88 | return true; 89 | } 90 | } 91 | ]; 92 | 93 | this.prompt(prompts, function (props) { 94 | this.project = this.getProjectObject(props.projectName); 95 | this.module = this.getModuleObject(props.moduleName); 96 | this.files(); 97 | cb(); 98 | }.bind(this)); 99 | } else { 100 | this.files(); 101 | cb(); 102 | } 103 | }; 104 | 105 | /* 106 | * Create module directory structure and module specific files, 107 | * copy the view files to the public resources 108 | */ 109 | ModuleGenerator.prototype.files = function files() 110 | { 111 | this.moduleFiles(); 112 | this.addModuleConfig(); 113 | }; 114 | 115 | /* 116 | * Add a module config entry to the application wide modules configuration. 117 | */ 118 | ModuleGenerator.prototype.addModuleConfig = function addModuleConfig() 119 | { 120 | var file = 'private/config/modules.php', 121 | moduleString = "\n\t'" + this.module.slug + "' => [\n\t\t" + 122 | "'className' => '\\" + this.project.namespace + "\\" + this.module.namespace + "\\Module',\n\t\t" + 123 | "'path' => __DIR__ . '/../modules/" + this.module.slug + "/Module.php',\n\t" + 124 | "],\n" + 125 | "];\n"; 126 | 127 | fs.readFile(file, 'utf8', function (err, data) { 128 | if (err) { 129 | return console.log(err); 130 | } else { 131 | var result = data.replace(/\];/g, moduleString); 132 | fs.writeFile(file, result, 'utf8', function (err) { 133 | if (err) { 134 | return console.log(err); 135 | } 136 | }); 137 | } 138 | }); 139 | }; 140 | 141 | /* 142 | * Create module directory structure and module specific files 143 | */ 144 | ModuleGenerator.prototype.moduleFiles = function moduleFiles() 145 | { 146 | var dir = 'private/modules/' + this.module.slug; 147 | this.mkdir(dir); 148 | this.directory('module', dir); 149 | this.directory('test', 'test/modules/' + this.module.slug); 150 | }; 151 | 152 | ModuleGenerator.prototype.getProjectObject = function getProjectObject(projectName) 153 | { 154 | return { 155 | name: projectName, 156 | namespace: this._.camelize(this._.capitalize(projectName)), 157 | slug: this._.slugify(projectName), 158 | camelCase: this._.camelize(projectName), 159 | rewritePath: '/' + this._.slugify(projectName) + '/', 160 | layoutsDir: "__DIR__ . '/../../../public/src/app/layouts/'" 161 | }; 162 | }; 163 | 164 | ModuleGenerator.prototype.getModuleObject = function getModuleObject(moduleName) 165 | { 166 | return { 167 | name: moduleName, 168 | namespace: this._.camelize(this._.capitalize(moduleName)), 169 | slug: this._.slugify(moduleName), 170 | camelCase: this._.camelize(moduleName), 171 | viewsDir: "__DIR__ . '/../../../public/src/app/modules/" + this._.slugify(moduleName) + "/views/'" 172 | }; 173 | }; -------------------------------------------------------------------------------- /module/templates/module/Module.php: -------------------------------------------------------------------------------- 1 | \<%= module.namespace %>; 4 | 5 | use \Phalcon\Loader, 6 | \Phalcon\DI, 7 | \Phalcon\Mvc\View, 8 | \Phalcon\Mvc\Dispatcher, 9 | \Phalcon\Config, 10 | \Phalcon\DiInterface, 11 | \Phalcon\Mvc\Url as UrlResolver, 12 | \Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter, 13 | \<%= project.namespace %>\Application\ApplicationModule; 14 | 15 | /** 16 | * Application module definition for multi module application 17 | * Defining the <%= module.namespace %> module 18 | */ 19 | class Module extends ApplicationModule 20 | { 21 | /** 22 | * Mount the module specific routes before the module is loaded. 23 | * Add ModuleRoutes Group and annotated controllers for parsing their routing information. 24 | * 25 | * @param \Phalcon\DiInterface $di 26 | */ 27 | public static function initRoutes(DiInterface $di) 28 | { 29 | $loader = new Loader(); 30 | $loader->registerNamespaces( 31 | [ 32 | '<%= project.namespace %>\<%= module.namespace %>' => __DIR__, 33 | '<%= project.namespace %>\<%= module.namespace %>\Controllers' => __DIR__ . '/controllers/', 34 | '<%= project.namespace %>\<%= module.namespace %>\Controllers\API' => __DIR__ . '/controllers/api/', 35 | '<%= project.namespace %>\<%= module.namespace %>\Controllers\View' => __DIR__ . '/controllers/view/', 36 | '<%= project.namespace %>\<%= module.namespace %>\Library\Controllers' => __DIR__ . '/lib/controllers' 37 | ], 38 | true 39 | )->register(); 40 | 41 | /** 42 | * Add ModuleRoutes Group and annotated controllers for parsing their routing information. 43 | * Be aware that the parsing will only be triggered if the request URI matches the third 44 | * parameter of addModuleResource. 45 | */ 46 | $router = $di->getRouter(); 47 | $router->mount(new ModuleRoutes()); 48 | 49 | /** 50 | * Read names of annotated controllers from the module config and add them to the router 51 | */ 52 | $moduleConfig = include __DIR__ . '/config/config.php'; 53 | if ( isset($moduleConfig['controllers']['annotationRouted']) ) { 54 | foreach ($moduleConfig['controllers']['annotationRouted'] as $ctrl) { 55 | $router->addModuleResource('<%= module.slug %>', $ctrl, '/<%= module.slug %>'); 56 | } 57 | } 58 | } 59 | 60 | /** 61 | * Registers the module auto-loader 62 | */ 63 | public function registerAutoloaders() 64 | { 65 | $loader = new Loader(); 66 | $loader->registerNamespaces( 67 | [ 68 | '<%= project.namespace %>\<%= module.namespace %>' => __DIR__, 69 | '<%= project.namespace %>\<%= module.namespace %>\Controllers' => __DIR__ . '/controllers/', 70 | '<%= project.namespace %>\<%= module.namespace %>\Controllers\API' => __DIR__ . '/controllers/api/', 71 | '<%= project.namespace %>\<%= module.namespace %>\Controllers\View' => __DIR__ . '/controllers/view/', 72 | '<%= project.namespace %>\<%= module.namespace %>\Models' => __DIR__ . '/models/', 73 | '<%= project.namespace %>\<%= module.namespace %>\Library' => __DIR__ . '/lib/', 74 | '<%= project.namespace %>\<%= module.namespace %>\Library\Models' => __DIR__ . '/lib/models', 75 | '<%= project.namespace %>\<%= module.namespace %>\Library\Controllers' => __DIR__ . '/lib/controllers' 76 | ], 77 | true 78 | )->register(); 79 | } 80 | 81 | /** 82 | * Registers the module-only services 83 | * 84 | * @param \Phalcon\DiInterface $di 85 | */ 86 | public function registerServices($di) 87 | { 88 | /** 89 | * Read application wide and module only configurations 90 | */ 91 | $appConfig = $di->get('config'); 92 | $moduleConfig = include __DIR__ . '/config/config.php'; 93 | 94 | $di->set('moduleConfig', $moduleConfig); 95 | 96 | /** 97 | * Setting up the view component 98 | */ 99 | $di->set( 100 | 'view', 101 | function() { 102 | $view = new View(); 103 | $view->setViewsDir(<%= module.viewsDir %>) 104 | ->setLayoutsDir('../../../layouts/') 105 | ->setPartialsDir('../../../partials/') 106 | ->setTemplateAfter('main') 107 | ->registerEngines(['.html' => 'Phalcon\Mvc\View\Engine\Php']); 108 | return $view; 109 | } 110 | ); 111 | 112 | /** 113 | * The URL component is used to generate all kind of urls in the application 114 | */ 115 | $di->set( 116 | 'url', 117 | function () use ($appConfig) { 118 | $url = new UrlResolver(); 119 | $url->setBaseUri($appConfig->application->baseUri); 120 | return $url; 121 | } 122 | ); 123 | 124 | /** 125 | * Module specific dispatcher 126 | */ 127 | $di->set( 128 | 'dispatcher', 129 | function () use ($di) { 130 | $dispatcher = new Dispatcher(); 131 | $dispatcher->setEventsManager($di->getShared('eventsManager')); 132 | $dispatcher->setDefaultNamespace('<%= project.namespace %>\<%= module.namespace %>\\'); 133 | return $dispatcher; 134 | } 135 | ); 136 | 137 | /** 138 | * Module specific database connection 139 | */ 140 | $di->set( 141 | 'db', 142 | function() use ($moduleConfig) { 143 | return new DbAdapter( 144 | [ 145 | 'host' => $moduleConfig->database->host, 146 | 'username' => $moduleConfig->database->username, 147 | 'password' => $moduleConfig->database->password, 148 | 'dbname' => $moduleConfig->database->dbname 149 | ] 150 | ); 151 | } 152 | ); 153 | 154 | /** 155 | * Module specific database connection 156 | */ 157 | $di->set( 158 | 'mongo', 159 | function () use ($moduleConfig) { 160 | $mongo = new Mongo($moduleConfig->mongoDB->connectionUrl); 161 | return $mongo->selectDb($moduleConfig->mongoDB->dbname); 162 | }, 163 | true 164 | ); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /module/templates/module/ModuleRoutes.php: -------------------------------------------------------------------------------- 1 | \<%= module.namespace %>; 4 | 5 | use \Phalcon\Mvc\Router\Group; 6 | 7 | /** 8 | * This class defines routes for the <%= project.namespace %>\<%= module.namespace %> module 9 | * which will be prefixed with '/<%= module.slug %>' 10 | */ 11 | class ModuleRoutes extends Group 12 | { 13 | /** 14 | * Initialize the router group for the <%= module.namespace %> module 15 | */ 16 | public function initialize() 17 | { 18 | /** 19 | * In the URI this module is prefixed by '/<%= module.slug %>' 20 | */ 21 | $this->setPrefix('/<%= module.slug %>'); 22 | 23 | /** 24 | * Configure the instance 25 | */ 26 | $this->setPaths( 27 | [ 28 | 'module' => '<%= module.slug %>', 29 | 'namespace' => '<%= project.namespace %>\<%= module.namespace %>\Controllers\View\\', 30 | 'controller' => 'index', 31 | 'action' => 'index' 32 | ] 33 | ); 34 | 35 | /** 36 | * Default route: '<%= module.slug %>-api-root' 37 | */ 38 | $this->addGet( 39 | '/api', 40 | [ 41 | 'namespace' => '<%= project.namespace %>\<%= module.namespace %>\Controllers\API\\' 42 | ] 43 | )->setName('<%= module.slug %>-api-root'); 44 | 45 | /** 46 | * API Controller route: '<%= module.slug %>-api-controller' 47 | */ 48 | $this->addGet( 49 | '/api/:controller', 50 | [ 51 | 'namespace' => '<%= project.namespace %>\<%= module.namespace %>\Controllers\API\\', 52 | 'controller' => 1 53 | ] 54 | )->setName('<%= module.slug %>-api-controller'); 55 | 56 | /** 57 | * API Action route: '<%= module.slug %>-api-action' 58 | */ 59 | $this->addGet( 60 | '/api/:controller/:action/:params', 61 | [ 62 | 'namespace' => '<%= project.namespace %>\<%= module.namespace %>\Controllers\API\\', 63 | 'controller' => 1, 64 | 'action' => 2, 65 | 'params' => 3 66 | ] 67 | )->setName('<%= module.slug %>-api-action'); 68 | 69 | /** 70 | * Default route: '<%= module.slug %>-view-root' 71 | */ 72 | $this->addGet( 73 | '/view', 74 | [ 75 | 'namespace' => '<%= project.namespace %>\<%= module.namespace %>\Controllers\View\\' 76 | ] 77 | )->setName('<%= module.slug %>-view-root'); 78 | 79 | /** 80 | * View Controller route: '<%= module.slug %>-view-controller' 81 | */ 82 | $this->addGet( 83 | '/view/:controller', 84 | [ 85 | 'namespace' => '<%= project.namespace %>\<%= module.namespace %>\Controllers\View\\', 86 | 'controller' => 1 87 | ] 88 | )->setName('<%= module.slug %>-view-controller'); 89 | 90 | /** 91 | * View Action route: '<%= module.slug %>-view-action' 92 | */ 93 | $this->addGet( 94 | '/api/:controller/:action/:params', 95 | [ 96 | 'namespace' => '<%= project.namespace %>\<%= module.namespace %>\Controllers\View\\', 97 | 'controller' => 1, 98 | 'action' => 2, 99 | 'params' => 3 100 | ] 101 | )->setName('<%= module.slug %>-view-action'); 102 | 103 | /** 104 | * Add all <%= project.namespace %>\<%= module.namespace %> specific routes here 105 | */ 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /module/templates/module/config/config.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'adapter' => 'Mysql', 6 | 'host' => 'localhost', 7 | 'username' => 'root', 8 | 'password' => '', 9 | 'dbname' => 'test', 10 | 'persistent' => true, 11 | 'charset' => 'utf8' 12 | ], 13 | 'mongoDB' => [ 14 | 'dbname' => 'test', 15 | 'connectionUrl' => 'localhost' 16 | ], 17 | 'controllers' => [ 18 | 'annotationRouted' => [ 19 | ] 20 | ] 21 | ]); 22 | -------------------------------------------------------------------------------- /module/templates/module/controllers/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelkrone/generator-phalcon/58daac265e575e7a4e9eb5eeefaa2e3547194281/module/templates/module/controllers/.gitignore -------------------------------------------------------------------------------- /module/templates/module/lib/controllers/ModuleApiController.php: -------------------------------------------------------------------------------- 1 | \<%= module.namespace %>\Library\Controllers; 4 | 5 | use <%= project.namespace %>\Application\Controllers\ApplicationApiController; 6 | 7 | /** 8 | * Base class of <%= module.namespace %> module API controller 9 | */ 10 | class ModuleApiController extends ApplicationApiController 11 | { 12 | public function beforeExecuteRoute($dispatcher) 13 | { 14 | $this->response->setContentType('application/json'); 15 | } 16 | } -------------------------------------------------------------------------------- /module/templates/module/lib/controllers/ModuleController.php: -------------------------------------------------------------------------------- 1 | \<%= module.namespace %>\Library\Controllers; 4 | 5 | use <%= project.namespace %>\Application\Controllers\ApplicationController; 6 | 7 | /** 8 | * Base class of <%= module.namespace %> module controller 9 | */ 10 | class ModuleController extends ApplicationController 11 | { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /module/templates/module/lib/controllers/ModuleViewController.php: -------------------------------------------------------------------------------- 1 | \<%= module.namespace %>\Library\Controllers; 4 | 5 | use <%= project.namespace %>\Application\Controllers\ApplicationController; 6 | 7 | /** 8 | * Base class of <%= module.namespace %> module View controller 9 | */ 10 | class ModuleViewController extends ApplicationController 11 | { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /module/templates/module/lib/models/ModuleCollection.php: -------------------------------------------------------------------------------- 1 | \<%= module.namespace %>\Library\Models; 4 | 5 | use <%= project.namespace %>\Application\Models\ApplicationCollection; 6 | 7 | class ModuleCollection extends ApplicationCollection 8 | { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /module/templates/module/lib/models/ModuleModel.php: -------------------------------------------------------------------------------- 1 | \<%= module.namespace %>\Library\Models; 4 | 5 | use <%= project.namespace %>\Application\Models\ApplicationModel; 6 | 7 | /** 8 | * Base class of <%= module.namespace %> model 9 | */ 10 | class ModuleModel extends ApplicationModel 11 | { 12 | 13 | } -------------------------------------------------------------------------------- /module/templates/module/models/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelkrone/generator-phalcon/58daac265e575e7a4e9eb5eeefaa2e3547194281/module/templates/module/models/.gitignore -------------------------------------------------------------------------------- /module/templates/test/ModuleTest.php: -------------------------------------------------------------------------------- 1 | \<%= module.namespace %>\Test; 4 | 5 | use Phalcon\DI, 6 | <%= project.namespace %>\<%= module.namespace %>\Test\Helper\ModuleUnitTestCase; 7 | 8 | /** 9 | * Test class for <%= module.namespace %> Module class 10 | */ 11 | class ModuleTest extends ModuleUnitTestCase 12 | { 13 | /** 14 | * Test class for module routes 15 | * @covers \<%= project.namespace %>\<%= module.namespace %>\Module::initRoutes 16 | */ 17 | public function testSimpleModuleRoute() 18 | { 19 | $di = $this->application->di; 20 | $router = $di->get('router'); 21 | $router->handle('/'); 22 | $this->assertEquals('<%= module.slug %>', $router->getModuleName()); 23 | $this->assertEquals('index', $router->getControllerName()); 24 | $this->assertEquals('index', $router->getActionName()); 25 | } 26 | 27 | /** 28 | * Test url generation 29 | * 30 | * @covers \<%= project.namespace %>\<%= module.namespace %>\Module::registerServices 31 | */ 32 | public function testServiceRegistration() 33 | { 34 | $this->assertInstanceOf('\Phalcon\Config', $this->application->di->get('moduleConfig')); 35 | $this->assertInstanceOf('\Phalcon\Mvc\View', $this->application->di->get('view')); 36 | $this->assertInstanceOf('\Phalcon\Mvc\Url', $this->application->di->get('url')); 37 | $this->assertInstanceOf('\Phalcon\Mvc\Dispatcher', $this->application->di->get('dispatcher')); 38 | $this->assertInstanceOf('\Phalcon\Db\AdapterInterface', $this->application->di->get('db')); 39 | $this->assertInstanceOf('\Phalcon\Db\AdapterInterface', $this->application->di->get('mongoDB')); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /module/templates/test/helpers/ModuleTestHelper.php: -------------------------------------------------------------------------------- 1 | registerNamespaces([ 21 | 'Phalcon\Test' => ROOT_PATH . 'test/phalcon/', 22 | '<%= project.namespace %>\Test\Helper' => ROOT_PATH . 'test/helpers/', 23 | '<%= project.namespace %>\Application' => ROOT_PATH . 'private/common/lib/application/', 24 | '<%= project.namespace %>\Application\Controllers' => ROOT_PATH . 'private/common/lib/application/controllers/', 25 | '<%= project.namespace %>\<%= module.namespace %>' => ROOT_PATH . 'private/modules/<%= module.slug %>/', 26 | '<%= project.namespace %>\<%= module.namespace %>\Controllers' => ROOT_PATH . 'private/modules/<%= module.slug %>/controllers/', 27 | '<%= project.namespace %>\<%= module.namespace %>\Controllers\API' => ROOT_PATH . 'private/modules/<%= module.slug %>/controllers/api/', 28 | '<%= project.namespace %>\<%= module.namespace %>\Controllers\View' => ROOT_PATH . 'private/modules/<%= module.slug %>/controllers/view/', 29 | '<%= project.namespace %>\<%= module.namespace %>\Models' => ROOT_PATH . 'private/modules/<%= module.slug %>/models/', 30 | '<%= project.namespace %>\<%= module.namespace %>\Library' => ROOT_PATH . 'private/modules/<%= module.slug %>/lib/', 31 | '<%= project.namespace %>\<%= module.namespace %>\Library\Models' => ROOT_PATH . 'private/modules/<%= module.slug %>/lib/models/', 32 | '<%= project.namespace %>\<%= module.namespace %>\Library\Controllers' => ROOT_PATH . 'private/modules/<%= module.slug %>/lib/Controllers/', 33 | '<%= project.namespace %>\<%= module.namespace %>\Test\Helper' => ROOT_PATH . 'test/modules/<%= module.slug %>/helpers/', 34 | 35 | ])->register(); 36 | 37 | $di = new FactoryDefault(); 38 | DI::reset(); 39 | 40 | // add any needed services to the DI here 41 | 42 | DI::setDefault($di); 43 | -------------------------------------------------------------------------------- /module/templates/test/helpers/ModuleUnitTestCase.php: -------------------------------------------------------------------------------- 1 | \<%= module.namespace %>\Test\Helper; 3 | 4 | use Phalcon\DI, 5 | \Phalcon\Test\UnitTestCase as PhalconTestCase, 6 | \<%= project.namespace %>\Application\Application, 7 | \<%= project.namespace %>\<%= module.namespace %>\Module; 8 | 9 | abstract class ModuleUnitTestCase extends PhalconTestCase 10 | { 11 | /** 12 | * @var \Voice\Cache 13 | */ 14 | protected $_cache; 15 | 16 | /** 17 | * @var \Phalcon\Config 18 | */ 19 | protected $_config; 20 | 21 | protected $application; 22 | 23 | /** 24 | * @var bool 25 | */ 26 | private $_loaded = false; 27 | 28 | public function setUp(\Phalcon\DiInterface $di = null, \Phalcon\Config $config = null) 29 | { 30 | // Load any additional services that might be required during testing 31 | $di = DI::getDefault(); 32 | $this->application = new Application($di); 33 | 34 | // init module 35 | $module = new Module(); 36 | $module->registerServices($di); 37 | 38 | // get any DI components here. If you have a config, be sure to pass it to the parent 39 | parent::setUp($this->application->di, $this->application->config); 40 | 41 | $this->_loaded = true; 42 | } 43 | 44 | public function tearDown() { 45 | $this->application = null; 46 | } 47 | 48 | /** 49 | * Check if the test case is setup properly 50 | * @throws \PHPUnit_Framework_IncompleteTestError; 51 | */ 52 | public function __destruct() { 53 | if(!$this->_loaded) { 54 | throw new \PHPUnit_Framework_IncompleteTestError('Please run parent::setUp().'); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /module/templates/test/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./ 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-phalcon", 3 | "version": "0.0.18", 4 | "description": "Let Yeoman generate a new Phalcon PHP framework multi module project. (Still under development)", 5 | "keywords": [ 6 | "yeoman-generator", 7 | "phalcon", 8 | "php" 9 | ], 10 | "homepage": "https://github.com/michaelkrone/generator-phalcon", 11 | "bugs": "https://github.com/michaelkrone/generator-phalcon/issues", 12 | "author": { 13 | "name": "Michael Krone", 14 | "email": "michael.krone@outlook.com", 15 | "url": "https://github.com/michaelkrone" 16 | }, 17 | "main": "app/index.js", 18 | "repository": { 19 | "type": "git", 20 | "url": "git://github.com/michaelkrone/generator-phalcon.git" 21 | }, 22 | "scripts": { 23 | "test": "mocha" 24 | }, 25 | "dependencies": { 26 | "yeoman-generator": "~0.13.0", 27 | "colors": "latest" 28 | }, 29 | "devDependencies": { 30 | "mocha": "~1.12.0" 31 | }, 32 | "peerDependencies": { 33 | "yo": ">=1.0.0-rc.1" 34 | }, 35 | "engines": { 36 | "node": ">=0.8.0", 37 | "npm": ">=1.2.10" 38 | }, 39 | "licenses": [ 40 | { 41 | "type": "MIT" 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /test/test-creation.js: -------------------------------------------------------------------------------- 1 | /*global describe, beforeEach, it*/ 2 | 'use strict'; 3 | 4 | var path = require('path'); 5 | var helpers = require('yeoman-generator').test; 6 | 7 | 8 | describe('phalcon generator', function () { 9 | beforeEach(function (done) { 10 | helpers.testDirectory(path.join(__dirname, 'temp'), function (err) { 11 | if (err) { 12 | return done(err); 13 | } 14 | 15 | this.app = helpers.createGenerator('phalcon:app', [ 16 | '../../app' 17 | ]); 18 | done(); 19 | }.bind(this)); 20 | }); 21 | 22 | it('creates expected files', function (done) { 23 | var expected = [ 24 | // add files you expect to exist here. 25 | '.jshintrc', 26 | '.editorconfig' 27 | ]; 28 | 29 | helpers.mockPrompt(this.app, { 30 | 'someOption': true 31 | }); 32 | this.app.options['skip-install'] = true; 33 | this.app.run({}, function () { 34 | helpers.assertFiles(expected); 35 | done(); 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /test/test-load.js: -------------------------------------------------------------------------------- 1 | /*global describe, beforeEach, it*/ 2 | 'use strict'; 3 | 4 | var assert = require('assert'); 5 | 6 | describe('phalcon generator', function () { 7 | it('can be imported without blowing up', function () { 8 | var app = require('../app'); 9 | assert(app !== undefined); 10 | }); 11 | }); 12 | --------------------------------------------------------------------------------