├── .gitignore ├── Command └── GenerateProjectCommand.php ├── Installer ├── Bundle │ ├── Bundle.php │ └── BundleCollection.php ├── Nspace │ ├── Nspace.php │ └── NspaceCollection.php ├── Prefix │ ├── Prefix.php │ └── PrefixCollection.php ├── Repository │ ├── Repository.php │ └── RepositoryCollection.php └── Tool │ └── Tool.php ├── LICENSE ├── README.markdown ├── Resources ├── Installer │ └── Config │ │ ├── annotation_odm.txt │ │ ├── annotation_orm.txt │ │ ├── assetic.txt │ │ ├── assetic_dev.txt │ │ ├── doctrine.txt │ │ ├── doctrine_mongodb.txt │ │ ├── mandango_config.txt │ │ ├── mandango_config_dev.txt │ │ ├── propel.txt │ │ ├── routing.txt │ │ ├── swiftmailer.txt │ │ ├── swiftmailer_autoload.txt │ │ ├── swiftmailer_test.txt │ │ └── twig.txt ├── Profile │ └── default.xml.dist └── skeleton │ ├── bundle │ ├── AppBundle.php │ ├── Controller │ │ └── BundleController.php │ └── Resources │ │ ├── config │ │ └── routing.yml │ │ └── views │ │ ├── Bundle │ │ ├── index.html.php │ │ ├── index.html.twig │ │ ├── welcome.html.php │ │ └── welcome.html.twig │ │ ├── layout.html.php │ │ └── layout.html.twig │ └── project │ ├── .gitignore │ ├── app │ ├── .htaccess │ ├── AppCache.php │ ├── AppKernel.php │ ├── Resources │ │ └── views │ │ │ ├── base.html.php │ │ │ └── base.html.twig │ ├── autoload.php │ ├── check.php │ ├── config │ │ ├── config.yml │ │ ├── config_dev.yml │ │ ├── config_prod.yml │ │ ├── config_test.yml │ │ ├── routing.yml │ │ └── routing_dev.yml │ ├── console │ └── phpunit.xml.dist │ ├── bin │ └── build_bootstrap.php │ └── web │ ├── .htaccess │ ├── index.php │ └── index_dev.php ├── Symfony ├── Bundle │ └── FrameworkBundle │ │ └── Util │ │ ├── Filesystem.php │ │ └── Mustache.php └── Component │ ├── ClassLoader │ ├── ClassCollectionLoader.php │ ├── MapFileClassLoader.php │ └── UniversalClassLoader.php │ └── Console │ ├── Application.php │ ├── Command │ ├── Command.php │ ├── HelpCommand.php │ └── ListCommand.php │ ├── Helper │ ├── DialogHelper.php │ ├── FormatterHelper.php │ ├── Helper.php │ ├── HelperInterface.php │ └── HelperSet.php │ ├── Input │ ├── ArgvInput.php │ ├── ArrayInput.php │ ├── Input.php │ ├── InputArgument.php │ ├── InputDefinition.php │ ├── InputInterface.php │ ├── InputOption.php │ └── StringInput.php │ ├── Output │ ├── ConsoleOutput.php │ ├── NullOutput.php │ ├── Output.php │ ├── OutputInterface.php │ └── StreamOutput.php │ ├── Shell.php │ └── Tester │ ├── ApplicationTester.php │ └── CommandTester.php └── symfony2project /.gitignore: -------------------------------------------------------------------------------- 1 | Resources/Profile/*.xml 2 | -------------------------------------------------------------------------------- /Installer/Bundle/Bundle.php: -------------------------------------------------------------------------------- 1 | 9 | * @author Clément Jobeili 10 | */ 11 | class Bundle 12 | { 13 | protected $name; 14 | 15 | protected $ns; 16 | 17 | protected $config; 18 | 19 | public function __construct($name, $ns = null, $config = null) 20 | { 21 | $this->name = (string) $name; 22 | $this->ns = $ns; 23 | $this->config = $config; 24 | } 25 | 26 | public function getName() 27 | { 28 | return $this->name; 29 | } 30 | 31 | public function getNs() 32 | { 33 | return $this->ns; 34 | } 35 | 36 | public function getConfig() 37 | { 38 | return $this->config; 39 | } 40 | 41 | public function get() 42 | { 43 | $namespace = $this->generateNamespace($this->name); 44 | 45 | return sprintf('new %s\%sBundle()', $namespace, $this->name); 46 | } 47 | 48 | private function generateNamespace($name) 49 | { 50 | return (!$this->ns) ? sprintf('Symfony\Bundle\%sBundle', $name) : $this->ns; 51 | } 52 | } -------------------------------------------------------------------------------- /Installer/Bundle/BundleCollection.php: -------------------------------------------------------------------------------- 1 | 9 | * @author Clément Jobeili 10 | */ 11 | class BundleCollection 12 | { 13 | protected $collection; 14 | 15 | public function add($bundle) 16 | { 17 | $this->collection[] = $bundle; 18 | } 19 | 20 | public function getCollection() 21 | { 22 | return $this->collection; 23 | } 24 | 25 | public function getFormatted($space = 4) 26 | { 27 | $bundles = ''; 28 | foreach ($this->collection as $bundle) 29 | { 30 | $bundles .= $bundle->get().",\n".str_repeat(' ', $space); 31 | } 32 | 33 | return trim($bundles); 34 | } 35 | } -------------------------------------------------------------------------------- /Installer/Nspace/Nspace.php: -------------------------------------------------------------------------------- 1 | 9 | * @author Clément Jobeili 10 | */ 11 | class Nspace 12 | { 13 | protected $ns; 14 | 15 | protected $path; 16 | 17 | public function __construct($ns, $path) 18 | { 19 | $this->ns = (string) str_replace('\\', '\\\\', $ns); 20 | 21 | if (!is_array($path)) { 22 | $path = (array) $path; 23 | } 24 | 25 | $this->path = $path; 26 | } 27 | 28 | public function getNamespace() 29 | { 30 | return $this->ns; 31 | } 32 | 33 | public function get($maxspace = 0) 34 | { 35 | $space = $maxspace - mb_strlen($this->ns) + 2; 36 | $mask = ''; 37 | 38 | if (count($this->path) == 1) { 39 | $mask = sprintf("__DIR__.'/../%s'", $this->path[0]); 40 | } else 41 | { 42 | foreach ($this->path as $path) { 43 | $mask .= sprintf("__DIR__.'/../%s', ", $path); 44 | } 45 | $mask = sprintf('array(%s)', substr($mask, 0, -2)); 46 | } 47 | 48 | return sprintf("'%s'%s => %s", $this->ns, str_repeat(' ',$space), $mask); 49 | } 50 | } -------------------------------------------------------------------------------- /Installer/Nspace/NspaceCollection.php: -------------------------------------------------------------------------------- 1 | 9 | * @author Clément Jobeili 10 | */ 11 | class NspaceCollection 12 | { 13 | protected $collection; 14 | 15 | protected $size; 16 | 17 | public function add($namespace) 18 | { 19 | $this->collection[] = $namespace; 20 | $this->calculateSize($namespace->getNamespace()); 21 | } 22 | 23 | public function getFormatted($space = 4) 24 | { 25 | $namespaces = ''; 26 | foreach ($this->collection as $namespace) 27 | { 28 | $namespaces .= $namespace->get($this->size).",\n".str_repeat(' ', $space); 29 | } 30 | 31 | return trim($namespaces); 32 | } 33 | 34 | private function calculateSize($name) 35 | { 36 | if ($this->size < mb_strlen($name)) { 37 | $this->size = mb_strlen($name); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Installer/Prefix/Prefix.php: -------------------------------------------------------------------------------- 1 | 9 | * @author Clément Jobeili 10 | */ 11 | class Prefix 12 | { 13 | public function __construct($prefix, $path) 14 | { 15 | $this->prefix = (string) $prefix; 16 | $this->path = (string) $path; 17 | } 18 | 19 | public function getPrefix() 20 | { 21 | return $this->prefix; 22 | } 23 | 24 | public function get($maxspace) 25 | { 26 | $space = $maxspace - mb_strlen($this->prefix) + 2; 27 | return sprintf("'%s_'%s => __DIR__.'/../%s'", $this->prefix, str_repeat(' ', $space), $this->path); 28 | } 29 | } -------------------------------------------------------------------------------- /Installer/Prefix/PrefixCollection.php: -------------------------------------------------------------------------------- 1 | 9 | * @author Clément Jobeili 10 | */ 11 | class PrefixCollection 12 | { 13 | protected $collection; 14 | 15 | protected $size; 16 | 17 | public function add($prefix) 18 | { 19 | $this->collection[] = $prefix; 20 | $this->calculateSize($prefix->getPrefix()); 21 | } 22 | 23 | public function getFormatted($space = 4) 24 | { 25 | $prefixes = ''; 26 | foreach ($this->collection as $prefix) 27 | { 28 | $prefixes .= $prefix->get($this->size).",\n".str_repeat(' ', $space); 29 | } 30 | 31 | return trim($prefixes); 32 | } 33 | 34 | private function calculateSize($name) 35 | { 36 | if ($this->size < mb_strlen($name)) { 37 | $this->size = mb_strlen($name); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Installer/Repository/Repository.php: -------------------------------------------------------------------------------- 1 | 8 | * @author Clément Jobeili 9 | */ 10 | class Repository 11 | { 12 | protected $source; 13 | 14 | protected $target; 15 | 16 | protected $type; 17 | 18 | protected $revision; 19 | 20 | public function __construct($source, $target, $type, $revision) 21 | { 22 | $this->source = (string) $source; 23 | $this->target = (string) $target; 24 | $this->type = (string) $type; 25 | $this->revision = (string) $revision; 26 | } 27 | 28 | public function getSource() 29 | { 30 | return $this->source; 31 | } 32 | 33 | public function getTarget() 34 | { 35 | return $this->target; 36 | } 37 | 38 | public function getType() 39 | { 40 | return $this->type; 41 | } 42 | 43 | public function getRevision() 44 | { 45 | return $this->revision; 46 | } 47 | } -------------------------------------------------------------------------------- /Installer/Repository/RepositoryCollection.php: -------------------------------------------------------------------------------- 1 | 8 | * @author Clément Jobeili 9 | */ 10 | class RepositoryCollection 11 | { 12 | protected $collection; 13 | 14 | public function add($repository) 15 | { 16 | $this->collection[] = $repository; 17 | } 18 | 19 | public function get() 20 | { 21 | return $this->collection; 22 | } 23 | } -------------------------------------------------------------------------------- /Installer/Tool/Tool.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class Tool 11 | { 12 | /** 13 | * Generate a random secret string 14 | * 15 | */ 16 | public static function generateSecret() 17 | { 18 | $secret = ''; 19 | $alphanum = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 20 | $length = strlen($alphanum); 21 | for($a = 0; $a < 32; $a++) { 22 | $secret .= substr($alphanum, rand(0, $length-1), 1); 23 | } 24 | 25 | return $secret; 26 | } 27 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-11 Bertrand Zuchuat, Clément Jobeili 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | ##Symfony2Project 2 | 3 | 4 | ##Usage 5 | 6 | symfony2project generate:project AppName VendorName Path [--controller="..."] [--protocol="..."] 7 | [--session-start] [--session-name="..."] [--orm="..."] [--odm="..."] [--assetic] [--swiftmailer] 8 | [--doctrine-migration] [--doctrine-fixtures] [--template-engine="..."] [--profile="..."] 9 | [--assets-symlink] [--force-delete] 10 | 11 | ###Arguments 12 | 13 | AppName : application name (mandatory) 14 | VendorName : vendor name (mandatory) 15 | Path : directory name (path) 16 | 17 | ###Options 18 | 19 | --controller : Your first controller name (default: Main) 20 | --protocol : git or http (default: git) 21 | --session-start : To start session automatically 22 | --session-name : Session name (default: symfony) 23 | --orm : doctrine or propel 24 | --odm : mongodb or mandango 25 | --assetic : Enable assetic 26 | --swiftmailer : Enable swiftmailer 27 | --doctrine-migration : Enable doctrine migration 28 | --doctrine-fixtures : Enable doctrine fixtures 29 | --template-engine : twig or php (default: twig) 30 | --profile : Profile name (default: default) or http url 31 | --assets-symlink : Symlink for web assets 32 | --force-delete : Force re-generation of project 33 | 34 | ###Profile 35 | 36 | Before execute this command, copy the file Resources/Profile/default.xml.dist 37 | to Resources/Profile/default.xml 38 | 39 | if you would like to personalize, open this file, modify or add some parameters. 40 | 41 | You can also create new profile, copy the file default.xml.dist, rename (ex: foo.xml) and use --profile=foo on command line. 42 | 43 | http server example: http://myserver/profile/default (not with xml) 44 | 45 | *Note: only tested on unix system.* 46 | -------------------------------------------------------------------------------- /Resources/Installer/Config/annotation_odm.txt: -------------------------------------------------------------------------------- 1 | AnnotationRegistry::registerFile(__DIR__.'/../vendor/doctrine-mongodb-odm/lib/Doctrine/ODM/MongoDB/Mapping/Annotations/DoctrineAnnotations.php'); 2 | -------------------------------------------------------------------------------- /Resources/Installer/Config/annotation_orm.txt: -------------------------------------------------------------------------------- 1 | AnnotationRegistry::registerFile(__DIR__.'/../vendor/doctrine/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php'); 2 | -------------------------------------------------------------------------------- /Resources/Installer/Config/assetic.txt: -------------------------------------------------------------------------------- 1 | 2 | # Assetic Configuration 3 | assetic: 4 | debug: %kernel.debug% 5 | use_controller: false 6 | filters: 7 | cssrewrite: ~ 8 | # closure: 9 | # jar: %kernel.root_dir%/java/compiler.jar 10 | # yui_css: 11 | # jar: %kernel.root_dir%/java/yuicompressor-2.4.2.jar -------------------------------------------------------------------------------- /Resources/Installer/Config/assetic_dev.txt: -------------------------------------------------------------------------------- 1 | 2 | # Twig Configuration 3 | assetic: 4 | use_controller: true -------------------------------------------------------------------------------- /Resources/Installer/Config/doctrine.txt: -------------------------------------------------------------------------------- 1 | 2 | ## Doctrine Configuration 3 | #doctrine: 4 | # dbal: 5 | # default_connection: default 6 | # connections: 7 | # default: 8 | # dbname: xxxxxxxx 9 | # user: xxxxxxxx 10 | # password: ~ 11 | # logging: %kernel.debug% 12 | # orm: 13 | # auto_generate_proxy_classes: %kernel.debug% 14 | # default_entity_manager: default 15 | # entity_managers: 16 | # default: 17 | # connection: default 18 | # mappings: 19 | # {{ namespace }}{{ app }}Bundle: ~ -------------------------------------------------------------------------------- /Resources/Installer/Config/doctrine_mongodb.txt: -------------------------------------------------------------------------------- 1 | 2 | ## Doctrine Mongodb Configuration 3 | # doctrine_mongodb: 4 | # connections: 5 | # default: 6 | # server: mongodb://localhost:27017 7 | # options: 8 | # connect: true 9 | # default_database: test_database 10 | # document_managers: 11 | # default: 12 | # auto_mapping: true -------------------------------------------------------------------------------- /Resources/Installer/Config/mandango_config.txt: -------------------------------------------------------------------------------- 1 | 2 | # Mandango configuration 3 | mandango: 4 | default_connection: local 5 | connections: 6 | local: 7 | server: mongodb://localhost:27017 8 | database: symfony2_local_%kernel.environment% -------------------------------------------------------------------------------- /Resources/Installer/Config/mandango_config_dev.txt: -------------------------------------------------------------------------------- 1 | 2 | # Mandango Configuration 3 | mandango: 4 | logging: true -------------------------------------------------------------------------------- /Resources/Installer/Config/propel.txt: -------------------------------------------------------------------------------- 1 | 2 | # Propel configuration 3 | propel: 4 | path: "%kernel.root_dir%/../vendor/propel" 5 | phing_path: "%kernel.root_dir%/../vendor/phing" 6 | dbal: 7 | driver: mysql 8 | options: {} 9 | user: xxxxxxxx 10 | password: xxxxxxxx 11 | dsn: mysql:host=localhost;dbname=xxxxxxx -------------------------------------------------------------------------------- /Resources/Installer/Config/routing.txt: -------------------------------------------------------------------------------- 1 | 2 | {{ app }}: 3 | resource: "@{{ namespace }}{{ app }}Bundle/Resources/config/routing.yml" -------------------------------------------------------------------------------- /Resources/Installer/Config/swiftmailer.txt: -------------------------------------------------------------------------------- 1 | 2 | ## Swiftmailer Configuration 3 | #swiftmailer: 4 | # transport: smtp 5 | # encryption: ssl 6 | # auth_mode: login 7 | # host: smtp.gmail.com 8 | # username: xxxxxxxx 9 | # password: xxxxxxxx -------------------------------------------------------------------------------- /Resources/Installer/Config/swiftmailer_autoload.txt: -------------------------------------------------------------------------------- 1 | 2 | // Swiftmailer needs a special autoloader to allow 3 | // the lazy loading of the init file (which is expensive) 4 | require_once __DIR__.'/../vendor/swiftmailer/lib/classes/Swift.php'; 5 | Swift::registerAutoload(__DIR__.'/../vendor/swiftmailer/lib/swift_init.php'); -------------------------------------------------------------------------------- /Resources/Installer/Config/swiftmailer_test.txt: -------------------------------------------------------------------------------- 1 | 2 | ## Swiftmailer Configuration 3 | swiftmailer: 4 | disable_delivery: true 5 | -------------------------------------------------------------------------------- /Resources/Installer/Config/twig.txt: -------------------------------------------------------------------------------- 1 | 2 | # Twig Configuration 3 | twig: 4 | debug: %kernel.debug% 5 | strict_variables: %kernel.debug% -------------------------------------------------------------------------------- /Resources/Profile/default.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | github.com/symfony/symfony.git 8 | vendor/symfony 9 | 2.0 10 | 11 | 12 | github.com/Seldaek/monolog.git 13 | vendor/monolog 14 | 1.0.1 15 | 16 | 17 | github.com/swiftmailer/swiftmailer.git 18 | vendor/swiftmailer 19 | v4.1.3 20 | 21 | 22 | github.com/kriswallsmith/assetic.git 23 | vendor/assetic 24 | 1.0.x 25 | 26 | 27 | github.com/symfony/AsseticBundle.git 28 | vendor/bundles/Symfony/Bundle/AsseticBundle 29 | v1.0.1 30 | 31 | 32 | github.com/fabpot/Twig.git 33 | vendor/twig 34 | 1.1 35 | 36 | 37 | github.com/fabpot/Twig-extensions.git 38 | vendor/twig-extensions 39 | master 40 | 41 | 42 | github.com/doctrine/doctrine2.git 43 | vendor/doctrine 44 | 2.1.x 45 | 46 | 47 | github.com/doctrine/dbal.git 48 | vendor/doctrine-dbal 49 | 2.1.x 50 | 51 | 52 | github.com/doctrine/data-fixtures.git 53 | vendor/doctrine-data-fixtures 54 | master 55 | 56 | 57 | github.com/symfony/DoctrineFixturesBundle.git 58 | vendor/bundles/Symfony/Bundle/DoctrineFixturesBundle 59 | master 60 | 61 | 62 | github.com/doctrine/migrations.git 63 | vendor/doctrine-migrations 64 | master 65 | 66 | 67 | github.com/symfony/DoctrineMigrationsBundle.git 68 | vendor/bundles/Symfony/Bundle/DoctrineMigrationsBundle 69 | master 70 | 71 | 72 | github.com/doctrine/common.git 73 | vendor/doctrine-common 74 | 2.1.x 75 | 76 | 77 | github.com/doctrine/mongodb.git 78 | vendor/doctrine-mongodb 79 | master 80 | 81 | 82 | github.com/doctrine/mongodb-odm.git 83 | vendor/doctrine-mongodb-odm 84 | master 85 | 86 | 87 | github.com/symfony/DoctrineMongoDBBundle.git 88 | vendor/bundles/Symfony/Bundle/DoctrineMongoDBBundle 89 | 2.0 90 | 91 | 92 | github.com/propelorm/PropelBundle.git 93 | vendor/bundles/Propel/PropelBundle 94 | master 95 | 96 | 97 | github.com/Xosofox/phing.git 98 | vendor/phing 99 | master 100 | 101 | 102 | github.com/propelorm/Propel.git 103 | vendor/propel 104 | master 105 | 106 | 107 | github.com/mandango/mandango.git 108 | vendor/mandango 109 | master 110 | 111 | 112 | github.com/mandango/mondator.git 113 | vendor/mondator 114 | master 115 | 116 | 117 | github.com/mandango/MandangoBundle.git 118 | vendor/bundles/Mandango/MandangoBundle 119 | master 120 | 121 | 122 | github.com/schmittjoh/metadata.git 123 | vendor/metadata 124 | master 125 | 126 | 127 | 128 | 129 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | Framework 145 | Symfony\Bundle\FrameworkBundle 146 | 147 | 148 | Monolog 149 | Symfony\Bundle\MonologBundle 150 | 151 | 152 | Twig 153 | Symfony\Bundle\TwigBundle 154 | 155 | 156 | Swiftmailer 157 | Symfony\Bundle\SwiftmailerBundle 158 | 159 | 160 | Assetic 161 | Symfony\Bundle\AsseticBundle 162 | 163 | 164 | Doctrine 165 | Symfony\Bundle\DoctrineBundle 166 | 167 | 168 | DoctrineMigrations 169 | Symfony\Bundle\DoctrineMigrationsBundle 170 | 171 | 172 | DoctrineFixtures 173 | Symfony\Bundle\DoctrineFixturesBundle 174 | 175 | 176 | Propel 177 | Propel\PropelBundle 178 | 179 | 180 | DoctrineMongoDB 181 | Symfony\Bundle\DoctrineMongoDBBundle 182 | 183 | 184 | Mandango 185 | Mandango\MandangoBundle 186 | 187 | 188 | 189 | 190 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | Symfony 227 | vendor/symfony/src 228 | vendor/bundles 229 | 230 | 231 | Doctrine\Common\DataFixtures 232 | vendor/doctrine-data-fixtures/lib 233 | 234 | 235 | Doctrine\Common 236 | vendor/doctrine-common/lib 237 | 238 | 239 | Doctrine\DBAL\Migrations 240 | vendor/doctrine-migrations/lib 241 | 242 | 243 | Doctrine\MongoDB 244 | vendor/doctrine-mongodb/lib 245 | 246 | 247 | Doctrine\ODM\MongoDB 248 | vendor/doctrine-mongodb-odm/lib 249 | 250 | 251 | Doctrine\DBAL 252 | vendor/doctrine-dbal/lib 253 | 254 | 255 | Doctrine 256 | vendor/doctrine/lib 257 | 258 | 259 | Propel 260 | vendor/bundles 261 | 262 | 263 | Assetic 264 | vendor/assetic/src 265 | 266 | 267 | Metadata 268 | vendor/metadata/src 269 | 270 | 271 | Monolog 272 | vendor/monolog/src 273 | 274 | 275 | Mandango\MandangoBundle 276 | vendor/bundles 277 | 278 | 279 | Mondator 280 | vendor/mondator/src 281 | 282 | 283 | Mandango 284 | vendor/mondator/src 285 | 286 | 287 | Model 288 | src 289 | 290 | 291 | 292 | 293 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | Twig_Extensions 308 | vendor/twig-extensions/lib 309 | 310 | 311 | Twig 312 | vendor/twig/lib 313 | 314 | 315 | 316 | 317 | 325 | 326 | 327 | -------------------------------------------------------------------------------- /Resources/skeleton/bundle/AppBundle.php: -------------------------------------------------------------------------------- 1 | render('{{ namespace }}{{ appname }}Bundle:{{ controller }}:index.html.{{ template_engine }}'); 12 | } 13 | 14 | public function welcomeAction() 15 | { 16 | return $this->render('{{ namespace }}{{ appname }}Bundle:{{ controller }}:welcome.html.{{ template_engine }}'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Resources/skeleton/bundle/Resources/config/routing.yml: -------------------------------------------------------------------------------- 1 | homepage: 2 | pattern: / 3 | defaults: { _controller: {{ namespace }}{{ appname }}Bundle:{{ controller }}:welcome } 4 | 5 | {{ appname }}: 6 | pattern: /{{ controller }} 7 | defaults: { _controller: {{ namespace }}{{ appname }}Bundle:{{ controller }}:index } 8 | -------------------------------------------------------------------------------- /Resources/skeleton/bundle/Resources/views/Bundle/index.html.php: -------------------------------------------------------------------------------- 1 | extend('{{ namespace }}{{ appname }}Bundle::layout.html.php') ?> 2 | 3 | {{ appname }}! 4 | -------------------------------------------------------------------------------- /Resources/skeleton/bundle/Resources/views/Bundle/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "{{ namespace }}{{ appname }}Bundle::layout.html.twig" %} 2 | 3 | {% block content %} 4 | {{ appname }}! 5 | {% endblock %} 6 | -------------------------------------------------------------------------------- /Resources/skeleton/bundle/Resources/views/Bundle/welcome.html.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Congratulations 6 | 7 | 8 |

Congratulations!

9 |

You have successfully created a new Symfony application.

10 | 11 | 12 | -------------------------------------------------------------------------------- /Resources/skeleton/bundle/Resources/views/Bundle/welcome.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Congratulations 6 | 7 | 8 |

Congratulations!

9 |

You have successfully created a new Symfony application.

10 | 11 | 12 | -------------------------------------------------------------------------------- /Resources/skeleton/bundle/Resources/views/layout.html.php: -------------------------------------------------------------------------------- 1 | extend('::base.html.php') ?> 2 | 3 |

{{ appname }} Application

4 | 5 | output('_content') ?> 6 | -------------------------------------------------------------------------------- /Resources/skeleton/bundle/Resources/views/layout.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "::base.html.twig" %} 2 | 3 | {% block body %} 4 |

{{ appname }} Application

5 | 6 | {% block content %}{% endblock %} 7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /Resources/skeleton/project/.gitignore: -------------------------------------------------------------------------------- 1 | app/cache/* 2 | app/logs/* 3 | app/phpunit.xml 4 | -------------------------------------------------------------------------------- /Resources/skeleton/project/app/.htaccess: -------------------------------------------------------------------------------- 1 | deny from all -------------------------------------------------------------------------------- /Resources/skeleton/project/app/AppCache.php: -------------------------------------------------------------------------------- 1 | getEnvironment(), array('dev', 'test'))) { 15 | $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); 16 | } 17 | 18 | return $bundles; 19 | } 20 | 21 | public function registerContainerConfiguration(LoaderInterface $loader) 22 | { 23 | // use YAML for configuration 24 | // comment to use another configuration format 25 | $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml'); 26 | 27 | // uncomment to use XML for configuration 28 | //$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.xml'); 29 | 30 | // uncomment to use PHP for configuration 31 | //$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.php'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Resources/skeleton/project/app/Resources/views/base.html.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <?php $view['slots']->output('title', '{{ appname }} Application') ?> 6 | 7 | 8 | output('_content') ?> 9 | 10 | 11 | -------------------------------------------------------------------------------- /Resources/skeleton/project/app/Resources/views/base.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block title %}{{ appname}} Application{% endblock %} 6 | 7 | 8 | {% block body %}{% endblock %} 9 | 10 | 11 | -------------------------------------------------------------------------------- /Resources/skeleton/project/app/autoload.php: -------------------------------------------------------------------------------- 1 | registerNamespaces(array( 8 | {{ registerNamespaces }} 9 | )); 10 | $loader->registerPrefixes(array( 11 | {{ registerPrefixes }} 12 | )); 13 | 14 | // intl 15 | if (!function_exists('intl_get_error_code')) { 16 | require_once __DIR__.'/../vendor/symfony/src/Symfony/Component/Locale/Resources/stubs/functions.php'; 17 | 18 | $loader->registerPrefixFallbacks(array(__DIR__.'/../vendor/symfony/src/Symfony/Component/Locale/Resources/stubs')); 19 | } 20 | 21 | $loader->registerNamespaceFallbacks(array( 22 | __DIR__.'/../src', 23 | )); 24 | $loader->register(); 25 | 26 | AnnotationRegistry::registerLoader(function($class) use ($loader) { 27 | $loader->loadClass($class); 28 | return class_exists($class, false); 29 | }); 30 | 31 | {{ annotation_orm }} 32 | {{ annotation_odm }} 33 | {{ swiftmailer_autoload }} -------------------------------------------------------------------------------- /Resources/skeleton/project/app/check.php: -------------------------------------------------------------------------------- 1 | ='), sprintf('Checking that PHP version is at least 5.3.2 (%s installed)', phpversion()), 'Install PHP 5.3.2 or newer (current version is '.phpversion(), true); 27 | check(ini_get('date.timezone'), 'Checking that the "date.timezone" setting is set', 'Set the "date.timezone" setting in php.ini (like Europe/Paris)', true); 28 | check(is_writable(__DIR__.'/../app/cache'), sprintf('Checking that app/cache/ directory is writable'), 'Change the permissions of the app/cache/ directory so that the web server can write in it', true); 29 | check(is_writable(__DIR__.'/../app/logs'), sprintf('Checking that the app/logs/ directory is writable'), 'Change the permissions of the app/logs/ directory so that the web server can write in it', true); 30 | check(function_exists('json_encode'), 'Checking that the json_encode() is available', 'Install and enable the json extension', true); 31 | check(class_exists('SQLite3') || in_array('sqlite', PDO::getAvailableDrivers()), 'Checking that the SQLite3 or PDO_SQLite extension is available', 'Install and enable the SQLite3 or PDO_SQLite extension.', true); 32 | check(function_exists('session_start'), 'Checking that the session_start() is available', 'Install and enable the session extension', true); 33 | check(function_exists('ctype_alpha'), 'Checking that the ctype_alpha() is available', 'Install and enable the ctype extension', true); 34 | check(!(function_exists('apc_store') && ini_get('apc.enabled')) || version_compare(phpversion('apc'), '3.0.17', '>='), 'Checking that the APC version is at least 3.0.17', 'Upgrade your APC extension (3.0.17+)', true); 35 | 36 | // warnings 37 | echo_title("Optional checks"); 38 | check(class_exists('DomDocument'), 'Checking that the PHP-XML module is installed', 'Install and enable the php-xml module', false); 39 | check(defined('LIBXML_COMPACT'), 'Checking that the libxml version is at least 2.6.21', 'Upgrade your php-xml module with a newer libxml', false); 40 | check(function_exists('token_get_all'), 'Checking that the token_get_all() function is available', 'Install and enable the Tokenizer extension (highly recommended)', false); 41 | check(function_exists('mb_strlen'), 'Checking that the mb_strlen() function is available', 'Install and enable the mbstring extension', false); 42 | check(function_exists('iconv'), 'Checking that the iconv() function is available', 'Install and enable the iconv extension', false); 43 | check(function_exists('utf8_decode'), 'Checking that the utf8_decode() is available', 'Install and enable the XML extension', false); 44 | if (PHP_OS != 'WINNT') { 45 | check(function_exists('posix_isatty'), 'Checking that the posix_isatty() is available', 'Install and enable the php_posix extension (used to colorized the CLI output)', false); 46 | } 47 | check(class_exists('Locale'), 'Checking that the intl extension is available', 'Install and enable the intl extension (used for validators)', false); 48 | if (class_exists('Locale')) { 49 | $version = ''; 50 | 51 | if (defined('INTL_ICU_VERSION')) { 52 | $version = INTL_ICU_VERSION; 53 | } else { 54 | $reflector = new \ReflectionExtension('intl'); 55 | 56 | ob_start(); 57 | $reflector->info(); 58 | $output = strip_tags(ob_get_clean()); 59 | 60 | preg_match('/^ICU version +(?:=> )?(.*)$/m', $output, $matches); 61 | $version = $matches[1]; 62 | } 63 | 64 | check(version_compare($version, '4.0', '>='), 'Checking that the intl ICU version is at least 4+', 'Upgrade your intl extension with a newer ICU version (4+)', false); 65 | } 66 | 67 | $accelerator = 68 | (function_exists('apc_store') && ini_get('apc.enabled')) 69 | || 70 | function_exists('eaccelerator_put') && ini_get('eaccelerator.enable') 71 | || 72 | function_exists('xcache_set') 73 | ; 74 | check($accelerator, 'Checking that a PHP accelerator is installed', 'Install a PHP accelerator like APC (highly recommended)', false); 75 | 76 | check(!ini_get('short_open_tag'), 'Checking that php.ini has short_open_tag set to off', 'Set short_open_tag to off in php.ini', false); 77 | check(!ini_get('magic_quotes_gpc'), 'Checking that php.ini has magic_quotes_gpc set to off', 'Set magic_quotes_gpc to off in php.ini', false); 78 | check(!ini_get('register_globals'), 'Checking that php.ini has register_globals set to off', 'Set register_globals to off in php.ini', false); 79 | check(!ini_get('session.auto_start'), 'Checking that php.ini has session.auto_start set to off', 'Set session.auto_start to off in php.ini', false); 80 | 81 | echo_title("Optional checks (Doctrine)"); 82 | 83 | check(class_exists('PDO'), 'Checking that PDO is installed', 'Install PDO (mandatory for Doctrine)', false); 84 | if (class_exists('PDO')) { 85 | $drivers = PDO::getAvailableDrivers(); 86 | check(count($drivers), 'Checking that PDO has some drivers installed: '.implode(', ', $drivers), 'Install PDO drivers (mandatory for Doctrine)'); 87 | } 88 | 89 | /** 90 | * Checks a configuration. 91 | */ 92 | function check($boolean, $message, $help = '', $fatal = false) 93 | { 94 | echo $boolean ? " OK " : sprintf("\n\n[[%s]] ", $fatal ? ' ERROR ' : 'WARNING'); 95 | echo sprintf("$message%s\n", $boolean ? '' : ': FAILED'); 96 | 97 | if (!$boolean) { 98 | echo " *** $help ***\n"; 99 | if ($fatal) { 100 | die("You must fix this problem before resuming the check.\n"); 101 | } 102 | } 103 | } 104 | 105 | function echo_title($title) 106 | { 107 | echo "\n** $title **\n\n"; 108 | } -------------------------------------------------------------------------------- /Resources/skeleton/project/app/config/config.yml: -------------------------------------------------------------------------------- 1 | framework: 2 | # esi: ~ 3 | secret: {{ secret }} 4 | charset: UTF-8 5 | router: { resource: "%kernel.root_dir%/config/routing.yml" } 6 | form: true 7 | csrf_protection: true 8 | validation: { enabled: true, enable_annotations: true } 9 | templating: { engines: ['{{ template_engine }}'] } #assets_version: SomeVersionScheme 10 | session: 11 | default_locale: en 12 | lifetime: 3600 13 | auto_start: {{ session_start }} 14 | name: {{ session_name }} 15 | {{ twig }} 16 | {{ assetic }} 17 | {{ doctrine }} 18 | {{ doctrine_mongodb }} 19 | {{ propel }} 20 | {{ swiftmailer }} 21 | {{ custom }} 22 | {{ mandango_config }} -------------------------------------------------------------------------------- /Resources/skeleton/project/app/config/config_dev.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: config.yml } 3 | 4 | framework: 5 | router: { resource: "%kernel.root_dir%/config/routing_dev.yml" } 6 | profiler: { only_exceptions: false } 7 | 8 | web_profiler: 9 | toolbar: true 10 | intercept_redirects: true 11 | 12 | monolog: 13 | handlers: 14 | main: 15 | type: stream 16 | path: %kernel.logs_dir%/%kernel.environment%.log 17 | level: debug 18 | 19 | {{ assetic_dev }} 20 | {{ mandango_config_dev }} -------------------------------------------------------------------------------- /Resources/skeleton/project/app/config/config_prod.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: config.yml } 3 | 4 | #doctrine: 5 | # metadata_cache_driver: apc 6 | # result_cache_driver: apc 7 | # query_cache_driver: apc 8 | 9 | monolog: 10 | handlers: 11 | main: 12 | type: fingers_crossed 13 | action_level: error 14 | handler: nested 15 | nested: 16 | type: stream 17 | path: %kernel.logs_dir%/%kernel.environment%.log 18 | level: debug 19 | -------------------------------------------------------------------------------- /Resources/skeleton/project/app/config/config_test.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: config_dev.yml } 3 | 4 | framework: 5 | test: ~ 6 | session: 7 | storage_id: session.storage.filesystem 8 | 9 | web_profiler: 10 | toolbar: false 11 | intercept_redirects: false 12 | {{ swiftmailer_test }} -------------------------------------------------------------------------------- /Resources/skeleton/project/app/config/routing.yml: -------------------------------------------------------------------------------- 1 | # Internal routing configuration to handle ESI 2 | #_internal: 3 | # resource: "@FrameworkBundle/Resources/config/routing/internal.xml" 4 | # prefix: /_internal 5 | 6 | {{ routing }} -------------------------------------------------------------------------------- /Resources/skeleton/project/app/config/routing_dev.yml: -------------------------------------------------------------------------------- 1 | _main: 2 | resource: routing.yml 3 | 4 | _wdt: 5 | resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml" 6 | prefix: /_wdt 7 | 8 | _profiler: 9 | resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml" 10 | prefix: /_profiler 11 | -------------------------------------------------------------------------------- /Resources/skeleton/project/app/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | getParameterOption(array('--env', '-e'), getenv('SYMFONY_ENV') ?: 'dev'); 12 | $debug = !$input->hasParameterOption(array('--no-debug', '')); 13 | 14 | $kernel = new AppKernel($env, $debug); 15 | $application = new Application($kernel); 16 | $application->run(); 17 | -------------------------------------------------------------------------------- /Resources/skeleton/project/app/phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | 18 | ../src/*/*Bundle/Tests 19 | ../src/*/Bundle/*Bundle/Tests 20 | 21 | 22 | 23 | 28 | 29 | 30 | 31 | ../src 32 | 33 | ../src/*/*Bundle/Resources 34 | ../src/*/*Bundle/Tests 35 | ../src/*/Bundle/*Bundle/Resources 36 | ../src/*/Bundle/*Bundle/Tests 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Resources/skeleton/project/bin/build_bootstrap.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 10 | * 11 | * For the full copyright and license information, please view the LICENSE 12 | * file that was distributed with this source code. 13 | */ 14 | 15 | use Symfony\Component\ClassLoader\UniversalClassLoader; 16 | use Symfony\Component\ClassLoader\ClassCollectionLoader; 17 | 18 | $loader = new UniversalClassLoader(); 19 | $loader->registerNamespaces(array('Symfony' => __DIR__.'/../vendor/symfony/src')); 20 | $loader->register(); 21 | 22 | $file = __DIR__.'/../app/bootstrap.php.cache'; 23 | if (file_exists($file)) { 24 | unlink($file); 25 | } 26 | 27 | ClassCollectionLoader::load(array( 28 | 'Symfony\\Component\\DependencyInjection\\ContainerAwareInterface', 29 | 'Symfony\\Component\\DependencyInjection\\ContainerAware', 30 | 'Symfony\\Component\\DependencyInjection\\ContainerInterface', 31 | 'Symfony\\Component\\DependencyInjection\\Container', 32 | 'Symfony\\Component\\HttpKernel\\HttpKernelInterface', 33 | 'Symfony\\Component\\HttpKernel\\KernelInterface', 34 | 'Symfony\\Component\\HttpKernel\\Kernel', 35 | 'Symfony\\Component\\ClassLoader\\ClassCollectionLoader', 36 | 'Symfony\\Component\\ClassLoader\\UniversalClassLoader', 37 | 'Symfony\\Component\\HttpKernel\\Bundle\\Bundle', 38 | 'Symfony\\Component\\HttpKernel\\Bundle\\BundleInterface', 39 | 'Symfony\\Component\\Config\\ConfigCache', 40 | // cannot be included as commands are discovered based on the path to this class via Reflection 41 | //'Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle', 42 | ), dirname($file), basename($file, '.php.cache'), false, false, '.php.cache'); 43 | 44 | file_put_contents($file, " 2 | RewriteEngine On 3 | RewriteCond %{REQUEST_FILENAME} !-f 4 | RewriteRule ^(.*)$ index.php [QSA,L] 5 | 6 | -------------------------------------------------------------------------------- /Resources/skeleton/project/web/index.php: -------------------------------------------------------------------------------- 1 | loadClassCache(); 11 | //$kernel = new AppCache($kernel); 12 | $kernel->handle(Request::createFromGlobals())->send(); 13 | -------------------------------------------------------------------------------- /Resources/skeleton/project/web/index_dev.php: -------------------------------------------------------------------------------- 1 | loadClassCache(); 20 | $kernel->handle(Request::createFromGlobals())->send(); 21 | -------------------------------------------------------------------------------- /Symfony/Bundle/FrameworkBundle/Util/Filesystem.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Util; 13 | 14 | /** 15 | * Provides basic utility to manipulate the file system. 16 | * 17 | * @author Fabien Potencier 18 | */ 19 | class Filesystem 20 | { 21 | /** 22 | * Copies a file. 23 | * 24 | * This method only copies the file if the origin file is newer than the target file. 25 | * 26 | * By default, if the target already exists, it is not overridden. 27 | * 28 | * To override existing files, pass the "override" option. 29 | * 30 | * @param string $originFile The original filename 31 | * @param string $targetFile The target filename 32 | * @param array $options An array of options 33 | */ 34 | public function copy($originFile, $targetFile, $options = array()) 35 | { 36 | if (!array_key_exists('override', $options)) { 37 | $options['override'] = false; 38 | } 39 | 40 | $this->mkdirs(dirname($targetFile)); 41 | 42 | $mostRecent = false; 43 | if (file_exists($targetFile)) { 44 | $statTarget = stat($targetFile); 45 | $stat_origin = stat($originFile); 46 | $mostRecent = ($stat_origin['mtime'] > $statTarget['mtime']) ? true : false; 47 | } 48 | 49 | if ($options['override'] || !file_exists($targetFile) || $mostRecent) { 50 | copy($originFile, $targetFile); 51 | } 52 | } 53 | 54 | /** 55 | * Creates a directory recursively. 56 | * 57 | * @param string $path The directory path 58 | * @param int $mode The directory mode 59 | * 60 | * @return Boolean true if the directory has been created, false otherwise 61 | */ 62 | public function mkdirs($path, $mode = 0777) 63 | { 64 | if (is_dir($path)) { 65 | return true; 66 | } 67 | 68 | return @mkdir($path, $mode, true); 69 | } 70 | 71 | /** 72 | * Creates empty files. 73 | * 74 | * @param mixed $files The filename, or an array of filenames 75 | */ 76 | public function touch($files) 77 | { 78 | if (!is_array($files)) { 79 | $files = array($files); 80 | } 81 | 82 | foreach ($files as $file) { 83 | touch($file); 84 | } 85 | } 86 | 87 | /** 88 | * Removes files or directories. 89 | * 90 | * @param mixed $files A filename or an array of files to remove 91 | */ 92 | public function remove($files) 93 | { 94 | if (!is_array($files)) { 95 | $files = array($files); 96 | } 97 | 98 | $files = array_reverse($files); 99 | foreach ($files as $file) { 100 | if (!file_exists($file)) { 101 | continue; 102 | } 103 | 104 | if (is_dir($file) && !is_link($file)) { 105 | $fp = opendir($file); 106 | while (false !== $item = readdir($fp)) { 107 | if (!in_array($item, array('.', '..'))) { 108 | $this->remove($file.'/'.$item); 109 | } 110 | } 111 | closedir($fp); 112 | 113 | rmdir($file); 114 | } else { 115 | unlink($file); 116 | } 117 | } 118 | } 119 | 120 | /** 121 | * Change mode for an array of files or directories. 122 | * 123 | * @param array $files An array of files or directories 124 | * @param integer $mode The new mode 125 | * @param integer $umask The mode mask (octal) 126 | */ 127 | public function chmod($files, $mode, $umask = 0000) 128 | { 129 | $currentUmask = umask(); 130 | umask($umask); 131 | 132 | if (!is_array($files)) { 133 | $files = array($files); 134 | } 135 | 136 | foreach ($files as $file) { 137 | chmod($file, $mode); 138 | } 139 | 140 | umask($currentUmask); 141 | } 142 | 143 | /** 144 | * Renames a file. 145 | * 146 | * @param string $origin The origin filename 147 | * @param string $target The new filename 148 | * 149 | * @throws \RuntimeException When target file already exists 150 | */ 151 | public function rename($origin, $target) 152 | { 153 | // we check that target does not exist 154 | if (is_readable($target)) { 155 | throw new \RuntimeException(sprintf('Cannot rename because the target "%" already exist.', $target)); 156 | } 157 | 158 | rename($origin, $target); 159 | } 160 | 161 | /** 162 | * Creates a symbolic link or copy a directory. 163 | * 164 | * @param string $originDir The origin directory path 165 | * @param string $targetDir The symbolic link name 166 | * @param Boolean $copyOnWindows Whether to copy files if on windows 167 | */ 168 | public function symlink($originDir, $targetDir, $copyOnWindows = false) 169 | { 170 | if (!function_exists('symlink') && $copyOnWindows) { 171 | $this->mirror($originDir, $targetDir); 172 | 173 | return; 174 | } 175 | 176 | $ok = false; 177 | if (is_link($targetDir)) { 178 | if (readlink($targetDir) != $originDir) { 179 | unlink($targetDir); 180 | } else { 181 | $ok = true; 182 | } 183 | } 184 | 185 | if (!$ok) { 186 | symlink($originDir, $targetDir); 187 | } 188 | } 189 | 190 | /** 191 | * Mirrors a directory to another. 192 | * 193 | * @param string $originDir The origin directory 194 | * @param string $targetDir The target directory 195 | * @param \Traversable $iterator A Traversable instance 196 | * @param array $options An array of options (see copy()) 197 | * 198 | * @throws \RuntimeException When file type is unknown 199 | */ 200 | public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array()) 201 | { 202 | if (null === $iterator) { 203 | $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST); 204 | } 205 | 206 | if ('/' === substr($targetDir, -1) || '\\' === substr($targetDir, -1)) { 207 | $targetDir = substr($targetDir, 0, -1); 208 | } 209 | 210 | if ('/' === substr($originDir, -1) || '\\' === substr($originDir, -1)) { 211 | $originDir = substr($originDir, 0, -1); 212 | } 213 | 214 | foreach ($iterator as $file) { 215 | $target = $targetDir.'/'.str_replace($originDir.DIRECTORY_SEPARATOR, '', $file->getPathname()); 216 | 217 | if (is_dir($file)) { 218 | $this->mkdirs($target); 219 | } else if (is_file($file)) { 220 | $this->copy($file, $target, $options); 221 | } else if (is_link($file)) { 222 | $this->symlink($file, $target); 223 | } else { 224 | throw new \RuntimeException(sprintf('Unable to guess "%s" file type.', $file)); 225 | } 226 | } 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /Symfony/Bundle/FrameworkBundle/Util/Mustache.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Bundle\FrameworkBundle\Util; 13 | 14 | /** 15 | * Mustache. 16 | * 17 | * @author Fabien Potencier 18 | */ 19 | class Mustache 20 | { 21 | /** 22 | * Renders a single line. Looks for {{ var }} 23 | * 24 | * @param string $string 25 | * @param array $parameters 26 | * 27 | * @return string 28 | */ 29 | static public function renderString($string, array $parameters) 30 | { 31 | $replacer = function ($match) use ($parameters) 32 | { 33 | return isset($parameters[$match[1]]) ? $parameters[$match[1]] : $match[0]; 34 | }; 35 | 36 | return preg_replace_callback('/{{\s*(.+?)\s*}}/', $replacer, $string); 37 | } 38 | 39 | /** 40 | * Renders a file by replacing the contents of $file with rendered output. 41 | * 42 | * @param string $file filename for the file to be rendered 43 | * @param array $parameters 44 | */ 45 | static public function renderFile($file, array $parameters) 46 | { 47 | file_put_contents($file, static::renderString(file_get_contents($file), $parameters)); 48 | } 49 | 50 | /** 51 | * Renders a directory recursively 52 | * 53 | * @param string $dir Path to the directory that will be recursively rendered 54 | * @param array $parameters 55 | */ 56 | static public function renderDir($dir, array $parameters) 57 | { 58 | foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { 59 | if ($file->isFile()) { 60 | static::renderFile((string) $file, $parameters); 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Symfony/Component/ClassLoader/ClassCollectionLoader.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\ClassLoader; 13 | 14 | /** 15 | * ClassCollectionLoader. 16 | * 17 | * @author Fabien Potencier 18 | */ 19 | class ClassCollectionLoader 20 | { 21 | static protected $loaded; 22 | 23 | /** 24 | * Loads a list of classes and caches them in one big file. 25 | * 26 | * @param array $classes An array of classes to load 27 | * @param string $cacheDir A cache directory 28 | * @param string $name The cache name prefix 29 | * @param Boolean $autoReload Whether to flush the cache when the cache is stale or not 30 | * @param Boolean $adaptive Whether to remove already declared classes or not 31 | * 32 | * @throws \InvalidArgumentException When class can't be loaded 33 | */ 34 | static public function load($classes, $cacheDir, $name, $autoReload, $adaptive = false) 35 | { 36 | // each $name can only be loaded once per PHP process 37 | if (isset(self::$loaded[$name])) { 38 | return; 39 | } 40 | 41 | self::$loaded[$name] = true; 42 | 43 | $classes = array_unique($classes); 44 | 45 | if ($adaptive) { 46 | // don't include already declared classes 47 | $classes = array_diff($classes, get_declared_classes(), get_declared_interfaces()); 48 | 49 | // the cache is different depending on which classes are already declared 50 | $name = $name.'-'.substr(md5(implode('|', $classes)), 0, 5); 51 | } 52 | 53 | $cache = $cacheDir.'/'.$name.'.php'; 54 | 55 | // auto-reload 56 | $reload = false; 57 | if ($autoReload) { 58 | $metadata = $cacheDir.'/'.$name.'.meta'; 59 | if (!file_exists($metadata) || !file_exists($cache)) { 60 | $reload = true; 61 | } else { 62 | $time = filemtime($cache); 63 | $meta = unserialize(file_get_contents($metadata)); 64 | 65 | if ($meta[1] != $classes) { 66 | $reload = true; 67 | } else { 68 | foreach ($meta[0] as $resource) { 69 | if (!file_exists($resource) || filemtime($resource) > $time) { 70 | $reload = true; 71 | 72 | break; 73 | } 74 | } 75 | } 76 | } 77 | } 78 | 79 | if (!$reload && file_exists($cache)) { 80 | require_once $cache; 81 | 82 | return; 83 | } 84 | 85 | $files = array(); 86 | $content = ''; 87 | foreach ($classes as $class) { 88 | if (!class_exists($class) && !interface_exists($class)) { 89 | throw new \InvalidArgumentException(sprintf('Unable to load class "%s"', $class)); 90 | } 91 | 92 | $r = new \ReflectionClass($class); 93 | $files[] = $r->getFileName(); 94 | 95 | $c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($r->getFileName())); 96 | 97 | // add namespace declaration for global code 98 | if (!$r->inNamespace()) { 99 | $c = "\nnamespace\n{\n$c\n}\n"; 100 | } else { 101 | $c = self::fixNamespaceDeclarations(' 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\ClassLoader; 13 | 14 | /** 15 | * A class loader that uses a mapping file to look up paths. 16 | * 17 | * @author Fabien Potencier 18 | */ 19 | class MapFileClassLoader 20 | { 21 | protected $map = array(); 22 | 23 | /** 24 | * Constructor. 25 | * 26 | * @param string $file Path to class mapping file 27 | */ 28 | public function __construct($file) 29 | { 30 | $this->map = require $file; 31 | } 32 | 33 | /** 34 | * Registers this instance as an autoloader. 35 | * 36 | * @param Boolean $prepend Whether to prepend the autoloader or not 37 | */ 38 | public function register($prepend = false) 39 | { 40 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 41 | } 42 | 43 | /** 44 | * Loads the given class or interface. 45 | * 46 | * @param string $class The name of the class 47 | */ 48 | public function loadClass($class) 49 | { 50 | if ('\\' === $class[0]) { 51 | $class = substr($class, 1); 52 | } 53 | 54 | if (isset($this->map[$class])) { 55 | require $this->map[$class]; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Symfony/Component/ClassLoader/UniversalClassLoader.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\ClassLoader; 13 | 14 | /** 15 | * UniversalClassLoader implements a "universal" autoloader for PHP 5.3. 16 | * 17 | * It is able to load classes that use either: 18 | * 19 | * * The technical interoperability standards for PHP 5.3 namespaces and 20 | * class names (http://groups.google.com/group/php-standards/web/psr-0-final-proposal); 21 | * 22 | * * The PEAR naming convention for classes (http://pear.php.net/). 23 | * 24 | * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be 25 | * looked for in a list of locations to ease the vendoring of a sub-set of 26 | * classes for large projects. 27 | * 28 | * Example usage: 29 | * 30 | * $loader = new UniversalClassLoader(); 31 | * 32 | * // register classes with namespaces 33 | * $loader->registerNamespaces(array( 34 | * 'Symfony\Component' => __DIR__.'/component', 35 | * 'Symfony' => __DIR__.'/framework', 36 | * 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'), 37 | * )); 38 | * 39 | * // register a library using the PEAR naming convention 40 | * $loader->registerPrefixes(array( 41 | * 'Swift_' => __DIR__.'/Swift', 42 | * )); 43 | * 44 | * // activate the autoloader 45 | * $loader->register(); 46 | * 47 | * In this example, if you try to use a class in the Symfony\Component 48 | * namespace or one of its children (Symfony\Component\Console for instance), 49 | * the autoloader will first look for the class under the component/ 50 | * directory, and it will then fallback to the framework/ directory if not 51 | * found before giving up. 52 | * 53 | * @author Fabien Potencier 54 | */ 55 | class UniversalClassLoader 56 | { 57 | protected $namespaces = array(); 58 | protected $prefixes = array(); 59 | protected $namespaceFallback = array(); 60 | protected $prefixFallback = array(); 61 | 62 | /** 63 | * Gets the configured namespaces. 64 | * 65 | * @return array A hash with namespaces as keys and directories as values 66 | */ 67 | public function getNamespaces() 68 | { 69 | return $this->namespaces; 70 | } 71 | 72 | /** 73 | * Gets the configured class prefixes. 74 | * 75 | * @return array A hash with class prefixes as keys and directories as values 76 | */ 77 | public function getPrefixes() 78 | { 79 | return $this->prefixes; 80 | } 81 | 82 | /** 83 | * Gets the directory(ies) to use as a fallback for namespaces. 84 | * 85 | * @return array An array of directories 86 | */ 87 | public function getNamespaceFallback() 88 | { 89 | return $this->namespaceFallback; 90 | } 91 | 92 | /** 93 | * Gets the directory(ies) to use as a fallback for class prefixes. 94 | * 95 | * @return array An array of directories 96 | */ 97 | public function getPrefixFallback() 98 | { 99 | return $this->prefixFallback; 100 | } 101 | 102 | /** 103 | * Registers the directory to use as a fallback for namespaces. 104 | * 105 | * @param string|array $dirs A directory path or an array of directories 106 | */ 107 | public function registerNamespaceFallback($dirs) 108 | { 109 | $this->namespaceFallback = (array) $dirs; 110 | } 111 | 112 | /** 113 | * Registers the directory to use as a fallback for class prefixes. 114 | * 115 | * @param string|array $dirs A directory path or an array of directories 116 | */ 117 | public function registerPrefixFallback($dirs) 118 | { 119 | $this->prefixFallback = (array) $dirs; 120 | } 121 | 122 | /** 123 | * Registers an array of namespaces 124 | * 125 | * @param array $namespaces An array of namespaces (namespaces as keys and locations as values) 126 | */ 127 | public function registerNamespaces(array $namespaces) 128 | { 129 | foreach ($namespaces as $namespace => $locations) { 130 | $this->namespaces[$namespace] = (array) $locations; 131 | } 132 | } 133 | 134 | /** 135 | * Registers a namespace. 136 | * 137 | * @param string $namespace The namespace 138 | * @param array|string $paths The location(s) of the namespace 139 | */ 140 | public function registerNamespace($namespace, $paths) 141 | { 142 | $this->namespaces[$namespace] = (array) $paths; 143 | } 144 | 145 | /** 146 | * Registers an array of classes using the PEAR naming convention. 147 | * 148 | * @param array $classes An array of classes (prefixes as keys and locations as values) 149 | */ 150 | public function registerPrefixes(array $classes) 151 | { 152 | foreach ($classes as $prefix => $locations) { 153 | $this->prefixes[$prefix] = (array) $locations; 154 | } 155 | } 156 | 157 | /** 158 | * Registers a set of classes using the PEAR naming convention. 159 | * 160 | * @param string $prefix The classes prefix 161 | * @param array|string $paths The location(s) of the classes 162 | */ 163 | public function registerPrefix($prefix, $paths) 164 | { 165 | $this->prefixes[$prefix] = (array) $paths; 166 | } 167 | 168 | /** 169 | * Registers this instance as an autoloader. 170 | * 171 | * @param Boolean $prepend Whether to prepend the autoloader or not 172 | */ 173 | public function register($prepend = false) 174 | { 175 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 176 | } 177 | 178 | /** 179 | * Loads the given class or interface. 180 | * 181 | * @param string $class The name of the class 182 | */ 183 | public function loadClass($class) 184 | { 185 | $class = ltrim($class, '\\'); 186 | 187 | if (false !== ($pos = strrpos($class, '\\'))) { 188 | // namespaced class name 189 | $namespace = substr($class, 0, $pos); 190 | foreach ($this->namespaces as $ns => $dirs) { 191 | foreach ($dirs as $dir) { 192 | if (0 === strpos($namespace, $ns)) { 193 | $className = substr($class, $pos + 1); 194 | $file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php'; 195 | if (file_exists($file)) { 196 | require $file; 197 | return; 198 | } 199 | } 200 | } 201 | } 202 | 203 | foreach ($this->namespaceFallback as $dir) { 204 | $file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php'; 205 | if (file_exists($file)) { 206 | require $file; 207 | return; 208 | } 209 | } 210 | } else { 211 | // PEAR-like class name 212 | foreach ($this->prefixes as $prefix => $dirs) { 213 | foreach ($dirs as $dir) { 214 | if (0 === strpos($class, $prefix)) { 215 | $file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php'; 216 | if (file_exists($file)) { 217 | require $file; 218 | return; 219 | } 220 | } 221 | } 222 | } 223 | 224 | foreach ($this->prefixFallback as $dir) { 225 | $file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php'; 226 | if (file_exists($file)) { 227 | require $file; 228 | return; 229 | } 230 | } 231 | } 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Application.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console; 13 | 14 | use Symfony\Component\Console\Input\InputInterface; 15 | use Symfony\Component\Console\Input\ArgvInput; 16 | use Symfony\Component\Console\Input\ArrayInput; 17 | use Symfony\Component\Console\Input\InputDefinition; 18 | use Symfony\Component\Console\Input\InputOption; 19 | use Symfony\Component\Console\Input\InputArgument; 20 | use Symfony\Component\Console\Output\OutputInterface; 21 | use Symfony\Component\Console\Output\Output; 22 | use Symfony\Component\Console\Output\ConsoleOutput; 23 | use Symfony\Component\Console\Command\Command; 24 | use Symfony\Component\Console\Command\HelpCommand; 25 | use Symfony\Component\Console\Command\ListCommand; 26 | use Symfony\Component\Console\Helper\HelperSet; 27 | use Symfony\Component\Console\Helper\FormatterHelper; 28 | use Symfony\Component\Console\Helper\DialogHelper; 29 | 30 | /** 31 | * An Application is the container for a collection of commands. 32 | * 33 | * It is the main entry point of a Console application. 34 | * 35 | * This class is optimized for a standard CLI environment. 36 | * 37 | * Usage: 38 | * 39 | * $app = new Application('myapp', '1.0 (stable)'); 40 | * $app->add(new SimpleCommand()); 41 | * $app->run(); 42 | * 43 | * @author Fabien Potencier 44 | */ 45 | class Application 46 | { 47 | protected $commands; 48 | protected $aliases; 49 | protected $wantHelps = false; 50 | protected $runningCommand; 51 | protected $name; 52 | protected $version; 53 | protected $catchExceptions; 54 | protected $autoExit; 55 | protected $definition; 56 | protected $helperSet; 57 | 58 | /** 59 | * Constructor. 60 | * 61 | * @param string $name The name of the application 62 | * @param string $version The version of the application 63 | */ 64 | public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN') 65 | { 66 | $this->name = $name; 67 | $this->version = $version; 68 | $this->catchExceptions = true; 69 | $this->autoExit = true; 70 | $this->commands = array(); 71 | $this->aliases = array(); 72 | $this->helperSet = new HelperSet(array( 73 | new FormatterHelper(), 74 | new DialogHelper(), 75 | )); 76 | 77 | $this->add(new HelpCommand()); 78 | $this->add(new ListCommand()); 79 | 80 | $this->definition = new InputDefinition(array( 81 | new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), 82 | 83 | new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message.'), 84 | new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message.'), 85 | new InputOption('--verbose', '-v', InputOption::VALUE_NONE, 'Increase verbosity of messages.'), 86 | new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this program version.'), 87 | new InputOption('--ansi', '-a', InputOption::VALUE_NONE, 'Force ANSI output.'), 88 | new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question.'), 89 | )); 90 | } 91 | 92 | /** 93 | * Runs the current application. 94 | * 95 | * @param InputInterface $input An Input instance 96 | * @param OutputInterface $output An Output instance 97 | * 98 | * @return integer 0 if everything went fine, or an error code 99 | * 100 | * @throws \Exception When doRun returns Exception 101 | */ 102 | public function run(InputInterface $input = null, OutputInterface $output = null) 103 | { 104 | if (null === $input) { 105 | $input = new ArgvInput(); 106 | } 107 | 108 | if (null === $output) { 109 | $output = new ConsoleOutput(); 110 | } 111 | 112 | try { 113 | $statusCode = $this->doRun($input, $output); 114 | } catch (\Exception $e) { 115 | if (!$this->catchExceptions) { 116 | throw $e; 117 | } 118 | 119 | $this->renderException($e, $output); 120 | $statusCode = $e->getCode(); 121 | 122 | $statusCode = is_numeric($statusCode) && $statusCode ? $statusCode : 1; 123 | } 124 | 125 | if ($this->autoExit) { 126 | if ($statusCode > 255) { 127 | $statusCode = 255; 128 | } 129 | // @codeCoverageIgnoreStart 130 | exit($statusCode); 131 | // @codeCoverageIgnoreEnd 132 | } else { 133 | return $statusCode; 134 | } 135 | } 136 | 137 | /** 138 | * Runs the current application. 139 | * 140 | * @param InputInterface $input An Input instance 141 | * @param OutputInterface $output An Output instance 142 | * 143 | * @return integer 0 if everything went fine, or an error code 144 | */ 145 | public function doRun(InputInterface $input, OutputInterface $output) 146 | { 147 | $name = $this->getCommandName($input); 148 | 149 | if (true === $input->hasParameterOption(array('--ansi', '-a'))) { 150 | $output->setDecorated(true); 151 | } 152 | 153 | if (true === $input->hasParameterOption(array('--help', '-h'))) { 154 | if (!$name) { 155 | $name = 'help'; 156 | $input = new ArrayInput(array('command' => 'help')); 157 | } else { 158 | $this->wantHelps = true; 159 | } 160 | } 161 | 162 | if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) { 163 | $input->setInteractive(false); 164 | } 165 | 166 | if (true === $input->hasParameterOption(array('--quiet', '-q'))) { 167 | $output->setVerbosity(Output::VERBOSITY_QUIET); 168 | } elseif (true === $input->hasParameterOption(array('--verbose', '-v'))) { 169 | $output->setVerbosity(Output::VERBOSITY_VERBOSE); 170 | } 171 | 172 | if (true === $input->hasParameterOption(array('--version', '-V'))) { 173 | $output->writeln($this->getLongVersion()); 174 | 175 | return 0; 176 | } 177 | 178 | if (!$name) { 179 | $name = 'list'; 180 | $input = new ArrayInput(array('command' => 'list')); 181 | } 182 | 183 | // the command name MUST be the first element of the input 184 | $command = $this->find($name); 185 | 186 | $this->runningCommand = $command; 187 | $statusCode = $command->run($input, $output); 188 | $this->runningCommand = null; 189 | 190 | return is_numeric($statusCode) ? $statusCode : 0; 191 | } 192 | 193 | /** 194 | * Set a helper set to be used with the command. 195 | * 196 | * @param HelperSet $helperSet The helper set 197 | */ 198 | public function setHelperSet(HelperSet $helperSet) 199 | { 200 | $this->helperSet = $helperSet; 201 | } 202 | 203 | /** 204 | * Get the helper set associated with the command. 205 | * 206 | * @return HelperSet The HelperSet instance associated with this command 207 | */ 208 | public function getHelperSet() 209 | { 210 | return $this->helperSet; 211 | } 212 | 213 | /** 214 | * Gets the InputDefinition related to this Application. 215 | * 216 | * @return InputDefinition The InputDefinition instance 217 | */ 218 | public function getDefinition() 219 | { 220 | return $this->definition; 221 | } 222 | 223 | /** 224 | * Gets the help message. 225 | * 226 | * @return string A help message. 227 | */ 228 | public function getHelp() 229 | { 230 | $messages = array( 231 | $this->getLongVersion(), 232 | '', 233 | 'Usage:', 234 | sprintf(" [options] command [arguments]\n"), 235 | 'Options:', 236 | ); 237 | 238 | foreach ($this->definition->getOptions() as $option) { 239 | $messages[] = sprintf(' %-29s %s %s', 240 | '--'.$option->getName().'', 241 | $option->getShortcut() ? '-'.$option->getShortcut().'' : ' ', 242 | $option->getDescription() 243 | ); 244 | } 245 | 246 | return implode("\n", $messages); 247 | } 248 | 249 | /** 250 | * Sets whether to catch exceptions or not during commands execution. 251 | * 252 | * @param Boolean $boolean Whether to catch exceptions or not during commands execution 253 | */ 254 | public function setCatchExceptions($boolean) 255 | { 256 | $this->catchExceptions = (Boolean) $boolean; 257 | } 258 | 259 | /** 260 | * Sets whether to automatically exit after a command execution or not. 261 | * 262 | * @param Boolean $boolean Whether to automatically exit after a command execution or not 263 | */ 264 | public function setAutoExit($boolean) 265 | { 266 | $this->autoExit = (Boolean) $boolean; 267 | } 268 | 269 | /** 270 | * Gets the name of the application. 271 | * 272 | * @return string The application name 273 | */ 274 | public function getName() 275 | { 276 | return $this->name; 277 | } 278 | 279 | /** 280 | * Sets the application name. 281 | * 282 | * @param string $name The application name 283 | */ 284 | public function setName($name) 285 | { 286 | $this->name = $name; 287 | } 288 | 289 | /** 290 | * Gets the application version. 291 | * 292 | * @return string The application version 293 | */ 294 | public function getVersion() 295 | { 296 | return $this->version; 297 | } 298 | 299 | /** 300 | * Sets the application version. 301 | * 302 | * @param string $version The application version 303 | */ 304 | public function setVersion($version) 305 | { 306 | $this->version = $version; 307 | } 308 | 309 | /** 310 | * Returns the long version of the application. 311 | * 312 | * @return string The long application version 313 | */ 314 | public function getLongVersion() 315 | { 316 | if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) { 317 | return sprintf('%s version %s', $this->getName(), $this->getVersion()); 318 | } else { 319 | return 'Console Tool'; 320 | } 321 | } 322 | 323 | /** 324 | * Registers a new command. 325 | * 326 | * @param string $name The command name 327 | * 328 | * @return Command The newly created command 329 | */ 330 | public function register($name) 331 | { 332 | return $this->add(new Command($name)); 333 | } 334 | 335 | /** 336 | * Adds an array of command objects. 337 | * 338 | * @param Command[] $commands An array of commands 339 | */ 340 | public function addCommands(array $commands) 341 | { 342 | foreach ($commands as $command) { 343 | $this->add($command); 344 | } 345 | } 346 | 347 | /** 348 | * Adds a command object. 349 | * 350 | * If a command with the same name already exists, it will be overridden. 351 | * 352 | * @param Command $command A Command object 353 | * 354 | * @return Command The registered command 355 | */ 356 | public function add(Command $command) 357 | { 358 | $command->setApplication($this); 359 | 360 | $this->commands[$command->getFullName()] = $command; 361 | 362 | foreach ($command->getAliases() as $alias) { 363 | $this->aliases[$alias] = $command; 364 | } 365 | 366 | return $command; 367 | } 368 | 369 | /** 370 | * Returns a registered command by name or alias. 371 | * 372 | * @param string $name The command name or alias 373 | * 374 | * @return Command A Command object 375 | * 376 | * @throws \InvalidArgumentException When command name given does not exist 377 | */ 378 | public function get($name) 379 | { 380 | if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) { 381 | throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name)); 382 | } 383 | 384 | $command = isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name]; 385 | 386 | if ($this->wantHelps) { 387 | $this->wantHelps = false; 388 | 389 | $helpCommand = $this->get('help'); 390 | $helpCommand->setCommand($command); 391 | 392 | return $helpCommand; 393 | } 394 | 395 | return $command; 396 | } 397 | 398 | /** 399 | * Returns true if the command exists, false otherwise. 400 | * 401 | * @param string $name The command name or alias 402 | * 403 | * @return Boolean true if the command exists, false otherwise 404 | */ 405 | public function has($name) 406 | { 407 | return isset($this->commands[$name]) || isset($this->aliases[$name]); 408 | } 409 | 410 | /** 411 | * Returns an array of all unique namespaces used by currently registered commands. 412 | * 413 | * It does not returns the global namespace which always exists. 414 | * 415 | * @return array An array of namespaces 416 | */ 417 | public function getNamespaces() 418 | { 419 | $namespaces = array(); 420 | foreach ($this->commands as $command) { 421 | if ($command->getNamespace()) { 422 | $namespaces[$command->getNamespace()] = true; 423 | } 424 | } 425 | 426 | return array_keys($namespaces); 427 | } 428 | 429 | /** 430 | * Finds a registered namespace by a name or an abbreviation. 431 | * 432 | * @param string $namespace A namespace or abbreviation to search for 433 | * 434 | * @return string A registered namespace 435 | * 436 | * @throws \InvalidArgumentException When namespace is incorrect or ambiguous 437 | */ 438 | public function findNamespace($namespace) 439 | { 440 | $abbrevs = static::getAbbreviations($this->getNamespaces()); 441 | 442 | if (!isset($abbrevs[$namespace])) { 443 | throw new \InvalidArgumentException(sprintf('There are no commands defined in the "%s" namespace.', $namespace)); 444 | } 445 | 446 | if (count($abbrevs[$namespace]) > 1) { 447 | throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions($abbrevs[$namespace]))); 448 | } 449 | 450 | return $abbrevs[$namespace][0]; 451 | } 452 | 453 | /** 454 | * Finds a command by name or alias. 455 | * 456 | * Contrary to get, this command tries to find the best 457 | * match if you give it an abbreviation of a name or alias. 458 | * 459 | * @param string $name A command name or a command alias 460 | * 461 | * @return Command A Command instance 462 | * 463 | * @throws \InvalidArgumentException When command name is incorrect or ambiguous 464 | */ 465 | public function find($name) 466 | { 467 | // namespace 468 | $namespace = ''; 469 | if (false !== $pos = strrpos($name, ':')) { 470 | $namespace = $this->findNamespace(substr($name, 0, $pos)); 471 | $name = substr($name, $pos + 1); 472 | } 473 | 474 | $fullName = $namespace ? $namespace.':'.$name : $name; 475 | 476 | // name 477 | $commands = array(); 478 | foreach ($this->commands as $command) { 479 | if ($command->getNamespace() == $namespace) { 480 | $commands[] = $command->getName(); 481 | } 482 | } 483 | 484 | $abbrevs = static::getAbbreviations($commands); 485 | if (isset($abbrevs[$name]) && 1 == count($abbrevs[$name])) { 486 | return $this->get($namespace ? $namespace.':'.$abbrevs[$name][0] : $abbrevs[$name][0]); 487 | } 488 | 489 | if (isset($abbrevs[$name]) && count($abbrevs[$name]) > 1) { 490 | $suggestions = $this->getAbbreviationSuggestions(array_map(function ($command) use ($namespace) { return $namespace.':'.$command; }, $abbrevs[$name])); 491 | 492 | throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $fullName, $suggestions)); 493 | } 494 | 495 | // aliases 496 | $abbrevs = static::getAbbreviations(array_keys($this->aliases)); 497 | if (!isset($abbrevs[$fullName])) { 498 | throw new \InvalidArgumentException(sprintf('Command "%s" is not defined.', $fullName)); 499 | } 500 | 501 | if (count($abbrevs[$fullName]) > 1) { 502 | throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $fullName, $this->getAbbreviationSuggestions($abbrevs[$fullName]))); 503 | } 504 | 505 | return $this->get($abbrevs[$fullName][0]); 506 | } 507 | 508 | /** 509 | * Gets the commands (registered in the given namespace if provided). 510 | * 511 | * The array keys are the full names and the values the command instances. 512 | * 513 | * @param string $namespace A namespace name 514 | * 515 | * @return array An array of Command instances 516 | */ 517 | public function all($namespace = null) 518 | { 519 | if (null === $namespace) { 520 | return $this->commands; 521 | } 522 | 523 | $commands = array(); 524 | foreach ($this->commands as $name => $command) { 525 | if ($namespace === $command->getNamespace()) { 526 | $commands[$name] = $command; 527 | } 528 | } 529 | 530 | return $commands; 531 | } 532 | 533 | /** 534 | * Returns an array of possible abbreviations given a set of names. 535 | * 536 | * @param array $names An array of names 537 | * 538 | * @return array An array of abbreviations 539 | */ 540 | static public function getAbbreviations($names) 541 | { 542 | $abbrevs = array(); 543 | foreach ($names as $name) { 544 | for ($len = strlen($name) - 1; $len > 0; --$len) { 545 | $abbrev = substr($name, 0, $len); 546 | if (!isset($abbrevs[$abbrev])) { 547 | $abbrevs[$abbrev] = array($name); 548 | } else { 549 | $abbrevs[$abbrev][] = $name; 550 | } 551 | } 552 | } 553 | 554 | // Non-abbreviations always get entered, even if they aren't unique 555 | foreach ($names as $name) { 556 | $abbrevs[$name] = array($name); 557 | } 558 | 559 | return $abbrevs; 560 | } 561 | 562 | /** 563 | * Returns a text representation of the Application. 564 | * 565 | * @param string $namespace An optional namespace name 566 | * 567 | * @return string A string representing the Application 568 | */ 569 | public function asText($namespace = null) 570 | { 571 | $commands = $namespace ? $this->all($this->findNamespace($namespace)) : $this->commands; 572 | 573 | $messages = array($this->getHelp(), ''); 574 | if ($namespace) { 575 | $messages[] = sprintf("Available commands for the \"%s\" namespace:", $namespace); 576 | } else { 577 | $messages[] = 'Available commands:'; 578 | } 579 | 580 | $width = 0; 581 | foreach ($commands as $command) { 582 | $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width; 583 | } 584 | $width += 2; 585 | 586 | // add commands by namespace 587 | foreach ($this->sortCommands($commands) as $space => $commands) { 588 | if (!$namespace && '_global' !== $space) { 589 | $messages[] = ''.$space.''; 590 | } 591 | 592 | foreach ($commands as $command) { 593 | $aliases = $command->getAliases() ? ' ('.implode(', ', $command->getAliases()).')' : ''; 594 | 595 | $messages[] = sprintf(" %-${width}s %s%s", ($command->getNamespace() ? ':' : '').$command->getName(), $command->getDescription(), $aliases); 596 | } 597 | } 598 | 599 | return implode("\n", $messages); 600 | } 601 | 602 | /** 603 | * Returns an XML representation of the Application. 604 | * 605 | * @param string $namespace An optional namespace name 606 | * @param Boolean $asDom Whether to return a DOM or an XML string 607 | * 608 | * @return string|DOMDocument An XML string representing the Application 609 | */ 610 | public function asXml($namespace = null, $asDom = false) 611 | { 612 | $commands = $namespace ? $this->all($this->findNamespace($namespace)) : $this->commands; 613 | 614 | $dom = new \DOMDocument('1.0', 'UTF-8'); 615 | $dom->formatOutput = true; 616 | $dom->appendChild($xml = $dom->createElement('symfony')); 617 | 618 | $xml->appendChild($commandsXML = $dom->createElement('commands')); 619 | 620 | if ($namespace) { 621 | $commandsXML->setAttribute('namespace', $namespace); 622 | } else { 623 | $namespacesXML = $dom->createElement('namespaces'); 624 | $xml->appendChild($namespacesXML); 625 | } 626 | 627 | // add commands by namespace 628 | foreach ($this->sortCommands($commands) as $space => $commands) { 629 | if (!$namespace) { 630 | $namespaceArrayXML = $dom->createElement('namespace'); 631 | $namespacesXML->appendChild($namespaceArrayXML); 632 | $namespaceArrayXML->setAttribute('id', $space); 633 | } 634 | 635 | foreach ($commands as $command) { 636 | if (!$namespace) { 637 | $commandXML = $dom->createElement('command'); 638 | $namespaceArrayXML->appendChild($commandXML); 639 | $commandXML->appendChild($dom->createTextNode($command->getName())); 640 | } 641 | 642 | $node = $command->asXml(true)->getElementsByTagName('command')->item(0); 643 | $node = $dom->importNode($node, true); 644 | 645 | $commandsXML->appendChild($node); 646 | } 647 | } 648 | 649 | return $asDom ? $dom : $dom->saveXml(); 650 | } 651 | 652 | /** 653 | * Renders a catched exception. 654 | * 655 | * @param Exception $e An exception instance 656 | * @param OutputInterface $output An OutputInterface instance 657 | */ 658 | public function renderException($e, $output) 659 | { 660 | $strlen = function ($string) 661 | { 662 | return function_exists('mb_strlen') ? mb_strlen($string) : strlen($string); 663 | }; 664 | 665 | do { 666 | $title = sprintf(' [%s] ', get_class($e)); 667 | $len = $strlen($title); 668 | $lines = array(); 669 | foreach (explode("\n", $e->getMessage()) as $line) { 670 | $lines[] = sprintf(' %s ', $line); 671 | $len = max($strlen($line) + 4, $len); 672 | } 673 | 674 | $messages = array(str_repeat(' ', $len), $title.str_repeat(' ', $len - $strlen($title))); 675 | 676 | foreach ($lines as $line) { 677 | $messages[] = $line.str_repeat(' ', $len - $strlen($line)); 678 | } 679 | 680 | $messages[] = str_repeat(' ', $len); 681 | 682 | $output->writeln("\n"); 683 | foreach ($messages as $message) { 684 | $output->writeln(''.$message.''); 685 | } 686 | $output->writeln("\n"); 687 | 688 | if (Output::VERBOSITY_VERBOSE === $output->getVerbosity()) { 689 | $output->writeln('Exception trace:'); 690 | 691 | // exception related properties 692 | $trace = $e->getTrace(); 693 | array_unshift($trace, array( 694 | 'function' => '', 695 | 'file' => $e->getFile() != null ? $e->getFile() : 'n/a', 696 | 'line' => $e->getLine() != null ? $e->getLine() : 'n/a', 697 | 'args' => array(), 698 | )); 699 | 700 | for ($i = 0, $count = count($trace); $i < $count; $i++) { 701 | $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; 702 | $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; 703 | $function = $trace[$i]['function']; 704 | $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; 705 | $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; 706 | 707 | $output->writeln(sprintf(' %s%s%s() at %s:%s', $class, $type, $function, $file, $line)); 708 | } 709 | 710 | $output->writeln("\n"); 711 | } 712 | } while ($e = $e->getPrevious()); 713 | 714 | if (null !== $this->runningCommand) { 715 | $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName()))); 716 | $output->writeln("\n"); 717 | } 718 | } 719 | 720 | /** 721 | * Gets the name of the command based on input. 722 | * 723 | * @param InputInterface $input The input interface 724 | * 725 | * @return string The command name 726 | */ 727 | protected function getCommandName(InputInterface $input) 728 | { 729 | return $input->getFirstArgument('command'); 730 | } 731 | 732 | /** 733 | * Sorts commands in alphabetical order. 734 | * 735 | * @param array $commands An associative array of commands to sort 736 | * 737 | * @return array A sorted array of commands 738 | */ 739 | protected function sortCommands($commands) 740 | { 741 | $namespacedCommands = array(); 742 | foreach ($commands as $name => $command) { 743 | $key = $command->getNamespace() ? $command->getNamespace() : '_global'; 744 | 745 | if (!isset($namespacedCommands[$key])) { 746 | $namespacedCommands[$key] = array(); 747 | } 748 | 749 | $namespacedCommands[$key][$name] = $command; 750 | } 751 | ksort($namespacedCommands); 752 | 753 | foreach ($namespacedCommands as &$commands) { 754 | ksort($commands); 755 | } 756 | 757 | return $namespacedCommands; 758 | } 759 | 760 | /** 761 | * Returns abbreviated suggestions in string format. 762 | * 763 | * @param array $abbrevs Abbreviated suggestions to convert 764 | * 765 | * @return string A formatted string of abbreviated suggestions 766 | */ 767 | protected function getAbbreviationSuggestions($abbrevs) 768 | { 769 | return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : ''); 770 | } 771 | } 772 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Command/Command.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Command; 13 | 14 | use Symfony\Component\Console\Input\InputDefinition; 15 | use Symfony\Component\Console\Input\InputOption; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Input\InputInterface; 18 | use Symfony\Component\Console\Output\OutputInterface; 19 | use Symfony\Component\Console\Application; 20 | 21 | /** 22 | * Base class for all commands. 23 | * 24 | * @author Fabien Potencier 25 | */ 26 | class Command 27 | { 28 | protected $name; 29 | protected $namespace; 30 | protected $aliases; 31 | protected $definition; 32 | protected $help; 33 | protected $application; 34 | protected $description; 35 | protected $ignoreValidationErrors; 36 | protected $applicationDefinitionMerged; 37 | protected $code; 38 | 39 | /** 40 | * Constructor. 41 | * 42 | * @param string $name The name of the command 43 | * 44 | * @throws \LogicException When the command name is empty 45 | */ 46 | public function __construct($name = null) 47 | { 48 | $this->definition = new InputDefinition(); 49 | $this->ignoreValidationErrors = false; 50 | $this->applicationDefinitionMerged = false; 51 | $this->aliases = array(); 52 | 53 | if (null !== $name) { 54 | $this->setName($name); 55 | } 56 | 57 | $this->configure(); 58 | 59 | if (!$this->name) { 60 | throw new \LogicException('The command name cannot be empty.'); 61 | } 62 | } 63 | 64 | /** 65 | * Sets the application instance for this command. 66 | * 67 | * @param Application $application An Application instance 68 | */ 69 | public function setApplication(Application $application = null) 70 | { 71 | $this->application = $application; 72 | } 73 | 74 | /** 75 | * Configures the current command. 76 | */ 77 | protected function configure() 78 | { 79 | } 80 | 81 | /** 82 | * Executes the current command. 83 | * 84 | * This method is not abstract because you can use this class 85 | * as a concrete class. In this case, instead of defining the 86 | * execute() method, you set the code to execute by passing 87 | * a Closure to the setCode() method. 88 | * 89 | * @param InputInterface $input An InputInterface instance 90 | * @param OutputInterface $output An OutputInterface instance 91 | * 92 | * @return integer 0 if everything went fine, or an error code 93 | * 94 | * @throws \LogicException When this abstract class is not implemented 95 | * @see setCode() 96 | */ 97 | protected function execute(InputInterface $input, OutputInterface $output) 98 | { 99 | throw new \LogicException('You must override the execute() method in the concrete command class.'); 100 | } 101 | 102 | /** 103 | * Interacts with the user. 104 | * 105 | * @param InputInterface $input An InputInterface instance 106 | * @param OutputInterface $output An OutputInterface instance 107 | */ 108 | protected function interact(InputInterface $input, OutputInterface $output) 109 | { 110 | } 111 | 112 | /** 113 | * Initializes the command just after the input has been validated. 114 | * 115 | * This is mainly useful when a lot of commands extends one main command 116 | * where some things need to be initialized based on the input arguments and options. 117 | * 118 | * @param InputInterface $input An InputInterface instance 119 | * @param OutputInterface $output An OutputInterface instance 120 | */ 121 | protected function initialize(InputInterface $input, OutputInterface $output) 122 | { 123 | } 124 | 125 | /** 126 | * Runs the command. 127 | * 128 | * The code to execute is either defined directly with the 129 | * setCode() method or by overriding the execute() method 130 | * in a sub-class. 131 | * 132 | * @param InputInterface $input An InputInterface instance 133 | * @param OutputInterface $output An OutputInterface instance 134 | * 135 | * @see setCode() 136 | * @see execute() 137 | */ 138 | public function run(InputInterface $input, OutputInterface $output) 139 | { 140 | // add the application arguments and options 141 | $this->mergeApplicationDefinition(); 142 | 143 | // bind the input against the command specific arguments/options 144 | try { 145 | $input->bind($this->definition); 146 | } catch (\Exception $e) { 147 | if (!$this->ignoreValidationErrors) { 148 | throw $e; 149 | } 150 | } 151 | 152 | $this->initialize($input, $output); 153 | 154 | if ($input->isInteractive()) { 155 | $this->interact($input, $output); 156 | } 157 | 158 | $input->validate(); 159 | 160 | if ($this->code) { 161 | return call_user_func($this->code, $input, $output); 162 | } else { 163 | return $this->execute($input, $output); 164 | } 165 | } 166 | 167 | /** 168 | * Sets the code to execute when running this command. 169 | * 170 | * If this method is used, it overrides the code defined 171 | * in the execute() method. 172 | * 173 | * @param \Closure $code A \Closure 174 | * 175 | * @return Command The current instance 176 | * 177 | * @see execute() 178 | */ 179 | public function setCode(\Closure $code) 180 | { 181 | $this->code = $code; 182 | 183 | return $this; 184 | } 185 | 186 | /** 187 | * Merges the application definition with the command definition. 188 | */ 189 | protected function mergeApplicationDefinition() 190 | { 191 | if (null === $this->application || true === $this->applicationDefinitionMerged) { 192 | return; 193 | } 194 | 195 | $this->definition->setArguments(array_merge( 196 | $this->application->getDefinition()->getArguments(), 197 | $this->definition->getArguments() 198 | )); 199 | 200 | $this->definition->addOptions($this->application->getDefinition()->getOptions()); 201 | 202 | $this->applicationDefinitionMerged = true; 203 | } 204 | 205 | /** 206 | * Sets an array of argument and option instances. 207 | * 208 | * @param array|Definition $definition An array of argument and option instances or a definition instance 209 | * 210 | * @return Command The current instance 211 | */ 212 | public function setDefinition($definition) 213 | { 214 | if ($definition instanceof InputDefinition) { 215 | $this->definition = $definition; 216 | } else { 217 | $this->definition->setDefinition($definition); 218 | } 219 | 220 | $this->applicationDefinitionMerged = false; 221 | 222 | return $this; 223 | } 224 | 225 | /** 226 | * Gets the InputDefinition attached to this Command. 227 | * 228 | * @return InputDefinition An InputDefinition instance 229 | */ 230 | public function getDefinition() 231 | { 232 | return $this->definition; 233 | } 234 | 235 | /** 236 | * Adds an argument. 237 | * 238 | * @param string $name The argument name 239 | * @param integer $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL 240 | * @param string $description A description text 241 | * @param mixed $default The default value (for InputArgument::OPTIONAL mode only) 242 | * 243 | * @return Command The current instance 244 | */ 245 | public function addArgument($name, $mode = null, $description = '', $default = null) 246 | { 247 | $this->definition->addArgument(new InputArgument($name, $mode, $description, $default)); 248 | 249 | return $this; 250 | } 251 | 252 | /** 253 | * Adds an option. 254 | * 255 | * @param string $name The option name 256 | * @param string $shortcut The shortcut (can be null) 257 | * @param integer $mode The option mode: One of the InputOption::VALUE_* constants 258 | * @param string $description A description text 259 | * @param mixed $default The default value (must be null for InputOption::VALUE_REQUIRED or self::VALUE_NONE) 260 | * 261 | * @return Command The current instance 262 | */ 263 | public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null) 264 | { 265 | $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default)); 266 | 267 | return $this; 268 | } 269 | 270 | /** 271 | * Sets the name of the command. 272 | * 273 | * This method can set both the namespace and the name if 274 | * you separate them by a colon (:) 275 | * 276 | * $command->setName('foo:bar'); 277 | * 278 | * @param string $name The command name 279 | * 280 | * @return Command The current instance 281 | * 282 | * @throws \InvalidArgumentException When command name given is empty 283 | */ 284 | public function setName($name) 285 | { 286 | if (false !== $pos = strrpos($name, ':')) { 287 | $namespace = substr($name, 0, $pos); 288 | $name = substr($name, $pos + 1); 289 | } else { 290 | $namespace = $this->namespace; 291 | } 292 | 293 | if (!$name) { 294 | throw new \InvalidArgumentException('A command name cannot be empty.'); 295 | } 296 | 297 | $this->namespace = $namespace; 298 | $this->name = $name; 299 | 300 | return $this; 301 | } 302 | 303 | /** 304 | * Returns the command namespace. 305 | * 306 | * @return string The command namespace 307 | */ 308 | public function getNamespace() 309 | { 310 | return $this->namespace; 311 | } 312 | 313 | /** 314 | * Returns the command name 315 | * 316 | * @return string The command name 317 | */ 318 | public function getName() 319 | { 320 | return $this->name; 321 | } 322 | 323 | /** 324 | * Returns the fully qualified command name. 325 | * 326 | * @return string The fully qualified command name 327 | */ 328 | public function getFullName() 329 | { 330 | return $this->getNamespace() ? $this->getNamespace().':'.$this->getName() : $this->getName(); 331 | } 332 | 333 | /** 334 | * Sets the description for the command. 335 | * 336 | * @param string $description The description for the command 337 | * 338 | * @return Command The current instance 339 | */ 340 | public function setDescription($description) 341 | { 342 | $this->description = $description; 343 | 344 | return $this; 345 | } 346 | 347 | /** 348 | * Returns the description for the command. 349 | * 350 | * @return string The description for the command 351 | */ 352 | public function getDescription() 353 | { 354 | return $this->description; 355 | } 356 | 357 | /** 358 | * Sets the help for the command. 359 | * 360 | * @param string $help The help for the command 361 | * 362 | * @return Command The current instance 363 | */ 364 | public function setHelp($help) 365 | { 366 | $this->help = $help; 367 | 368 | return $this; 369 | } 370 | 371 | /** 372 | * Returns the help for the command. 373 | * 374 | * @return string The help for the command 375 | */ 376 | public function getHelp() 377 | { 378 | return $this->help; 379 | } 380 | 381 | /** 382 | * Returns the processed help for the command replacing the %command.name% and 383 | * %command.full_name% patterns with the real values dynamically. 384 | * 385 | * @return string The processed help for the command 386 | */ 387 | public function getProcessedHelp() 388 | { 389 | $name = $this->namespace.':'.$this->name; 390 | 391 | $placeholders = array( 392 | '%command.name%', 393 | '%command.full_name%' 394 | ); 395 | $replacements = array( 396 | $name, 397 | $_SERVER['PHP_SELF'].' '.$name 398 | ); 399 | 400 | return str_replace($placeholders, $replacements, $this->getHelp()); 401 | } 402 | 403 | /** 404 | * Sets the aliases for the command. 405 | * 406 | * @param array $aliases An array of aliases for the command 407 | * 408 | * @return Command The current instance 409 | */ 410 | public function setAliases($aliases) 411 | { 412 | $this->aliases = $aliases; 413 | 414 | return $this; 415 | } 416 | 417 | /** 418 | * Returns the aliases for the command. 419 | * 420 | * @return array An array of aliases for the command 421 | */ 422 | public function getAliases() 423 | { 424 | return $this->aliases; 425 | } 426 | 427 | /** 428 | * Returns the synopsis for the command. 429 | * 430 | * @return string The synopsis 431 | */ 432 | public function getSynopsis() 433 | { 434 | return sprintf('%s %s', $this->getFullName(), $this->definition->getSynopsis()); 435 | } 436 | 437 | /** 438 | * Gets a helper instance by name. 439 | * 440 | * @param string $name The helper name 441 | * 442 | * @return mixed The helper value 443 | * 444 | * @throws \InvalidArgumentException if the helper is not defined 445 | */ 446 | protected function getHelper($name) 447 | { 448 | return $this->application->getHelperSet()->get($name); 449 | } 450 | 451 | /** 452 | * Gets a helper instance by name. 453 | * 454 | * @param string $name The helper name 455 | * 456 | * @return mixed The helper value 457 | * 458 | * @throws \InvalidArgumentException if the helper is not defined 459 | */ 460 | public function __get($name) 461 | { 462 | return $this->application->getHelperSet()->get($name); 463 | } 464 | 465 | /** 466 | * Returns a text representation of the command. 467 | * 468 | * @return string A string representing the command 469 | */ 470 | public function asText() 471 | { 472 | $messages = array( 473 | 'Usage:', 474 | ' '.$this->getSynopsis(), 475 | '', 476 | ); 477 | 478 | if ($this->getAliases()) { 479 | $messages[] = 'Aliases: '.implode(', ', $this->getAliases()).''; 480 | } 481 | 482 | $messages[] = $this->definition->asText(); 483 | 484 | if ($help = $this->getProcessedHelp()) { 485 | $messages[] = 'Help:'; 486 | $messages[] = ' '.implode("\n ", explode("\n", $help))."\n"; 487 | } 488 | 489 | return implode("\n", $messages); 490 | } 491 | 492 | /** 493 | * Returns an XML representation of the command. 494 | * 495 | * @param Boolean $asDom Whether to return a DOM or an XML string 496 | * 497 | * @return string|DOMDocument An XML string representing the command 498 | */ 499 | public function asXml($asDom = false) 500 | { 501 | $dom = new \DOMDocument('1.0', 'UTF-8'); 502 | $dom->formatOutput = true; 503 | $dom->appendChild($commandXML = $dom->createElement('command')); 504 | $commandXML->setAttribute('id', $this->getFullName()); 505 | $commandXML->setAttribute('namespace', $this->getNamespace() ? $this->getNamespace() : '_global'); 506 | $commandXML->setAttribute('name', $this->getName()); 507 | 508 | $commandXML->appendChild($usageXML = $dom->createElement('usage')); 509 | $usageXML->appendChild($dom->createTextNode(sprintf($this->getSynopsis(), ''))); 510 | 511 | $commandXML->appendChild($descriptionXML = $dom->createElement('description')); 512 | $descriptionXML->appendChild($dom->createTextNode(implode("\n ", explode("\n", $this->getDescription())))); 513 | 514 | $commandXML->appendChild($helpXML = $dom->createElement('help')); 515 | $help = $this->help; 516 | $helpXML->appendChild($dom->createTextNode(implode("\n ", explode("\n", $help)))); 517 | 518 | $commandXML->appendChild($aliasesXML = $dom->createElement('aliases')); 519 | foreach ($this->getAliases() as $alias) { 520 | $aliasesXML->appendChild($aliasXML = $dom->createElement('alias')); 521 | $aliasXML->appendChild($dom->createTextNode($alias)); 522 | } 523 | 524 | $definition = $this->definition->asXml(true); 525 | $commandXML->appendChild($dom->importNode($definition->getElementsByTagName('arguments')->item(0), true)); 526 | $commandXML->appendChild($dom->importNode($definition->getElementsByTagName('options')->item(0), true)); 527 | 528 | return $asDom ? $dom : $dom->saveXml(); 529 | } 530 | } 531 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Command/HelpCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Command; 13 | 14 | use Symfony\Component\Console\Input\InputArgument; 15 | use Symfony\Component\Console\Input\InputOption; 16 | use Symfony\Component\Console\Input\InputInterface; 17 | use Symfony\Component\Console\Output\OutputInterface; 18 | use Symfony\Component\Console\Output\Output; 19 | use Symfony\Component\Console\Command\Command; 20 | 21 | /** 22 | * HelpCommand displays the help for a given command. 23 | * 24 | * @author Fabien Potencier 25 | */ 26 | class HelpCommand extends Command 27 | { 28 | protected $command; 29 | 30 | /** 31 | * {@inheritdoc} 32 | */ 33 | protected function configure() 34 | { 35 | $this->ignoreValidationErrors = true; 36 | 37 | $this 38 | ->setDefinition(array( 39 | new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), 40 | new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'), 41 | )) 42 | ->setName('help') 43 | ->setAliases(array('?')) 44 | ->setDescription('Displays help for a command') 45 | ->setHelp(<<help command displays help for a given command: 47 | 48 | ./symfony help list 49 | 50 | You can also output the help as XML by using the --xml option: 51 | 52 | ./symfony help --xml list 53 | EOF 54 | ); 55 | } 56 | 57 | /** 58 | * Sets the command 59 | * 60 | * @param Command $command The command to set 61 | */ 62 | public function setCommand(Command $command) 63 | { 64 | $this->command = $command; 65 | } 66 | 67 | /** 68 | * {@inheritdoc} 69 | */ 70 | protected function execute(InputInterface $input, OutputInterface $output) 71 | { 72 | if (null === $this->command) { 73 | $this->command = $this->application->get($input->getArgument('command_name')); 74 | } 75 | 76 | if ($input->getOption('xml')) { 77 | $output->writeln($this->command->asXml(), Output::OUTPUT_RAW); 78 | } else { 79 | $output->writeln($this->command->asText()); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Command/ListCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Command; 13 | 14 | use Symfony\Component\Console\Input\InputArgument; 15 | use Symfony\Component\Console\Input\InputOption; 16 | use Symfony\Component\Console\Input\InputInterface; 17 | use Symfony\Component\Console\Output\OutputInterface; 18 | use Symfony\Component\Console\Output\Output; 19 | use Symfony\Component\Console\Command\Command; 20 | 21 | /** 22 | * ListCommand displays the list of all available commands for the application. 23 | * 24 | * @author Fabien Potencier 25 | */ 26 | class ListCommand extends Command 27 | { 28 | /** 29 | * {@inheritdoc} 30 | */ 31 | protected function configure() 32 | { 33 | $this 34 | ->setDefinition(array( 35 | new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), 36 | new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'), 37 | )) 38 | ->setName('list') 39 | ->setDescription('Lists commands') 40 | ->setHelp(<<list command lists all commands: 42 | 43 | ./symfony list 44 | 45 | You can also display the commands for a specific namespace: 46 | 47 | ./symfony list test 48 | 49 | You can also output the information as XML by using the --xml option: 50 | 51 | ./symfony list --xml 52 | EOF 53 | ); 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | protected function execute(InputInterface $input, OutputInterface $output) 60 | { 61 | if ($input->getOption('xml')) { 62 | $output->writeln($this->application->asXml($input->getArgument('namespace')), Output::OUTPUT_RAW); 63 | } else { 64 | $output->writeln($this->application->asText($input->getArgument('namespace'))); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Helper/DialogHelper.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Helper; 13 | 14 | use Symfony\Component\Console\Output\OutputInterface; 15 | 16 | /** 17 | * The Dialog class provides helpers to interact with the user. 18 | * 19 | * @author Fabien Potencier 20 | */ 21 | class DialogHelper extends Helper 22 | { 23 | /** 24 | * Asks a question to the user. 25 | * 26 | * @param OutputInterface $output 27 | * @param string|array $question The question to ask 28 | * @param string $default The default answer if none is given by the user 29 | * 30 | * @return string The user answer 31 | */ 32 | public function ask(OutputInterface $output, $question, $default = null) 33 | { 34 | // @codeCoverageIgnoreStart 35 | $output->writeln($question); 36 | 37 | $ret = trim(fgets(STDIN)); 38 | 39 | return $ret ? $ret : $default; 40 | // @codeCoverageIgnoreEnd 41 | } 42 | 43 | /** 44 | * Asks a confirmation to the user. 45 | * 46 | * The question will be asked until the user answer by nothing, yes, or no. 47 | * 48 | * @param OutputInterface $output 49 | * @param string|array $question The question to ask 50 | * @param Boolean $default The default answer if the user enters nothing 51 | * 52 | * @return Boolean true if the user has confirmed, false otherwise 53 | */ 54 | public function askConfirmation(OutputInterface $output, $question, $default = true) 55 | { 56 | // @codeCoverageIgnoreStart 57 | $answer = 'z'; 58 | while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) { 59 | $answer = $this->ask($output, $question); 60 | } 61 | 62 | if (false === $default) { 63 | return $answer && 'y' == strtolower($answer[0]); 64 | } else { 65 | return !$answer || 'y' == strtolower($answer[0]); 66 | } 67 | // @codeCoverageIgnoreEnd 68 | } 69 | 70 | /** 71 | * Asks for a value and validates the response. 72 | * 73 | * @param OutputInterface $output 74 | * @param string|array $question 75 | * @param Closure $validator 76 | * @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite) 77 | * 78 | * @return mixed 79 | * 80 | * @throws \Exception When any of the validator returns an error 81 | */ 82 | public function askAndValidate(OutputInterface $output, $question, \Closure $validator, $attempts = false) 83 | { 84 | // @codeCoverageIgnoreStart 85 | $error = null; 86 | while (false === $attempts || $attempts--) { 87 | if (null !== $error) { 88 | $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error')); 89 | } 90 | 91 | $value = $this->ask($output, $question, null); 92 | 93 | try { 94 | return $validator($value); 95 | } catch (\Exception $error) { 96 | } 97 | } 98 | 99 | throw $error; 100 | // @codeCoverageIgnoreEnd 101 | } 102 | 103 | /** 104 | * Returns the helper's canonical name 105 | */ 106 | public function getName() 107 | { 108 | return 'dialog'; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Helper/FormatterHelper.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Helper; 13 | 14 | /** 15 | * The Formatter class provides helpers to format messages. 16 | * 17 | * @author Fabien Potencier 18 | */ 19 | class FormatterHelper extends Helper 20 | { 21 | /** 22 | * Formats a message within a section. 23 | * 24 | * @param string $section The section name 25 | * @param string $message The message 26 | * @param string $style The style to apply to the section 27 | */ 28 | public function formatSection($section, $message, $style = 'info') 29 | { 30 | return sprintf('<%s>[%s] %s', $style, $section, $style, $message); 31 | } 32 | 33 | /** 34 | * Formats a message as a block of text. 35 | * 36 | * @param string|array $messages The message to write in the block 37 | * @param string $style The style to apply to the whole block 38 | * @param Boolean $large Whether to return a large block 39 | * 40 | * @return string The formatter message 41 | */ 42 | public function formatBlock($messages, $style, $large = false) 43 | { 44 | if (!is_array($messages)) { 45 | $messages = array($messages); 46 | } 47 | 48 | $len = 0; 49 | $lines = array(); 50 | foreach ($messages as $message) { 51 | $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); 52 | $len = max($this->strlen($message) + ($large ? 4 : 2), $len); 53 | } 54 | 55 | $messages = $large ? array(str_repeat(' ', $len)) : array(); 56 | foreach ($lines as $line) { 57 | $messages[] = $line.str_repeat(' ', $len - $this->strlen($line)); 58 | } 59 | if ($large) { 60 | $messages[] = str_repeat(' ', $len); 61 | } 62 | 63 | foreach ($messages as &$message) { 64 | $message = sprintf('<%s>%s', $style, $message, $style); 65 | } 66 | 67 | return implode("\n", $messages); 68 | } 69 | 70 | /** 71 | * Returns the length of a string, uses mb_strlen if it is available. 72 | * 73 | * @param string $string The string to check its length 74 | * 75 | * @return integer The length of the string 76 | */ 77 | protected function strlen($string) 78 | { 79 | return function_exists('mb_strlen') ? mb_strlen($string) : strlen($string); 80 | } 81 | 82 | /** 83 | * Returns the helper's canonical name 84 | * 85 | * @return string The canonical name of the helper 86 | */ 87 | public function getName() 88 | { 89 | return 'formatter'; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Helper/Helper.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Helper; 13 | 14 | /** 15 | * Helper is the base class for all helper classes. 16 | * 17 | * @author Fabien Potencier 18 | */ 19 | abstract class Helper implements HelperInterface 20 | { 21 | protected $helperSet = null; 22 | 23 | /** 24 | * Sets the helper set associated with this helper. 25 | * 26 | * @param HelperSet $helperSet A HelperSet instance 27 | */ 28 | public function setHelperSet(HelperSet $helperSet = null) 29 | { 30 | $this->helperSet = $helperSet; 31 | } 32 | 33 | /** 34 | * Gets the helper set associated with this helper. 35 | * 36 | * @return HelperSet A HelperSet instance 37 | */ 38 | public function getHelperSet() 39 | { 40 | return $this->helperSet; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Helper/HelperInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Helper; 13 | 14 | /** 15 | * HelperInterface is the interface all helpers must implement. 16 | * 17 | * @author Fabien Potencier 18 | */ 19 | interface HelperInterface 20 | { 21 | /** 22 | * Sets the helper set associated with this helper. 23 | * 24 | * @param HelperSet $helperSet A HelperSet instance 25 | */ 26 | function setHelperSet(HelperSet $helperSet = null); 27 | 28 | /** 29 | * Gets the helper set associated with this helper. 30 | * 31 | * @return HelperSet A HelperSet instance 32 | */ 33 | function getHelperSet(); 34 | 35 | /** 36 | * Returns the canonical name of this helper. 37 | * 38 | * @return string The canonical name 39 | */ 40 | function getName(); 41 | } 42 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Helper/HelperSet.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Helper; 13 | 14 | use Symfony\Component\Console\Command\Command; 15 | 16 | /** 17 | * HelperSet represents a set of helpers to be used with a command. 18 | * 19 | * @author Fabien Potencier 20 | */ 21 | class HelperSet 22 | { 23 | protected $helpers; 24 | protected $command; 25 | 26 | /** 27 | * @param Helper[] $helpers An array of helper. 28 | */ 29 | public function __construct(array $helpers = array()) 30 | { 31 | $this->helpers = array(); 32 | foreach ($helpers as $alias => $helper) { 33 | $this->set($helper, is_int($alias) ? null : $alias); 34 | } 35 | } 36 | 37 | /** 38 | * Sets a helper. 39 | * 40 | * @param HelperInterface $value The helper instance 41 | * @param string $alias An alias 42 | */ 43 | public function set(HelperInterface $helper, $alias = null) 44 | { 45 | $this->helpers[$helper->getName()] = $helper; 46 | if (null !== $alias) { 47 | $this->helpers[$alias] = $helper; 48 | } 49 | 50 | $helper->setHelperSet($this); 51 | } 52 | 53 | /** 54 | * Returns true if the helper if defined. 55 | * 56 | * @param string $name The helper name 57 | * 58 | * @return Boolean true if the helper is defined, false otherwise 59 | */ 60 | public function has($name) 61 | { 62 | return isset($this->helpers[$name]); 63 | } 64 | 65 | /** 66 | * Gets a helper value. 67 | * 68 | * @param string $name The helper name 69 | * 70 | * @return HelperInterface The helper instance 71 | * 72 | * @throws \InvalidArgumentException if the helper is not defined 73 | */ 74 | public function get($name) 75 | { 76 | if (!$this->has($name)) { 77 | throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); 78 | } 79 | 80 | return $this->helpers[$name]; 81 | } 82 | 83 | /** 84 | * Sets the command associated with this helper set. 85 | * 86 | * @param Command $command A Command instance 87 | */ 88 | public function setCommand(Command $command = null) 89 | { 90 | $this->command = $command; 91 | } 92 | 93 | /** 94 | * Gets the command associated with this helper set. 95 | * 96 | * @return Command A Command instance 97 | */ 98 | public function getCommand() 99 | { 100 | return $this->command; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Input/ArgvInput.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Input; 13 | 14 | /** 15 | * ArgvInput represents an input coming from the CLI arguments. 16 | * 17 | * Usage: 18 | * 19 | * $input = new ArgvInput(); 20 | * 21 | * By default, the `$_SERVER['argv']` array is used for the input values. 22 | * 23 | * This can be overridden by explicitly passing the input values in the constructor: 24 | * 25 | * $input = new ArgvInput($_SERVER['argv']); 26 | * 27 | * If you pass it yourself, don't forget that the first element of the array 28 | * is the name of the running program. 29 | * 30 | * When passing an argument to the constructor, be sure that it respects 31 | * the same rules as the argv one. It's almost always better to use the 32 | * `StringInput` when you want to provide your own input. 33 | * 34 | * @author Fabien Potencier 35 | * 36 | * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html 37 | * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02 38 | */ 39 | class ArgvInput extends Input 40 | { 41 | protected $tokens; 42 | protected $parsed; 43 | 44 | /** 45 | * Constructor. 46 | * 47 | * @param array $argv An array of parameters from the CLI (in the argv format) 48 | * @param InputDefinition $definition A InputDefinition instance 49 | */ 50 | public function __construct(array $argv = null, InputDefinition $definition = null) 51 | { 52 | if (null === $argv) { 53 | $argv = $_SERVER['argv']; 54 | } 55 | 56 | // strip the program name 57 | array_shift($argv); 58 | 59 | $this->tokens = $argv; 60 | 61 | parent::__construct($definition); 62 | } 63 | 64 | /** 65 | * Processes command line arguments. 66 | */ 67 | protected function parse() 68 | { 69 | $this->parsed = $this->tokens; 70 | while (null !== $token = array_shift($this->parsed)) { 71 | if ('--' === substr($token, 0, 2)) { 72 | $this->parseLongOption($token); 73 | } elseif ('-' === $token[0]) { 74 | $this->parseShortOption($token); 75 | } else { 76 | $this->parseArgument($token); 77 | } 78 | } 79 | } 80 | 81 | /** 82 | * Parses a short option. 83 | * 84 | * @param string $token The current token. 85 | */ 86 | protected function parseShortOption($token) 87 | { 88 | $name = substr($token, 1); 89 | 90 | if (strlen($name) > 1) { 91 | if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) { 92 | // an option with a value (with no space) 93 | $this->addShortOption($name[0], substr($name, 1)); 94 | } else { 95 | $this->parseShortOptionSet($name); 96 | } 97 | } else { 98 | $this->addShortOption($name, null); 99 | } 100 | } 101 | 102 | /** 103 | * Parses a short option set. 104 | * 105 | * @param string $token The current token 106 | * 107 | * @throws \RuntimeException When option given doesn't exist 108 | */ 109 | protected function parseShortOptionSet($name) 110 | { 111 | $len = strlen($name); 112 | for ($i = 0; $i < $len; $i++) { 113 | if (!$this->definition->hasShortcut($name[$i])) { 114 | throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i])); 115 | } 116 | 117 | $option = $this->definition->getOptionForShortcut($name[$i]); 118 | if ($option->acceptValue()) { 119 | $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1)); 120 | 121 | break; 122 | } else { 123 | $this->addLongOption($option->getName(), true); 124 | } 125 | } 126 | } 127 | 128 | /** 129 | * Parses a long option. 130 | * 131 | * @param string $token The current token 132 | */ 133 | protected function parseLongOption($token) 134 | { 135 | $name = substr($token, 2); 136 | 137 | if (false !== $pos = strpos($name, '=')) { 138 | $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1)); 139 | } else { 140 | $this->addLongOption($name, null); 141 | } 142 | } 143 | 144 | /** 145 | * Parses an argument. 146 | * 147 | * @param string $token The current token 148 | * 149 | * @throws \RuntimeException When too many arguments are given 150 | */ 151 | protected function parseArgument($token) 152 | { 153 | if (!$this->definition->hasArgument(count($this->arguments))) { 154 | throw new \RuntimeException('Too many arguments.'); 155 | } 156 | 157 | $this->arguments[$this->definition->getArgument(count($this->arguments))->getName()] = $token; 158 | } 159 | 160 | /** 161 | * Adds a short option value. 162 | * 163 | * @param string $shortcut The short option key 164 | * @param mixed $value The value for the option 165 | * 166 | * @throws \RuntimeException When option given doesn't exist 167 | */ 168 | protected function addShortOption($shortcut, $value) 169 | { 170 | if (!$this->definition->hasShortcut($shortcut)) { 171 | throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); 172 | } 173 | 174 | $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); 175 | } 176 | 177 | /** 178 | * Adds a long option value. 179 | * 180 | * @param string $name The long option key 181 | * @param mixed $value The value for the option 182 | * 183 | * @throws \RuntimeException When option given doesn't exist 184 | */ 185 | protected function addLongOption($name, $value) 186 | { 187 | if (!$this->definition->hasOption($name)) { 188 | throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name)); 189 | } 190 | 191 | $option = $this->definition->getOption($name); 192 | 193 | if (null === $value && $option->acceptValue()) { 194 | // if option accepts an optional or mandatory argument 195 | // let's see if there is one provided 196 | $next = array_shift($this->parsed); 197 | if ('-' !== $next[0]) { 198 | $value = $next; 199 | } else { 200 | array_unshift($this->parsed, $next); 201 | } 202 | } 203 | 204 | if (null === $value) { 205 | if ($option->isValueRequired()) { 206 | throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name)); 207 | } 208 | 209 | $value = $option->isValueOptional() ? $option->getDefault() : true; 210 | } 211 | 212 | $this->options[$name] = $value; 213 | } 214 | 215 | /** 216 | * Returns the first argument from the raw parameters (not parsed). 217 | * 218 | * @return string The value of the first argument or null otherwise 219 | */ 220 | public function getFirstArgument() 221 | { 222 | foreach ($this->tokens as $token) { 223 | if ($token && '-' === $token[0]) { 224 | continue; 225 | } 226 | 227 | return $token; 228 | } 229 | } 230 | 231 | /** 232 | * Returns true if the raw parameters (not parsed) contains a value. 233 | * 234 | * This method is to be used to introspect the input parameters 235 | * before it has been validated. It must be used carefully. 236 | * 237 | * @param string|array $values The value(s) to look for in the raw parameters (can be an array) 238 | * 239 | * @return Boolean true if the value is contained in the raw parameters 240 | */ 241 | public function hasParameterOption($values) 242 | { 243 | if (!is_array($values)) { 244 | $values = array($values); 245 | } 246 | 247 | foreach ($this->tokens as $v) { 248 | if (in_array($v, $values)) { 249 | return true; 250 | } 251 | } 252 | 253 | return false; 254 | } 255 | 256 | /** 257 | * Returns the value of a raw option (not parsed). 258 | * 259 | * This method is to be used to introspect the input parameters 260 | * before it has been validated. It must be used carefully. 261 | * 262 | * @param string|array $values The value(s) to look for in the raw parameters (can be an array) 263 | * @param mixed $default The default value to return if no result is found 264 | * @return mixed The option value 265 | */ 266 | public function getParameterOption($values, $default = false) 267 | { 268 | if (!is_array($values)) { 269 | $values = array($values); 270 | } 271 | 272 | $tokens = $this->tokens; 273 | while ($token = array_shift($tokens)) { 274 | foreach ($values as $value) { 275 | if (0 === strpos($token, $value)) { 276 | if (false !== $pos = strpos($token, '=')) { 277 | return substr($token, $pos + 1); 278 | } else { 279 | return array_shift($tokens); 280 | } 281 | } 282 | } 283 | } 284 | 285 | return $default; 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Input/ArrayInput.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Input; 13 | 14 | /** 15 | * ArrayInput represents an input provided as an array. 16 | * 17 | * Usage: 18 | * 19 | * $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar')); 20 | * 21 | * @author Fabien Potencier 22 | */ 23 | class ArrayInput extends Input 24 | { 25 | protected $parameters; 26 | 27 | /** 28 | * Constructor. 29 | * 30 | * @param array $param An array of parameters 31 | * @param InputDefinition $definition A InputDefinition instance 32 | */ 33 | public function __construct(array $parameters, InputDefinition $definition = null) 34 | { 35 | $this->parameters = $parameters; 36 | 37 | parent::__construct($definition); 38 | } 39 | 40 | /** 41 | * Returns the first argument from the raw parameters (not parsed). 42 | * 43 | * @return string The value of the first argument or null otherwise 44 | */ 45 | public function getFirstArgument() 46 | { 47 | foreach ($this->parameters as $key => $value) { 48 | if ($key && '-' === $key[0]) { 49 | continue; 50 | } 51 | 52 | return $value; 53 | } 54 | } 55 | 56 | /** 57 | * Returns true if the raw parameters (not parsed) contains a value. 58 | * 59 | * This method is to be used to introspect the input parameters 60 | * before it has been validated. It must be used carefully. 61 | * 62 | * @param string|array $value The values to look for in the raw parameters (can be an array) 63 | * 64 | * @return Boolean true if the value is contained in the raw parameters 65 | */ 66 | public function hasParameterOption($values) 67 | { 68 | if (!is_array($values)) { 69 | $values = array($values); 70 | } 71 | 72 | foreach ($this->parameters as $k => $v) { 73 | if (!is_int($k)) { 74 | $v = $k; 75 | } 76 | 77 | if (in_array($v, $values)) { 78 | return true; 79 | } 80 | } 81 | 82 | return false; 83 | } 84 | 85 | /** 86 | * Returns the value of a raw option (not parsed). 87 | * 88 | * This method is to be used to introspect the input parameters 89 | * before it has been validated. It must be used carefully. 90 | * 91 | * @param string|array $values The value(s) to look for in the raw parameters (can be an array) 92 | * @param mixed $default The default value to return if no result is found 93 | * 94 | * @return mixed The option value 95 | */ 96 | public function getParameterOption($values, $default = false) 97 | { 98 | if (!is_array($values)) { 99 | $values = array($values); 100 | } 101 | 102 | foreach ($this->parameters as $k => $v) { 103 | if (is_int($k) && in_array($v, $values)) { 104 | return true; 105 | } elseif (in_array($k, $values)) { 106 | return $v; 107 | } 108 | } 109 | 110 | return $default; 111 | } 112 | 113 | /** 114 | * Processes command line arguments. 115 | */ 116 | protected function parse() 117 | { 118 | foreach ($this->parameters as $key => $value) { 119 | if ('--' === substr($key, 0, 2)) { 120 | $this->addLongOption(substr($key, 2), $value); 121 | } elseif ('-' === $key[0]) { 122 | $this->addShortOption(substr($key, 1), $value); 123 | } else { 124 | $this->addArgument($key, $value); 125 | } 126 | } 127 | } 128 | 129 | /** 130 | * Adds a short option value. 131 | * 132 | * @param string $shortcut The short option key 133 | * @param mixed $value The value for the option 134 | * 135 | * @throws \RuntimeException When option given doesn't exist 136 | */ 137 | protected function addShortOption($shortcut, $value) 138 | { 139 | if (!$this->definition->hasShortcut($shortcut)) { 140 | throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); 141 | } 142 | 143 | $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); 144 | } 145 | 146 | /** 147 | * Adds a long option value. 148 | * 149 | * @param string $name The long option key 150 | * @param mixed $value The value for the option 151 | * 152 | * @throws \InvalidArgumentException When option given doesn't exist 153 | * @throws \InvalidArgumentException When a required value is missing 154 | */ 155 | protected function addLongOption($name, $value) 156 | { 157 | if (!$this->definition->hasOption($name)) { 158 | throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); 159 | } 160 | 161 | $option = $this->definition->getOption($name); 162 | 163 | if (null === $value) { 164 | if ($option->isValueRequired()) { 165 | throw new \InvalidArgumentException(sprintf('The "--%s" option requires a value.', $name)); 166 | } 167 | 168 | $value = $option->isValueOptional() ? $option->getDefault() : true; 169 | } 170 | 171 | $this->options[$name] = $value; 172 | } 173 | 174 | /** 175 | * Adds an argument value. 176 | * 177 | * @param string $name The argument name 178 | * @param mixed $value The value for the argument 179 | * 180 | * @throws \InvalidArgumentException When argument given doesn't exist 181 | */ 182 | protected function addArgument($name, $value) 183 | { 184 | if (!$this->definition->hasArgument($name)) { 185 | throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); 186 | } 187 | 188 | $this->arguments[$name] = $value; 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Input/Input.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Input; 13 | 14 | /** 15 | * Input is the base class for all concrete Input classes. 16 | * 17 | * Three concrete classes are provided by default: 18 | * 19 | * * `ArgvInput`: The input comes from the CLI arguments (argv) 20 | * * `StringInput`: The input is provided as a string 21 | * * `ArrayInput`: The input is provided as an array 22 | * 23 | * @author Fabien Potencier 24 | */ 25 | abstract class Input implements InputInterface 26 | { 27 | protected $definition; 28 | protected $options; 29 | protected $arguments; 30 | protected $interactive = true; 31 | 32 | /** 33 | * Constructor. 34 | * 35 | * @param InputDefinition $definition A InputDefinition instance 36 | */ 37 | public function __construct(InputDefinition $definition = null) 38 | { 39 | if (null === $definition) { 40 | $this->definition = new InputDefinition(); 41 | } else { 42 | $this->bind($definition); 43 | $this->validate(); 44 | } 45 | } 46 | 47 | /** 48 | * Binds the current Input instance with the given arguments and options. 49 | * 50 | * @param InputDefinition $definition A InputDefinition instance 51 | */ 52 | public function bind(InputDefinition $definition) 53 | { 54 | $this->arguments = array(); 55 | $this->options = array(); 56 | $this->definition = $definition; 57 | 58 | $this->parse(); 59 | } 60 | 61 | /** 62 | * Processes command line arguments. 63 | */ 64 | abstract protected function parse(); 65 | 66 | /** 67 | * Validates the input. 68 | * 69 | * @throws \RuntimeException When not enough arguments are given 70 | */ 71 | public function validate() 72 | { 73 | if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) { 74 | throw new \RuntimeException('Not enough arguments.'); 75 | } 76 | } 77 | 78 | /** 79 | * Checks if the input is interactive. 80 | * 81 | * @return Boolean Returns true if the input is interactive 82 | */ 83 | public function isInteractive() 84 | { 85 | return $this->interactive; 86 | } 87 | 88 | /** 89 | * Sets the input interactivity. 90 | * 91 | * @param Boolean $interactive If the input should be interactive 92 | */ 93 | public function setInteractive($interactive) 94 | { 95 | $this->interactive = (Boolean) $interactive; 96 | } 97 | 98 | /** 99 | * Returns the argument values. 100 | * 101 | * @return array An array of argument values 102 | */ 103 | public function getArguments() 104 | { 105 | return array_merge($this->definition->getArgumentDefaults(), $this->arguments); 106 | } 107 | 108 | /** 109 | * Returns the argument value for a given argument name. 110 | * 111 | * @param string $name The argument name 112 | * 113 | * @return mixed The argument value 114 | * 115 | * @throws \InvalidArgumentException When argument given doesn't exist 116 | */ 117 | public function getArgument($name) 118 | { 119 | if (!$this->definition->hasArgument($name)) { 120 | throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); 121 | } 122 | 123 | return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault(); 124 | } 125 | 126 | /** 127 | * Sets an argument value by name. 128 | * 129 | * @param string $name The argument name 130 | * @param string $value The argument value 131 | * 132 | * @throws \InvalidArgumentException When argument given doesn't exist 133 | */ 134 | public function setArgument($name, $value) 135 | { 136 | if (!$this->definition->hasArgument($name)) { 137 | throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); 138 | } 139 | 140 | $this->arguments[$name] = $value; 141 | } 142 | 143 | /** 144 | * Returns true if an InputArgument object exists by name or position. 145 | * 146 | * @param string|integer $name The InputArgument name or position 147 | * 148 | * @return Boolean true if the InputArgument object exists, false otherwise 149 | */ 150 | public function hasArgument($name) 151 | { 152 | return $this->definition->hasArgument($name); 153 | } 154 | 155 | /** 156 | * Returns the options values. 157 | * 158 | * @return array An array of option values 159 | */ 160 | public function getOptions() 161 | { 162 | return array_merge($this->definition->getOptionDefaults(), $this->options); 163 | } 164 | 165 | /** 166 | * Returns the option value for a given option name. 167 | * 168 | * @param string $name The option name 169 | * 170 | * @return mixed The option value 171 | * 172 | * @throws \InvalidArgumentException When option given doesn't exist 173 | */ 174 | public function getOption($name) 175 | { 176 | if (!$this->definition->hasOption($name)) { 177 | throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); 178 | } 179 | 180 | return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); 181 | } 182 | 183 | /** 184 | * Sets an option value by name. 185 | * 186 | * @param string $name The option name 187 | * @param string $value The option value 188 | * 189 | * @throws \InvalidArgumentException When option given doesn't exist 190 | */ 191 | public function setOption($name, $value) 192 | { 193 | if (!$this->definition->hasOption($name)) { 194 | throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); 195 | } 196 | 197 | $this->options[$name] = $value; 198 | } 199 | 200 | /** 201 | * Returns true if an InputOption object exists by name. 202 | * 203 | * @param string $name The InputOption name 204 | * 205 | * @return Boolean true if the InputOption object exists, false otherwise 206 | */ 207 | public function hasOption($name) 208 | { 209 | return $this->definition->hasOption($name); 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Input/InputArgument.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Input; 13 | 14 | /** 15 | * Represents a command line argument. 16 | * 17 | * @author Fabien Potencier 18 | */ 19 | class InputArgument 20 | { 21 | const REQUIRED = 1; 22 | const OPTIONAL = 2; 23 | const IS_ARRAY = 4; 24 | 25 | protected $name; 26 | protected $mode; 27 | protected $default; 28 | protected $description; 29 | 30 | /** 31 | * Constructor. 32 | * 33 | * @param string $name The argument name 34 | * @param integer $mode The argument mode: self::REQUIRED or self::OPTIONAL 35 | * @param string $description A description text 36 | * @param mixed $default The default value (for self::OPTIONAL mode only) 37 | * 38 | * @throws \InvalidArgumentException When argument mode is not valid 39 | */ 40 | public function __construct($name, $mode = null, $description = '', $default = null) 41 | { 42 | if (null === $mode) { 43 | $mode = self::OPTIONAL; 44 | } else if (is_string($mode) || $mode > 7) { 45 | throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode)); 46 | } 47 | 48 | $this->name = $name; 49 | $this->mode = $mode; 50 | $this->description = $description; 51 | 52 | $this->setDefault($default); 53 | } 54 | 55 | /** 56 | * Returns the argument name. 57 | * 58 | * @return string The argument name 59 | */ 60 | public function getName() 61 | { 62 | return $this->name; 63 | } 64 | 65 | /** 66 | * Returns true if the argument is required. 67 | * 68 | * @return Boolean true if parameter mode is self::REQUIRED, false otherwise 69 | */ 70 | public function isRequired() 71 | { 72 | return self::REQUIRED === (self::REQUIRED & $this->mode); 73 | } 74 | 75 | /** 76 | * Returns true if the argument can take multiple values. 77 | * 78 | * @return Boolean true if mode is self::IS_ARRAY, false otherwise 79 | */ 80 | public function isArray() 81 | { 82 | return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); 83 | } 84 | 85 | /** 86 | * Sets the default value. 87 | * 88 | * @param mixed $default The default value 89 | * 90 | * @throws \LogicException When incorrect default value is given 91 | */ 92 | public function setDefault($default = null) 93 | { 94 | if (self::REQUIRED === $this->mode && null !== $default) { 95 | throw new \LogicException('Cannot set a default value except for Parameter::OPTIONAL mode.'); 96 | } 97 | 98 | if ($this->isArray()) { 99 | if (null === $default) { 100 | $default = array(); 101 | } else if (!is_array($default)) { 102 | throw new \LogicException('A default value for an array argument must be an array.'); 103 | } 104 | } 105 | 106 | $this->default = $default; 107 | } 108 | 109 | /** 110 | * Returns the default value. 111 | * 112 | * @return mixed The default value 113 | */ 114 | public function getDefault() 115 | { 116 | return $this->default; 117 | } 118 | 119 | /** 120 | * Returns the description text. 121 | * 122 | * @return string The description text 123 | */ 124 | public function getDescription() 125 | { 126 | return $this->description; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Input/InputDefinition.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Input; 13 | 14 | /** 15 | * A InputDefinition represents a set of valid command line arguments and options. 16 | * 17 | * Usage: 18 | * 19 | * $definition = new InputDefinition(array( 20 | * new InputArgument('name', InputArgument::REQUIRED), 21 | * new InputOption('foo', 'f', InputOption::VALUE_REQUIRED), 22 | * )); 23 | * 24 | * @author Fabien Potencier 25 | */ 26 | class InputDefinition 27 | { 28 | protected $arguments; 29 | protected $requiredCount; 30 | protected $hasAnArrayArgument = false; 31 | protected $hasOptional; 32 | protected $options; 33 | protected $shortcuts; 34 | 35 | /** 36 | * Constructor. 37 | * 38 | * @param array $definition An array of InputArgument and InputOption instance 39 | */ 40 | public function __construct(array $definition = array()) 41 | { 42 | $this->setDefinition($definition); 43 | } 44 | 45 | /** 46 | * Sets the definition of the input. 47 | * 48 | * @param array $definition The definition array 49 | */ 50 | public function setDefinition(array $definition) 51 | { 52 | $arguments = array(); 53 | $options = array(); 54 | foreach ($definition as $item) { 55 | if ($item instanceof InputOption) { 56 | $options[] = $item; 57 | } else { 58 | $arguments[] = $item; 59 | } 60 | } 61 | 62 | $this->setArguments($arguments); 63 | $this->setOptions($options); 64 | } 65 | 66 | /** 67 | * Sets the InputArgument objects. 68 | * 69 | * @param array $arguments An array of InputArgument objects 70 | */ 71 | public function setArguments($arguments = array()) 72 | { 73 | $this->arguments = array(); 74 | $this->requiredCount = 0; 75 | $this->hasOptional = false; 76 | $this->hasAnArrayArgument = false; 77 | $this->addArguments($arguments); 78 | } 79 | 80 | /** 81 | * Add an array of InputArgument objects. 82 | * 83 | * @param InputArgument[] $arguments An array of InputArgument objects 84 | */ 85 | public function addArguments($arguments = array()) 86 | { 87 | if (null !== $arguments) { 88 | foreach ($arguments as $argument) { 89 | $this->addArgument($argument); 90 | } 91 | } 92 | } 93 | 94 | /** 95 | * Add an InputArgument object. 96 | * 97 | * @param InputArgument $argument An InputArgument object 98 | * 99 | * @throws \LogicException When incorrect argument is given 100 | */ 101 | public function addArgument(InputArgument $argument) 102 | { 103 | if (isset($this->arguments[$argument->getName()])) { 104 | throw new \LogicException(sprintf('An argument with name "%s" already exist.', $argument->getName())); 105 | } 106 | 107 | if ($this->hasAnArrayArgument) { 108 | throw new \LogicException('Cannot add an argument after an array argument.'); 109 | } 110 | 111 | if ($argument->isRequired() && $this->hasOptional) { 112 | throw new \LogicException('Cannot add a required argument after an optional one.'); 113 | } 114 | 115 | if ($argument->isArray()) { 116 | $this->hasAnArrayArgument = true; 117 | } 118 | 119 | if ($argument->isRequired()) { 120 | ++$this->requiredCount; 121 | } else { 122 | $this->hasOptional = true; 123 | } 124 | 125 | $this->arguments[$argument->getName()] = $argument; 126 | } 127 | 128 | /** 129 | * Returns an InputArgument by name or by position. 130 | * 131 | * @param string|integer $name The InputArgument name or position 132 | * 133 | * @return InputArgument An InputArgument object 134 | * 135 | * @throws \InvalidArgumentException When argument given doesn't exist 136 | */ 137 | public function getArgument($name) 138 | { 139 | $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments; 140 | 141 | if (!$this->hasArgument($name)) { 142 | throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); 143 | } 144 | 145 | return $arguments[$name]; 146 | } 147 | 148 | /** 149 | * Returns true if an InputArgument object exists by name or position. 150 | * 151 | * @param string|integer $name The InputArgument name or position 152 | * 153 | * @return Boolean true if the InputArgument object exists, false otherwise 154 | */ 155 | public function hasArgument($name) 156 | { 157 | $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments; 158 | 159 | return isset($arguments[$name]); 160 | } 161 | 162 | /** 163 | * Gets the array of InputArgument objects. 164 | * 165 | * @return array An array of InputArgument objects 166 | */ 167 | public function getArguments() 168 | { 169 | return $this->arguments; 170 | } 171 | 172 | /** 173 | * Returns the number of InputArguments. 174 | * 175 | * @return integer The number of InputArguments 176 | */ 177 | public function getArgumentCount() 178 | { 179 | return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments); 180 | } 181 | 182 | /** 183 | * Returns the number of required InputArguments. 184 | * 185 | * @return integer The number of required InputArguments 186 | */ 187 | public function getArgumentRequiredCount() 188 | { 189 | return $this->requiredCount; 190 | } 191 | 192 | /** 193 | * Gets the default values. 194 | * 195 | * @return array An array of default values 196 | */ 197 | public function getArgumentDefaults() 198 | { 199 | $values = array(); 200 | foreach ($this->arguments as $argument) { 201 | $values[$argument->getName()] = $argument->getDefault(); 202 | } 203 | 204 | return $values; 205 | } 206 | 207 | /** 208 | * Sets the InputOption objects. 209 | * 210 | * @param array $options An array of InputOption objects 211 | */ 212 | public function setOptions($options = array()) 213 | { 214 | $this->options = array(); 215 | $this->shortcuts = array(); 216 | $this->addOptions($options); 217 | } 218 | 219 | /** 220 | * Add an array of InputOption objects. 221 | * 222 | * @param InputOption[] $options An array of InputOption objects 223 | */ 224 | public function addOptions($options = array()) 225 | { 226 | foreach ($options as $option) { 227 | $this->addOption($option); 228 | } 229 | } 230 | 231 | /** 232 | * Add an InputOption object. 233 | * 234 | * @param InputOption $option An InputOption object 235 | * 236 | * @throws \LogicException When option given already exist 237 | */ 238 | public function addOption(InputOption $option) 239 | { 240 | if (isset($this->options[$option->getName()])) { 241 | throw new \LogicException(sprintf('An option named "%s" already exist.', $option->getName())); 242 | } else if (isset($this->shortcuts[$option->getShortcut()])) { 243 | throw new \LogicException(sprintf('An option with shortcut "%s" already exist.', $option->getShortcut())); 244 | } 245 | 246 | $this->options[$option->getName()] = $option; 247 | if ($option->getShortcut()) { 248 | $this->shortcuts[$option->getShortcut()] = $option->getName(); 249 | } 250 | } 251 | 252 | /** 253 | * Returns an InputOption by name. 254 | * 255 | * @param string $name The InputOption name 256 | * 257 | * @return InputOption A InputOption object 258 | */ 259 | public function getOption($name) 260 | { 261 | if (!$this->hasOption($name)) { 262 | throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); 263 | } 264 | 265 | return $this->options[$name]; 266 | } 267 | 268 | /** 269 | * Returns true if an InputOption object exists by name. 270 | * 271 | * @param string $name The InputOption name 272 | * 273 | * @return Boolean true if the InputOption object exists, false otherwise 274 | */ 275 | public function hasOption($name) 276 | { 277 | return isset($this->options[$name]); 278 | } 279 | 280 | /** 281 | * Gets the array of InputOption objects. 282 | * 283 | * @return array An array of InputOption objects 284 | */ 285 | public function getOptions() 286 | { 287 | return $this->options; 288 | } 289 | 290 | /** 291 | * Returns true if an InputOption object exists by shortcut. 292 | * 293 | * @param string $name The InputOption shortcut 294 | * 295 | * @return Boolean true if the InputOption object exists, false otherwise 296 | */ 297 | public function hasShortcut($name) 298 | { 299 | return isset($this->shortcuts[$name]); 300 | } 301 | 302 | /** 303 | * Gets an InputOption by shortcut. 304 | * 305 | * @param string $shortcut the Shortcut name 306 | * 307 | * @return InputOption An InputOption object 308 | */ 309 | public function getOptionForShortcut($shortcut) 310 | { 311 | return $this->getOption($this->shortcutToName($shortcut)); 312 | } 313 | 314 | /** 315 | * Gets an array of default values. 316 | * 317 | * @return array An array of all default values 318 | */ 319 | public function getOptionDefaults() 320 | { 321 | $values = array(); 322 | foreach ($this->options as $option) { 323 | $values[$option->getName()] = $option->getDefault(); 324 | } 325 | 326 | return $values; 327 | } 328 | 329 | /** 330 | * Returns the InputOption name given a shortcut. 331 | * 332 | * @param string $shortcut The shortcut 333 | * 334 | * @return string The InputOption name 335 | * 336 | * @throws \InvalidArgumentException When option given does not exist 337 | */ 338 | protected function shortcutToName($shortcut) 339 | { 340 | if (!isset($this->shortcuts[$shortcut])) { 341 | throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); 342 | } 343 | 344 | return $this->shortcuts[$shortcut]; 345 | } 346 | 347 | /** 348 | * Gets the synopsis. 349 | * 350 | * @return string The synopsis 351 | */ 352 | public function getSynopsis() 353 | { 354 | $elements = array(); 355 | foreach ($this->getOptions() as $option) { 356 | $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : ''; 357 | $elements[] = sprintf('['.($option->isValueRequired() ? '%s--%s="..."' : ($option->isValueOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName()); 358 | } 359 | 360 | foreach ($this->getArguments() as $argument) { 361 | $elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : '')); 362 | 363 | if ($argument->isArray()) { 364 | $elements[] = sprintf('... [%sN]', $argument->getName()); 365 | } 366 | } 367 | 368 | return implode(' ', $elements); 369 | } 370 | 371 | /** 372 | * Returns a textual representation of the InputDefinition. 373 | * 374 | * @return string A string representing the InputDefinition 375 | */ 376 | public function asText() 377 | { 378 | // find the largest option or argument name 379 | $max = 0; 380 | foreach ($this->getOptions() as $option) { 381 | $max = strlen($option->getName()) + 2 > $max ? strlen($option->getName()) + 2 : $max; 382 | } 383 | foreach ($this->getArguments() as $argument) { 384 | $max = strlen($argument->getName()) > $max ? strlen($argument->getName()) : $max; 385 | } 386 | ++$max; 387 | 388 | $text = array(); 389 | 390 | if ($this->getArguments()) { 391 | $text[] = 'Arguments:'; 392 | foreach ($this->getArguments() as $argument) { 393 | if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) { 394 | $default = sprintf(' (default: %s)', is_array($argument->getDefault()) ? str_replace("\n", '', var_export($argument->getDefault(), true)): $argument->getDefault()); 395 | } else { 396 | $default = ''; 397 | } 398 | 399 | $text[] = sprintf(" %-${max}s %s%s", $argument->getName(), $argument->getDescription(), $default); 400 | } 401 | 402 | $text[] = ''; 403 | } 404 | 405 | if ($this->getOptions()) { 406 | $text[] = 'Options:'; 407 | 408 | foreach ($this->getOptions() as $option) { 409 | if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) { 410 | $default = sprintf(' (default: %s)', is_array($option->getDefault()) ? str_replace("\n", '', print_r($option->getDefault(), true)): $option->getDefault()); 411 | } else { 412 | $default = ''; 413 | } 414 | 415 | $multiple = $option->isArray() ? ' (multiple values allowed)' : ''; 416 | $text[] = sprintf(' %-'.$max.'s %s%s%s%s', '--'.$option->getName().'', $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '', $option->getDescription(), $default, $multiple); 417 | } 418 | 419 | $text[] = ''; 420 | } 421 | 422 | return implode("\n", $text); 423 | } 424 | 425 | /** 426 | * Returns an XML representation of the InputDefinition. 427 | * 428 | * @param Boolean $asDom Whether to return a DOM or an XML string 429 | * 430 | * @return string|DOMDocument An XML string representing the InputDefinition 431 | */ 432 | public function asXml($asDom = false) 433 | { 434 | $dom = new \DOMDocument('1.0', 'UTF-8'); 435 | $dom->formatOutput = true; 436 | $dom->appendChild($definitionXML = $dom->createElement('definition')); 437 | 438 | $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments')); 439 | foreach ($this->getArguments() as $argument) { 440 | $argumentsXML->appendChild($argumentXML = $dom->createElement('argument')); 441 | $argumentXML->setAttribute('name', $argument->getName()); 442 | $argumentXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0); 443 | $argumentXML->setAttribute('is_array', $argument->isArray() ? 1 : 0); 444 | $argumentXML->appendChild($descriptionXML = $dom->createElement('description')); 445 | $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); 446 | 447 | $argumentXML->appendChild($defaultsXML = $dom->createElement('defaults')); 448 | $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : ($argument->getDefault() ? array($argument->getDefault()) : array()); 449 | foreach ($defaults as $default) { 450 | $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); 451 | $defaultXML->appendChild($dom->createTextNode($default)); 452 | } 453 | } 454 | 455 | $definitionXML->appendChild($optionsXML = $dom->createElement('options')); 456 | foreach ($this->getOptions() as $option) { 457 | $optionsXML->appendChild($optionXML = $dom->createElement('option')); 458 | $optionXML->setAttribute('name', '--'.$option->getName()); 459 | $optionXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); 460 | $optionXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0); 461 | $optionXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0); 462 | $optionXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0); 463 | $optionXML->appendChild($descriptionXML = $dom->createElement('description')); 464 | $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); 465 | 466 | if ($option->acceptValue()) { 467 | $optionXML->appendChild($defaultsXML = $dom->createElement('defaults')); 468 | $defaults = is_array($option->getDefault()) ? $option->getDefault() : ($option->getDefault() ? array($option->getDefault()) : array()); 469 | foreach ($defaults as $default) { 470 | $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); 471 | $defaultXML->appendChild($dom->createTextNode($default)); 472 | } 473 | } 474 | } 475 | 476 | return $asDom ? $dom : $dom->saveXml(); 477 | } 478 | } 479 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Input/InputInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Input; 13 | 14 | /** 15 | * InputInterface is the interface implemented by all input classes. 16 | * 17 | * @author Fabien Potencier 18 | */ 19 | interface InputInterface 20 | { 21 | /** 22 | * Returns the first argument from the raw parameters (not parsed). 23 | * 24 | * @return string The value of the first argument or null otherwise 25 | */ 26 | function getFirstArgument(); 27 | 28 | /** 29 | * Returns true if the raw parameters (not parsed) contains a value. 30 | * 31 | * This method is to be used to introspect the input parameters 32 | * before it has been validated. It must be used carefully. 33 | * 34 | * @param string|array $value The values to look for in the raw parameters (can be an array) 35 | * 36 | * @return Boolean true if the value is contained in the raw parameters 37 | */ 38 | function hasParameterOption($values); 39 | 40 | /** 41 | * Returns the value of a raw option (not parsed). 42 | * 43 | * This method is to be used to introspect the input parameters 44 | * before it has been validated. It must be used carefully. 45 | * 46 | * @param string|array $values The value(s) to look for in the raw parameters (can be an array) 47 | * @param mixed $default The default value to return if no result is found 48 | * 49 | * @return mixed The option value 50 | */ 51 | function getParameterOption($values, $default = false); 52 | 53 | /** 54 | * Binds the current Input instance with the given arguments and options. 55 | * 56 | * @param InputDefinition $definition A InputDefinition instance 57 | */ 58 | function bind(InputDefinition $definition); 59 | 60 | /** 61 | * Validate if arguments given are correct. 62 | * 63 | * Throws an exception when not enough arguments are given. 64 | * 65 | * @throws \RuntimeException 66 | */ 67 | function validate(); 68 | 69 | /** 70 | * Returns all the given arguments merged with the default values. 71 | * 72 | * @return array 73 | */ 74 | function getArguments(); 75 | 76 | /** 77 | * Get argument by name. 78 | * 79 | * @param string $name The name of the argument 80 | * @return mixed 81 | */ 82 | function getArgument($name); 83 | 84 | /** 85 | * @return array 86 | */ 87 | function getOptions(); 88 | 89 | /** 90 | * Get an option by name. 91 | * 92 | * @param string $name The name of the option 93 | * @return mixed 94 | */ 95 | function getOption($name); 96 | 97 | /** 98 | * Is this input means interactive? 99 | * 100 | * @return bool 101 | */ 102 | function isInteractive(); 103 | } 104 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Input/InputOption.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Input; 13 | 14 | /** 15 | * Represents a command line option. 16 | * 17 | * @author Fabien Potencier 18 | */ 19 | class InputOption 20 | { 21 | const VALUE_NONE = 1; 22 | const VALUE_REQUIRED = 2; 23 | const VALUE_OPTIONAL = 4; 24 | const VALUE_IS_ARRAY = 8; 25 | 26 | protected $name; 27 | protected $shortcut; 28 | protected $mode; 29 | protected $default; 30 | protected $description; 31 | 32 | /** 33 | * Constructor. 34 | * 35 | * @param string $name The option name 36 | * @param string $shortcut The shortcut (can be null) 37 | * @param integer $mode The option mode: One of the VALUE_* constants 38 | * @param string $description A description text 39 | * @param mixed $default The default value (must be null for self::VALUE_REQUIRED or self::VALUE_NONE) 40 | * 41 | * @throws \InvalidArgumentException If option mode is invalid or incompatible 42 | */ 43 | public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null) 44 | { 45 | if ('--' === substr($name, 0, 2)) { 46 | $name = substr($name, 2); 47 | } 48 | 49 | if (empty($shortcut)) { 50 | $shortcut = null; 51 | } 52 | 53 | if (null !== $shortcut) { 54 | if ('-' === $shortcut[0]) { 55 | $shortcut = substr($shortcut, 1); 56 | } 57 | } 58 | 59 | if (null === $mode) { 60 | $mode = self::VALUE_NONE; 61 | } else if (!is_int($mode) || $mode > 15) { 62 | throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode)); 63 | } 64 | 65 | $this->name = $name; 66 | $this->shortcut = $shortcut; 67 | $this->mode = $mode; 68 | $this->description = $description; 69 | 70 | if ($this->isArray() && !$this->acceptValue()) { 71 | throw new \InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.'); 72 | } 73 | 74 | $this->setDefault($default); 75 | } 76 | 77 | /** 78 | * Returns the shortcut. 79 | * 80 | * @return string The shortcut 81 | */ 82 | public function getShortcut() 83 | { 84 | return $this->shortcut; 85 | } 86 | 87 | /** 88 | * Returns the name. 89 | * 90 | * @return string The name 91 | */ 92 | public function getName() 93 | { 94 | return $this->name; 95 | } 96 | 97 | /** 98 | * Returns true if the option accepts a value. 99 | * 100 | * @return Boolean true if value mode is not self::VALUE_NONE, false otherwise 101 | */ 102 | public function acceptValue() 103 | { 104 | return $this->isValueRequired() || $this->isValueOptional(); 105 | } 106 | 107 | /** 108 | * Returns true if the option requires a value. 109 | * 110 | * @return Boolean true if value mode is self::VALUE_REQUIRED, false otherwise 111 | */ 112 | public function isValueRequired() 113 | { 114 | return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode); 115 | } 116 | 117 | /** 118 | * Returns true if the option takes an optional value. 119 | * 120 | * @return Boolean true if value mode is self::VALUE_OPTIONAL, false otherwise 121 | */ 122 | public function isValueOptional() 123 | { 124 | return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode); 125 | } 126 | 127 | /** 128 | * Returns true if the option can take multiple values. 129 | * 130 | * @return Boolean true if mode is self::VALUE_IS_ARRAY, false otherwise 131 | */ 132 | public function isArray() 133 | { 134 | return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); 135 | } 136 | 137 | /** 138 | * Sets the default value. 139 | * 140 | * @param mixed $default The default value 141 | */ 142 | public function setDefault($default = null) 143 | { 144 | if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) { 145 | throw new \LogicException('Cannot set a default value when using Option::VALUE_NONE mode.'); 146 | } 147 | 148 | if ($this->isArray()) { 149 | if (null === $default) { 150 | $default = array(); 151 | } elseif (!is_array($default)) { 152 | throw new \LogicException('A default value for an array option must be an array.'); 153 | } 154 | } 155 | 156 | $this->default = $this->acceptValue() ? $default : false; 157 | } 158 | 159 | /** 160 | * Returns the default value. 161 | * 162 | * @return mixed The default value 163 | */ 164 | public function getDefault() 165 | { 166 | return $this->default; 167 | } 168 | 169 | /** 170 | * Returns the description text. 171 | * 172 | * @return string The description text 173 | */ 174 | public function getDescription() 175 | { 176 | return $this->description; 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Input/StringInput.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Input; 13 | 14 | /** 15 | * StringInput represents an input provided as a string. 16 | * 17 | * Usage: 18 | * 19 | * $input = new StringInput('foo --bar="foobar"'); 20 | * 21 | * @author Fabien Potencier 22 | */ 23 | class StringInput extends ArgvInput 24 | { 25 | const REGEX_STRING = '([^ ]+?)(?: |(?tokens = $this->tokenize($input); 39 | } 40 | 41 | /** 42 | * Tokenizes a string. 43 | * 44 | * @param string $input The input to tokenise 45 | * @throws \InvalidArgumentException When unable to parse input (should never happen) 46 | */ 47 | protected function tokenize($input) 48 | { 49 | $input = preg_replace('/(\r\n|\r|\n|\t)/', ' ', $input); 50 | 51 | $tokens = array(); 52 | $length = strlen($input); 53 | $cursor = 0; 54 | while ($cursor < $length) { 55 | if (preg_match('/\s+/A', $input, $match, null, $cursor)) { 56 | } elseif (preg_match('/([^="\' ]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) { 57 | $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2))); 58 | } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) { 59 | $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2)); 60 | } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) { 61 | $tokens[] = stripcslashes($match[1]); 62 | } else { 63 | // should never happen 64 | // @codeCoverageIgnoreStart 65 | throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10))); 66 | // @codeCoverageIgnoreEnd 67 | } 68 | 69 | $cursor += strlen($match[0]); 70 | } 71 | 72 | return $tokens; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Output/ConsoleOutput.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Output; 13 | 14 | /** 15 | * ConsoleOutput is the default class for all CLI output. It uses STDOUT. 16 | * 17 | * This class is a convenient wrapper around `StreamOutput`. 18 | * 19 | * $output = new ConsoleOutput(); 20 | * 21 | * This is equivalent to: 22 | * 23 | * $output = new StreamOutput(fopen('php://stdout', 'w')); 24 | * 25 | * @author Fabien Potencier 26 | */ 27 | class ConsoleOutput extends StreamOutput 28 | { 29 | /** 30 | * Constructor. 31 | * 32 | * @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE) 33 | * @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing) 34 | */ 35 | public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null) 36 | { 37 | parent::__construct(fopen('php://stdout', 'w'), $verbosity, $decorated); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Output/NullOutput.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Output; 13 | 14 | /** 15 | * NullOutput suppresses all output. 16 | * 17 | * $output = new NullOutput(); 18 | * 19 | * @author Fabien Potencier 20 | */ 21 | class NullOutput extends Output 22 | { 23 | /** 24 | * Writes a message to the output. 25 | * 26 | * @param string $message A message to write to the output 27 | * @param Boolean $newline Whether to add a newline or not 28 | */ 29 | public function doWrite($message, $newline) 30 | { 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Output/Output.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Output; 13 | 14 | /** 15 | * Base class for output classes. 16 | * 17 | * There is three level of verbosity: 18 | * 19 | * * normal: no option passed (normal output - information) 20 | * * verbose: -v (more output - debug) 21 | * * quiet: -q (no output) 22 | * 23 | * @author Fabien Potencier 24 | */ 25 | abstract class Output implements OutputInterface 26 | { 27 | const VERBOSITY_QUIET = 0; 28 | const VERBOSITY_NORMAL = 1; 29 | const VERBOSITY_VERBOSE = 2; 30 | 31 | const OUTPUT_NORMAL = 0; 32 | const OUTPUT_RAW = 1; 33 | const OUTPUT_PLAIN = 2; 34 | 35 | protected $verbosity; 36 | protected $decorated; 37 | 38 | static protected $styles = array( 39 | 'error' => array('bg' => 'red', 'fg' => 'white'), 40 | 'info' => array('fg' => 'green'), 41 | 'comment' => array('fg' => 'yellow'), 42 | 'question' => array('bg' => 'cyan', 'fg' => 'black'), 43 | ); 44 | static protected $options = array('bold' => 1, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'conceal' => 8); 45 | static protected $foreground = array('black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37); 46 | static protected $background = array('black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47); 47 | 48 | /** 49 | * Constructor. 50 | * 51 | * @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE) 52 | * @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing) 53 | */ 54 | public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null) 55 | { 56 | $this->decorated = (Boolean) $decorated; 57 | $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity; 58 | } 59 | 60 | /** 61 | * Sets a new style. 62 | * 63 | * @param string $name The style name 64 | * @param array $options An array of options 65 | */ 66 | static public function setStyle($name, $options = array()) 67 | { 68 | static::$styles[strtolower($name)] = $options; 69 | } 70 | 71 | /** 72 | * Sets the decorated flag. 73 | * 74 | * @param Boolean $decorated Whether to decorated the messages or not 75 | */ 76 | public function setDecorated($decorated) 77 | { 78 | $this->decorated = (Boolean) $decorated; 79 | } 80 | 81 | /** 82 | * Gets the decorated flag. 83 | * 84 | * @return Boolean true if the output will decorate messages, false otherwise 85 | */ 86 | public function isDecorated() 87 | { 88 | return $this->decorated; 89 | } 90 | 91 | /** 92 | * Sets the verbosity of the output. 93 | * 94 | * @param integer $level The level of verbosity 95 | */ 96 | public function setVerbosity($level) 97 | { 98 | $this->verbosity = (int) $level; 99 | } 100 | 101 | /** 102 | * Gets the current verbosity of the output. 103 | * 104 | * @return integer The current level of verbosity 105 | */ 106 | public function getVerbosity() 107 | { 108 | return $this->verbosity; 109 | } 110 | 111 | /** 112 | * Writes a message to the output and adds a newline at the end. 113 | * 114 | * @param string|array $messages The message as an array of lines of a single string 115 | * @param integer $type The type of output 116 | */ 117 | public function writeln($messages, $type = 0) 118 | { 119 | $this->write($messages, true, $type); 120 | } 121 | 122 | /** 123 | * Writes a message to the output. 124 | * 125 | * @param string|array $messages The message as an array of lines of a single string 126 | * @param Boolean $newline Whether to add a newline or not 127 | * @param integer $type The type of output 128 | * 129 | * @throws \InvalidArgumentException When unknown output type is given 130 | */ 131 | public function write($messages, $newline = false, $type = 0) 132 | { 133 | if (self::VERBOSITY_QUIET === $this->verbosity) { 134 | return; 135 | } 136 | 137 | if (!is_array($messages)) { 138 | $messages = array($messages); 139 | } 140 | 141 | foreach ($messages as $message) { 142 | switch ($type) { 143 | case Output::OUTPUT_NORMAL: 144 | $message = $this->format($message); 145 | break; 146 | case Output::OUTPUT_RAW: 147 | break; 148 | case Output::OUTPUT_PLAIN: 149 | $message = strip_tags($this->format($message)); 150 | break; 151 | default: 152 | throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type)); 153 | } 154 | 155 | $this->doWrite($message, $newline); 156 | } 157 | } 158 | 159 | /** 160 | * Writes a message to the output. 161 | * 162 | * @param string $message A message to write to the output 163 | * @param Boolean $newline Whether to add a newline or not 164 | */ 165 | abstract public function doWrite($message, $newline); 166 | 167 | /** 168 | * Formats a message according to the given styles. 169 | * 170 | * @param string $message The message to style 171 | * 172 | * @return string The styled message 173 | */ 174 | protected function format($message) 175 | { 176 | $message = preg_replace_callback('#<([a-z][a-z0-9\-_=;]+)>#i', array($this, 'replaceStartStyle'), $message); 177 | 178 | return preg_replace_callback('##i', array($this, 'replaceEndStyle'), $message); 179 | } 180 | 181 | /** 182 | * Replaces the starting style of the output. 183 | * 184 | * @param array $match 185 | * 186 | * @return string The replaced style 187 | * 188 | * @throws \InvalidArgumentException When style is unknown 189 | */ 190 | protected function replaceStartStyle($match) 191 | { 192 | if (!$this->decorated) { 193 | return ''; 194 | } 195 | 196 | if (isset(static::$styles[strtolower($match[1])])) { 197 | $parameters = static::$styles[strtolower($match[1])]; 198 | } else { 199 | // bg=blue;fg=red 200 | if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($match[1]), $matches, PREG_SET_ORDER)) { 201 | throw new \InvalidArgumentException(sprintf('Unknown style "%s".', $match[1])); 202 | } 203 | 204 | $parameters = array(); 205 | foreach ($matches as $match) { 206 | $parameters[$match[1]] = $match[2]; 207 | } 208 | } 209 | 210 | $codes = array(); 211 | 212 | if (isset($parameters['fg'])) { 213 | $codes[] = static::$foreground[$parameters['fg']]; 214 | } 215 | 216 | if (isset($parameters['bg'])) { 217 | $codes[] = static::$background[$parameters['bg']]; 218 | } 219 | 220 | foreach (static::$options as $option => $value) { 221 | if (isset($parameters[$option]) && $parameters[$option]) { 222 | $codes[] = $value; 223 | } 224 | } 225 | 226 | return "\033[".implode(';', $codes).'m'; 227 | } 228 | 229 | /** 230 | * Replaces the end style. 231 | * 232 | * @param string $match The text to match 233 | * 234 | * @return string The end style 235 | */ 236 | protected function replaceEndStyle($match) 237 | { 238 | if (!$this->decorated) { 239 | return ''; 240 | } 241 | 242 | return "\033[0m"; 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Output/OutputInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Output; 13 | 14 | /** 15 | * OutputInterface is the interface implemented by all Output classes. 16 | * 17 | * @author Fabien Potencier 18 | */ 19 | interface OutputInterface 20 | { 21 | /** 22 | * Writes a message to the output. 23 | * 24 | * @param string|array $messages The message as an array of lines of a single string 25 | * @param Boolean $newline Whether to add a newline or not 26 | * @param integer $type The type of output 27 | * 28 | * @throws \InvalidArgumentException When unknown output type is given 29 | */ 30 | function write($messages, $newline = false, $type = 0); 31 | 32 | /** 33 | * Writes a message to the output and adds a newline at the end. 34 | * 35 | * @param string|array $messages The message as an array of lines of a single string 36 | * @param integer $type The type of output 37 | */ 38 | function writeln($messages, $type = 0); 39 | 40 | /** 41 | * Sets the verbosity of the output. 42 | * 43 | * @param integer $level The level of verbosity 44 | */ 45 | function setVerbosity($level); 46 | 47 | /** 48 | * Sets the decorated flag. 49 | * 50 | * @param Boolean $decorated Whether to decorated the messages or not 51 | */ 52 | function setDecorated($decorated); 53 | } 54 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Output/StreamOutput.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Output; 13 | 14 | /** 15 | * StreamOutput writes the output to a given stream. 16 | * 17 | * Usage: 18 | * 19 | * $output = new StreamOutput(fopen('php://stdout', 'w')); 20 | * 21 | * As `StreamOutput` can use any stream, you can also use a file: 22 | * 23 | * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false)); 24 | * 25 | * @author Fabien Potencier 26 | */ 27 | class StreamOutput extends Output 28 | { 29 | protected $stream; 30 | 31 | /** 32 | * Constructor. 33 | * 34 | * @param mixed $stream A stream resource 35 | * @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE) 36 | * @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing) 37 | * 38 | * @throws \InvalidArgumentException When first argument is not a real stream 39 | */ 40 | public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null) 41 | { 42 | if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) { 43 | throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.'); 44 | } 45 | 46 | $this->stream = $stream; 47 | 48 | if (null === $decorated) { 49 | $decorated = $this->hasColorSupport($decorated); 50 | } 51 | 52 | parent::__construct($verbosity, $decorated); 53 | } 54 | 55 | /** 56 | * Gets the stream attached to this StreamOutput instance. 57 | * 58 | * @return resource A stream resource 59 | */ 60 | public function getStream() 61 | { 62 | return $this->stream; 63 | } 64 | 65 | /** 66 | * Writes a message to the output. 67 | * 68 | * @param string $message A message to write to the output 69 | * @param Boolean $newline Whether to add a newline or not 70 | * 71 | * @throws \RuntimeException When unable to write output (should never happen) 72 | */ 73 | public function doWrite($message, $newline) 74 | { 75 | if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) { 76 | // @codeCoverageIgnoreStart 77 | // should never happen 78 | throw new \RuntimeException('Unable to write output.'); 79 | // @codeCoverageIgnoreEnd 80 | } 81 | 82 | fflush($this->stream); 83 | } 84 | 85 | /** 86 | * Returns true if the stream supports colorization. 87 | * 88 | * Colorization is disabled if not supported by the stream: 89 | * 90 | * - windows without ansicon 91 | * - non tty consoles 92 | * 93 | * @return Boolean true if the stream supports colorization, false otherwise 94 | */ 95 | protected function hasColorSupport() 96 | { 97 | // @codeCoverageIgnoreStart 98 | if (DIRECTORY_SEPARATOR == '\\') { 99 | return false !== getenv('ANSICON'); 100 | } else { 101 | return function_exists('posix_isatty') && @posix_isatty($this->stream); 102 | } 103 | // @codeCoverageIgnoreEnd 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Shell.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console; 13 | 14 | use Symfony\Component\Console\Application; 15 | use Symfony\Component\Console\Input\StringInput; 16 | use Symfony\Component\Console\Output\ConsoleOutput; 17 | 18 | /** 19 | * A Shell wraps an Application to add shell capabilities to it. 20 | * 21 | * This class only works with a PHP compiled with readline support 22 | * (either --with-readline or --with-libedit) 23 | * 24 | * @author Fabien Potencier 25 | */ 26 | class Shell 27 | { 28 | protected $application; 29 | protected $history; 30 | protected $output; 31 | 32 | /** 33 | * Constructor. 34 | * 35 | * If there is no readline support for the current PHP executable 36 | * a \RuntimeException exception is thrown. 37 | * 38 | * @param Application $application An application instance 39 | * 40 | * @throws \RuntimeException When Readline extension is not enabled 41 | */ 42 | public function __construct(Application $application) 43 | { 44 | if (!function_exists('readline')) { 45 | throw new \RuntimeException('Unable to start the shell as the Readline extension is not enabled.'); 46 | } 47 | 48 | $this->application = $application; 49 | $this->history = getenv('HOME').'/.history_'.$application->getName(); 50 | $this->output = new ConsoleOutput(); 51 | } 52 | 53 | /** 54 | * Runs the shell. 55 | */ 56 | public function run() 57 | { 58 | $this->application->setAutoExit(false); 59 | $this->application->setCatchExceptions(true); 60 | 61 | readline_read_history($this->history); 62 | readline_completion_function(array($this, 'autocompleter')); 63 | 64 | $this->output->writeln($this->getHeader()); 65 | while (true) { 66 | $command = readline($this->application->getName().' > '); 67 | 68 | if (false === $command) { 69 | $this->output->writeln("\n"); 70 | 71 | break; 72 | } 73 | 74 | readline_add_history($command); 75 | readline_write_history($this->history); 76 | 77 | if (0 !== $ret = $this->application->run(new StringInput($command), $this->output)) { 78 | $this->output->writeln(sprintf('The command terminated with an error status (%s)', $ret)); 79 | } 80 | } 81 | } 82 | 83 | /** 84 | * Tries to return autocompletion for the current entered text. 85 | * 86 | * @param string $text The last segment of the entered text 87 | * @param integer $position The current position 88 | */ 89 | protected function autocompleter($text, $position) 90 | { 91 | $info = readline_info(); 92 | $text = substr($info['line_buffer'], 0, $info['end']); 93 | 94 | if ($info['point'] !== $info['end']) { 95 | return true; 96 | } 97 | 98 | // task name? 99 | if (false === strpos($text, ' ') || !$text) { 100 | return array_keys($this->application->all()); 101 | } 102 | 103 | // options and arguments? 104 | try { 105 | $command = $this->application->find(substr($text, 0, strpos($text, ' '))); 106 | } catch (\Exception $e) { 107 | return true; 108 | } 109 | 110 | $list = array('--help'); 111 | foreach ($command->getDefinition()->getOptions() as $option) { 112 | $list[] = '--'.$option->getName(); 113 | } 114 | 115 | return $list; 116 | } 117 | 118 | /** 119 | * Returns the shell header. 120 | * 121 | * @return string The header string 122 | */ 123 | protected function getHeader() 124 | { 125 | return <<{$this->application->getName()} shell ({$this->application->getVersion()}). 128 | 129 | At the prompt, type help for some help, 130 | or list to get a list available commands. 131 | 132 | To exit the shell, type ^D. 133 | 134 | EOF; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Tester/ApplicationTester.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Tester; 13 | 14 | use Symfony\Component\Console\Application; 15 | use Symfony\Component\Console\Input\ArrayInput; 16 | use Symfony\Component\Console\Output\StreamOutput; 17 | 18 | /** 19 | * @author Fabien Potencier 20 | */ 21 | class ApplicationTester 22 | { 23 | protected $application; 24 | protected $display; 25 | protected $input; 26 | protected $output; 27 | 28 | /** 29 | * Constructor. 30 | * 31 | * @param Application $application A Application instance to test. 32 | */ 33 | public function __construct(Application $application) 34 | { 35 | $this->application = $application; 36 | } 37 | 38 | /** 39 | * Executes the application. 40 | * 41 | * Available options: 42 | * 43 | * * interactive: Sets the input interactive flag 44 | * * decorated: Sets the output decorated flag 45 | * * verbosity: Sets the output verbosity flag 46 | * 47 | * @param array $input An array of arguments and options 48 | * @param array $options An array of options 49 | */ 50 | public function run(array $input, $options = array()) 51 | { 52 | $this->input = new ArrayInput($input); 53 | if (isset($options['interactive'])) { 54 | $this->input->setInteractive($options['interactive']); 55 | } 56 | 57 | $this->output = new StreamOutput(fopen('php://memory', 'w', false)); 58 | if (isset($options['decorated'])) { 59 | $this->output->setDecorated($options['decorated']); 60 | } 61 | if (isset($options['verbosity'])) { 62 | $this->output->setVerbosity($options['verbosity']); 63 | } 64 | 65 | $this->application->run($this->input, $this->output); 66 | 67 | rewind($this->output->getStream()); 68 | 69 | return $this->display = stream_get_contents($this->output->getStream()); 70 | } 71 | 72 | /** 73 | * Gets the display returned by the last execution of the application. 74 | * 75 | * @return string The display 76 | */ 77 | public function getDisplay() 78 | { 79 | return $this->display; 80 | } 81 | 82 | /** 83 | * Gets the input instance used by the last execution of the application. 84 | * 85 | * @return InputInterface The current input instance 86 | */ 87 | public function getInput() 88 | { 89 | return $this->input; 90 | } 91 | 92 | /** 93 | * Gets the output instance used by the last execution of the application. 94 | * 95 | * @return OutputInterface The current output instance 96 | */ 97 | public function getOutput() 98 | { 99 | return $this->output; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Symfony/Component/Console/Tester/CommandTester.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Console\Tester; 13 | 14 | use Symfony\Component\Console\Command\Command; 15 | use Symfony\Component\Console\Input\ArrayInput; 16 | use Symfony\Component\Console\Output\StreamOutput; 17 | 18 | /** 19 | * @author Fabien Potencier 20 | */ 21 | class CommandTester 22 | { 23 | protected $command; 24 | protected $display; 25 | protected $input; 26 | protected $output; 27 | 28 | /** 29 | * Constructor. 30 | * 31 | * @param Command $command A Command instance to test. 32 | */ 33 | public function __construct(Command $command) 34 | { 35 | $this->command = $command; 36 | } 37 | 38 | /** 39 | * Executes the command. 40 | * 41 | * Available options: 42 | * 43 | * * interactive: Sets the input interactive flag 44 | * * decorated: Sets the output decorated flag 45 | * * verbosity: Sets the output verbosity flag 46 | * 47 | * @param array $input An array of arguments and options 48 | * @param array $options An array of options 49 | */ 50 | public function execute(array $input, array $options = array()) 51 | { 52 | $this->input = new ArrayInput($input); 53 | if (isset($options['interactive'])) { 54 | $this->input->setInteractive($options['interactive']); 55 | } 56 | 57 | $this->output = new StreamOutput(fopen('php://memory', 'w', false)); 58 | if (isset($options['decorated'])) { 59 | $this->output->setDecorated($options['decorated']); 60 | } 61 | if (isset($options['verbosity'])) { 62 | $this->output->setVerbosity($options['verbosity']); 63 | } 64 | 65 | $this->command->run($this->input, $this->output); 66 | 67 | rewind($this->output->getStream()); 68 | 69 | return $this->display = stream_get_contents($this->output->getStream()); 70 | } 71 | 72 | /** 73 | * Gets the display returned by the last execution of the command. 74 | * 75 | * @return string The display 76 | */ 77 | public function getDisplay() 78 | { 79 | return $this->display; 80 | } 81 | 82 | /** 83 | * Gets the input instance used by the last execution of the command. 84 | * 85 | * @return InputInterface The current input instance 86 | */ 87 | public function getInput() 88 | { 89 | return $this->input; 90 | } 91 | 92 | /** 93 | * Gets the output instance used by the last execution of the command. 94 | * 95 | * @return OutputInterface The current output instance 96 | */ 97 | public function getOutput() 98 | { 99 | return $this->output; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /symfony2project: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 9 | */ 10 | 11 | use Symfony\Component\ClassLoader\UniversalClassLoader; 12 | use Symfony\Component\Console\Application; 13 | use Symfony\Component\Console\Input\ArgvInput; 14 | use Symfony\Component\Console\Output\ConsoleOutput; 15 | use Symfony\Component\Console\Input\StringInput; 16 | use Command\GenerateProjectCommand; 17 | 18 | $loader = new UniversalClassLoader(); 19 | $loader->registerNamespaces(array( 20 | 'Command' => __DIR__, 21 | 'Symfony' => __DIR__, 22 | 'Installer' => __DIR__, 23 | )); 24 | $loader->register(); 25 | 26 | $application = new Application('symfony2project', '1.0'); 27 | $application->add(new GenerateProjectCommand()); 28 | $application->run(); 29 | --------------------------------------------------------------------------------