| 1 |
<?php |
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
require_once(dirname(__FILE__).'/sfGeneratorBaseTask.class.php'); |
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
class sfGenerateAppTask extends sfGeneratorBaseTask |
|---|
| 22 |
{ |
|---|
| 23 |
|
|---|
| 24 |
* @see sfTask |
|---|
| 25 |
*/ |
|---|
| 26 |
protected function configure() |
|---|
| 27 |
{ |
|---|
| 28 |
$this->addArguments(array( |
|---|
| 29 |
new sfCommandArgument('app', sfCommandArgument::REQUIRED, 'The application name'), |
|---|
| 30 |
)); |
|---|
| 31 |
|
|---|
| 32 |
$this->addOptions(array( |
|---|
| 33 |
new sfCommandOption('escaping-strategy', null, sfCommandOption::PARAMETER_REQUIRED, 'Output escaping strategy', true), |
|---|
| 34 |
new sfCommandOption('csrf-secret', null, sfCommandOption::PARAMETER_REQUIRED, 'Secret to use for CSRF protection', true), |
|---|
| 35 |
)); |
|---|
| 36 |
|
|---|
| 37 |
$this->namespace = 'generate'; |
|---|
| 38 |
$this->name = 'app'; |
|---|
| 39 |
|
|---|
| 40 |
$this->briefDescription = 'Generates a new application'; |
|---|
| 41 |
|
|---|
| 42 |
$this->detailedDescription = <<<EOF |
|---|
| 43 |
The [generate:app|INFO] task creates the basic directory structure |
|---|
| 44 |
for a new application in the current project: |
|---|
| 45 |
|
|---|
| 46 |
[./symfony generate:app frontend|INFO] |
|---|
| 47 |
|
|---|
| 48 |
This task also creates two front controller scripts in the |
|---|
| 49 |
[web/|COMMENT] directory: |
|---|
| 50 |
|
|---|
| 51 |
[web/%application%.php|INFO] for the production environment |
|---|
| 52 |
[web/%application%_dev.php|INFO] for the development environment |
|---|
| 53 |
|
|---|
| 54 |
For the first application, the production environment script is named |
|---|
| 55 |
[index.php|COMMENT]. |
|---|
| 56 |
|
|---|
| 57 |
If an application with the same name already exists, |
|---|
| 58 |
it throws a [sfCommandException|COMMENT]. |
|---|
| 59 |
|
|---|
| 60 |
By default, the output escaping is enabled (to prevent XSS), and a random |
|---|
| 61 |
secret is also generated to prevent CSRF. |
|---|
| 62 |
|
|---|
| 63 |
You can disable output escaping by using the [escaping-strategy|COMMENT] |
|---|
| 64 |
option: |
|---|
| 65 |
|
|---|
| 66 |
[./symfony generate:app frontend --escaping-strategy=false|INFO] |
|---|
| 67 |
|
|---|
| 68 |
You can enable session token in forms (to prevent CSRF) by defining |
|---|
| 69 |
a secret with the [csrf-secret|COMMENT] option: |
|---|
| 70 |
|
|---|
| 71 |
[./symfony generate:app frontend --csrf-secret=UniqueSecret|INFO] |
|---|
| 72 |
|
|---|
| 73 |
You can customize the default skeleton used by the task by creating a |
|---|
| 74 |
[%sf_data_dir%/skeleton/app|COMMENT] directory. |
|---|
| 75 |
EOF; |
|---|
| 76 |
} |
|---|
| 77 |
|
|---|
| 78 |
|
|---|
| 79 |
* @see sfTask |
|---|
| 80 |
*/ |
|---|
| 81 |
protected function execute($arguments = array(), $options = array()) |
|---|
| 82 |
{ |
|---|
| 83 |
$app = $arguments['app']; |
|---|
| 84 |
|
|---|
| 85 |
|
|---|
| 86 |
if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $app)) |
|---|
| 87 |
{ |
|---|
| 88 |
throw new sfCommandException(sprintf('The application name "%s" is invalid.', $app)); |
|---|
| 89 |
} |
|---|
| 90 |
|
|---|
| 91 |
$appDir = sfConfig::get('sf_apps_dir').'/'.$app; |
|---|
| 92 |
|
|---|
| 93 |
if (is_dir($appDir)) |
|---|
| 94 |
{ |
|---|
| 95 |
throw new sfCommandException(sprintf('The application "%s" already exists.', $appDir)); |
|---|
| 96 |
} |
|---|
| 97 |
|
|---|
| 98 |
if (is_readable(sfConfig::get('sf_data_dir').'/skeleton/app')) |
|---|
| 99 |
{ |
|---|
| 100 |
$skeletonDir = sfConfig::get('sf_data_dir').'/skeleton/app'; |
|---|
| 101 |
} |
|---|
| 102 |
else |
|---|
| 103 |
{ |
|---|
| 104 |
$skeletonDir = dirname(__FILE__).'/skeleton/app'; |
|---|
| 105 |
} |
|---|
| 106 |
|
|---|
| 107 |
|
|---|
| 108 |
$finder = sfFinder::type('any')->discard('.sf'); |
|---|
| 109 |
$this->getFilesystem()->mirror($skeletonDir.'/app', $appDir, $finder); |
|---|
| 110 |
|
|---|
| 111 |
|
|---|
| 112 |
$indexName = 'index'; |
|---|
| 113 |
$firstApp = !file_exists(sfConfig::get('sf_web_dir').'/index.php'); |
|---|
| 114 |
if (!$firstApp) |
|---|
| 115 |
{ |
|---|
| 116 |
$indexName = $app; |
|---|
| 117 |
} |
|---|
| 118 |
|
|---|
| 119 |
if (true === $options['csrf-secret']) |
|---|
| 120 |
{ |
|---|
| 121 |
$options['csrf-secret'] = sha1(rand(111111111, 99999999).getmypid()); |
|---|
| 122 |
} |
|---|
| 123 |
|
|---|
| 124 |
|
|---|
| 125 |
$finder = sfFinder::type('file')->name('settings.yml'); |
|---|
| 126 |
$this->getFilesystem()->replaceTokens($finder->in($appDir.'/config'), '##', '##', array( |
|---|
| 127 |
'NO_SCRIPT_NAME' => $firstApp ? 'true' : 'false', |
|---|
| 128 |
'CSRF_SECRET' => sfYamlInline::dump(sfYamlInline::parseScalar($options['csrf-secret'])), |
|---|
| 129 |
'ESCAPING_STRATEGY' => sfYamlInline::dump((boolean) sfYamlInline::parseScalar($options['escaping-strategy'])), |
|---|
| 130 |
'USE_DATABASE' => sfConfig::has('sf_orm') ? 'true' : 'false', |
|---|
| 131 |
)); |
|---|
| 132 |
|
|---|
| 133 |
$this->getFilesystem()->copy($skeletonDir.'/web/index.php', sfConfig::get('sf_web_dir').'/'.$indexName.'.php'); |
|---|
| 134 |
$this->getFilesystem()->copy($skeletonDir.'/web/index.php', sfConfig::get('sf_web_dir').'/'.$app.'_dev.php'); |
|---|
| 135 |
|
|---|
| 136 |
$this->getFilesystem()->replaceTokens(sfConfig::get('sf_web_dir').'/'.$indexName.'.php', '##', '##', array( |
|---|
| 137 |
'APP_NAME' => $app, |
|---|
| 138 |
'ENVIRONMENT' => 'prod', |
|---|
| 139 |
'IS_DEBUG' => 'false', |
|---|
| 140 |
'IP_CHECK' => '', |
|---|
| 141 |
)); |
|---|
| 142 |
|
|---|
| 143 |
$this->getFilesystem()->replaceTokens(sfConfig::get('sf_web_dir').'/'.$app.'_dev.php', '##', '##', array( |
|---|
| 144 |
'APP_NAME' => $app, |
|---|
| 145 |
'ENVIRONMENT' => 'dev', |
|---|
| 146 |
'IS_DEBUG' => 'true', |
|---|
| 147 |
'IP_CHECK' => '// this check prevents access to debug front controllers that are deployed by accident to production servers.'.PHP_EOL. |
|---|
| 148 |
'// feel free to remove this, extend it or make something more sophisticated.'.PHP_EOL. |
|---|
| 149 |
'if (!in_array(@$_SERVER[\'REMOTE_ADDR\'], array(\'127.0.0.1\', \'::1\')))'.PHP_EOL. |
|---|
| 150 |
'{'.PHP_EOL. |
|---|
| 151 |
' die(\'You are not allowed to access this file. Check \'.basename(__FILE__).\' for more information.\');'.PHP_EOL. |
|---|
| 152 |
'}'.PHP_EOL, |
|---|
| 153 |
)); |
|---|
| 154 |
|
|---|
| 155 |
$this->getFilesystem()->rename($appDir.'/config/ApplicationConfiguration.class.php', $appDir.'/config/'.$app.'Configuration.class.php'); |
|---|
| 156 |
|
|---|
| 157 |
$this->getFilesystem()->replaceTokens($appDir.'/config/'.$app.'Configuration.class.php', '##', '##', array('APP_NAME' => $app)); |
|---|
| 158 |
|
|---|
| 159 |
$fixPerms = new sfProjectPermissionsTask($this->dispatcher, $this->formatter); |
|---|
| 160 |
$fixPerms->setCommandApplication($this->commandApplication); |
|---|
| 161 |
$fixPerms->setConfiguration($this->configuration); |
|---|
| 162 |
$fixPerms->run(); |
|---|
| 163 |
|
|---|
| 164 |
|
|---|
| 165 |
$this->getFilesystem()->mkdirs(sfConfig::get('sf_test_dir').'/functional/'.$app); |
|---|
| 166 |
} |
|---|
| 167 |
} |
|---|
| 168 |
|
|---|