Update Composer, update everything

This commit is contained in:
Oliver Davies 2018-11-23 12:29:20 +00:00
parent ea3e94409f
commit dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions

26
vendor/drupal/console-core/.gitignore vendored Normal file
View file

@ -0,0 +1,26 @@
# deprecation-detector
/.rules
# Composer
composer.lock
/vendor
/bin/phpunit
/bin/jsonlint
/bin/phpcbf
/bin/phpcs
/bin/validate-json
/bin/pdepend
/bin/php-cs-fixer
/bin/phpmd
# Binaries
/box.phar
/console.phar
/drupal.phar
/drupal.phar.version
# Test
/phpunit.xml
# Drupal
/core

10
vendor/drupal/console-core/.php_cs vendored Normal file
View file

@ -0,0 +1,10 @@
<?php
return PhpCsFixer\Config::create()
->setRules(
[
'@PSR2' => true,
'array_syntax' => ['syntax' => 'short'],
]
)
->setUsingCache(false);

3
vendor/drupal/console-core/README.md vendored Normal file
View file

@ -0,0 +1,3 @@
# Drupal Console Core
Drupal Console Core, this project contains commands and features to be shared across DrupalConsole projects.

View file

@ -0,0 +1,65 @@
{
"name": "drupal/console-core",
"description": "Drupal Console Core",
"keywords": ["Drupal", "Console", "Development", "Symfony"],
"homepage": "http://drupalconsole.com/",
"type": "library",
"license": "GPL-2.0-or-later",
"authors": [
{
"name": "David Flores",
"email": "dmousex@gmail.com",
"homepage": "http://dmouse.net"
},
{
"name": "Jesus Manuel Olivas",
"email": "jesus.olivas@gmail.com",
"homepage": "http://jmolivas.com"
},
{
"name": "Eduardo Garcia",
"email": "enzo@enzolutions.com",
"homepage": "http://enzolutions.com/"
},
{
"name": "Omar Aguirre",
"email": "omersguchigu@gmail.com"
},
{
"name": "Drupal Console Contributors",
"homepage": "https://github.com/hechoendrupal/DrupalConsole/graphs/contributors"
}
],
"support": {
"issues": "https://github.com/hechoendrupal/DrupalConsole/issues",
"forum": "https://gitter.im/hechoendrupal/DrupalConsole",
"docs": "http://docs.drupalconsole.com/"
},
"require": {
"php": "^5.5.9 || ^7.0",
"dflydev/dot-access-configuration": "^1.0",
"drupal/console-en": "1.8.0",
"stecman/symfony-console-completion": "~0.7",
"symfony/config": "~2.8|~3.0",
"symfony/console": "~2.8|~3.0",
"symfony/debug": "~2.8|~3.0",
"symfony/dependency-injection": "~2.8|~3.0",
"symfony/event-dispatcher": "~2.8|~3.0",
"symfony/filesystem": "~2.8|~3.0",
"symfony/finder": "~2.8|~3.0",
"symfony/process": "~2.8|~3.0",
"symfony/translation": "~2.8|~3.0",
"symfony/yaml": "~2.8|~3.0",
"twig/twig": "^1.23.1",
"webflo/drupal-finder": "^1.0",
"webmozart/path-util": "^2.3"
},
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {"Drupal\\Console\\Core\\": "src"}
}
}

View file

@ -0,0 +1,44 @@
aliases:
debug:container:
- cod
config:edit:
- cdit
cron:execute:
- cre
database:connect:
- sqlc
database:query:
- sqlq
debug:database:log:
- ws
debug:multisite:
- msd
debug:router:
- rod
debug:theme:
- tde
debug:update:
- upd
multisite:new:
- sn
router:rebuild:
- ror
site:status:
- st
user:login:clear:attempts:
- uslca
user:login:url:
- usli
- uli
user:password:hash:
- usph
user:password:reset:
- upsr
views:disable:
- vdi
cache:rebuild:
- cc
update:execute:
- updb
server:
- rs

View file

@ -0,0 +1,23 @@
# How to use
# develop:contribute --drupal=/path/to/drupal-directory --code=/path/to/code-directory
command:
name: develop:contribute
description: 'Download Drupal + Drupal Console to contribute.'
vars:
repository: drupal-composer/drupal-project:8.x-dev
commands:
- command: exec
arguments:
bin: composer create-project {{repository}} {{drupal}} --prefer-dist --no-progress --no-interaction --no-install
- command: exec
arguments:
bin: composer require drupal/console-develop --dev --working-dir={{drupal}} --no-update
- command: exec
arguments:
bin: composer install --working-dir={{drupal}}
- command: exec
arguments:
bin: drupal site:install standard --root={{drupal}} --db-type="sqlite" --no-interaction
- command: exec
arguments:
bin: drupal develop:create:symlinks --code-directory={{code}} --root={{drupal}}

View file

@ -0,0 +1,27 @@
# How to use
# quick:start --directory=/path/to/drupal-project/
# quick:start --directory=/path/to/drupal-project/ --profile=minimal
# quick:start --repository=weknowinc/drupal-project --directory=/path/to/drupal-project/ --profile=standard
command:
name: quick:start
description: 'Download, install and serve a new Drupal project'
vars:
repository:
- weknowinc/drupal-project
- drupal-composer/drupal-project:8.x-dev
- acquia/lightning-project
- acquia/reservoir-project
profile: standard
commands:
# Create Drupal project using DrupalComposer
- command: exec
arguments:
bin: composer create-project {{repository}} {{directory}} --prefer-dist --no-progress --no-interaction
# Install Drupal
- command: exec
arguments:
bin: drupal site:install {{profile}} --root={{directory}} --db-type="sqlite" --no-interaction
# Start PHP built-in server
- command: exec
arguments:
bin: drupal server --root={{directory}}

View file

@ -0,0 +1,18 @@
# How to use
# site:new --directory=/path/to/drupal-project/
# site:new --repository=weknowinc/drupal-project --directory=/path/to/drupal-project/
command:
name: site:new
description: 'Download a new Drupal project'
vars:
repository:
- weknowinc/drupal-project
- drupal-composer/drupal-project:8.x-dev
- acquia/lightning-project
- acquia/reservoir-project
- drupal/drupal
commands:
# Create Drupal project using Composer
- command: exec
arguments:
bin: composer create-project {{repository}} {{directory}} --prefer-dist --no-progress --no-interaction

View file

@ -0,0 +1,37 @@
application:
language: 'en'
autowire:
commands:
forced:
_completion:
class: '\Stecman\Component\Symfony\Console\BashCompletion\CompletionCommand'
name:
elephpant:
class: '\Drupal\Console\Core\Command\Exclude\ElephpantCommand'
arguments: ['@app.root', '@console.renderer', '@console.configuration_manager']
druplicon:
class: '\Drupal\Console\Core\Command\Exclude\DrupliconCommand'
arguments: ['@app.root', '@console.renderer', '@console.configuration_manager']
commands:
aliases: ~
defaults: ~
mappings: ~
languages:
en: 'English'
es: 'Español'
ca: 'Català'
fr: 'Français'
ko: '한국어'
hi: 'हिन्दी'
hu: 'Magyar'
id: 'Bahasa Indonesia'
ja: '日本語'
mr: 'मराठी'
pa: 'ਪੰਜਾਬੀ'
pt-br: 'Português'
ro: 'Romanian'
ru: 'pусский язык'
tl: 'Tagalog'
vn: 'Tiếng Việt'
zh-hans: '简体中文'
zh-hant: '繁體中文'

View file

@ -0,0 +1,116 @@
commands:
config:
config-delete: 'config:delete'
config-edit: 'config:edit'
config-export: 'config:export'
config-get: 'debug:config CONFIG_NAME'
config-import: 'config:import'
config-list: 'debug:config'
config-pull: ~
config-set: 'config:override'
core:
archive-dump: ~
archive-restore: ~
core-cli: 'shell'
core-config: ~
core-cron: 'cron:execute'
core-execute: 'exec'
core-init: 'init'
core-quick-drupal: 'quick:start'
core-requirements: 'site:status'
core-rsync: ~
core-status: 'site:status'
core-topic: ~
drupal-directory: ~
entity-updates: 'update:entities'
help: 'help'
image-derive: ~
image-flush: 'image:styles:flush'
php-eval: ~
php-script: ~
queue-list: 'debug:queue'
queue-run: 'queue:run'
shell-alias: ~
site-alias: 'debug:site'
site-install: 'site:install'
site-set: ~
site-ssh: ~
twig-compile: ~
updatedb: 'update:execute'
updatedb-status: 'debug:update'
version: '--version'
field:
field-clone: ~
field-create: ~
field-delete: ~
field-info: 'field:info'
field-update: ~
language:
language-add: 'locale:language:add'
language-disable: 'locale:language:delete'
make:
make: ~
make-convert: ~
make-generate: ~
make-lock: ~
make-update: ~
other:
registry-rebuild: 'cache:rebuild all'
pm:
pm-disable: 'module:uninstall, theme:uninstall'
pm-download: 'module:download, theme:download'
pm-enable: 'module:install, theme:install'
pm-info: ~
pm-list: 'debug:module, debug:theme'
pm-projectinfo: ~
pm-refresh: ~
pm-releasenotes: ~
pm-releases: ~
pm-uninstall: 'module:uninstall, theme:uninstall'
pm-update: 'module:update, theme:update'
pm-updatecode: ~
pm-updatestatus: ~
role:
role-add-perm: ~
role-create: ~
role-delete: ~
role-list: ~
role-remove-perm: ~
runserver:
runserver: 'server'
sql:
sql-cli: 'database:client'
sql-connect: 'database:connect'
sql-create: ~
sql-drop: 'database:drop'
sql-dump: 'database:dump'
sql-query: 'database:query'
sql-sanitize: ~
sql-sync: ~
search:
search-index: ~
search-reindex: ~
search-status: ~
site_audit:
cache-clear: 'cache:rebuild'
cache-get: ~
cache-rebuild: 'cache:rebuild'
cache-set: ~
state:
state-delete: 'state:delete'
state-get: 'debug:state'
state-set: 'state:override'
user:
user-add-role: 'user:role'
user-block: ~
user-cancel: ~
user-create: 'user:create'
user-information: ~
user-login: 'user:login:url'
user-password: 'user:password:reset'
user-remove-role: 'user:role'
user-unblock: ~
watchdog:
watchdog-delete: 'database:log:clear'
watchdog-list: 'database:log:poll'
watchdog-show: 'debug:database:log'

View file

@ -0,0 +1,29 @@
mappings:
breakpoints:debug: debug:breakpoints
cache:context:debug: debug:cache:context
chain:debug: debug:chain
config:debug: debug:config
config:settings:debug: debug:config:settings
config:validate:debug: debug:config:validate
container:debug: debug:container
cron:debug: debug:cron
database:log:debug: debug:database:log
database:table:debug: debug:database:table
entity:debug: debug:entity
event:debug: debug:event
image:styles:debug: debug:image:styles
libraries:debug: debug:libraries
module:debug: debug:module
multisite:debug: debug:multisite
permission:debug: debug:permission
plugin:debug: debug:plugin
queue:debug: debug:queue
router:debug: debug:router
settings:debug: debug:settings
site:debug: debug:site
state:debug: debug:state
theme:debug: debug:theme
update:debug: debug:update
user:debug: debug:user
views:debug: debug:views
views:plugins:debug: debug:views:plugins

View file

@ -0,0 +1,25 @@
requirements:
php:
required: 5.5.9
configurations:
required:
- date.timezone: 'America/Tijuana'
- memory_limit: 1024M
recomended: {}
extensions:
required:
- date
- dom
- filter
- gd
- hash
- json
- pcre
- pdo
- session
- SimpleXML
- SPL
- tokenizer
- xml
- curl
recommended: {}

View file

@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/*
* This file implements rewrite rules for PHP built-in web server.
*
* See: http://www.php.net/manual/en/features.commandline.webserver.php
*
* If you have custom directory layout, then you have to write your own router
* and pass it as a value to 'router' option of server:run command.
*
* @author: Michał Pipa <michal.pipa.xsolve@gmail.com>
* @author: Albert Jessurum <ajessu@gmail.com>
*/
// Workaround https://bugs.php.net/64566
if (ini_get('auto_prepend_file') && !in_array(realpath(ini_get('auto_prepend_file')), get_included_files(), true)) {
include ini_get('auto_prepend_file');
}
if (is_file($_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.$_SERVER['SCRIPT_NAME'])) {
return false;
}
$_SERVER = array_merge($_SERVER, $_ENV);
$_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.'index.php';
// Since we are rewriting to index.php, adjust SCRIPT_NAME and PHP_SELF accordingly
$_SERVER['SCRIPT_NAME'] = DIRECTORY_SEPARATOR.'index.php';
$_SERVER['PHP_SELF'] = DIRECTORY_SEPARATOR.'index.php';
require 'index.php';

View file

@ -0,0 +1,45 @@
configurations:
system.performance:
cache.page.use_internal:
dev: false
prod: true
css.preprocess:
dev: false
prod: true
css.gzip:
dev: false
prod: true
js.preprocess:
dev: false
prod: true
js.gzip:
dev: false
prod: true
response.gzip:
dev: false
prod: true
views.settings:
ui.show.sql_query.enabled:
dev: true
prod: false
ui.show.performance_statistics:
dev: true
prod: false
system.logging:
error_level:
dev: all
prod: none
services:
http.response.debug_cacheability_headers:
dev: true
prod: false
twig.config:
debug:
dev: true
prod: false
auto_reload:
dev: true
prod: false
cache:
dev: true
prod: true

View file

@ -0,0 +1,13 @@
command:
name: build:install
description: 'Build site by installing and importing configuration'
commands:
# Install site
- command: site:install
options:
force: true
no-interaction: true
arguments:
profile: standard
# Import configuration
- command: build

View file

@ -0,0 +1,10 @@
command:
name: build
description: 'Build site'
commands:
# Import configuration
- command: config:import
# Rebuild caches.
- command: cache:rebuild
arguments:
cache: all

View file

@ -0,0 +1,17 @@
command:
name: create:data
description: 'Create dummy data'
commands:
# Create dummy data
- command: create:users
options:
limit: 5
- command: create:vocabularies
options:
limit: 5
name-words: 5
learning: true
- command: create:terms
- command: create:nodes
options:
limit: 50

View file

@ -0,0 +1,38 @@
command:
name: generate:example:form
description: 'Generate form example'
commands:
- command: generate:form:config
options:
module: example
class: ConfigForm
form-id: config_form
services:
- state
inputs:
- name: email
type: email
label: Email
description: 'Enter a valid email.'
fieldset: ''
- name: api_key
type: textfield
label: 'API Key'
description: 'Enter API Key'
maxlength: '64'
size: '64'
- name: number_field
type: number
label: 'Number field'
description: 'Enter a valid number.'
- name: big_text
type: textarea
label: 'Big text'
description: 'Enter a big text, you can user <enter> key'
path: '/admin/config/form'
menu_link_gen: true
menu_link_title: 'Example Config Form'
menu_parent: system.admin_config_system
menu_link_desc: 'A Example Config Form.'
# Rebuild routes
- command: router:rebuild

View file

@ -0,0 +1,113 @@
command:
name: generate:example:module
description: 'Generate example module'
commands:
- command: generate:module
options:
module: Example module
machine-name: example
module-path: /modules/custom/
description: My example module
core: 8.x
package: Custom
dependencies:
- command: generate:controller
options:
module: example
class: HelloWorldController
routes:
- title: 'Hello World'
name: 'example.hello_name'
method: hello
path: '/example/hello/{name}'
services:
- entity_field.manager
- theme_handler
- config.factory
test: true
- command: generate:form:config
options:
module: example
class: SettingsForm
form-id: settings_form
inputs:
- name: foo_field
type: textfield
label: 'Foo field'
options: ''
description: ''
maxlength: '64'
size: '64'
default_value: ''
weight: '0'
fieldset: ''
- name: bar_number
type: number
label: 'Bar number'
options: ''
description: ''
maxlength: null
size: null
default_value: ''
weight: '0'
fieldset: ''
path: '/admin/setting/form'
menu_link_gen: true
menu_link_title: SettingsForm
menu_parent: system.admin_config_system
menu_link_desc: 'A description for the menu entry'
- command: generate:entity:content
options:
module: example
entity-class: Foo
entity-name: foo
label: Foo
- command: generate:entity:config
options:
module: example
entity-class: Bar
entity-name: bar
label: Bar
- command: generate:command
options:
module: example
class: ExampleCommand
name: example:command
container-aware: false
- command: generate:authentication:provider
options:
module: example
class: ExampleAuthenticationProvider
- command: generate:plugin:block
options:
module: example
class: ExampleBlock
label: Example plugin block
plugin-id: example_block
- command: generate:plugin:imageeffect
options:
module: example
class: ExampleImageEffect
plugin-id: example_image_effect
label: Example image effect
description: Example image effect
- command: generate:plugin:rest:resource
options:
module: example
class: ExampleRestResource
plugin-id: example_rest_resource
plugin-label: Example Rest Resource
plugin-url: example_rest_resource
plugin-states:
- GET
- PUT
- POST
- command: generate:service
options:
module: example
class: ExampleService
name: example.service
interface: yes
- command: module:install
arguments:
module: [example]

View file

@ -0,0 +1,21 @@
command:
name: site:install:env
description: 'Install site using environment placeholders'
commands:
# Install Drupal
- command: site:install
options:
langcode: en
db-type: '{{ env("DATABASE_TYPE") }}'
db-host: '{{ env("DATABASE_HOST") }}'
db-name: '{{ env("DATABASE_NAME") }}'
db-user: '{{ env("DATABASE_USER") }}'
db-pass: '{{ env("DATABASE_PASSWORD") }}'
db-port: '{{ env("DATABASE_PORT") }}'
site-name: 'Drupal 8 site'
site-mail: admin@example.org # default email
account-name: admin # default account
account-mail: admin@example.org # default email
account-pass: admin # default pass
arguments:
profile: 'standard'

View file

@ -0,0 +1,26 @@
command:
name: site:install:inline
description: 'Install site using inline placeholders'
vars:
db_type: mysql
db_host: 127.0.0.1
db_name: drupal
db_port: 3306
commands:
# Install Drupal
- command: site:install
options:
langcode: 'en'
db-type: '{{db_type}}'
db-host: '{{db_host}}'
db-name: '{{db_name}}'
db-user: '{{db_user}}'
db-pass: '{{db_pass}}'
db-port: '{{db_port}}'
site-name: 'Drupal 8 site'
site-mail: 'admin@example.org' # default email
account-name: 'admin' # default account
account-mail: 'admin@example.org' # default email
account-pass: 'admin' # default pass
arguments:
profile: 'standard'

View file

@ -0,0 +1,17 @@
command:
name: site:install:sqlite
description: 'Install site using sqlite'
commands:
# Install Drupal
- command: site:install
options:
langcode: en
db-type: sqlite
db-file: sites/default/files/.ht.sqlite
site-name: 'Drupal 8 Quick Start'
site-mail: admin@example.com
account-name: admin
account-mail: admin@example.com
account-pass: admin
arguments:
profile: standard

View file

@ -0,0 +1,20 @@
command:
name: site:update
description: 'Execute update commands'
commands:
# Backup current database
- command: database:dump
arguments:
database: 'default'
# Import configurations
- command: config:import
# Run pending update hooks
- command: update:execute
arguments:
module: 'all'
# Run pending update entities
- command: update:entities
# Rebuild caches
- command: cache:rebuild
arguments:
cache: 'all'

View file

@ -0,0 +1,20 @@
# How to use
# update:command:data --directory="/path/to/drupal-project/"
command:
name: update:command:data
description: 'Update gitbook'
commands:
{% set languages = ['en', 'es', 'hi', 'hu', 'pt_br', 'ro', 'vn', 'zh_hans'] %}
{% for language in languages %}
- command: settings:set
arguments:
name: language
value: {{ language }}
- command: generate:doc:data
options:
file: '{{ directory }}/{{ language }}.json'
{% endfor %}
- command: settings:set
arguments:
name: language
value: en

View file

@ -0,0 +1,32 @@
# How to use
# update:gitbook --directory="/path/to/drupal-project/"
command:
name: update:gitbook
description: 'Update gitbook'
commands:
- command: 'module:install'
arguments:
module:
- rest
- taxonomy
- locale
- migrate
- simpletest
- breakpoint
- node
- views
- features
{% set languages = ['en', 'es', 'hi', 'hu', 'pt_br', 'ro', 'vn', 'zh_hans'] %}
{% for language in languages %}
- command: settings:set
arguments:
name: language
value: {{ language }}
- command: develop:doc:gitbook
options:
path: '{{ directory }}/{{ language }}'
{% endfor %}
- command: settings:set
arguments:
name: language
value: en

View file

@ -0,0 +1,14 @@
#defaults:
# cache:
# rebuild:
# arguments:
# cache: all
# config:
# export:
# options:
# remove-uuid: true
# remove-config-hash: true
# generate:
# controller:
# options:
# module: example

View file

@ -0,0 +1,5 @@
# Drupal4Docker example
dev:
root: /var/www/html
extra-options: docker-compose exec --user=82 php
type: container

View file

@ -0,0 +1,3 @@
local:
root: /var/www/drupal8.dev
type: local

View file

@ -0,0 +1,5 @@
dev:
root: /var/www/html/drupal
host: drupal.org
user: drupal
type: ssh

View file

@ -0,0 +1,7 @@
# DrupalVM Example
dev:
root: /var/www/drupalvm/drupal
host: 192.168.88.88
user: vagrant
extra-options: '-o PasswordAuthentication=no -i ~/.vagrant.d/insecure_private_key'
type: ssh

69
vendor/drupal/console-core/phpqa.yml vendored Normal file
View file

@ -0,0 +1,69 @@
application:
method:
git:
enabled: true
exception: false
composer:
enabled: true
exception: false
analyzer:
parallel-lint:
enabled: true
exception: true
options:
e: 'php'
exclude: vendor/
arguments:
php-cs-fixer:
enabled: true
exception: false
options:
level: psr2
arguments:
prefixes:
- fix
postfixes:
phpcbf:
enabled: true
exception: false
options:
standard: PSR2
severity: 0
ignore: /vendor
arguments:
- '-n'
phpcs:
enabled: false
exception: false
options:
standard: PSR2
severity: 0
ignore: /vendor
arguments:
- '-n'
phpmd:
enabled: false
exception: false
options:
arguments:
prefixes:
postfixes:
- 'text'
- 'cleancode'
phploc:
enabled: false
exception: false
phpcpd:
enabled: false
exception: false
phpdcd:
enabled: false
exception: false
phpunit:
enabled: false
exception: true
file:
configuration: phpunit.xml.dist
single-execution: true
options:
arguments:

113
vendor/drupal/console-core/services.yml vendored Normal file
View file

@ -0,0 +1,113 @@
services:
# DrupalConsoleCore Services
console.translator_manager:
class: Drupal\Console\Core\Utils\TranslatorManager
console.configuration_manager:
class: Drupal\Console\Core\Utils\ConfigurationManager
console.requirement_checker:
class: Drupal\Console\Core\Utils\RequirementChecker
console.chain_queue:
class: Drupal\Console\Core\Utils\ChainQueue
console.nested_array:
class: Drupal\Console\Core\Utils\NestedArray
console.show_file:
class: Drupal\Console\Core\Utils\ShowFile
arguments: ['@app.root', '@console.translator_manager']
console.renderer:
class: Drupal\Console\Core\Utils\TwigRenderer
arguments: ['@console.translator_manager', '@console.string_converter']
console.file_queue:
class: Drupal\Console\Core\Utils\FileQueue
arguments: ['@app.root']
console.shell_process:
class: Drupal\Console\Core\Utils\ShellProcess
arguments: ['@app.root', '@console.translator_manager']
console.string_converter:
class: Drupal\Console\Core\Utils\StringConverter
console.chain_discovery:
class: Drupal\Console\Core\Utils\ChainDiscovery
arguments: ['@console.root', '@console.configuration_manager', '@console.message_manager', '@console.translator_manager']
console.count_code_lines:
class: Drupal\Console\Core\Utils\CountCodeLines
console.message_manager:
class: Drupal\Console\Core\Utils\MessageManager
console.drupal_finder:
class: Drupal\Console\Core\Utils\DrupalFinder
console.key_value_storage:
class: Drupal\Console\Core\Utils\KeyValueStorage
# DrupalConsoleCore Commands
console.about:
class: Drupal\Console\Core\Command\AboutCommand
tags:
- { name: drupal.command }
console.list:
class: Drupal\Console\Core\Command\ListCommand
tags:
- { name: drupal.command }
console.help:
class: Drupal\Console\Core\Command\HelpCommand
tags:
- { name: drupal.command }
console.complete:
class: Drupal\Console\Core\Command\CompleteCommand
tags:
- { name: drupal.command }
console.check:
class: Drupal\Console\Core\Command\CheckCommand
arguments: ['@console.requirement_checker', '@console.chain_queue', '@console.configuration_manager']
tags:
- { name: drupal.command }
console.init:
class: Drupal\Console\Core\Command\InitCommand
arguments: ['@console.show_file', '@console.configuration_manager', '@console.init_generator', '@app.root', '@?console.root']
tags:
- { name: drupal.command }
console.settings_debug:
class: Drupal\Console\Core\Command\Debug\SettingsCommand
arguments: ['@console.configuration_manager']
tags:
- { name: drupal.command }
console.settings_set:
class: Drupal\Console\Core\Command\Settings\SetCommand
arguments: ['@console.configuration_manager', '@console.nested_array']
tags:
- { name: drupal.command }
console.exec:
class: Drupal\Console\Core\Command\Exec\ExecCommand
arguments: ['@console.shell_process']
tags:
- { name: drupal.command }
console.chain:
class: Drupal\Console\Core\Command\Chain\ChainCommand
arguments: ['@console.chain_queue', '@console.chain_discovery']
tags:
- { name: drupal.command }
console.chain_debug:
class: Drupal\Console\Core\Command\Debug\ChainCommand
arguments: ['@console.chain_discovery']
tags:
- { name: drupal.command }
console.site_debug:
class: Drupal\Console\Core\Command\Debug\SiteCommand
arguments: ['@console.configuration_manager']
tags:
- { name: drupal.command }
console.drush:
class: Drupal\Console\Core\Command\DrushCommand
arguments: ['@console.configuration_manager', '@console.chain_queue']
tags:
- { name: drupal.command }
console.generate_site_alias:
class: Drupal\Console\Core\Command\Generate\SiteAliasCommand
arguments: ['@console.site_alias_generator', '@console.configuration_manager', '@console.drupal_finder']
tags:
- { name: drupal.command }
# DrupalConsoleCore Generators
console.init_generator:
class: Drupal\Console\Core\Generator\InitGenerator
tags:
- { name: drupal.generator }
console.site_alias_generator:
class: Drupal\Console\Core\Generator\SiteAliasGenerator
tags:
- { name: drupal.generator }

View file

@ -0,0 +1,911 @@
<?php
namespace Drupal\Console\Core;
use Drupal\Console\Core\EventSubscriber\RemoveMessagesListener;
use Drupal\Console\Core\EventSubscriber\ShowGenerateCountCodeLinesListener;
use Drupal\Console\Core\Utils\TranslatorManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Application as BaseApplication;
use Symfony\Component\Console\Input\ArrayInput;
use Drupal\Console\Core\EventSubscriber\DefaultValueEventListener;
use Drupal\Console\Core\EventSubscriber\ShowGenerateChainListener;
use Drupal\Console\Core\EventSubscriber\ShowTipsListener;
use Drupal\Console\Core\EventSubscriber\ShowWelcomeMessageListener;
use Drupal\Console\Core\EventSubscriber\ValidateExecutionListener;
use Drupal\Console\Core\EventSubscriber\ShowGeneratedFilesListener;
use Drupal\Console\Core\EventSubscriber\ShowGenerateInlineListener;
use Drupal\Console\Core\EventSubscriber\CallCommandListener;
use Drupal\Console\Core\Utils\ConfigurationManager;
use Drupal\Console\Core\Style\DrupalStyle;
use Drupal\Console\Core\Utils\ChainDiscovery;
use Drupal\Console\Core\Command\Chain\ChainCustomCommand;
use Drupal\Console\Core\Bootstrap\DrupalInterface;
/**
* Class Application
*
* @package Drupal\Console
*/
class Application extends BaseApplication
{
/**
* @var ContainerInterface
*/
protected $container;
/**
* @var string
*/
protected $commandName;
/**
* @var DrupalInterface
*/
protected $drupal;
/**
* @var bool
*/
protected $eventRegistered;
/**
* ConsoleApplication constructor.
*
* @param ContainerInterface $container
* @param string $name
* @param string $version
*/
public function __construct(
ContainerInterface $container,
$name,
$version
) {
$this->container = $container;
$this->eventRegistered = false;
parent::__construct($name, $version);
$this->addOptions();
}
/**
* @return TranslatorManagerInterface
*/
public function getTranslator()
{
if ($this->container) {
return $this->container->get('console.translator_manager');
}
return null;
}
/**
* @param $key string
*
* @return string
*/
public function trans($key)
{
if ($this->getTranslator()) {
return $this->getTranslator()->trans($key);
}
return null;
}
/**
* {@inheritdoc}
*/
public function doRun(InputInterface $input, OutputInterface $output)
{
$io = new DrupalStyle($input, $output);
$messageManager = $this->container->get('console.message_manager');
$this->commandName = $this->getCommandName($input)?:'list';
$clear = $this->container->get('console.configuration_manager')
->getConfiguration()
->get('application.clear')?:false;
if ($clear === true || $clear === 'true') {
$output->write(sprintf("\033\143"));
}
$this->loadCommands();
/**
* @var ConfigurationManager $configurationManager
*/
$configurationManager = $this->container
->get('console.configuration_manager');
if (!$this->has($this->commandName)) {
$isValidCommand = false;
$config = $configurationManager->getConfiguration();
$mappings = $config->get('application.commands.mappings');
if (array_key_exists($this->commandName, $mappings)) {
$commandNameMap = $mappings[$this->commandName];
$messageManager->warning(
sprintf(
$this->trans('application.errors.renamed-command'),
$this->commandName,
$commandNameMap
)
);
$this->add(
$this->find($commandNameMap)->setAliases([$this->commandName])
);
$isValidCommand = true;
}
$drushCommand = $configurationManager->readDrushEquivalents($this->commandName);
if ($drushCommand) {
$this->add(
$this->find($drushCommand)->setAliases([$this->commandName])
);
$isValidCommand = true;
$messageManager->warning(
sprintf(
$this->trans('application.errors.drush-command'),
$this->commandName,
$drushCommand
)
);
}
$namespaces = $this->getNamespaces();
if (in_array($this->commandName, $namespaces)) {
$input = new ArrayInput(
[
'command' => 'list',
'namespace' => $this->commandName
]
);
$this->commandName = 'list';
$isValidCommand = true;
}
if (!$isValidCommand) {
$io->error(
sprintf(
$this->trans('application.errors.invalid-command'),
$this->commandName
)
);
return 1;
}
}
$code = parent::doRun(
$input,
$output
);
// Propagate Drupal messages.
$this->addDrupalMessages($messageManager);
if ($this->showMessages($input)) {
$messages = $messageManager->getMessages();
foreach ($messages as $message) {
$showBy = $message['showBy'];
if ($showBy!=='all' && $showBy!==$this->commandName) {
continue;
}
$type = $message['type'];
$io->$type($message['message']);
}
}
return $code;
}
public function loadCommands()
{
$this->registerGenerators();
$this->registerCommands();
$this->registerEvents();
$this->registerExtendCommands();
/**
* @var ConfigurationManager $configurationManager
*/
$configurationManager = $this->container
->get('console.configuration_manager');
$config = $configurationManager->getConfiguration()
->get('application.extras.config')?:'true';
if ($config === 'true') {
$this->registerCommandsFromAutoWireConfiguration();
}
$chains = $configurationManager->getConfiguration()
->get('application.extras.chains')?:'true';
if ($chains === 'true') {
$this->registerChainCommands();
}
}
/**
* @param InputInterface $input
*
* @return bool
*/
private function showMessages(InputInterface $input)
{
$format = $input->hasOption('format')?$input->getOption('format'):'txt';
if ($format !== 'txt') {
return false;
}
return true;
}
/**
* registerEvents
*/
private function registerEvents()
{
if (!$this->eventRegistered) {
$dispatcher = new EventDispatcher();
$dispatcher->addSubscriber(
new ValidateExecutionListener(
$this->container->get('console.translator_manager'),
$this->container->get('console.configuration_manager')
)
);
$dispatcher->addSubscriber(
new ShowWelcomeMessageListener(
$this->container->get('console.translator_manager')
)
);
$dispatcher->addSubscriber(
new DefaultValueEventListener(
$this->container->get('console.configuration_manager')
)
);
$dispatcher->addSubscriber(
new ShowTipsListener(
$this->container->get('console.translator_manager')
)
);
$dispatcher->addSubscriber(
new CallCommandListener(
$this->container->get('console.chain_queue')
)
);
$dispatcher->addSubscriber(
new ShowGeneratedFilesListener(
$this->container->get('console.file_queue'),
$this->container->get('console.show_file')
)
);
$dispatcher->addSubscriber(
new ShowGenerateInlineListener(
$this->container->get('console.translator_manager')
)
);
$dispatcher->addSubscriber(
new ShowGenerateChainListener(
$this->container->get('console.translator_manager')
)
);
$dispatcher->addSubscriber(
new ShowGenerateCountCodeLinesListener(
$this->container->get('console.translator_manager'),
$this->container->get('console.count_code_lines')
)
);
$dispatcher->addSubscriber(
new RemoveMessagesListener(
$this->container->get('console.message_manager')
)
);
$this->setDispatcher($dispatcher);
$this->eventRegistered = true;
}
}
/**
* addOptions
*/
private function addOptions()
{
// Get the configuration from config.yml.
$env = $this->container
->get('console.configuration_manager')
->getConfiguration()
->get('application.environment');
$this->getDefinition()->addOption(
new InputOption(
'--env',
'-e',
InputOption::VALUE_OPTIONAL,
$this->trans('application.options.env'),
!empty($env) ? $env : 'prod'
)
);
$this->getDefinition()->addOption(
new InputOption(
'--root',
null,
InputOption::VALUE_OPTIONAL,
$this->trans('application.options.root')
)
);
$this->getDefinition()->addOption(
new InputOption(
'--debug',
null,
InputOption::VALUE_NONE,
$this->trans('application.options.debug')
)
);
$this->getDefinition()->addOption(
new InputOption(
'--learning',
null,
InputOption::VALUE_NONE,
$this->trans('application.options.learning')
)
);
$this->getDefinition()->addOption(
new InputOption(
'--generate-chain',
'-c',
InputOption::VALUE_NONE,
$this->trans('application.options.generate-chain')
)
);
$this->getDefinition()->addOption(
new InputOption(
'--generate-inline',
'-i',
InputOption::VALUE_NONE,
$this->trans('application.options.generate-inline')
)
);
$this->getDefinition()->addOption(
new InputOption(
'--generate-doc',
'-d',
InputOption::VALUE_NONE,
$this->trans('application.options.generate-doc')
)
);
$this->getDefinition()->addOption(
new InputOption(
'--target',
'-t',
InputOption::VALUE_OPTIONAL,
$this->trans('application.options.target')
)
);
$this->getDefinition()->addOption(
new InputOption(
'--uri',
'-l',
InputOption::VALUE_REQUIRED,
$this->trans('application.options.uri')
)
);
$this->getDefinition()->addOption(
new InputOption(
'--yes',
'-y',
InputOption::VALUE_NONE,
$this->trans('application.options.yes')
)
);
}
/**
* registerCommands
*/
private function registerCommands()
{
$consoleCommands = $this->container
->findTaggedServiceIds('drupal.command');
$aliases = $this->container->get('console.configuration_manager')
->getConfiguration()
->get('application.commands.aliases')?:[];
$invalidCommands = [];
if ($this->container->has('console.key_value_storage')) {
$invalidCommands = $this->container
->get('console.key_value_storage')
->get('invalid_commands', []);
}
foreach ($consoleCommands as $name => $tags) {
if (in_array($name, $invalidCommands)) {
continue;
}
if (!$this->container->has($name)) {
continue;
}
try {
$command = $this->container->get($name);
} catch (\Exception $e) {
echo $name . ' - ' . $e->getMessage() . PHP_EOL;
continue;
}
if (!$command) {
continue;
}
if (method_exists($command, 'setTranslator')) {
$command->setTranslator(
$this->container->get('console.translator_manager')
);
}
if (method_exists($command, 'setContainer')) {
$command->setContainer(
$this->container->get('service_container')
);
}
if (method_exists($command, 'setDrupalFinder')) {
$command->setDrupalFinder(
$this->container->get('console.drupal_finder')
);
}
if (array_key_exists($command->getName(), $aliases)) {
$commandAliases = $aliases[$command->getName()];
if (!is_array($commandAliases)) {
$commandAliases = [$commandAliases];
}
$commandAliases = array_merge(
$command->getAliases(),
$commandAliases
);
$command->setAliases($commandAliases);
}
$this->add($command);
}
}
/**
* registerGenerators
*/
private function registerGenerators()
{
$consoleGenerators = $this->container
->findTaggedServiceIds('drupal.generator');
foreach ($consoleGenerators as $name => $tags) {
if (!$this->container->has($name)) {
continue;
}
try {
$generator = $this->container->get($name);
} catch (\Exception $e) {
echo $name . ' - ' . $e->getMessage() . PHP_EOL;
continue;
}
if (!$generator) {
continue;
}
if (method_exists($generator, 'setRenderer')) {
$generator->setRenderer(
$this->container->get('console.renderer')
);
}
if (method_exists($generator, 'setFileQueue')) {
$generator->setFileQueue(
$this->container->get('console.file_queue')
);
}
if (method_exists($generator, 'setCountCodeLines')) {
$generator->setCountCodeLines(
$this->container->get('console.count_code_lines')
);
}
if (method_exists($generator, 'setDrupalFinder')) {
$generator->setDrupalFinder(
$this->container->get('console.drupal_finder')
);
}
}
}
/**
* registerCommandsFromAutoWireConfiguration
*/
private function registerCommandsFromAutoWireConfiguration()
{
$configuration = $this->container->get('console.configuration_manager')
->getConfiguration();
$autoWireForcedCommands = $configuration
->get('application.autowire.commands.forced');
if (!is_array($autoWireForcedCommands)) {
return;
}
foreach ($autoWireForcedCommands as $autoWireForcedCommand) {
try {
if (!$autoWireForcedCommand['class']) {
continue;
}
$reflectionClass = new \ReflectionClass(
$autoWireForcedCommand['class']
);
$arguments = [];
if (array_key_exists('arguments', $autoWireForcedCommand)) {
foreach ($autoWireForcedCommand['arguments'] as $argument) {
$argument = substr($argument, 1);
$arguments[] = $this->container->get($argument);
}
}
$command = $reflectionClass->newInstanceArgs($arguments);
if (method_exists($command, 'setTranslator')) {
$command->setTranslator(
$this->container->get('console.translator_manager')
);
}
if (method_exists($command, 'setContainer')) {
$command->setContainer(
$this->container->get('service_container')
);
}
$this->add($command);
} catch (\Exception $e) {
echo $e->getMessage() . PHP_EOL;
continue;
}
}
$autoWireNameCommand = $configuration->get(
sprintf(
'application.autowire.commands.name.%s',
$this->commandName
)
);
if ($autoWireNameCommand) {
try {
$arguments = [];
if (array_key_exists('arguments', $autoWireNameCommand)) {
foreach ($autoWireNameCommand['arguments'] as $argument) {
$argument = substr($argument, 1);
$arguments[] = $this->container->get($argument);
}
}
$reflectionClass = new \ReflectionClass(
$autoWireNameCommand['class']
);
$command = $reflectionClass->newInstanceArgs($arguments);
if (method_exists($command, 'setTranslator')) {
$command->setTranslator(
$this->container->get('console.translator_manager')
);
}
if (method_exists($command, 'setContainer')) {
$command->setContainer(
$this->container->get('service_container')
);
}
$this->add($command);
} catch (\Exception $e) {
echo $e->getMessage() . PHP_EOL;
}
}
}
/**
* registerChainCommands
*/
public function registerChainCommands()
{
/**
* @var ChainDiscovery $chainDiscovery
*/
$chainDiscovery = $this->container->get('console.chain_discovery');
$chainCommands = $chainDiscovery->getChainCommands();
foreach ($chainCommands as $name => $chainCommand) {
try {
$file = $chainCommand['file'];
$description = $chainCommand['description'];
$command = new ChainCustomCommand(
$name,
$description,
$file,
$chainDiscovery
);
$this->add($command);
} catch (\Exception $e) {
echo $e->getMessage() . PHP_EOL;
}
}
}
/**
* registerExtendCommands
*/
private function registerExtendCommands()
{
$this->container->get('console.configuration_manager')
->loadExtendConfiguration();
}
public function getData()
{
$singleCommands = [
'about',
'chain',
'check',
'composerize',
'exec',
'help',
'init',
'list',
'shell',
'server'
];
$languages = $this->container->get('console.configuration_manager')
->getConfiguration()
->get('application.languages');
$data = [];
foreach ($singleCommands as $singleCommand) {
$data['commands']['misc'][] = $this->commandData($singleCommand);
}
$namespaces = array_filter(
$this->getNamespaces(), function ($item) {
return (strpos($item, ':')<=0);
}
);
sort($namespaces);
array_unshift($namespaces, 'misc');
foreach ($namespaces as $namespace) {
$commands = $this->all($namespace);
usort(
$commands, function ($cmd1, $cmd2) {
return strcmp($cmd1->getName(), $cmd2->getName());
}
);
foreach ($commands as $command) {
if (method_exists($command, 'getModule')) {
if ($command->getModule() == 'Console') {
$data['commands'][$namespace][] = $this->commandData(
$command->getName()
);
}
} else {
$data['commands'][$namespace][] = $this->commandData(
$command->getName()
);
}
}
}
$input = $this->getDefinition();
$options = [];
foreach ($input->getOptions() as $option) {
$options[] = [
'name' => $option->getName(),
'description' => $this->trans('application.options.'.$option->getName())
];
}
$arguments = [];
foreach ($input->getArguments() as $argument) {
$arguments[] = [
'name' => $argument->getName(),
'description' => $this->trans('application.arguments.'.$argument->getName())
];
}
$data['application'] = [
'namespaces' => $namespaces,
'options' => $options,
'arguments' => $arguments,
'languages' => $languages,
'messages' => [
'title' => $this->trans('application.gitbook.messages.title'),
'note' => $this->trans('application.gitbook.messages.note'),
'note_description' => $this->trans('application.gitbook.messages.note-description'),
'command' => $this->trans('application.gitbook.messages.command'),
'options' => $this->trans('application.gitbook.messages.options'),
'option' => $this->trans('application.gitbook.messages.option'),
'details' => $this->trans('application.gitbook.messages.details'),
'arguments' => $this->trans('application.gitbook.messages.arguments'),
'argument' => $this->trans('application.gitbook.messages.argument'),
'examples' => $this->trans('application.gitbook.messages.examples')
],
'examples' => []
];
return $data;
}
private function commandData($commandName)
{
if (!$this->has($commandName)) {
return [];
}
$command = $this->find($commandName);
$input = $command->getDefinition();
$options = [];
foreach ($input->getOptions() as $option) {
$options[$option->getName()] = [
'name' => $option->getName(),
'description' => $this->trans($option->getDescription()),
];
}
$arguments = [];
foreach ($input->getArguments() as $argument) {
$arguments[$argument->getName()] = [
'name' => $argument->getName(),
'description' => $this->trans($argument->getDescription()),
];
}
$commandKey = str_replace(':', '.', $command->getName());
$examples = [];
for ($i = 0; $i < 5; $i++) {
$description = sprintf(
'commands.%s.examples.%s.description',
$commandKey,
$i
);
$execution = sprintf(
'commands.%s.examples.%s.execution',
$commandKey,
$i
);
if ($description != $this->trans($description)) {
$examples[] = [
'description' => $this->trans($description),
'execution' => $this->trans($execution)
];
} else {
break;
}
}
$data = [
'name' => $command->getName(),
'description' => $command->getDescription(),
'options' => $options,
'arguments' => $arguments,
'examples' => $examples,
'aliases' => $command->getAliases(),
'key' => $commandKey,
'dashed' => str_replace(':', '-', $command->getName()),
'messages' => [
'usage' => $this->trans('application.gitbook.messages.usage'),
'options' => $this->trans('application.gitbook.messages.options'),
'option' => $this->trans('application.gitbook.messages.option'),
'details' => $this->trans('application.gitbook.messages.details'),
'arguments' => $this->trans('application.gitbook.messages.arguments'),
'argument' => $this->trans('application.gitbook.messages.argument'),
'examples' => $this->trans('application.gitbook.messages.examples')
],
];
return $data;
}
/**
* @return DrupalInterface
*/
public function getDrupal()
{
return $this->drupal;
}
/**
* @param DrupalInterface $drupal
*/
public function setDrupal($drupal)
{
$this->drupal = $drupal;
}
public function setContainer($container)
{
$this->container = $container;
}
public function getContainer()
{
return $this->container;
}
/**
* Add Drupal system messages.
*/
protected function addDrupalMessages($messageManager) {
if (function_exists('drupal_get_messages')) {
$drupalMessages = drupal_get_messages();
foreach ($drupalMessages as $type => $messages) {
foreach ($messages as $message) {
$method = $this->getMessageMethod($type);
$messageManager->{$method}((string)$message);
}
}
}
}
/**
* Gets method name for MessageManager.
*
* @param string $type
* Type of the message.
*
* @return string
* Name of the method
*/
protected function getMessageMethod($type) {
$methodName = 'info';
switch ($type) {
case 'error':
case 'warning':
$methodName = $type;
break;
}
return $methodName;
}
/**
* Finds a command by name or alias.
*
* @param string $name A command name or a command alias
*
* @return mixed A Command instance
*
* Override parent find method to avoid name collisions with automatically
* generated command abbreviations.
* Command name validation was previously done at doRun method.
*/
public function find($name)
{
return $this->get($name);
}
}

View file

@ -0,0 +1,126 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Bootstrap.
*/
namespace Drupal\Console\Core\Bootstrap;
use Drupal\Console\Core\Utils\DrupalFinder;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
/**
* Class DrupalConsoleCore
*
* @package Drupal\Console\Core\Bootstrap
*/
class DrupalConsoleCore
{
/**
* @var string
*/
protected $root;
/**
* @var string
*/
protected $appRoot;
/**
* @var DrupalFinder
*/
protected $drupalFinder;
/**
* DrupalConsole constructor.
*
* @param string $root
* @param string $appRoot
* @param DrupalFinder $drupalFinder
*/
public function __construct(
$root,
$appRoot = null,
DrupalFinder $drupalFinder
) {
$this->root = $root;
$this->appRoot = $appRoot;
$this->drupalFinder = $drupalFinder;
}
/**
* @return ContainerBuilder
*/
public function boot()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator($this->root));
if (substr($this->root, -1) === DIRECTORY_SEPARATOR) {
$this->root = substr($this->root, 0, -1);
}
$servicesFiles = [
$this->root.DRUPAL_CONSOLE_CORE.'services.yml',
$this->root.'/services.yml',
$this->root.DRUPAL_CONSOLE.'uninstall.services.yml',
$this->root.DRUPAL_CONSOLE.'extend.console.uninstall.services.yml'
];
foreach ($servicesFiles as $servicesFile) {
if (file_exists($servicesFile)) {
$loader->load($servicesFile);
}
}
$container->get('console.configuration_manager')
->loadConfiguration($this->root)
->getConfiguration();
$container->get('console.translator_manager')
->loadCoreLanguage('en', $this->root);
$appRoot = $this->appRoot?$this->appRoot:$this->root;
$container->set(
'app.root',
$appRoot
);
$consoleRoot = $appRoot;
if (stripos($this->root, '/bin/') <= 0) {
$consoleRoot = $this->root;
}
$container->set(
'console.root',
$consoleRoot
);
$container->set(
'console.drupal_finder',
$this->drupalFinder
);
$configurationManager = $container->get('console.configuration_manager');
$directory = $configurationManager->getConsoleDirectory() . 'extend/';
$autoloadFile = $directory . 'vendor/autoload.php';
if (is_file($autoloadFile)) {
include_once $autoloadFile;
$extendServicesFile = $directory . 'extend.console.uninstall.services.yml';
if (is_file($extendServicesFile)) {
$loader->load($extendServicesFile);
}
}
$container->get('console.renderer')
->setSkeletonDirs(
[
$this->root.'/templates/',
$this->root.DRUPAL_CONSOLE_CORE.'/templates/'
]
);
return $container;
}
}

View file

@ -0,0 +1,17 @@
<?php
namespace Drupal\Console\Core\Bootstrap;
use Drupal\Console\Core\Utils\ConfigurationManager;
use Drupal\Console\Core\Utils\DrupalFinder;
interface DrupalInterface
{
public function __construct(
$autoload,
DrupalFinder $drupalFinder,
ConfigurationManager $configurationManager
);
public function boot();
}

View file

@ -0,0 +1,83 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\AboutCommand.
*/
namespace Drupal\Console\Core\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Class AboutCommand
*
* @package Drupal\Console\Core\Command
*/
class AboutCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('about')
->setDescription($this->trans('commands.about.description'));
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$application = $this->getApplication();
$aboutTitle = sprintf(
'%s (%s)',
$application->getName(),
$application->getVersion()
);
$this->getIo()->setDecorated(false);
$this->getIo()->title($aboutTitle);
$this->getIo()->setDecorated(true);
$commands = [
'init' => [
$this->trans('commands.init.description'),
'drupal init'
],
'quick-start' => [
$this->trans('commands.common.messages.quick-start'),
'drupal quick:start'
],
'site-new' => [
$this->trans('commands.site.new.description'),
'drupal site:new'
],
'site-install' => [
$this->trans('commands.site.install.description'),
sprintf(
'drupal site:install'
)
],
'list' => [
$this->trans('commands.list.description'),
'drupal list',
]
];
foreach ($commands as $command => $commandInfo) {
$this->getIo()->writeln($commandInfo[0]);
$this->getIo()->comment(sprintf(' %s', $commandInfo[1]));
$this->getIo()->newLine();
}
$this->getIo()->writeln($this->trans('commands.self-update.description'));
$this->getIo()->comment(' drupal self-update');
$this->getIo()->newLine();
}
}

View file

@ -0,0 +1,121 @@
<?php
/**
* Created by PhpStorm.
* User: jmolivas
* Date: 1/16/18
* Time: 2:22 PM
*/
namespace Drupal\Console\Core\Command\Chain;
use Drupal\Console\Core\Command\Command;
use Drupal\Console\Core\Utils\ChainDiscovery;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class BaseCommand extends Command
{
/**
* @var ChainDiscovery
*/
protected $chainDiscovery;
/**
* BaseCommand constructor.
*
* @param ChainDiscovery $chainDiscovery
*/
public function __construct(
ChainDiscovery $chainDiscovery
) {
$this->chainDiscovery = $chainDiscovery;
parent::__construct();
$this->ignoreValidationErrors();
}
protected function initialize(
InputInterface $input,
OutputInterface $output
) {
parent::initialize($input, $output);
$options = [];
foreach ($_SERVER['argv'] as $index => $element) {
if ($index<2) {
continue;
}
if (substr($element, 0, 2) !== "--") {
continue;
}
$element = substr($element, 2);
$exploded = explode("=", $element);
if (!$exploded) {
$exploded = explode(" ", $element);
}
if (count($exploded)>1) {
$options[trim($exploded[0])] = trim($exploded[1]);
}
}
$file = $input->getOption('file');
$file = calculateRealPath($file);
$content = $this->chainDiscovery->getFileContents($file);
$variables = $this->chainDiscovery->extractInlinePlaceHolderNames($content);
foreach ($variables as $variable) {
if (!array_key_exists($variable, $options)) {
$options[$variable] = null;
}
}
foreach ($options as $optionName => $optionValue) {
if ($input->hasOption($optionName)) {
continue;
}
$this->addOption(
$optionName,
null,
InputOption::VALUE_OPTIONAL,
$optionName,
$optionValue
);
}
}
protected function getFileOption()
{
$input = $this->getIo()->getInput();
$file = $input->getOption('file');
if (!$file) {
$files = array_keys($this->chainDiscovery->getFiles());
$file = $this->getIo()->choice(
$this->trans('commands.chain.questions.chain-file'),
$files
);
}
$file = calculateRealPath($file);
$input->setOption('file', $file);
return $file;
}
protected function getOptionsAsArray()
{
$input = $this->getIo()->getInput();
$options = [];
foreach ($input->getOptions() as $option => $value) {
$options[$option] = $value;
}
return $options;
}
}

View file

@ -0,0 +1,284 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\Chain\ChainCommand.
*/
namespace Drupal\Console\Core\Command\Chain;
use Dflydev\PlaceholderResolver\DataSource\ArrayDataSource;
use Dflydev\PlaceholderResolver\RegexPlaceholderResolver;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Yaml\Parser;
use Drupal\Console\Core\Utils\ChainQueue;
use Drupal\Console\Core\Utils\ChainDiscovery;
use Drupal\Console\Core\Command\Shared\InputTrait;
/**
* Class ChainCommand
*
* @package Drupal\Console\Core\Command\Chain
*/
class ChainCommand extends BaseCommand
{
use InputTrait;
/**
* @var ChainQueue
*/
protected $chainQueue;
/**
* ChainCommand constructor.
*
* @param ChainQueue $chainQueue
* @param ChainDiscovery $chainDiscovery
*/
public function __construct(
ChainQueue $chainQueue,
ChainDiscovery $chainDiscovery
) {
$this->chainQueue = $chainQueue;
parent::__construct($chainDiscovery);
$this->ignoreValidationErrors();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('chain')
->setDescription($this->trans('commands.chain.description'))
->addOption(
'file',
null,
InputOption::VALUE_OPTIONAL,
$this->trans('commands.chain.options.file')
);
}
/**
* {@inheritdoc}
*/
protected function interact(InputInterface $input, OutputInterface $output)
{
$file = $this->getFileOption();
$chainContent = $this->chainDiscovery
->parseContent(
$file,
$this->getOptionsAsArray()
);
$inlinePlaceHolders = $this->chainDiscovery
->extractInlinePlaceHolders($chainContent);
foreach ($inlinePlaceHolders as $inlinePlaceHolder => $inlinePlaceHolderValue) {
if (is_array($inlinePlaceHolderValue)) {
$placeHolderValue = $this->getIo()->choice(
sprintf(
$this->trans('commands.chain.messages.select-value-for-placeholder'),
$inlinePlaceHolder
),
$inlinePlaceHolderValue,
current($inlinePlaceHolderValue)
);
} else {
$placeHolderValue = $this->getIo()->ask(
sprintf(
$this->trans(
'commands.chain.messages.enter-value-for-placeholder'
),
$inlinePlaceHolder
),
$inlinePlaceHolderValue
);
}
if (!$input->hasOption($inlinePlaceHolder)) {
$this->addOption(
$inlinePlaceHolder,
null,
InputOption::VALUE_OPTIONAL,
null,
null
);
}
$input->setOption($inlinePlaceHolder, $placeHolderValue);
}
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$interactive = false;
$file = $input->getOption('file');
if (!$file) {
$this->getIo()->error($this->trans('commands.chain.messages.missing-file'));
return 1;
}
$fileSystem = new Filesystem();
$file = calculateRealPath($file);
if (!$fileSystem->exists($file)) {
$this->getIo()->error(
sprintf(
$this->trans('commands.chain.messages.invalid-file'),
$file
)
);
return 1;
}
$chainContent = $this->chainDiscovery
->parseContent(
$file,
$this->getOptionsAsArray()
);
// Resolve inlinePlaceHolders
$inlinePlaceHolders = $this->chainDiscovery
->extractInlinePlaceHolders($chainContent);
if ($inlinePlaceHolders) {
$this->getIo()->error(
sprintf(
$this->trans('commands.chain.messages.missing-inline-placeholders'),
implode(', ', array_keys($inlinePlaceHolders))
)
);
$this->getIo()->info(
$this->trans(
'commands.chain.messages.set-inline-placeholders'
)
);
foreach ($inlinePlaceHolders as $inlinePlaceHolder => $inlinePlaceHolderValue) {
$missingInlinePlaceHoldersMessage = sprintf(
'--%s="%s_VALUE"',
$inlinePlaceHolder,
strtoupper($inlinePlaceHolder)
);
$this->getIo()->block($missingInlinePlaceHoldersMessage);
}
return 1;
}
// Resolve environmentPlaceHolders
$environmentPlaceHolders = $this->chainDiscovery
->extractEnvironmentPlaceHolders($chainContent);
if ($environmentPlaceHolders) {
$this->getIo()->error(
sprintf(
$this->trans(
'commands.chain.messages.missing-environment-placeholders'
),
implode(
', ',
array_values($environmentPlaceHolders)
)
)
);
$this->getIo()->info(
$this->trans(
'commands.chain.messages.set-environment-placeholders'
)
);
foreach ($environmentPlaceHolders as $envPlaceHolder) {
$missingEnvironmentPlaceHoldersMessage = sprintf(
'export %s=%s_VALUE',
$envPlaceHolder,
strtoupper($envPlaceHolder)
);
$this->getIo()->block($missingEnvironmentPlaceHoldersMessage);
}
return 1;
}
$parser = new Parser();
$chainData = $parser->parse($chainContent);
$commands = [];
if (array_key_exists('commands', $chainData)) {
$commands = $chainData['commands'];
}
$chainInlineOptions = $input->getOptions();
unset($chainInlineOptions['file']);
foreach ($commands as $command) {
$moduleInputs = [];
$arguments = !empty($command['arguments']) ? $command['arguments'] : [];
$options = !empty($command['options']) ? $command['options'] : [];
foreach ($arguments as $key => $value) {
$moduleInputs[$key] = is_null($value) ? '' : $value;
}
foreach ($options as $key => $value) {
$moduleInputs['--'.$key] = is_null($value) ? '' : $value;
}
// Get application global options
foreach ($this->getApplication()->getDefinition()->getOptions() as $option) {
$optionName = $option->getName();
if (array_key_exists($optionName, $chainInlineOptions)) {
$optionValue = $chainInlineOptions[$optionName];
// Set global option only if is not available in command options
if (!isset($moduleInputs['--' . $optionName]) && $optionValue) {
$moduleInputs['--' . $optionName] = $optionValue;
}
}
}
$application = $this->getApplication();
$callCommand = $application->find($command['command']);
if (!$callCommand) {
continue;
}
$this->getIo()->text($command['command']);
$this->getIo()->newLine();
$input = new ArrayInput($moduleInputs);
if (!is_null($interactive)) {
$input->setInteractive($interactive);
}
$allowFailure = array_key_exists('allow_failure', $command)?$command['allow_failure']:false;
try {
$callCommand->run($input, $this->getIo());
} catch (\Exception $e) {
if (!$allowFailure) {
$this->getIo()->error($e->getMessage());
return 1;
}
}
}
return 0;
}
}

View file

@ -0,0 +1,103 @@
<?php
/**
* @file
* Contains Drupal\Console\Core\Command\ChainCustomCommand.
*/
namespace Drupal\Console\Core\Command\Chain;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Drupal\Console\Core\Command\Shared\InputTrait;
/**
* Class ChainCustomCommand
*
* @package Drupal\Console\Core\Command\ChainCustomCommand
*/
class ChainCustomCommand extends BaseCommand
{
use InputTrait;
/**
* @var string
*/
protected $name;
/**
* @var string
*/
protected $description;
/**
* @var string
*/
protected $file;
/**
* ChainCustomCommand constructor.
*
* @param $name
* @param $description
* @param $file
* @param $chainDiscovery
*/
public function __construct(
$name,
$description,
$file,
$chainDiscovery
) {
$this->name = $name;
$this->description = $description;
$this->file = $file;
parent::__construct($chainDiscovery);
$this->ignoreValidationErrors();
$this->addOption(
'file',
null,
InputOption::VALUE_OPTIONAL,
null,
$file
);
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName($this->name)
->setDescription($this->description);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$command = $this->getApplication()->find('chain');
$arguments = [
'command' => 'chain',
'--file' => $this->file,
];
foreach ($input->getOptions() as $option => $value) {
if ($value) {
$arguments['--' . $option] = $value;
}
}
$commandInput = new ArrayInput($arguments);
$commandInput->setInteractive(true);
return $command->run($commandInput, $output);
}
}

View file

@ -0,0 +1,149 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\CheckCommand.
*/
namespace Drupal\Console\Core\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Drupal\Console\Core\Utils\ConfigurationManager;
use Drupal\Console\Core\Utils\RequirementChecker;
use Drupal\Console\Core\Utils\ChainQueue;
/**
* Class CheckCommand
*
* @package Drupal\Console\Core\Command
*/
class CheckCommand extends Command
{
/**
* @var RequirementChecker
*/
protected $requirementChecker;
/**
* @var ChainQueue
*/
protected $chainQueue;
/**
* @var ConfigurationManager
*/
protected $configurationManager;
/**
* CheckCommand constructor.
*
* @param RequirementChecker $requirementChecker
* @param ChainQueue $chainQueue
* @param ConfigurationManager $configurationManager
*/
public function __construct(
RequirementChecker $requirementChecker,
ChainQueue $chainQueue,
ConfigurationManager $configurationManager
) {
$this->requirementChecker = $requirementChecker;
$this->chainQueue = $chainQueue;
$this->configurationManager = $configurationManager;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('check')
->setDescription($this->trans('commands.check.description'));
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$checks = $this->requirementChecker->getCheckResult();
if (!$checks) {
$phpCheckFile = $this->configurationManager
->getVendorCoreDirectory() . 'phpcheck.yml';
$checks = $this->requirementChecker->validate($phpCheckFile);
}
if (!$checks['php']['valid']) {
$this->getIo()->error(
sprintf(
$this->trans('commands.check.messages.php-invalid'),
$checks['php']['current'],
$checks['php']['required']
)
);
return 1;
}
if ($extensions = $checks['extensions']['required']['missing']) {
foreach ($extensions as $extension) {
$this->getIo()->error(
sprintf(
$this->trans('commands.check.messages.extension-missing'),
$extension
)
);
}
}
if ($extensions = $checks['extensions']['recommended']['missing']) {
foreach ($extensions as $extension) {
$this->getIo()->commentBlock(
sprintf(
$this->trans(
'commands.check.messages.extension-recommended'
),
$extension
)
);
}
}
if ($configurations = $checks['configurations']['required']['missing']) {
foreach ($configurations as $configuration) {
$this->getIo()->error(
sprintf(
$this->trans('commands.check.messages.configuration-missing'),
$configuration
)
);
}
}
if ($configurations = $checks['configurations']['required']['overwritten']) {
foreach ($configurations as $configuration => $overwritten) {
$this->getIo()->commentBlock(
sprintf(
$this->trans(
'commands.check.messages.configuration-overwritten'
),
$configuration,
$overwritten
)
);
}
}
if ($this->requirementChecker->isValid() && !$this->requirementChecker->isOverwritten()) {
$this->getIo()->success(
$this->trans('commands.check.messages.success')
);
}
return $this->requirementChecker->isValid();
}
}

View file

@ -0,0 +1,63 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\Command.
*/
namespace Drupal\Console\Core\Command;
use Symfony\Component\Console\Command\Command as BaseCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Drupal\Console\Core\Command\Shared\CommandTrait;
use Drupal\Console\Core\Style\DrupalStyle;
use Drupal\Console\Core\Utils\DrupalFinder;
/**
* Class Command
*
* @package Drupal\Console\Core\Command
*/
abstract class Command extends BaseCommand
{
use CommandTrait;
/**
* @var DrupalFinder;
*/
protected $drupalFinder;
/**
* @var DrupalStyle
*/
private $io;
/**
* {@inheritdoc}
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
$this->io = new DrupalStyle($input, $output);
}
/**
* @return \Drupal\Console\Core\Style\DrupalStyle
*/
public function getIo()
{
return $this->io;
}
public function createException($message) {
$this->getIo()->error($message);
exit(1);
}
/**
* @param \Drupal\Console\Core\Utils\DrupalFinder $drupalFinder
*/
public function setDrupalFinder($drupalFinder) {
$this->drupalFinder = $drupalFinder;
}
}

View file

@ -0,0 +1,36 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\CompleteCommand.
*/
namespace Drupal\Console\Core\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class CompleteCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('complete')
->setDescription($this->trans('commands.complete.description'));
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$commands = array_keys($this->getApplication()->all());
asort($commands);
$output->writeln($commands);
return 0;
}
}

View file

@ -0,0 +1,20 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\ContainerAwareCommand.
*/
namespace Drupal\Console\Core\Command;
use Drupal\Console\Core\Command\Shared\ContainerAwareCommandTrait;
/**
* Class ContainerAwareCommand
*
* @package Drupal\Console\Core\Command
*/
abstract class ContainerAwareCommand extends Command
{
use ContainerAwareCommandTrait;
}

View file

@ -0,0 +1,91 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\Debug\ChainCommand.
*/
namespace Drupal\Console\Core\Command\Debug;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Drupal\Console\Core\Command\Command;
use Drupal\Console\Core\Utils\ChainDiscovery;
/**
* Class ChainCommand
*
* @package Drupal\Console\Core\Command\Debug
*/
class ChainCommand extends Command
{
/**
* @var ChainDiscovery
*/
protected $chainDiscovery;
/**
* ChainCommand constructor.
*
* @param ChainDiscovery $chainDiscovery
*/
public function __construct(
ChainDiscovery $chainDiscovery
) {
$this->chainDiscovery = $chainDiscovery;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('debug:chain')
->setDescription($this->trans('commands.debug.chain.description'))
->setAliases(['dch']);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$files = $this->chainDiscovery->getFiles();
$filesPerDirectory = $this->chainDiscovery->getFilesPerDirectory();
if (!$files || !$filesPerDirectory) {
$this->getIo()->warning($this->trans('commands.debug.chain.messages.no-files'));
return 0;
}
foreach ($filesPerDirectory as $directory => $fileNames) {
$this->getIo()->info(' ' . $this->trans('commands.debug.chain.messages.directory'), false);
$this->getIo()->comment($directory);
$tableHeader = [
$this->trans('commands.debug.chain.messages.file'),
$this->trans('commands.debug.chain.messages.command')
];
$tableRows = [];
foreach ($fileNames as $file) {
$commandName = '';
if (array_key_exists('command', $files[$directory.$file])) {
$commandName = $files[$directory.$file]['command'];
}
$tableRows[] = [
'file' => $file,
'command' => $commandName
];
}
$this->getIo()->table($tableHeader, $tableRows);
}
return 0;
}
}

View file

@ -0,0 +1,68 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\Debug\SettingsCommand.
*/
namespace Drupal\Console\Core\Command\Debug;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Drupal\Console\Core\Command\Command;
use Drupal\Console\Core\Utils\ConfigurationManager;
use Symfony\Component\Yaml\Yaml;
/**
* Class SettingsCommand
*
* @package Drupal\Console\Core\Command\Settings
*/
class SettingsCommand extends Command
{
/**
* @var ConfigurationManager
*/
protected $configurationManager;
/**
* CheckCommand constructor.
*
* @param ConfigurationManager $configurationManager
*/
public function __construct(
ConfigurationManager $configurationManager
) {
$this->configurationManager = $configurationManager;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('debug:settings')
->setDescription($this->trans('commands.debug.settings.description'))
->setAliases(['dse']);
;
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$configuration = $this->configurationManager->getConfiguration();
$configApplication['application'] = $configuration->getRaw('application');
unset($configApplication['application']['autowire']);
unset($configApplication['application']['languages']);
$this->getIo()->write(Yaml::dump($configApplication, 6, 2));
$this->getIo()->newLine();
return 0;
}
}

View file

@ -0,0 +1,125 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\Debug\SiteCommand.
*/
namespace Drupal\Console\Core\Command\Debug;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Yaml\Dumper;
use Drupal\Console\Core\Command\Command;
use Drupal\Console\Core\Utils\ConfigurationManager;
/**
* Class SiteCommand
*
* @package Drupal\Console\Core\Command\Debug
*/
class SiteCommand extends Command
{
/**
* @var ConfigurationManager
*/
protected $configurationManager;
/**
* SiteCommand constructor.
*
* @param ConfigurationManager $configurationManager
*/
public function __construct(
ConfigurationManager $configurationManager
) {
$this->configurationManager = $configurationManager;
parent::__construct();
}
/**
* @{@inheritdoc}
*/
public function configure()
{
$this
->setName('debug:site')
->setDescription($this->trans('commands.debug.site.description'))
->addArgument(
'target',
InputArgument::OPTIONAL,
$this->trans('commands.debug.site.options.target'),
null
)
->addArgument(
'property',
InputArgument::OPTIONAL,
$this->trans('commands.debug.site.options.property'),
null
)
->setHelp($this->trans('commands.debug.site.help'))
->setAliases(['dsi']);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$sites = $this->configurationManager->getSites();
if (!$sites) {
$this->getIo()->warning($this->trans('commands.debug.site.messages.invalid-sites'));
return 0;
}
$target = $input->getArgument('target');
if (!$target) {
foreach ($sites as $key => $site) {
$environments = array_keys($site);
unset($environments[0]);
$environments = array_map(
function ($element) use ($key) {
return $key . '.' . $element;
},
$environments
);
$this->getIo()->info($key);
$this->getIo()->listing($environments);
}
return 0;
}
$targetConfig = $this->configurationManager->readTarget($target);
if (!$targetConfig) {
$this->getIo()->error($this->trans('commands.debug.site.messages.invalid-site'));
return 1;
}
// --property argument, allows the user to fetch specific properties of the selected site
$property = $input->getArgument('property');
if ($property) {
$property_keys = explode('.', $property);
$val = $targetConfig;
foreach ($property_keys as $property_key) {
$val = &$val[$property_key];
}
$this->getIo()->writeln($val);
return 0;
}
$this->getIo()->info($target);
$dumper = new Dumper();
$this->getIo()->writeln($dumper->dump($targetConfig, 4, 2));
return 0;
}
}

View file

@ -0,0 +1,109 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\Exclude\DrushCommand.
*/
namespace Drupal\Console\Core\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Drupal\Console\Core\Utils\ConfigurationManager;
use Drupal\Console\Core\Utils\ChainQueue;
/**
* Class DrushCommand
*
* @package Drupal\Console\Core\Command
*/
class DrushCommand extends Command
{
/**
* @var ConfigurationManager
*/
protected $configurationManager;
/**
* @var ChainQueue
*/
protected $chainQueue;
/**
* DrushCommand constructor.
*
* @param ConfigurationManager $configurationManager
* @param ChainQueue $chainQueue
*/
public function __construct(
ConfigurationManager $configurationManager,
ChainQueue $chainQueue
) {
$this->configurationManager = $configurationManager;
$this->chainQueue = $chainQueue;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('drush')
->setDescription($this->trans('commands.drush.description'))
->addArgument(
'command-name',
InputArgument::OPTIONAL,
$this->trans('commands.drush.arguments.command-name'),
null
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$commandName = $input->getArgument('command-name');
$alternative = $this->configurationManager->readDrushEquivalents($commandName);
$this->getIo()->newLine();
$this->getIo()->info($this->trans('commands.drush.description'));
$this->getIo()->newLine();
if (!$alternative) {
$this->getIo()->error($this->trans('commands.drush.messages.not-found'));
return 1;
}
$tableHeader = ['drush','drupal console'];
if (is_array($alternative)) {
$this->getIo()->table(
$tableHeader,
$alternative
);
return 0;
}
$this->getIo()->table(
$tableHeader,
[[$commandName, $alternative]]
);
if ($this->getApplication()->has($alternative)) {
$this->chainQueue->addCommand(
'help',
['command_name' => $alternative]
);
return 0;
}
return 0;
}
}

View file

@ -0,0 +1,97 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\Exclude\DrupliconCommand.
*/
namespace Drupal\Console\Core\Command\Exclude;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Finder\Finder;
use Drupal\Console\Core\Command\Command;
use Drupal\Console\Core\Utils\TwigRenderer;
use Drupal\Console\Core\Utils\ConfigurationManager;
/**
* Class DrupliconCommand
*
* @package Drupal\Console\Core\Command\Exclude
*/
class DrupliconCommand extends Command
{
/**
* @var string
*/
protected $appRoot;
/**
* @var TwigRenderer
*/
protected $renderer;
/**
* @var ConfigurationManager
*/
protected $configurationManager;
/**
* DrupliconCommand constructor.
*
* @param string $appRoot
* @param TwigRenderer $renderer
* @param ConfigurationManager $configurationManager
*/
public function __construct(
$appRoot,
TwigRenderer $renderer,
ConfigurationManager $configurationManager
) {
$this->appRoot = $appRoot;
$this->renderer = $renderer;
$this->configurationManager = $configurationManager;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('druplicon')
->setDescription($this->trans('application.commands.druplicon.description'));
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$directory = sprintf(
'%s/templates/core/druplicon/',
$this->configurationManager->getVendorCoreRoot()
);
$finder = new Finder();
$finder->files()
->name('*.twig')
->in($directory);
$templates = [];
foreach ($finder as $template) {
$templates[] = $template->getRelativePathname();
}
$druplicon = $this->renderer->render(
sprintf(
'core/druplicon/%s',
$templates[array_rand($templates)]
)
);
$this->getIo()->writeln($druplicon);
return 0;
}
}

View file

@ -0,0 +1,99 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\Exclude\ElephpantCommand.
*/
namespace Drupal\Console\Core\Command\Exclude;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Finder\Finder;
use Drupal\Console\Core\Command\Command;
use Drupal\Console\Core\Utils\TwigRenderer;
use Drupal\Console\Core\Utils\ConfigurationManager;
/**
* Class ElephpantCommand
*
* @package Drupal\Console\Core\Command\Exclude
*/
class ElephpantCommand extends Command
{
/**
* @var string
*/
protected $appRoot;
/**
* @var TwigRenderer
*/
protected $renderer;
/**
* @var ConfigurationManager
*/
protected $configurationManager;
/**
* ElephpantCommand constructor.
*
* @param string $appRoot
* @param TwigRenderer $renderer
* @param ConfigurationManager $configurationManager
*/
public function __construct(
$appRoot,
TwigRenderer $renderer,
ConfigurationManager $configurationManager
) {
$this->appRoot = $appRoot;
$this->renderer = $renderer;
$this->configurationManager = $configurationManager;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('elephpant')
->setDescription($this->trans('application.commands.elephpant.description'));
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$directory = sprintf(
'%stemplates/core/elephpant/',
$this->configurationManager->getVendorCoreRoot()
);
$finder = new Finder();
$finder->files()
->name('*.twig')
->in($directory);
$templates = [];
foreach ($finder as $template) {
$templates[] = $template->getRelativePathname();
}
$elephpant = $this->renderer->render(
sprintf(
'core/elephpant/%s',
$templates[array_rand($templates)]
)
);
$this->getIo()->writeln($elephpant);
return 0;
}
}

View file

@ -0,0 +1,115 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\Exec\ExecCommand.
*/
namespace Drupal\Console\Core\Command\Exec;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\ExecutableFinder;
use Drupal\Console\Core\Utils\ShellProcess;
use Drupal\Console\Core\Command\Command;
/**
* Class ExecCommand
*
* @package Drupal\Console\Core\Command\Exec
*/
class ExecCommand extends Command
{
/**
* @var ShellProcess
*/
protected $shellProcess;
/**
* ExecCommand constructor.
*
* @param ShellProcess $shellProcess
*/
public function __construct(ShellProcess $shellProcess)
{
$this->shellProcess = $shellProcess;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('exec')
->setDescription($this->trans('commands.exec.description'))
->addArgument(
'bin',
InputArgument::REQUIRED,
$this->trans('commands.exec.arguments.bin')
)->addOption(
'working-directory',
null,
InputOption::VALUE_OPTIONAL,
$this->trans('commands.exec.options.working-directory')
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$bin = $input->getArgument('bin');
$workingDirectory = $input->getOption('working-directory');
if (!$bin) {
$this->getIo()->error(
$this->trans('commands.exec.messages.missing-bin')
);
return 1;
}
$name = $bin;
if ($index = stripos($name, " ")) {
$name = substr($name, 0, $index);
}
$finder = new ExecutableFinder();
if (!$finder->find($name)) {
$this->getIo()->error(
sprintf(
$this->trans('commands.exec.messages.binary-not-found'),
$name
)
);
return 1;
}
if (!$this->shellProcess->exec($bin, $workingDirectory)) {
$this->getIo()->error(
sprintf(
$this->trans('commands.exec.messages.invalid-bin')
)
);
$this->getIo()->writeln($this->shellProcess->getOutput());
return 1;
}
$this->getIo()->success(
sprintf(
$this->trans('commands.exec.messages.success'),
$bin
)
);
return 0;
}
}

View file

@ -0,0 +1,320 @@
<?php
namespace Drupal\Console\Core\Command\Generate;
use Drupal\Console\Core\Command\Command;
use Drupal\Console\Core\Utils\ConfigurationManager;
use Drupal\Console\Core\Utils\DrupalFinder;
use Drupal\Console\Core\Generator\SiteAliasGenerator;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Class SiteAliasCommand
*
* @package Drupal\Console\Command\Generate
*/
class SiteAliasCommand extends Command
{
/**
* @var SiteAliasGenerator
*/
protected $generator;
/**
* @var DrupalFinder
*/
protected $drupalFinder;
/**
* @var ConfigurationManager
*/
protected $configurationManager;
/**
* @var array
*/
private $types = [
'local',
'ssh',
'container'
];
/**
* @var array
*/
private $extraOptions = [
'ssh' => [
'none' => '',
'vagrant' => '-o PasswordAuthentication=no -i ~/.vagrant.d/insecure_private_key',
],
'container' => [
'none' => '',
'drupal4docker' => 'docker-compose exec --user=82 php'
]
];
public function __construct(
SiteAliasGenerator $generator,
ConfigurationManager $configurationManager,
DrupalFinder $drupalFinder
) {
$this->generator = $generator;
$this->configurationManager = $configurationManager;
$this->drupalFinder = $drupalFinder;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('generate:site:alias')
->setDescription(
$this->trans('commands.generate.site.alias.description')
)
->setHelp($this->trans('commands.generate.site.alias.help'))
->addOption(
'site',
null,
InputOption::VALUE_NONE,
$this->trans('commands.generate.site.alias.options.site')
)
->addOption(
'name',
null,
InputOption::VALUE_REQUIRED,
$this->trans('commands.generate.site.alias.options.name')
)
->addOption(
'environment',
null,
InputOption::VALUE_REQUIRED,
$this->trans('commands.generate.site.alias.options.environment')
)
->addOption(
'type',
null,
InputOption::VALUE_REQUIRED,
$this->trans('commands.generate.site.alias.options.type')
)
->addOption(
'composer-root',
null,
InputOption::VALUE_OPTIONAL,
$this->trans('commands.generate.site.alias.options.composer-root')
)
->addOption(
'site-uri',
null,
InputOption::VALUE_OPTIONAL,
$this->trans('commands.generate.site.alias.options.site-uri')
)
->addOption(
'host',
null,
InputOption::VALUE_OPTIONAL,
$this->trans('commands.generate.site.alias.options.host')
)
->addOption(
'user',
null,
InputOption::VALUE_OPTIONAL,
$this->trans('commands.generate.site.alias.options.user')
)
->addOption(
'port',
null,
InputOption::VALUE_OPTIONAL,
$this->trans('commands.generate.site.alias.options.port')
)
->addOption(
'extra-options',
null,
InputOption::VALUE_OPTIONAL,
$this->trans('commands.generate.site.alias.options.extra-options')
)
->addOption(
'directory',
null,
InputOption::VALUE_REQUIRED,
$this->trans('commands.generate.site.alias.options.directory')
)
->setAliases(['gsa']);
}
/**
* {@inheritdoc}
*/
protected function interact(
InputInterface $input,
OutputInterface $output
) {
$site = $input->getOption('site');
$name = $input->getOption('name');
if (!$name) {
$sites = $this->configurationManager->getSites();
if (!empty($sites)) {
$sites = array_keys($this->configurationManager->getSites());
$name = $this->getIo()->choiceNoList(
$this->trans('commands.generate.site.alias.questions.name'),
$sites,
current($sites),
TRUE
);
if (is_numeric($name)) {
$name = $sites[$name];
}
} else {
$name = $this->getIo()->ask(
$this->trans('commands.generate.site.alias.questions.name')
);
}
$input->setOption('name', $name);
}
$environment = $input->getOption('environment');
if (!$environment) {
$environment = $this->getIo()->ask(
$this->trans('commands.generate.site.alias.questions.environment'),
null
);
$input->setOption('environment', $environment);
}
$type = $input->getOption('type');
if (!$type) {
$type = $this->getIo()->choiceNoList(
$this->trans('commands.generate.site.alias.questions.type'),
$this->types
);
$input->setOption('type', $type);
}
$composerRoot = $input->getOption('composer-root');
if (!$composerRoot) {
$root = $this->drupalFinder->getComposerRoot();
if ($type === 'container') {
$root = '/var/www/html';
}
if ($type === 'ssh') {
$root = '/var/www/'.$name;
}
$composerRoot = $this->getIo()->ask(
$this->trans('commands.generate.site.alias.questions.composer-root'),
$root
);
$input->setOption('composer-root', $composerRoot);
}
$siteUri = $input->getOption('site-uri');
if (!$siteUri) {
$uri = explode('.', $environment);
if (count($uri)>1) {
$uri = $uri[1];
} else {
$uri = 'default';
}
$siteUri = $this->getIo()->askEmpty(
$this->trans('commands.generate.site.alias.questions.site-uri'),
$uri
);
$input->setOption('site-uri', $siteUri);
}
if ($type !== 'local') {
$extraOptions = $input->getOption('extra-options');
if (!$extraOptions) {
$options = array_values($this->extraOptions[$type]);
$extraOptions = $this->getIo()->choiceNoList(
$this->trans(
'commands.generate.site.alias.questions.extra-options'
),
$options,
current($options)
);
$input->setOption('extra-options', $extraOptions);
}
$host = $input->getOption('host');
if (!$host) {
$host = $this->getIo()->askEmpty(
$this->trans('commands.generate.site.alias.questions.host')
);
$input->setOption('host', $host);
}
$user = $input->getOption('user');
if (!$user) {
$user = $this->getIo()->askEmpty(
$this->trans('commands.generate.site.alias.questions.user')
);
$input->setOption('user', $user);
}
$port = $input->getOption('port');
if (!$port) {
$port = $this->getIo()->askEmpty(
$this->trans('commands.generate.site.alias.questions.port')
);
$input->setOption('port', $port);
}
}
$directory = $input->getOption('directory');
if ($site && $this->drupalFinder->getComposerRoot()) {
$directory = $this->drupalFinder->getComposerRoot() . '/console/';
}
if (!$directory) {
$directory = $this->getIo()->choice(
$this->trans('commands.generate.site.alias.questions.directory'),
$this->configurationManager->getConfigurationDirectories()
);
$input->setOption('directory', $directory);
}
}
/**
* {@inheritdoc}
*/
protected function execute(
InputInterface $input,
OutputInterface $output
) {
$site = $input->getOption('site');
$directory = $input->getOption('directory');
if ($site && $this->drupalFinder->isValidDrupal()) {
$directory = $this->drupalFinder->getComposerRoot() . '/console/';
}
$this->generator->generate(
[
'name' => $input->getOption('name'),
'environment' => $input->getOption('environment'),
'type' => $input->getOption('type'),
'extra_options' => $input->getOption('extra-options'),
'root' => $input->getOption('composer-root'),
'uri' => $input->getOption('site-uri'),
'port' => $input->getOption('port'),
'user' => $input->getOption('user'),
'host' => $input->getOption('host'),
'directory' => $directory
]
);
}
}

View file

@ -0,0 +1,84 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\GenerateCommand.
*/
namespace Drupal\Console\Core\Command;
use Symfony\Component\Filesystem\Filesystem;
use Webmozart\PathUtil\Path;
/**
* Class GenerateCommand
*
* @package Drupal\Console\Core\Command
*/
abstract class GenerateCommand extends Command
{
protected function validateFileExists(
Filesystem $fs,
$sourceFiles,
$stopOnException = true
) {
$notFound = [];
if (!is_array($sourceFiles)) {
$sourceFiles = [$sourceFiles];
}
foreach ($sourceFiles as $sourceFile) {
if ($fs->exists($sourceFile)) {
return $sourceFile;
}
$notFound[] = Path::makeRelative(
$sourceFile,
$this->drupalFinder->getComposerRoot()
);
}
if ($stopOnException) {
$this->createException(
'File(s): ' . implode(', ', $notFound) . ' not found.'
);
}
return null;
}
protected function backUpFile(Filesystem $fs, $fileName)
{
$fileNameBackup = $fileName.'.original';
if ($fs->exists($fileName)) {
if ($fs->exists($fileNameBackup)) {
$fs->remove($fileName);
return;
}
$fs->rename(
$fileName,
$fileNameBackup,
TRUE
);
$fileNameBackup = Path::makeRelative(
$fileNameBackup,
$this->drupalFinder->getComposerRoot()
);
$this->getIo()->success(
'File ' . $fileNameBackup . ' created.'
);
}
}
protected function showFileCreatedMessage($fileName) {
$fileName = Path::makeRelative(
$fileName,
$this->drupalFinder->getComposerRoot()
);
$this->getIo()->success('File: ' . $fileName . ' created.');
}
}

View file

@ -0,0 +1,95 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\HelpCommand.
*/
namespace Drupal\Console\Core\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Output\OutputInterface;
use Drupal\Console\Core\Helper\DescriptorHelper;
/**
* HelpCommand displays the help for a given command.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class HelpCommand extends Command
{
private $command;
/**
* {@inheritdoc}
*/
protected function configure()
{
$this->ignoreValidationErrors();
$this
->setName('help')
->setDefinition($this->createDefinition())
->setDescription($this->trans('commands.help.description'))
->setHelp($this->trans('commands.help.help'));
}
/**
* Sets the command.
*
* @param $command
* The command to set
*/
public function setCommand($command)
{
$this->command = $command;
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if (null === $this->command) {
$this->command = $this->getApplication()->find($input->getArgument('command_name'));
}
if ($input->getOption('xml')) {
$this->getIo()->info($this->trans('commands.help.messages.deprecated'), E_USER_DEPRECATED);
$input->setOption('format', 'xml');
}
$helper = new DescriptorHelper();
$helper->describe(
$this->getIo(),
$this->command,
[
'format' => $input->getOption('format'),
'raw_text' => $input->getOption('raw'),
'command_name' => $input->getArgument('command_name'),
'translator' => $this->getApplication()->getTranslator()
]
);
$this->command = null;
$this->getIo()->newLine();
}
/**
* {@inheritdoc}
*/
private function createDefinition()
{
return new InputDefinition(
[
new InputArgument('command_name', InputArgument::OPTIONAL, $this->trans('commands.help.arguments.command-name'), 'help'),
new InputOption('xml', null, InputOption::VALUE_NONE, $this->trans('commands.help.options.xml')),
new InputOption('raw', null, InputOption::VALUE_NONE, $this->trans('commands.help.options.raw')),
new InputOption('format', null, InputOption::VALUE_REQUIRED, $this->trans('commands.help.options.format'), 'txt'),
]
);
}
}

View file

@ -0,0 +1,314 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\InitCommand.
*/
namespace Drupal\Console\Core\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Process\ProcessBuilder;
use Symfony\Component\Finder\Finder;
use Drupal\Console\Core\Utils\ConfigurationManager;
use Drupal\Console\Core\Generator\InitGenerator;
use Drupal\Console\Core\Utils\ShowFile;
/**
* Class InitCommand
*
* @package Drupal\Console\Core\Command
*/
class InitCommand extends Command
{
/**
* @var ShowFile
*/
protected $showFile;
/**
* @var ConfigurationManager
*/
protected $configurationManager;
/**
* @var string
*/
protected $appRoot;
/**
* @var string
*/
protected $consoleRoot;
/**
* @var InitGenerator
*/
protected $generator;
private $configParameters = [
'language' => 'en',
'temp' => '/tmp',
'chain' => false,
'sites' => false,
'learning' => false,
'generate_inline' => false,
'generate_chain' => false
];
private $directories = [
'chain',
'sites',
];
/**
* InitCommand constructor.
*
* @param ShowFile $showFile
* @param ConfigurationManager $configurationManager
* @param InitGenerator $generator
* @param string $appRoot
* @param string $consoleRoot
*/
public function __construct(
ShowFile $showFile,
ConfigurationManager $configurationManager,
InitGenerator $generator,
$appRoot,
$consoleRoot = null
) {
$this->showFile = $showFile;
$this->configurationManager = $configurationManager;
$this->generator = $generator;
$this->appRoot = $appRoot;
$this->consoleRoot = $consoleRoot;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('init')
->setDescription($this->trans('commands.init.description'))
->addOption(
'destination',
null,
InputOption::VALUE_OPTIONAL,
$this->trans('commands.init.options.destination')
)
->addOption(
'site',
null,
InputOption::VALUE_NONE,
$this->trans('commands.init.options.site')
)
->addOption(
'override',
null,
InputOption::VALUE_NONE,
$this->trans('commands.init.options.override')
)
->addOption(
'autocomplete',
null,
InputOption::VALUE_NONE,
$this->trans('commands.init.options.autocomplete')
);
}
/**
* {@inheritdoc}
*/
protected function interact(InputInterface $input, OutputInterface $output)
{
$destination = $input->getOption('destination');
$site = $input->getOption('site');
$autocomplete = $input->getOption('autocomplete');
$configuration = $this->configurationManager->getConfiguration();
if ($site && $this->appRoot && $this->consoleRoot) {
$destination = $this->consoleRoot . '/console/';
}
if (!$destination) {
if ($this->appRoot && $this->consoleRoot) {
$destination = $this->getIo()->choice(
$this->trans('commands.init.questions.destination'),
$this->configurationManager->getConfigurationDirectories()
);
} else {
$destination = $this->configurationManager
->getConsoleDirectory();
}
$input->setOption('destination', $destination);
}
$this->configParameters['language'] = $this->getIo()->choiceNoList(
$this->trans('commands.init.questions.language'),
array_keys($configuration->get('application.languages'))
);
$this->configParameters['temp'] = $this->getIo()->ask(
$this->trans('commands.init.questions.temp'),
'/tmp'
);
$this->configParameters['chain'] = $this->getIo()->confirm(
$this->trans('commands.init.questions.chain'),
false
);
$this->configParameters['sites'] = $this->getIo()->confirm(
$this->trans('commands.init.questions.sites'),
false
);
$this->configParameters['learning'] = $this->getIo()->confirm(
$this->trans('commands.init.questions.learning'),
false
);
$this->configParameters['generate_inline'] = $this->getIo()->confirm(
$this->trans('commands.init.questions.generate-inline'),
false
);
$this->configParameters['generate_chain'] = $this->getIo()->confirm(
$this->trans('commands.init.questions.generate-chain'),
false
);
if (!$autocomplete) {
$autocomplete = $this->getIo()->confirm(
$this->trans('commands.init.questions.autocomplete'),
false
);
$input->setOption('autocomplete', $autocomplete);
}
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$copiedFiles = [];
$destination = $input->getOption('destination');
$site = $input->getOption('site');
$autocomplete = $input->getOption('autocomplete');
$override = $input->getOption('override');
if ($site && $this->appRoot && $this->consoleRoot) {
$destination = $this->consoleRoot . '/console/';
}
if (!$destination) {
$destination = $this->configurationManager->getConsoleDirectory();
}
$finder = new Finder();
$finder->in(
sprintf(
'%sdist/',
$this->configurationManager->getVendorCoreRoot()
)
);
if (!$this->configParameters['chain']) {
$finder->exclude('chain');
}
if (!$this->configParameters['sites']) {
$finder->exclude('sites');
}
$finder->files();
foreach ($finder as $configFile) {
$sourceFile = sprintf(
'%sdist/%s',
$this->configurationManager->getVendorCoreRoot(),
$configFile->getRelativePathname()
);
$destinationFile = sprintf(
'%s%s',
$destination,
$configFile->getRelativePathname()
);
$fs = new Filesystem();
foreach ($this->directories as $directory) {
if (!$fs->exists($destination.$directory)) {
$fs->mkdir($destination.$directory);
}
}
if ($this->copyFile($sourceFile, $destinationFile, $override)) {
$copiedFiles[] = $destinationFile;
}
}
if ($copiedFiles) {
$this->showFile->copiedFiles($this->getIo(), $copiedFiles, false);
$this->getIo()->newLine();
}
$executableName = null;
if ($autocomplete) {
$processBuilder = new ProcessBuilder(['bash']);
$process = $processBuilder->getProcess();
$process->setCommandLine('echo $_');
$process->run();
$fullPathExecutable = explode('/', $process->getOutput());
$executableName = trim(end($fullPathExecutable));
$process->stop();
}
$this->generator->generate([
'user_home' => $this->configurationManager->getConsoleDirectory(),
'executable_name' => $executableName,
'override' => $override,
'destination' => $destination,
'config_parameters' => $this->configParameters,
]);
$this->getIo()->writeln($this->trans('application.messages.autocomplete'));
return 0;
}
/**
* @param string $source
* @param string $destination
* @param string $override
* @return bool
*/
private function copyFile($source, $destination, $override)
{
if (file_exists($destination)) {
if ($override) {
copy(
$destination,
$destination . '.old'
);
} else {
return false;
}
}
$filePath = dirname($destination);
if (!is_dir($filePath)) {
mkdir($filePath, 0777, true);
}
return copy(
$source,
$destination
);
}
}

View file

@ -0,0 +1,85 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\ListCommand.
*/
namespace Drupal\Console\Core\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Drupal\Console\Core\Helper\DescriptorHelper;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Class ListCommand
*
* @package Drupal\Console\Core\Command
*/
class ListCommand extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('list')
->setDefinition($this->createDefinition())
->setDescription($this->trans('commands.list.description'))
->setHelp($this->trans('commands.list.help'));
}
/**
* {@inheritdoc}
*/
public function getNativeDefinition()
{
return $this->createDefinition();
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if ($input->getOption('xml')) {
$this->getIo()->info(
'The --xml option was deprecated in version 2.7 and will be removed in version 3.0. Use the --format option instead',
E_USER_DEPRECATED
);
$input->setOption('format', 'xml');
}
$commandName = $input->getFirstArgument()?$input->getFirstArgument():'help';
$helper = new DescriptorHelper();
$helper->describe(
$this->getIo(),
$this->getApplication(),
[
'format' => $input->getOption('format'),
'raw_text' => $input->getOption('raw'),
'namespace' => $input->getArgument('namespace'),
'translator' => $this->getApplication()->getTranslator(),
'command' => $this->getApplication()->find($commandName)
]
);
$this->getIo()->newLine();
}
/**
* {@inheritdoc}
*/
private function createDefinition()
{
return new InputDefinition(
[
new InputArgument('namespace', InputArgument::OPTIONAL, $this->trans('commands.list.arguments.namespace')),
new InputOption('xml', null, InputOption::VALUE_NONE, $this->trans('commands.list.options.xml')),
new InputOption('raw', null, InputOption::VALUE_NONE, $this->trans('commands.list.options.raw')),
new InputOption('format', null, InputOption::VALUE_REQUIRED, $this->trans('commands.list.options.format'), 'txt'),
]
);
}
}

View file

@ -0,0 +1,176 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Command\Settings\SetCommand.
*/
namespace Drupal\Console\Core\Command\Settings;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Yaml\Dumper;
use Symfony\Component\Yaml\Parser;
use Drupal\Console\Core\Command\Command;
use Drupal\Console\Core\Utils\ConfigurationManager;
use Drupal\Console\Core\Utils\NestedArray;
/**
* Class SetCommand
*
* @package Drupal\Console\Core\Command\Settings
*/
class SetCommand extends Command
{
/**
* @var ConfigurationManager
*/
protected $configurationManager;
/**
* @var NestedArray
*/
protected $nestedArray;
/**
* CheckCommand constructor.
*
* @param ConfigurationManager $configurationManager
* @param NestedArray $nestedArray
*/
public function __construct(
ConfigurationManager $configurationManager,
NestedArray $nestedArray
) {
$this->configurationManager = $configurationManager;
$this->nestedArray = $nestedArray;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('settings:set')
->addArgument(
'name',
InputArgument::REQUIRED,
$this->trans('commands.settings.set.arguments.name'),
null
)
->addArgument(
'value',
InputArgument::REQUIRED,
$this->trans('commands.settings.set.arguments.value'),
null
)
->setDescription($this->trans('commands.settings.set.description'));
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$parser = new Parser();
$dumper = new Dumper();
$settingName = $input->getArgument('name');
$settingValue = $input->getArgument('value');
$userConfigFile = sprintf(
'%s/.console/config.yml',
$this->configurationManager->getHomeDirectory()
);
if (!file_exists($userConfigFile)) {
$this->getIo()->error(
sprintf(
$this->trans('commands.settings.set.messages.missing-file'),
$userConfigFile
)
);
return 1;
}
try {
$userConfigFileParsed = $parser->parse(
file_get_contents($userConfigFile)
);
} catch (\Exception $e) {
$this->getIo()->error(
$this->trans(
'commands.settings.set.messages.error-parsing'
) . ': ' . $e->getMessage()
);
return 1;
}
$parents = array_merge(['application'], explode(".", $settingName));
$this->nestedArray->setValue(
$userConfigFileParsed,
$parents,
$settingValue,
true
);
try {
$userConfigFileDump = $dumper->dump($userConfigFileParsed, 10);
} catch (\Exception $e) {
$this->getIo()->error(
[
$this->trans('commands.settings.set.messages.error-generating'),
$e->getMessage()
]
);
return 1;
}
if ($settingName == 'language') {
$this->getApplication()
->getTranslator()
->changeCoreLanguage($settingValue);
$translatorLanguage = $this->getApplication()->getTranslator()->getLanguage();
if ($translatorLanguage != $settingValue) {
$this->getIo()->error(
sprintf(
$this->trans('commands.settings.set.messages.missing-language'),
$settingValue
)
);
return 1;
}
}
try {
file_put_contents($userConfigFile, $userConfigFileDump);
} catch (\Exception $e) {
$this->getIo()->error(
[
$this->trans('commands.settings.set.messages.error-writing'),
$e->getMessage()
]
);
return 1;
}
$this->getIo()->success(
sprintf(
$this->trans('commands.settings.set.messages.success'),
$settingName,
$settingValue
)
);
return 0;
}
}

View file

@ -0,0 +1,79 @@
<?php
/**
* @file
* Contains Drupal\Console\Core\Command\Shared\CommandTrait.
*/
namespace Drupal\Console\Core\Command\Shared;
use Drupal\Console\Core\Utils\TranslatorManagerInterface;
/**
* Class CommandTrait
*
* @package Drupal\Console\Core\Command
*/
trait CommandTrait
{
/**
* @var TranslatorManagerInterface
*/
protected $translator;
/**
* @param $translator
*/
public function setTranslator($translator)
{
$this->translator = $translator;
}
/**
* @param $key string
*
* @return string
*/
public function trans($key)
{
if (!$this->translator) {
return $key;
}
return $this->translator->trans($key);
}
/**
* @inheritdoc
*/
public function getDescription()
{
$description = sprintf(
'commands.%s.description',
str_replace(':', '.', $this->getName())
);
if (parent::getDescription()==$description) {
return $this->trans($description);
}
return parent::getDescription();
}
/**
* @inheritdoc
*/
public function getHelp()
{
$help = sprintf(
'commands.%s.help',
str_replace(':', '.', $this->getName())
);
if (parent::getHelp()==$help) {
return $this->trans($help);
}
return parent::getHelp();
}
}

View file

@ -0,0 +1,58 @@
<?php
/**
* @file
* Contains Drupal\Console\Core\Command\Shared\ContainerAwareCommandTrait.
*/
namespace Drupal\Console\Core\Command\Shared;
/**
* Class CommandTrait
*
* @package Drupal\Console\Core\Command
*/
trait ContainerAwareCommandTrait
{
use CommandTrait;
protected $container;
/**
* @param mixed $container
*/
public function setContainer($container)
{
$this->container = $container;
}
/**
* @param $key
* @return null|object
*/
public function has($key)
{
if (!$key) {
return null;
}
return $this->container->has($key);
}
/**
* @param $key
* @return null|object
*/
public function get($key)
{
if (!$key) {
return null;
}
if ($this->has($key)) {
return $this->container->get($key);
}
return null;
}
}

View file

@ -0,0 +1,56 @@
<?php
/**
* @file
* Contains Drupal\Console\Core\Command\Shared\InputTrait.
*/
namespace Drupal\Console\Core\Command\Shared;
/**
* Class InputTrait
*
* @package Drupal\Console\Core\Command\Shared
*/
trait InputTrait
{
/**
* @return array
*/
private function inlineValueAsArray($inputValue)
{
$inputAsArray = [];
foreach ($inputValue as $key => $value) {
if (!is_array($value)) {
try {
$inputAsArray[] = json_decode('[{'.$value.'}]', true)[0];
} catch (\Exception $e) {
continue;
}
}
}
return $inputAsArray?$inputAsArray:$inputValue;
}
/**
* @return array
*/
private function placeHolderInlineValueAsArray($inputValue)
{
$inputArrayValue = [];
foreach ($inputValue as $key => $value) {
if (!is_array($value)) {
$separatorIndex = strpos($value, ':');
if (!$separatorIndex) {
continue;
}
$inputKeyItem = substr($value, 0, $separatorIndex);
$inputValueItem = substr($value, $separatorIndex+1);
$inputArrayValue[$inputKeyItem] = $inputValueItem;
}
}
return $inputArrayValue?$inputArrayValue:$inputValue;
}
}

View file

@ -0,0 +1,378 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Drupal\Console\Core\Descriptor;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Descriptor\Descriptor;
use Symfony\Component\Console\Descriptor\ApplicationDescription;
/**
* Text descriptor.
*
* @author Jean-François Simon <contact@jfsimon.fr>
*
* @internal
*/
class TextDescriptor extends Descriptor
{
/**
* {@inheritdoc}
*/
protected function describeInputArgument(InputArgument $argument, array $options = [])
{
if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
$default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
} else {
$default = '';
}
$totalWidth = isset($options['total_width']) ? $options['total_width'] : strlen($argument->getName());
$spacingWidth = $totalWidth - strlen($argument->getName()) + 2;
$this->writeText(
sprintf(
' <info>%s</info>%s%s%s',
$argument->getName(),
str_repeat(' ', $spacingWidth),
// + 17 = 2 spaces + <info> + </info> + 2 spaces
preg_replace(
'/\s*\R\s*/',
PHP_EOL.str_repeat(' ', $totalWidth + 17),
$options['translator']->trans($argument->getDescription())
),
$default
), $options
);
}
/**
* {@inheritdoc}
*/
protected function describeInputOption(InputOption $option, array $options = [])
{
if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
$default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
} else {
$default = '';
}
$value = '';
if ($option->acceptValue()) {
$value = '='.strtoupper($option->getName());
if ($option->isValueOptional()) {
$value = '['.$value.']';
}
}
$totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions([$option]);
$synopsis = sprintf(
'%s%s',
$option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ',
sprintf('--%s%s', $option->getName(), $value)
);
$spacingWidth = $totalWidth - strlen($synopsis) + 2;
$this->writeText(
sprintf(
' <info>%s</info>%s%s%s%s',
$synopsis,
str_repeat(' ', $spacingWidth),
// + 17 = 2 spaces + <info> + </info> + 2 spaces
preg_replace(
'/\s*\R\s*/',
"\n".str_repeat(' ', $totalWidth + 17),
$options['translator']->trans($option->getDescription())
),
$default,
$option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
), $options
);
}
/**
* {@inheritdoc}
*/
protected function describeInputDefinition(InputDefinition $definition, array $options = [])
{
$command_name = null;
if (array_key_exists('command', $options)) {
$command_name = $options['command']->getName();
}
$totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
foreach ($definition->getArguments() as $argument) {
$totalWidth = max($totalWidth, strlen($argument->getName()));
}
if ($definition->getArguments()) {
$this->writeText($options['translator']->trans('commands.list.messages.arguments'), $options);
$this->writeText("\n");
foreach ($definition->getArguments() as $argument) {
$this->describeInputArgument($argument, array_merge($options, ['total_width' => $totalWidth]));
$this->writeText("\n");
}
}
if ($definition->getArguments() && $definition->getOptions()) {
$this->writeText("\n");
}
if ($definition->getOptions()) {
$laterOptions = [];
$this->writeText($options['translator']->trans('commands.list.messages.options'), $options);
$exitOptionName = 'help';
if ($command_name === $exitOptionName) {
$exitOptionName = '';
}
foreach ($definition->getOptions() as $option) {
if ($option->getName() === $exitOptionName) {
break;
}
if (strlen($option->getShortcut()) > 1) {
$laterOptions[] = $option;
continue;
}
$this->writeText("\n");
$this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth]));
}
foreach ($laterOptions as $option) {
$this->writeText("\n");
$this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth]));
}
}
}
/**
* {@inheritdoc}
*/
protected function describeCommand(Command $command, array $options = [])
{
$namespace = substr(
$command->getName(),
0,
(strpos($command->getName(), ':')?:0)
);
$commandData = $command->getApplication()->getData();
$examples = [];
if (array_key_exists($namespace, $commandData['commands'])) {
$commands = $commandData['commands'][$namespace];
foreach ($commands as $item) {
if ($item['name'] == $command->getName()) {
$examples = $item['examples'];
break;
}
}
}
$command->getSynopsis(true);
$command->getSynopsis(false);
$command->mergeApplicationDefinition(false);
$this->writeText($command->trans('commands.list.messages.usage'), $options);
foreach (array_merge([$command->getSynopsis(true)], $command->getAliases(), $command->getUsages()) as $key => $usage) {
if ($key > 0) {
$this->writeText("\n");
}
$this->writeText(' '.$usage, $options);
}
$this->writeText("\n");
$definition = $command->getNativeDefinition();
if ($definition->getOptions() || $definition->getArguments()) {
$this->writeText("\n");
$options =
array_merge(
$options,
[ 'command' => $command ]
);
$this->describeInputDefinition($definition, $options);
$this->writeText("\n");
}
if ($examples) {
$this->writeText("\n");
$this->writeText("<comment>Examples:</comment>", $options);
foreach ($examples as $key => $example) {
$this->writeText("\n");
if ($key != 0) {
$this->writeText("\n");
}
$this->writeText(' <info>'.$example['description'].'</info>');
$this->writeText("\n");
$this->writeText(' '.$example['execution']);
}
}
if ($help = $command->getProcessedHelp()) {
$this->writeText("\n");
$this->writeText($command->trans('commands.list.messages.help'), $options);
$this->writeText("\n");
$this->writeText(' '.str_replace("\n", "\n ", $help), $options);
$this->writeText("\n");
}
}
/**
* {@inheritdoc}
*/
protected function describeApplication(Application $application, array $options = [])
{
$describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
$description = new ApplicationDescription($application, $describedNamespace);
if (isset($options['raw_text']) && $options['raw_text']) {
$width = $this->getColumnWidth($description->getCommands());
foreach ($description->getCommands() as $command) {
$this->writeText(sprintf("%-${width}s %s", $command->getName(), $command->getDescription()), $options);
$this->writeText("\n");
}
} else {
if ('' != $help = $application->getHelp()) {
$this->writeText("$help\n\n", $options);
}
if (empty($describedNamespace)) {
$this->writeText(
$application->trans('commands.list.messages.usage'),
$options
);
$this->writeText(
$application->trans(
'commands.list.messages.usage-details'
),
$options
);
$options['application'] = $application;
$this->describeInputDefinition(
new InputDefinition(
$application->getDefinition()->getOptions()
),
$options
);
$this->writeText("\n");
$this->writeText("\n");
}
$width = $this->getColumnWidth($description->getCommands()) + 4;
if ($describedNamespace) {
$this->writeText(sprintf($application->trans('commands.list.messages.comment'), $describedNamespace), $options);
} else {
$this->writeText($application->trans('commands.list.messages.available-commands'), $options);
}
$singleCommands = [
'about',
'chain',
'check',
'composerize',
'exec',
'help',
'init',
'list',
'shell',
'server'
];
// add commands by namespace
foreach ($description->getNamespaces() as $namespace) {
if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
$this->writeText("\n");
$this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
}
foreach ($namespace['commands'] as $name) {
if (ApplicationDescription::GLOBAL_NAMESPACE == $namespace['id']) {
if (!in_array($name, $singleCommands)) {
continue;
}
}
$this->writeText("\n");
$alias = '';
if ($description->getCommand($name)->getAliases()) {
$alias = sprintf(
'(%s)',
implode(',', $description->getCommand($name)->getAliases())
);
}
$spacingWidth = $width - strlen($name.$alias);
if ($spacingWidth < 0) {
$spacingWidth = 0;
}
$this->writeText(
sprintf(
' <info>%s</info> <comment>%s</comment> %s%s',
$name,
$alias,
str_repeat(' ', $spacingWidth),
$description->getCommand($name)->getDescription(
)
),
$options
);
}
}
$this->writeText("\n");
}
}
/**
* {@inheritdoc}
*/
private function writeText($content, array $options = [])
{
$this->write(
isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
isset($options['raw_output']) ? !$options['raw_output'] : true
);
}
/**
* Formats input option/argument default value.
*
* @param mixed $default
*
* @return string
*/
private function formatDefaultValue($default)
{
if (PHP_VERSION_ID < 50400) {
return str_replace('\/', '/', json_encode($default));
}
return json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
/**
* @param Command[] $commands
*
* @return int
*/
private function getColumnWidth(array $commands)
{
$width = 0;
foreach ($commands as $command) {
$width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width;
}
return $width + 2;
}
/**
* @param InputOption[] $options
*
* @return int
*/
private function calculateTotalWidthForOptions($options)
{
$totalWidth = 0;
foreach ($options as $option) {
// "-" + shortcut + ", --" + name
$nameLength = 1 + max(strlen($option->getShortcut()), 1) + 4 + strlen($option->getName());
if ($option->acceptValue()) {
$valueLength = 1 + strlen($option->getName()); // = + value
$valueLength += $option->isValueOptional() ? 2 : 0; // [ + ]
$nameLength += $valueLength;
}
$totalWidth = max($totalWidth, $nameLength);
}
return $totalWidth;
}
}

View file

@ -0,0 +1,93 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\EventSubscriber\CallCommandListener.
*/
namespace Drupal\Console\Core\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Command\Command;
use Drupal\Console\Core\Utils\ChainQueue;
use Drupal\Console\Core\Style\DrupalStyle;
/**
* Class CallCommandListener
*
* @package Drupal\Console\Core\EventSubscriber
*/
class CallCommandListener implements EventSubscriberInterface
{
/**
* @var ChainQueue
*/
protected $chainQueue;
/**
* CallCommandListener constructor.
*
* @param ChainQueue $chainQueue
*/
public function __construct(ChainQueue $chainQueue)
{
$this->chainQueue = $chainQueue;
}
/**
* @param ConsoleTerminateEvent $event
*/
public function callCommands(ConsoleTerminateEvent $event)
{
$command = $event->getCommand();
/* @var DrupalStyle $io */
$io = new DrupalStyle($event->getInput(), $event->getOutput());
if (!$command instanceof Command) {
return 0;
}
$application = $command->getApplication();
$commands = $this->chainQueue->getCommands();
if (!$commands) {
return 0;
}
foreach ($commands as $chainedCommand) {
$callCommand = $application->find($chainedCommand['name']);
if (!$callCommand) {
continue;
}
$input = new ArrayInput($chainedCommand['inputs']);
if (!is_null($chainedCommand['interactive'])) {
$input->setInteractive($chainedCommand['interactive']);
}
$io->text($chainedCommand['name']);
$allowFailure = array_key_exists('allow_failure', $chainedCommand)?$chainedCommand['allow_failure']:false;
try {
$callCommand->run($input, $io);
} catch (\Exception $e) {
if (!$allowFailure) {
$io->error($e->getMessage());
return 1;
}
}
}
}
/**
* @{@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [ConsoleEvents::TERMINATE => 'callCommands'];
}
}

View file

@ -0,0 +1,146 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\EventSubscriber\DefaultValueEventListener.
*/
namespace Drupal\Console\Core\EventSubscriber;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Console\Command\Command;
use Drupal\Console\Core\Utils\ConfigurationManager;
/**
* Class DefaultValueEventListener
*
* @package Drupal\Console\Core\EventSubscriber
*/
class DefaultValueEventListener implements EventSubscriberInterface
{
/**
* @var ConfigurationManager
*/
protected $configurationManager;
/**
* @var array
*/
private $skipCommands = [
'self-update',
'list',
'chain',
'drush'
];
/**
* DefaultValueEventListener constructor.
*
* @param ConfigurationManager $configurationManager
*/
public function __construct(
ConfigurationManager $configurationManager
) {
$this->configurationManager = $configurationManager;
}
/**
* @param ConsoleCommandEvent $event
*/
public function setDefaultValues(ConsoleCommandEvent $event)
{
/* @var Command $command */
$command = $event->getCommand();
$configuration = $this->configurationManager
->getConfiguration();
if (in_array($command->getName(), $this->skipCommands)) {
return;
}
$inputDefinition = $command->getDefinition();
$input = $event->getInput();
$commandConfigKey = sprintf(
'application.commands.defaults.%s',
str_replace(':', '.', $command->getName())
);
$defaults = $configuration->get($commandConfigKey);
$this->setOptions($defaults, $input, $inputDefinition);
$this->setArguments($defaults, $input, $inputDefinition);
}
private function setOptions($defaults, $input, $inputDefinition)
{
$defaultOptions = $this->extractKey($defaults, 'options');
$defaultValues = [];
if ($defaultOptions) {
$reflection = new \ReflectionObject($input);
$prop = $reflection->getProperty('tokens');
$prop->setAccessible(true);
$tokens = $prop->getValue($input);
foreach ($defaultOptions as $key => $defaultValue) {
$option = $inputDefinition->getOption($key);
if ($input->getOption($key)) {
continue;
}
if ($option->acceptValue()) {
$defaultValues[] = sprintf(
'--%s=%s',
$key,
$defaultValue
);
continue;
}
$defaultValues[] = sprintf(
'--%s',
$key
);
}
$prop->setValue(
$input,
array_unique(array_merge($tokens, $defaultValues))
);
}
}
private function setArguments($defaults, $input, $inputDefinition)
{
$defaultArguments = $this->extractKey($defaults, 'arguments');
foreach ($defaultArguments as $key => $defaultValue) {
if ($input->getArgument($key)) {
continue;
}
if ($argument = $inputDefinition->getArgument($key)) {
$argument->setDefault($defaultValue);
}
}
}
private function extractKey($defaults, $key)
{
if (!$defaults || !is_array($defaults)) {
return [];
}
$defaults = array_key_exists($key, $defaults)?$defaults[$key]:[];
if (!is_array($defaults)) {
return [];
}
return $defaults;
}
/**
* @{@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [ConsoleEvents::COMMAND => 'setDefaultValues'];
}
}

View file

@ -0,0 +1,64 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\EventSubscriber\RemoveMessagesListener.
*/
namespace Drupal\Console\Core\EventSubscriber;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\Console\Core\Command\Command;
use Drupal\Console\Core\Utils\TranslatorManagerInterface;
use Drupal\Console\Core\Utils\MessageManager;
/**
* Class RemoveMessagesListener
*
* @package Drupal\Console\Core\EventSubscriber
*/
class RemoveMessagesListener implements EventSubscriberInterface
{
/**
* @var MessageManager
*/
protected $messageManager;
/**
* ShowGenerateInlineListener constructor.
*
* @param MessageManager $messageManager
*/
public function __construct(
MessageManager $messageManager
) {
$this->messageManager = $messageManager;
}
/**
* @param ConsoleTerminateEvent $event
*/
public function removeMessages(ConsoleTerminateEvent $event)
{
if ($event->getExitCode() != 0) {
return;
}
/* @var Command $command */
$command = $event->getCommand();
$commandName = $command->getName();
$this->messageManager->remove($commandName);
}
/**
* @{@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [ConsoleEvents::TERMINATE => 'removeMessages'];
}
}

View file

@ -0,0 +1,136 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\EventSubscriber\ShowGenerateChainListener.
*/
namespace Drupal\Console\Core\EventSubscriber;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Yaml\Dumper;
use Symfony\Component\Console\Command\Command;
use Drupal\Console\Core\Utils\TranslatorManagerInterface;
use Drupal\Console\Core\Style\DrupalStyle;
/**
* Class ShowGenerateChainListener
*
* @package Drupal\Console\Core\EventSubscriber
*/
class ShowGenerateChainListener implements EventSubscriberInterface
{
/**
* @var TranslatorManagerInterface
*/
protected $translator;
/**
* @var array
*/
private $skipCommands = [
'self-update',
'list',
'help',
'drush'
];
/**
* @var array
*/
private $skipOptions = [
'env',
'generate-inline',
'generate-chain',
'no-interaction'
];
/**
* @var array
*/
private $skipArguments = [
'command',
'command_name'
];
/**
* ShowGenerateChainListener constructor.
*
* @param TranslatorManagerInterface $translator
*/
public function __construct(
TranslatorManagerInterface $translator
) {
$this->translator = $translator;
}
/**
* @param ConsoleTerminateEvent $event
*/
public function showGenerateChain(ConsoleTerminateEvent $event)
{
if ($event->getExitCode() != 0) {
return;
}
/* @var Command $command */
$command = $event->getCommand();
/* @var DrupalStyle $io */
$io = new DrupalStyle($event->getInput(), $event->getOutput());
$command_name = $command->getName();
$this->skipArguments[] = $command_name;
if (in_array($command->getName(), $this->skipCommands)) {
return;
}
$input = $event->getInput();
if ($input->getOption('generate-chain')) {
$options = array_filter($input->getOptions());
foreach ($this->skipOptions as $remove_option) {
unset($options[$remove_option]);
}
$arguments = array_filter($input->getArguments());
foreach ($this->skipArguments as $remove_argument) {
unset($arguments[$remove_argument]);
}
$commandData['command'] = $command_name;
if ($options) {
$commandData['options'] = $options;
}
if ($arguments) {
$commandData['arguments'] = $arguments;
}
$io->commentBlock(
$this->translator->trans('application.messages.chain.generated')
);
$dumper = new Dumper();
$tableRows = [
' -',
$dumper->dump($commandData, 4)
];
$io->writeln('commands:');
$io->table([], [$tableRows], 'compact');
}
}
/**
* @{@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [ConsoleEvents::TERMINATE => 'showGenerateChain'];
}
}

View file

@ -0,0 +1,81 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\EventSubscriber\ShowGenerateCountCodeLinesListener.
*/
namespace Drupal\Console\Core\EventSubscriber;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Console\Command\Command;
use Drupal\Console\Core\Utils\TranslatorManagerInterface;
use Drupal\Console\Core\Utils\CountCodeLines;
use Drupal\Console\Core\Style\DrupalStyle;
/**
* Class ShowGenerateCountCodeLinesListener
*
* @package Drupal\Console\Core\EventSubscriber
*/
class ShowGenerateCountCodeLinesListener implements EventSubscriberInterface
{
/**
* @var ShowGenerateChainListener
*/
protected $countCodeLines;
/**
* @var TranslatorManagerInterface
*/
protected $translator;
/**
* ShowGenerateChainListener constructor.
*
* @param TranslatorManagerInterface $translator
*
* @param CountCodeLines $countCodeLines
*/
public function __construct(
TranslatorManagerInterface $translator,
CountCodeLines $countCodeLines
) {
$this->translator = $translator;
$this->countCodeLines = $countCodeLines;
}
/**
* @param ConsoleTerminateEvent $event
*/
public function showGenerateCountCodeLines(ConsoleTerminateEvent $event)
{
if ($event->getExitCode() != 0) {
return;
}
/* @var DrupalStyle $io */
$io = new DrupalStyle($event->getInput(), $event->getOutput());
$countCodeLines = $this->countCodeLines->getCountCodeLines();
if ($countCodeLines > 0) {
$io->commentBlock(
sprintf(
$this->translator->trans('application.messages.lines-code'),
$countCodeLines
)
);
}
}
/**
* @{@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [ConsoleEvents::TERMINATE => 'showGenerateCountCodeLines'];
}
}

View file

@ -0,0 +1,163 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\EventSubscriber\ShowGenerateInlineListener.
*/
namespace Drupal\Console\Core\EventSubscriber;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Console\Command\Command;
use Drupal\Console\Core\Utils\TranslatorManagerInterface;
use Drupal\Console\Core\Style\DrupalStyle;
/**
* Class ShowGenerateInlineListener
*
* @package Drupal\Console\Core\EventSubscriber
*/
class ShowGenerateInlineListener implements EventSubscriberInterface
{
/**
* @var TranslatorManagerInterface
*/
protected $translator;
/**
* @var array
*/
private $skipCommands = [
'self-update',
'list',
'help',
'drush'
];
/**
* @var array
*/
private $skipOptions = [
'env',
'generate-inline',
'generate-chain',
'no-interaction'
];
/**
* @var array
*/
private $skipArguments = [
'command',
'command_name'
];
/**
* ShowGenerateInlineListener constructor.
*
* @param TranslatorManagerInterface $translator
*/
public function __construct(
TranslatorManagerInterface $translator
) {
$this->translator = $translator;
}
/**
* @param ConsoleTerminateEvent $event
*/
public function showGenerateInline(ConsoleTerminateEvent $event)
{
if ($event->getExitCode() != 0) {
return;
}
/* @var Command $command */
$command = $event->getCommand();
/* @var DrupalStyle $io */
$io = new DrupalStyle($event->getInput(), $event->getOutput());
$command_name = $command->getName();
$this->skipArguments[] = $command_name;
if (in_array($command->getName(), $this->skipCommands)) {
return;
}
$input = $event->getInput();
if ($input->getOption('generate-inline')) {
$options = array_filter($input->getOptions());
foreach ($this->skipOptions as $remove_option) {
unset($options[$remove_option]);
}
$arguments = array_filter($input->getArguments());
foreach ($this->skipArguments as $remove_argument) {
unset($arguments[$remove_argument]);
}
$inline = '';
foreach ($arguments as $argument_id => $argument) {
if (is_array($argument)) {
$argument = implode(" ", $argument);
} elseif (strstr($argument, ' ')) {
$argument = '"' . $argument . '"';
}
$inline .= " $argument";
}
// Refactor and remove nested levels. Then apply to arguments.
foreach ($options as $optionName => $optionValue) {
if (is_array($optionValue)) {
foreach ($optionValue as $optionItem) {
if (is_array($optionItem)) {
$inlineValue = implode(
', ', array_map(
function ($v, $k) {
return '"'.$k . '":"' . $v . '"';
},
$optionItem,
array_keys($optionItem)
)
);
} else {
$inlineValue = $optionItem;
}
$inline .= ' --' . $optionName . '=\'' . $inlineValue . '\'';
}
} else {
if (is_bool($optionValue)) {
$inline.= ' --' . $optionName;
} else {
$inline.= ' --' . $optionName . '="' . $optionValue . '"';
}
}
}
// Print YML output and message
$io->commentBlock(
$this->translator->trans('application.messages.inline.generated')
);
$io->writeln(
sprintf(
'$ drupal %s %s --no-interaction',
$command_name,
$inline
)
);
}
}
/**
* @{@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [ConsoleEvents::TERMINATE => 'showGenerateInline'];
}
}

View file

@ -0,0 +1,78 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\EventSubscriber\ShowGeneratedFilesListener.
*/
namespace Drupal\Console\Core\EventSubscriber;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Console\Command\Command;
use Drupal\Console\Core\Style\DrupalStyle;
use Drupal\Console\Core\Utils\FileQueue;
use Drupal\Console\Core\Utils\ShowFile;
/**
* Class ShowGeneratedFilesListener
*
* @package Drupal\Console\Core\EventSubscriber
*/
class ShowGeneratedFilesListener implements EventSubscriberInterface
{
/**
* @var FileQueue
*/
protected $fileQueue;
/**
* @var ShowFile
*/
protected $showFile;
/**
* ShowGeneratedFilesListener constructor.
*
* @param FileQueue $fileQueue
* @param ShowFile $showFile
*/
public function __construct(FileQueue $fileQueue, ShowFile $showFile)
{
$this->fileQueue = $fileQueue;
$this->showFile = $showFile;
}
/**
* @param ConsoleTerminateEvent $event
*/
public function showGeneratedFiles(ConsoleTerminateEvent $event)
{
/* @var Command $command */
$command = $event->getCommand();
/* @var DrupalStyle $io */
$io = new DrupalStyle($event->getInput(), $event->getOutput());
if ($event->getExitCode() != 0) {
return;
}
if ('self-update' == $command->getName()) {
return;
}
$files = $this->fileQueue->getFiles();
if ($files) {
$this->showFile->generatedFiles($io, $files, true);
}
}
/**
* @{@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [ConsoleEvents::TERMINATE => 'showGeneratedFiles'];
}
}

View file

@ -0,0 +1,93 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\EventSubscriber\ShowTipsListener.
*/
namespace Drupal\Console\Core\EventSubscriber;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Console\Command\Command;
use Drupal\Console\Core\Utils\TranslatorManagerInterface;
use Drupal\Console\Core\Style\DrupalStyle;
/**
* Class ShowTipsListener
*
* @package Drupal\Console\Core\EventSubscriber
*/
class ShowTipsListener implements EventSubscriberInterface
{
/**
* @var TranslatorManagerInterface
*/
protected $translator;
/**
* ShowGenerateChainListener constructor.
*
* @param TranslatorManagerInterface $translator
*/
public function __construct(
TranslatorManagerInterface $translator
) {
$this->translator = $translator;
}
/**
* @param ConsoleCommandEvent $event
*/
public function showTips(ConsoleCommandEvent $event)
{
/* @var Command $command */
$command = $event->getCommand();
$input = $command->getDefinition();
/* @var DrupalStyle $io */
$io = new DrupalStyle($event->getInput(), $event->getOutput());
$learning = $input->getOption('learning');
// pick randomly one of the tips (5 tips as maximum).
$tips = $this->getTip($command->getName());
if ($learning && $tips) {
$io->commentBlock($tips);
}
}
/**
* @param $commandName
* @return bool|string
*/
private function getTip($commandName)
{
$get_tip = $this->translator
->trans('commands.'.str_replace(':', '.', $commandName).'.tips.0.tip');
preg_match("/^commands./", $get_tip, $matches, null, 0);
if (!empty($matches)) {
return false;
}
$n = rand(0, 5);
$get_tip = $this->translator
->trans('commands.'.str_replace(':', '.', $commandName).'.tips.' . $n . '.tip');
preg_match("/^commands./", $get_tip, $matches, null, 0);
if (empty($matches)) {
return $get_tip;
} else {
return $this->getTip($commandName);
}
}
/**
* @{@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [ConsoleEvents::COMMAND => 'showTips'];
}
}

View file

@ -0,0 +1,66 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\EventSubscriber\ShowWelcomeMessageListener.
*/
namespace Drupal\Console\Core\EventSubscriber;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Console\Command\Command;
use Drupal\Console\Core\Utils\TranslatorManagerInterface;
use Drupal\Console\Core\Style\DrupalStyle;
/**
* Class ShowWelcomeMessageListener
*
* @package Drupal\Console\Core\EventSubscriber
*/
class ShowWelcomeMessageListener implements EventSubscriberInterface
{
/**
* @var TranslatorManagerInterface
*/
protected $translator;
/**
* ShowWelcomeMessageListener constructor.
*
* @param TranslatorManagerInterface $translator
*/
public function __construct(
TranslatorManagerInterface $translator
) {
$this->translator = $translator;
}
/**
* @param ConsoleCommandEvent $event
*/
public function showWelcomeMessage(ConsoleCommandEvent $event)
{
/* @var Command $command */
$command = $event->getCommand();
/* @var DrupalStyle $io */
$io = new DrupalStyle($event->getInput(), $event->getOutput());
$welcomeMessageKey = 'commands.'.str_replace(':', '.', $command->getName()).'.welcome';
$welcomeMessage = $this->translator->trans($welcomeMessageKey);
if ($welcomeMessage != $welcomeMessageKey) {
$io->text($welcomeMessage);
}
}
/**
* @{@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [ConsoleEvents::COMMAND => 'showWelcomeMessage'];
}
}

View file

@ -0,0 +1,85 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\EventSubscriber\ValidateDependenciesListener.
*/
namespace Drupal\Console\Core\EventSubscriber;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Console\Command\Command;
use Drupal\Console\Core\Utils\ConfigurationManager;
use Drupal\Console\Core\Utils\TranslatorManagerInterface;
use Drupal\Console\Core\Style\DrupalStyle;
/**
* Class ValidateExecutionListener
*
* @package Drupal\Console\Core\EventSubscriber
*/
class ValidateExecutionListener implements EventSubscriberInterface
{
/**
* @var TranslatorManagerInterface
*/
protected $translator;
/**
* @var ConfigurationManager
*/
protected $configurationManager;
/**
* ValidateExecutionListener constructor.
*
* @param TranslatorManagerInterface $translator
* @param ConfigurationManager $configurationManager
*/
public function __construct(
TranslatorManagerInterface $translator,
ConfigurationManager $configurationManager
) {
$this->translator = $translator;
$this->configurationManager = $configurationManager;
}
/**
* @param ConsoleCommandEvent $event
*/
public function validateExecution(ConsoleCommandEvent $event)
{
/* @var Command $command */
$command = $event->getCommand();
/* @var DrupalStyle $io */
$io = new DrupalStyle($event->getInput(), $event->getOutput());
$configuration = $this->configurationManager->getConfiguration();
$mapping = $configuration->get('application.disable.commands')?:[];
if (array_key_exists($command->getName(), $mapping)) {
$extra = $mapping[$command->getName()];
$message[] = sprintf(
$this->translator->trans('application.messages.disable.command.error'),
$command->getName()
);
if ($extra) {
$message[] = sprintf(
$this->translator->trans('application.messages.disable.command.extra'),
$extra
);
}
$io->commentBlock($message);
}
}
/**
* @{@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [ConsoleEvents::COMMAND => 'validateExecution'];
}
}

View file

@ -0,0 +1,146 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Generator\Generator.
*/
namespace Drupal\Console\Core\Generator;
use Drupal\Console\Core\Utils\TwigRenderer;
use Drupal\Console\Core\Utils\FileQueue;
use Drupal\Console\Core\Utils\CountCodeLines;
use Drupal\Console\Core\Utils\DrupalFinder;
use Drupal\Console\Core\Style\DrupalStyle;
/**
* Class Generator
*
* @package Drupal\Console\Core\Generator
*/
abstract class Generator
{
/**
* @var TwigRenderer
*/
protected $renderer;
/**
* @var FileQueue
*/
protected $fileQueue;
/**
* @var CountCodeLines
*/
protected $countCodeLines;
/**
* @var DrupalFinder
*/
protected $drupalFinder;
/**
* @var DrupalStyle
*/
protected $io;
/**
* @param $renderer
*/
public function setRenderer(TwigRenderer $renderer)
{
$this->renderer = $renderer;
}
/**
* @param $fileQueue
*/
public function setFileQueue(FileQueue $fileQueue)
{
$this->fileQueue = $fileQueue;
}
/**
* @param $countCodeLines
*/
public function setCountCodeLines(CountCodeLines $countCodeLines)
{
$this->countCodeLines = $countCodeLines;
}
/**
* @param DrupalFinder $drupalFinder
*/
public function setDrupalFinder($drupalFinder)
{
$this->drupalFinder = $drupalFinder;
}
/**
* @return \Drupal\Console\Core\Style\DrupalStyle
*/
public function getIo() {
return $this->io;
}
/**
* @param \Drupal\Console\Core\Style\DrupalStyle $io
*/
public function setIo($io) {
$this->io = $io;
}
/**
* @param string $template
* @param string $target
* @param array $parameters
* @param null $flag
*
* @return bool
*/
protected function renderFile(
$template,
$target,
$parameters = [],
$flag = null
) {
if (!is_dir(dirname($target))) {
if (!mkdir(dirname($target), 0777, true)) {
throw new \InvalidArgumentException(
sprintf(
'Path "%s" is invalid. You need to provide a valid path.',
dirname($target)
)
);
}
}
$currentLine = 0;
if (!empty($flag) && file_exists($target)) {
$currentLine = count(file($target));
}
$content = $this->renderer->render($template, $parameters);
if (file_put_contents($target, $content, $flag)) {
$this->fileQueue->addFile($target);
$newCodeLine = count(file($target));
if ($currentLine > 0) {
$newCodeLine = ($newCodeLine-$currentLine);
}
$this->countCodeLines->addCountCodeLines($newCodeLine);
return true;
}
return false;
}
public function addSkeletonDir($skeletonDir)
{
$this->renderer->addSkeletonDir($skeletonDir);
}
}

View file

@ -0,0 +1,23 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Generator\Generator.
*/
namespace Drupal\Console\Core\Generator;
/**
* Class Generator
*
* @package Drupal\Console\Core\GeneratorInterface
*/
interface GeneratorInterface
{
/**
* @param array $parameters
* @return void
*/
public function generate(array $parameters);
}

View file

@ -0,0 +1,72 @@
<?php
/**
* @file
* Contains Drupal\Console\Core\Generator\InitGenerator.
*/
namespace Drupal\Console\Core\Generator;
/**
* Class InitGenerator
*
* @package Drupal\Console\Core\Generator
*/
class InitGenerator extends Generator
{
/**
* {@inheritdoc}
*/
public function generate(array $parameters) {
$userHome = $parameters['user_home'];
$executableName = $parameters['executable_name'];
$override = $parameters['override'];
$destination = $parameters['destination'];
$configParameters = $parameters['config_parameters'];
$configParameters = array_map(
function ($item) {
if (is_bool($item)) {
return $item ? 'true' : 'false';
}
return $item;
},
$configParameters
);
$configFile = $userHome . 'config.yml';
if ($destination) {
$configFile = $destination . 'config.yml';
}
if (file_exists($configFile) && $override) {
copy(
$configFile,
$configFile . '.old'
);
}
$this->renderFile(
'core/init/config.yml.twig',
$configFile,
$configParameters
);
if ($executableName) {
$parameters = [
'executable' => $executableName,
];
$this->renderFile(
'core/autocomplete/console.rc.twig',
$userHome . 'console.rc',
$parameters
);
$this->renderFile(
'core/autocomplete/console.fish.twig',
$userHome . 'drupal.fish',
$parameters
);
}
}
}

View file

@ -0,0 +1,24 @@
<?php
namespace Drupal\Console\Core\Generator;
/**
* Class SiteAliasGenerator
*
* @package Drupal\Console\Generator
*/
class SiteAliasGenerator extends Generator
{
/**
* {@inheritdoc}
*/
public function generate(array $parameters)
{
$this->renderFile(
'core/sites/alias.yml.twig',
$parameters['directory'] . '/sites/' . $parameters['name'] . '.yml',
$parameters,
FILE_APPEND
);
}
}

View file

@ -0,0 +1,84 @@
<?php
/*
* This file is part of the Drupal Console.
*/
namespace Drupal\Console\Core\Helper;
use Symfony\Component\Console\Helper\Helper as BaseHelper;
use Symfony\Component\Console\Descriptor\DescriptorInterface;
use Symfony\Component\Console\Descriptor\JsonDescriptor;
use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
use Drupal\Console\Core\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Output\OutputInterface;
/**
* This class adds helper method to describe objects in various formats.
*
* @author Jean-François Simon <contact@jfsimon.fr>
*/
class DescriptorHelper extends BaseHelper
{
/**
* @var DescriptorInterface[]
*/
private $descriptors = [];
/**
* Constructor.
*/
public function __construct()
{
$this
->register('txt', new TextDescriptor())
->register('xml', new XmlDescriptor())
->register('json', new JsonDescriptor())
->register('md', new MarkdownDescriptor());
}
/**
* Describes an object if supported.
*
* Available options are:
* * format: string, the output format name
* * raw_text: boolean, sets output type as raw
*
* @param OutputInterface $output
* @param object $object
* @param array $options
*
* @throws \InvalidArgumentException when the given format is not supported
*/
public function describe(OutputInterface $output, $object, array $options = [])
{
$options = array_merge(
[
'raw_text' => false,
'format' => 'txt',
], $options
);
if (!isset($this->descriptors[$options['format']])) {
throw new \InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
}
$descriptor = $this->descriptors[$options['format']];
$descriptor->describe($output, $object, $options);
}
/**
* Registers a descriptor.
*
* @param string $format
* @param DescriptorInterface $descriptor
*
* @return DescriptorHelper
*/
public function register($format, DescriptorInterface $descriptor)
{
$this->descriptors[$format] = $descriptor;
return $this;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'descriptor';
}
}

View file

@ -0,0 +1,35 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Helper\DrupalChoiceQuestionHelper.
*/
namespace Drupal\Console\Core\Helper;
use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\Question;
/**
* Class DrupalChoiceQuestionHelper
*
* @package Drupal\Console\Core\Helper
*/
class DrupalChoiceQuestionHelper extends SymfonyQuestionHelper
{
/**
* {@inheritdoc}
*/
protected function writePrompt(OutputInterface $output, Question $question)
{
$text = $question->getQuestion();
$default = $question->getDefault();
$choices = $question->getChoices();
$text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, $choices[$default]);
$output->writeln($text);
$output->write(' > ');
}
}

View file

@ -0,0 +1,309 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Style\DrupalStyle.
*/
namespace Drupal\Console\Core\Style;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Console\Helper\Table;
use Drupal\Console\Core\Helper\DrupalChoiceQuestionHelper;
/**
* Class DrupalStyle
*
* @package Drupal\Console\Core\Style
*/
class DrupalStyle extends SymfonyStyle
{
/**
* @var InputInterface
*/
private $input;
/**
* @param InputInterface $input
* @param OutputInterface $output
*/
public function __construct(InputInterface $input, OutputInterface $output)
{
$this->input = $input;
parent::__construct($input, $output);
}
/**
* @param string $question
* @param array $choices
* @param mixed $default
* @param bool $skipValidation
*
* @return string
*/
public function choiceNoList(
$question,
array $choices,
$default = null,
$skipValidation = false
) {
if (is_null($default)) {
$default = current($choices);
}
if (!in_array($default, $choices)) {
$choices[] = $default;
}
if (null !== $default) {
$values = array_flip($choices);
$default = $values[$default];
}
$choiceQuestion = new ChoiceQuestion($question, $choices, $default);
if ($skipValidation) {
$choiceQuestion->setValidator(
function ($answer) {
return $answer;
}
);
}
return trim($this->askChoiceQuestion($choiceQuestion));
}
/**
* @param string $question
* @param array $choices
* @param null $default
* @param bool $multiple
*
* @return string
*/
public function choice($question, array $choices, $default = null, $multiple = false)
{
if (null !== $default) {
$values = array_flip($choices);
$default = $values[$default];
}
$choiceQuestion = new ChoiceQuestion($question, $choices, $default);
$choiceQuestion->setMultiselect($multiple);
return $this->askQuestion($choiceQuestion);
}
/**
* @param ChoiceQuestion $question
*
* @return string
*/
public function askChoiceQuestion(ChoiceQuestion $question)
{
$questionHelper = new DrupalChoiceQuestionHelper();
$answer = $questionHelper->ask($this->input, $this, $question);
return $answer;
}
/**
* @param $question
*
* @return string
*/
public function askHiddenEmpty($question)
{
$question = new Question($question, '');
$question->setHidden(true);
$question->setValidator(
function ($answer) {
return $answer;
}
);
return trim($this->askQuestion($question));
}
/**
* @param string $question
* @param string $default
* @param null|callable $validator
*
* @return string
*/
public function askEmpty($question, $default = '', $validator = null)
{
$question = new Question($question, $default);
if (!$validator) {
$validator = function ($answer) {
return $answer;
};
}
$question->setValidator($validator);
return trim($this->askQuestion($question));
}
/**
* @param $message
* @param bool $newLine
*/
public function info($message, $newLine = true)
{
$message = sprintf('<info> %s</info>', $message);
if ($newLine) {
$this->writeln($message);
} else {
$this->write($message);
}
}
/**
* @param array|string $message
* @param bool $newLine
*/
public function comment($message, $newLine = true)
{
$message = sprintf('<comment> %s</comment>', $message);
if ($newLine) {
$this->writeln($message);
} else {
$this->write($message);
}
}
/**
* @param $message
*/
public function commentBlock($message)
{
$this->block(
$message, null,
'bg=yellow;fg=black',
' ',
true
);
}
/**
* @param array $headers
* @param array $rows
* @param string $style
*/
public function table(array $headers, array $rows, $style = 'symfony-style-guide')
{
$headers = array_map(
function ($value) {
return sprintf('<info>%s</info>', $value);
}, $headers
);
if (!is_array(current($rows))) {
$rows = array_map(
function ($row) {
return [$row];
},
$rows
);
}
$table = new Table($this);
$table->setHeaders($headers);
$table->setRows($rows);
$table->setStyle($style);
$table->render();
$this->newLine();
}
/**
* @param $message
* @param bool $newLine
*/
public function simple($message, $newLine = true)
{
$message = sprintf(' %s', $message);
if ($newLine) {
$this->writeln($message);
} else {
$this->write($message);
}
}
/**
* {@inheritdoc}
*/
public function warning($message)
{
$this->block($message, 'WARNING', 'fg=white;bg=yellow', ' ', true);
}
/**
* @param array|string $message
*/
public function text($message)
{
$message = sprintf('// %s', $message);
parent::text($message);
}
public function successLite($message, $newLine = false)
{
$message = sprintf('<info>✔</info> %s', $message);
parent::text($message);
if ($newLine) {
parent::newLine();
}
}
public function errorLite($message, $newLine = false)
{
$message = sprintf('<fg=red>✘</> %s', $message);
parent::text($message);
if ($newLine) {
parent::newLine();
}
}
public function warningLite($message, $newLine = false)
{
$message = sprintf('<comment>!</comment> %s', $message);
parent::text($message);
if ($newLine) {
parent::newLine();
}
}
public function customLite($message, $prefix = '*', $style = '', $newLine = false)
{
if ($style) {
$message = sprintf(
'<%s>%s</%s> %s',
$style,
$prefix,
$style,
$message
);
} else {
$message = sprintf(
'%s %s',
$prefix,
$message
);
}
parent::text($message);
if ($newLine) {
parent::newLine();
}
}
/**
* @return InputInterface
*/
public function getInput()
{
return $this->input;
}
}

View file

@ -0,0 +1,238 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Utils\ArgvInputReader.
*/
namespace Drupal\Console\Core\Utils;
use Symfony\Component\Console\Input\ArgvInput;
/**
* Class ArgvInputReader.
*/
class ArgvInputReader
{
/**
* @var array
*/
protected $options;
/**
* @var
*/
protected $input;
/**
* @var array
*/
protected $originalArgvValues;
/**
* ArgvInputReader constructor.
*/
public function __construct()
{
$this->originalArgvValues = $_SERVER['argv'];
$this->options = [];
$this->setOptionsFromPlaceHolders();
$this->readArgvInputValues();
}
/**
* @param array $targetConfig
*/
public function setOptionsFromTargetConfiguration($targetConfig)
{
$options = [];
if (array_key_exists('root', $targetConfig)) {
$options['root'] = $targetConfig['root'];
}
if (array_key_exists('uri', $targetConfig)) {
$options['uri'] = $targetConfig['uri'];
}
if (array_key_exists('remote', $targetConfig)) {
$this->set('remote', true);
}
$this->setArgvOptions($options);
}
/**
* @param array $options
*/
public function setOptionsFromConfiguration($options)
{
$this->setArgvOptions($options);
}
/**
* @param $options
*/
private function setArgvOptions($options)
{
$argvInput = new ArgvInput();
foreach ($options as $key => $option) {
if (!$option) {
continue;
}
if (!$argvInput->hasParameterOption($key)) {
if ($option == 1) {
$_SERVER['argv'][] = sprintf('--%s', $key);
} else {
$_SERVER['argv'][] = sprintf('--%s=%s', $key, $option);
}
continue;
}
if ($key === 'root') {
$option = sprintf(
'%s%s',
$argvInput->getParameterOption(['--root'], null),
$option
);
}
foreach ($_SERVER['argv'] as $argvKey => $argv) {
if (strpos($argv, '--'.$key) === 0) {
if ($option == 1) {
$_SERVER['argv'][$argvKey] = sprintf('--%s', $key);
} else {
$_SERVER['argv'][$argvKey] = sprintf(
'--%s=%s',
$key,
$option
);
}
continue;
}
}
}
$this->readArgvInputValues();
}
/**
* setOptionsFromPlaceHolders.
*/
private function setOptionsFromPlaceHolders()
{
if (count($_SERVER['argv']) > 2
&& stripos($_SERVER['argv'][1], '@') === 0
&& stripos($_SERVER['argv'][2], '@') === 0
) {
$_SERVER['argv'][1] = sprintf(
'--source=%s',
substr($_SERVER['argv'][1], 1)
);
$_SERVER['argv'][2] = sprintf(
'--target=%s',
substr($_SERVER['argv'][2], 1)
);
return;
}
if (count($_SERVER['argv']) > 1 && stripos($_SERVER['argv'][1], '@') === 0) {
$_SERVER['argv'][1] = sprintf(
'--target=%s',
substr($_SERVER['argv'][1], 1)
);
}
}
/**
* ReadArgvInputValues.
*/
private function readArgvInputValues()
{
$input = new ArgvInput();
$source = $input->getParameterOption(['--source', '-s'], null);
$target = $input->getParameterOption(['--target', '-t'], null);
$root = $input->getParameterOption(['--root'], null);
$debug = $input->hasParameterOption(['--debug']);
$uri = $input->getParameterOption(['--uri', '-l']) ?: 'default';
if ($uri && !preg_match('/^(http|https):\/\//', $uri)) {
$uri = sprintf('http://%s', $uri);
}
$this->set('command', $input->getFirstArgument());
$this->set('root', $root);
$this->set('uri', $uri);
$this->set('debug', $debug);
$this->set('source', $source);
$this->set('target', $target);
}
/**
* @param $option
* @param $value
*/
public function set($option, $value)
{
if ($value) {
$this->options[$option] = $value;
return;
}
if (!array_key_exists($option, $this->options)) {
unset($this->options[$option]);
}
}
/**
* @param $option
* @param null $value
*
* @return string
*/
public function get($option, $value = null)
{
if (!array_key_exists($option, $this->options)) {
return $value;
}
return $this->options[$option];
}
/**
* @return array
*/
public function getAll()
{
return $this->options;
}
/**
* setOptionsAsArgv
*/
public function setOptionsAsArgv()
{
foreach ($this->options as $optionName => $optionValue) {
if ($optionName == 'command') {
continue;
}
$optionFound = false;
foreach ($_SERVER['argv'] as $key => $argv) {
if (strpos($argv, '--'.$optionName) === 0) {
$_SERVER['argv'][$key] = '--'.$optionName.'='.$optionValue;
$optionFound = true;
break;
}
}
if (!$optionFound) {
$_SERVER['argv'][] = '--'.$optionName.'='.$optionValue;
}
}
}
/**
* @return array
*/
public function restoreOriginalArgvValues()
{
return $_SERVER['argv'] = $this->originalArgvValues;
}
}

View file

@ -0,0 +1,479 @@
<?php
/**
* @file
* Contains Drupal\Console\Core\Utils\Site.
*/
namespace Drupal\Console\Core\Utils;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Yaml\Yaml;
/**
* Class ChainDiscovery
*
* @package Drupal\Console\Core\Utils
*/
class ChainDiscovery
{
/**
* @var string
*/
protected $appRoot;
/**
* @var ConfigurationManager
*/
protected $configurationManager;
/**
* @var MessageManager
*/
protected $messageManager;
/**
* @var TranslatorManagerInterface
*/
protected $translatorManager;
/**
* @var array
*/
private $directories = [];
/**
* @var array
*/
private $files = [];
/**
* @var array
*/
private $filesPerDirectory = [];
const INLINE_REGEX = '/{{(.*?)}}/';
const ENV_REGEX = '/%env\((.*?)\)%/';
/**
* @var array
*/
private $inlineRegexLegacy = [
'/%{{(.*?)}}/',
'/%{{ (.*?) }}/',
];
/**
* @var array
*/
private $envRegexLegacy = [
'/\${{(.*?)}}/',
'/\${{ (.*?) }}/',
'/%env\((.*?)\)%/',
'/% env\((.*?)\) %/'
];
/**
* ChainDiscovery constructor.
*
* @param string $appRoot
* @param ConfigurationManager $configurationManager
* @param MessageManager $messageManager
* @param TranslatorManagerInterface $translatorManager
*/
public function __construct(
$appRoot,
ConfigurationManager $configurationManager,
MessageManager $messageManager,
TranslatorManagerInterface $translatorManager
) {
$this->appRoot = $appRoot;
$this->configurationManager = $configurationManager;
$this->messageManager = $messageManager;
$this->translatorManager = $translatorManager;
$directories = array_map(
function ($item) {
return $item . 'chain/';
},
$configurationManager->getConfigurationDirectories(true)
);
$this->addDirectories($directories);
}
/**
* @param array $directories
*/
public function addDirectories(array $directories)
{
$this->directories = array_merge($this->directories, $directories);
}
/**
* @deprecated
*
* @return array
*/
public function getChainFiles()
{
return $this->getFiles();
}
/**
* @return array
*/
public function getFiles()
{
if ($this->files) {
return $this->files;
}
foreach ($this->directories as $directory) {
if (!is_dir($directory)) {
continue;
}
$finder = new Finder();
$finder->files()
->name('*.yml')
->in($directory);
foreach ($finder as $file) {
$filePath = $file->getRealPath();
if (empty($filePath)) {
$filePath = $directory . $file->getBasename();
}
if (!is_file($filePath)) {
continue;
}
$this->files[$filePath] = [
'directory' => $directory,
'file_name' => $file->getBasename(),
'messages' => []
];
$this->getFileContents($filePath);
$this->getFileMetadata($filePath);
if ($this->files[$filePath]['messages']) {
$this->messageManager->comment(
$filePath,
0,
'list'
);
$this->messageManager->listing(
$this->files[$filePath]['messages'],
0,
'list'
);
}
$this->filesPerDirectory[$directory][] = $file->getBasename();
}
}
return $this->files;
}
/**
* @return array
*/
public function getFilesPerDirectory()
{
return $this->filesPerDirectory;
}
/**
* @return array
*/
public function getChainCommands()
{
$chainCommands = [];
$files = array_keys($this->getFiles());
foreach ($files as $file) {
$chainMetadata = $this->getFileMetadata($file);
if (!$chainMetadata) {
continue;
}
$name = $chainMetadata['command']['name'];
$description = $chainMetadata['command']['description'];
$chainCommands[$name] = [
'description' => $description,
'file' => $file,
];
$this->files[$file]['command'] = $name;
$this->files[$file]['description'] = $description;
}
return $chainCommands;
}
public function parseContent($file, $placeholders)
{
$placeholders = array_filter(
$placeholders,
function ($element) {
return $element !== null;
}
);
unset($placeholders['file']);
unset($placeholders['placeholder']);
$contents = $this->getFileContents($file);
$loader = new \Twig_Loader_Array(
[
'chain' => $contents,
]
);
$twig = new \Twig_Environment($loader);
$envFunction = new \Twig_SimpleFunction(
'env',
function ($variableName) {
$variableValue = getenv($variableName);
if (!empty($variableValue)) {
return $variableValue;
}
return '%env('.$variableName.')%';
}
);
$twig->addFunction($envFunction);
$variables = $this->extractInlinePlaceHolderNames($contents);
foreach ($variables as $variable) {
if (!array_key_exists($variable, $placeholders)) {
$placeholders[$variable] = '{{ ' . $variable . ' }}';
}
}
return $twig->render('chain', $placeholders);
}
public function getFileMetadata($file)
{
if ($metadata = $this->getCacheMetadata($file)) {
return $metadata;
}
$contents = $this->getFileContents($file);
$line = strtok($contents, PHP_EOL);
$index = 0;
while ($line !== false) {
$index++;
if ($index === 1 && $line !== 'command:') {
break;
}
if ($index > 1 && substr($line, 0, 2) !== " ") {
break;
}
$metadata .= $line . PHP_EOL;
$line = strtok(PHP_EOL);
}
$chainMetadata = $this->processMetadata($metadata);
if (!$chainMetadata) {
$this->files[$file]['messages'][] = $this->translatorManager
->trans('commands.chain.messages.metadata-registration');
return [];
}
$this->files[$file]['metadata'] = $chainMetadata;
return $chainMetadata;
}
private function processMetadata($metadata) {
if (!$metadata) {
return [];
}
$chainMetadata = Yaml::parse($metadata);
if (!$chainMetadata || !is_array($chainMetadata)) {
return [];
}
if (!array_key_exists('command', $chainMetadata) || !is_array($chainMetadata['command'])) {
return [];
}
if (!array_key_exists('name', $chainMetadata['command'])) {
return [];
}
if (!array_key_exists('description', $chainMetadata['command'])) {
$chainMetadata['command']['description'] = '';
}
return $chainMetadata;
}
/**
* Helper to load and clean up the chain file.
*
* @param string $file The file name
*
* @return string $contents The contents of the file
*/
public function getFileContents($file)
{
if (empty($file)) {
return '';
}
if ($contents = $this->getCacheContent($file)) {
return $contents;
}
$contents = file_get_contents($file);
// Support BC for legacy inline variables.
$inlineLegacyContent = preg_replace(
$this->inlineRegexLegacy,
'{{ $1 }}',
$contents
);
if ($contents !== $inlineLegacyContent) {
$this->files[$file]['messages'][] = $this->translatorManager
->trans('commands.chain.messages.legacy-inline');
$contents = $inlineLegacyContent;
}
// Support BC for legacy environment variables.
$envLegacyContent = preg_replace(
$this->envRegexLegacy,
'{{ env("$1") }}',
$contents
);
if ($contents !== $envLegacyContent) {
$this->files[$file]['messages'][] = $this->translatorManager
->trans('commands.chain.messages.legacy-environment');
$contents = $envLegacyContent;
}
// Remove lines with comments.
$contents = preg_replace(
'![ \t]*#.*[ \t]*[\r|\r\n|\n]!',
PHP_EOL,
$contents
);
// Strip blank lines
$contents = preg_replace(
"/(^[\r\n]*|[\r\n]+)[\t]*[\r\n]+/",
PHP_EOL,
$contents
);
$this->files[$file]['content'] = $contents;
return $contents;
}
private function getCacheContent($file)
{
if (!array_key_exists($file, $this->files)) {
return null;
}
if (!array_key_exists('content', $this->files[$file])) {
return null;
}
return $this->files[$file]['content'];
}
private function getCacheMetadata($file)
{
if (!array_key_exists($file, $this->files)) {
return null;
}
if (!array_key_exists('metadata', $this->files[$file])) {
return null;
}
return $this->files[$file]['metadata'];
}
private function extractPlaceHolders(
$chainContent,
$regex
) {
$placeHoldersExtracted = [];
preg_match_all(
$regex,
$chainContent,
$placeHoldersExtracted
);
if (!$placeHoldersExtracted) {
return [];
}
return array_unique($placeHoldersExtracted[1]);
}
public function extractInlinePlaceHolderNames($content)
{
preg_match_all($this::INLINE_REGEX, $content, $matches);
return array_map(
function ($item) {
return trim($item);
},
$matches[1]
);
}
public function extractInlinePlaceHolders($chainContent)
{
$extractedInlinePlaceHolders = $this->extractPlaceHolders(
$chainContent,
$this::INLINE_REGEX
);
$extractedVars = $this->extractVars($chainContent);
$inlinePlaceHolders = [];
foreach ($extractedInlinePlaceHolders as $key => $inlinePlaceHolder) {
$inlinePlaceHolder = trim($inlinePlaceHolder);
$placeholderValue = null;
if (array_key_exists($inlinePlaceHolder, $extractedVars)) {
$placeholderValue = $extractedVars[$inlinePlaceHolder];
}
$inlinePlaceHolders[$inlinePlaceHolder] = $placeholderValue;
}
return $inlinePlaceHolders;
}
public function extractEnvironmentPlaceHolders($chainContent)
{
return $this->extractPlaceHolders($chainContent, $this::ENV_REGEX);
}
public function extractVars($chainContent)
{
$chain = Yaml::parse($chainContent);
if (!array_key_exists('vars', $chain)) {
return [];
}
return $chain['vars'];
}
}

View file

@ -0,0 +1,53 @@
<?php
/**
* @file
* Contains Drupal\Console\Core\Utils\ChainQueue.
*/
namespace Drupal\Console\Core\Utils;
/**
* Class ChainQueue
*
* @package Drupal\Console\Core\Helper
*/
class ChainQueue
{
/**
* @var $commands array
*/
private $commands;
/**
* @param $name string
* @param $inputs array
* @param $interactive boolean
* @param $learning boolean
*/
public function addCommand(
$name,
$inputs = [],
$interactive = null,
$learning = null
) {
$inputs['command'] = $name;
if (!is_null($learning)) {
$inputs['--learning'] = $learning;
}
$this->commands[] =
[
'name' => $name,
'inputs' => $inputs,
'interactive' => $interactive
];
}
/**
* @return array
*/
public function getCommands()
{
return $this->commands;
}
}

View file

@ -0,0 +1,454 @@
<?php
namespace Drupal\Console\Core\Utils;
use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Finder\Finder;
use Dflydev\DotAccessConfiguration\YamlFileConfigurationBuilder;
use Dflydev\DotAccessConfiguration\ConfigurationInterface;
use Webmozart\PathUtil\Path;
/**
* Class ConfigurationManager.
*/
class ConfigurationManager
{
/**
* @var ConfigurationInterface
*/
private $configuration = null;
/**
* @var string
*/
private $applicationDirectory = null;
/**
* @var array
*/
private $configurationDirectories = [];
/**
* @var array
*/
private $sites = [];
/**
* @var array
*/
private $configurationFiles = [];
/**
* @param $directory
* @return $this
*/
public function loadConfiguration($directory)
{
$this->locateConfigurationFiles();
$this->applicationDirectory = $directory;
if ($directory && is_dir($directory) && strpos($directory, 'phar:')!==0) {
$this->addConfigurationFilesByDirectory(
$directory . '/console/',
true
);
}
$input = new ArgvInput();
$root = $input->getParameterOption(['--root']);
if ($root && is_dir($root)) {
$this->addConfigurationFilesByDirectory(
$root. '/console/',
true
);
}
$builder = new YamlFileConfigurationBuilder(
$this->configurationFiles['config']
);
$this->configuration = $builder->build();
$extras = [
'aliases',
'mappings',
'defaults'
];
foreach ($extras as $extra) {
$extraKey = 'application.extras.'.$extra;
$extraFlag = $this->configuration->get($extraKey)?:'true';
if ($extraFlag === 'true') {
$this->appendExtraConfiguration($extra);
}
}
return $this;
}
/**
* @return ConfigurationInterface
*/
public function getConfiguration()
{
return $this->configuration;
}
private function readSite($siteFile)
{
if (!file_exists($siteFile)) {
return [];
}
return Yaml::parse(file_get_contents($siteFile));
}
/**
* @param $target
*
* @return array
*/
public function readTarget($target)
{
$site = $target;
$environment = null;
$exploded = explode('.', $target, 2);
if (count($exploded)>1) {
$site = $exploded[0];
$environment = $exploded[1];
}
$sites = $this->getSites();
if (!array_key_exists($site, $sites)) {
return [];
}
$targetInformation = $sites[$site];
if ($environment) {
if (!array_key_exists($environment, $sites[$site])) {
return [];
}
$targetInformation = $sites[$site][$environment];
}
return $targetInformation;
}
/**
* @return string
*/
public function getApplicationDirectory()
{
return $this->applicationDirectory;
}
/**
* Return the sites config directory.
*
* @return array
*/
private function getSitesDirectories()
{
$sitesDirectories = array_map(
function ($directory) {
return $directory . 'sites';
},
$this->getConfigurationDirectories()
);
$sitesDirectories = array_filter(
$sitesDirectories,
function ($directory) {
return is_dir($directory);
}
);
$sitesDirectories = array_unique($sitesDirectories);
return $sitesDirectories;
}
/**
* @param string $commandName
* @return mixed
*/
public function readDrushEquivalents($commandName)
{
$equivalents = [];
$drushMappings = Yaml::parse(
file_get_contents(
$this->applicationDirectory . DRUPAL_CONSOLE_CORE . 'config/drush.yml'
)
);
foreach ($drushMappings['commands'] as $key => $commands) {
foreach ($commands as $namespace => $command) {
if ($command) {
$equivalents[$namespace] = $command;
}
}
}
if (!$commandName) {
$drushMappings = [];
foreach ($equivalents as $key => $alternative) {
$drushMappings[] = [$key, $alternative];
}
return $drushMappings;
}
if (array_key_exists($commandName, $equivalents)) {
return $equivalents[$commandName] ?: ' ';
}
return [];
}
public function getVendorCoreRoot()
{
$consoleCoreDirectory = dirname(dirname(dirname(__FILE__))) . '/';
if (is_dir($consoleCoreDirectory)) {
return $consoleCoreDirectory;
}
return null;
}
public function getVendorCoreDirectory()
{
$consoleCoreDirectory = dirname(dirname(dirname(__FILE__))) . '/config/';
if (is_dir($consoleCoreDirectory)) {
return $consoleCoreDirectory;
}
return null;
}
public function getSystemDirectory()
{
$systemDirectory = '/etc/console/';
if (is_dir($systemDirectory)) {
return $systemDirectory;
}
return null;
}
/**
* @return string
*/
public function getConsoleDirectory()
{
$consoleDirectory = sprintf(
'%s/.console/',
$this->getHomeDirectory()
);
if (is_dir($consoleDirectory)) {
return $consoleDirectory;
}
try {
mkdir($consoleDirectory, 0777, true);
} catch (\Exception $exception) {
return null;
}
return $consoleDirectory;
}
/**
* @param $includeVendorCore
*
* @return array
*/
public function getConfigurationDirectories($includeVendorCore = false)
{
if ($this->configurationDirectories) {
if ($includeVendorCore) {
return array_merge(
[$this->getVendorCoreDirectory()],
$this->configurationDirectories
);
}
return $this->configurationDirectories;
}
return [];
}
private function addConfigurationFilesByDirectory(
$directory,
$addDirectory = false
) {
if ($addDirectory) {
$this->configurationDirectories[] = $directory;
}
$configurationFiles = [
'config' => 'config.yml',
'drush' => 'drush.yml',
'aliases' => 'aliases.yml',
'mappings' => 'mappings.yml',
'defaults' => 'defaults.yml',
];
foreach ($configurationFiles as $key => $file) {
$configFile = $directory.$file;
if (is_file($configFile)) {
$this->configurationFiles[$key][] = $configFile;
}
}
}
private function locateConfigurationFiles()
{
if ($this->getVendorCoreDirectory()) {
$this->addConfigurationFilesByDirectory(
$this->getVendorCoreDirectory()
);
}
if ($this->getSystemDirectory()) {
$this->addConfigurationFilesByDirectory(
$this->getSystemDirectory(),
true
);
}
if ($this->getConsoleDirectory()) {
$this->addConfigurationFilesByDirectory(
$this->getConsoleDirectory(),
true
);
}
}
/**
* @return void
*/
private function appendExtraConfiguration($type)
{
if (!array_key_exists($type, $this->configurationFiles)) {
return;
}
$configData = [];
foreach ($this->configurationFiles[$type] as $configFile) {
if (file_get_contents($configFile)==='') {
continue;
}
$parsed = Yaml::parse(file_get_contents($configFile));
$configData = array_merge(
$configData,
is_array($parsed)?$parsed:[]
);
}
if ($configData && array_key_exists($type, $configData)) {
$this->configuration->set(
'application.commands.'.$type,
$configData[$type]
);
}
}
public function loadExtendConfiguration()
{
$directory = $this->getConsoleDirectory() . '/extend/';
if (!is_dir($directory)) {
return null;
}
$autoloadFile = $directory . 'vendor/autoload.php';
if (!is_file($autoloadFile)) {
return null;
}
include_once $autoloadFile;
$extendFile = $directory . 'extend.console.config.yml';
$this->importConfigurationFromFile($extendFile);
}
private function importConfigurationFromFile($configFile)
{
if (is_file($configFile) && file_get_contents($configFile)!='') {
$builder = new YamlFileConfigurationBuilder([$configFile]);
if ($this->configuration) {
$this->configuration->import($builder->build());
} else {
$this->configuration = $builder->build();
}
}
}
/**
* @return array
*/
public function getSites()
{
if ($this->sites) {
return $this->sites;
}
$sitesDirectories = $this->getSitesDirectories();
if (!$sitesDirectories) {
return [];
}
$finder = new Finder();
$finder->in($sitesDirectories);
$finder->name("*.yml");
foreach ($finder as $site) {
$siteName = $site->getBasename('.yml');
$environments = $this->readSite($site->getRealPath());
if (!$environments || !is_array($environments)) {
continue;
}
$this->sites[$siteName] = [
'file' => $site->getRealPath()
];
foreach ($environments as $environment => $config) {
if (!array_key_exists('type', $config)) {
throw new \UnexpectedValueException("The 'type' parameter is required in sites configuration.");
}
if ($config['type'] !== 'local') {
if (array_key_exists('host', $config)) {
$targetInformation['remote'] = true;
}
$config = array_merge(
$this->configuration->get('application.remote')?:[],
$config
);
}
$this->sites[$siteName][$environment] = $config;
}
}
return $this->sites;
}
/**
* @return array
*/
public function getConfigurationFiles()
{
return $this->configurationFiles;
}
public function getHomeDirectory()
{
return Path::getHomeDirectory();
}
}

View file

@ -0,0 +1,37 @@
<?php
/**
* @file
* Contains Drupal\Console\Core\Command\CountCodeLines.
*/
namespace Drupal\Console\Core\Utils;
/**
* Class CountCodeLines
*
* @package Drupal\Console\Core\Utils
*/
class CountCodeLines
{
/**
* @var $countCodeLine integer
*/
private $countCodeLine;
/**
* @param $countCodeLine integer
*/
public function addCountCodeLines($countCodeLine)
{
$this->countCodeLine = $this->countCodeLine + $countCodeLine;
}
/**
* @return integer
*/
public function getCountCodeLines()
{
return $this->countCodeLine;
}
}

View file

@ -0,0 +1,117 @@
<?php
/**
* @file
* Contains Drupal\Console\Core\Utils\DrupalFinder.
*/
namespace Drupal\Console\Core\Utils;
use DrupalFinder\DrupalFinder as DrupalFinderBase;
use Webmozart\PathUtil\Path;
/**
* Class DrupalFinder
*
* @package Drupal\Console\Core\Utils
*/
class DrupalFinder extends DrupalFinderBase
{
/**
* @var string
*/
protected $consoleCorePath;
/**
* @var string
*/
protected $consolePath;
/**
* @var string
*/
protected $consoleLanguagePath;
public function locateRoot($start_path)
{
$vendorDir = 'vendor';
if (parent::locateRoot($start_path)) {
$vendorDir = Path::makeRelative(
$this->getVendorDir(),
$this->getComposerRoot()
);
$this->definePaths($vendorDir);
$this->defineConstants($vendorDir);
return true;
}
$this->definePaths($vendorDir);
$this->defineConstants($vendorDir);
return false;
}
protected function definePaths($vendorDir)
{
$this->consoleCorePath = "/{$vendorDir}/drupal/console-core/";
$this->consolePath = "/{$vendorDir}/drupal/console/";
$this->consoleLanguagePath = "/{$vendorDir}/drupal/console-%s/translations/";
}
protected function defineConstants($vendorDir)
{
if (!defined("DRUPAL_CONSOLE_CORE")) {
define(
"DRUPAL_CONSOLE_CORE",
"/{$vendorDir}/drupal/console-core/"
);
}
if (!defined("DRUPAL_CONSOLE")) {
define("DRUPAL_CONSOLE", "/{$vendorDir}/drupal/console/");
}
if (!defined("DRUPAL_CONSOLE_LANGUAGE")) {
define(
"DRUPAL_CONSOLE_LANGUAGE",
"/{$vendorDir}/drupal/console-%s/translations/"
);
}
if (!defined("DRUPAL_CONSOLE_LIBRARY")) {
define(
"DRUPAL_CONSOLE_LIBRARY",
"/{$vendorDir}/drupal/%s/console/translations/%s"
);
}
}
/**
* @return string
*/
public function getConsoleCorePath()
{
return $this->consoleCorePath;
}
/**
* @return string
*/
public function getConsolePath()
{
return $this->consolePath;
}
/**
* @return string
*/
public function getConsoleLanguagePath()
{
return $this->consoleLanguagePath;
}
public function isValidDrupal() {
return ($this->getComposerRoot() && $this->getDrupalRoot());
}
}

View file

@ -0,0 +1,53 @@
<?php
/**
* @file
* Contains Drupal\Console\Core\Utils\ChainQueue.
*/
namespace Drupal\Console\Core\Utils;
/**
* Class FileQueue
*
* @package Drupal\Console\Core\Utils
*/
class FileQueue
{
/**
* @var $commands array
*/
private $files;
/**
* @var string
*/
protected $appRoot;
/**
* FileQueue constructor.
*
* @param string $appRoot
*/
public function __construct($appRoot)
{
$this->appRoot = $appRoot;
}
/**
* @param $file string
*/
public function addFile($file)
{
$file = str_replace($this->appRoot, '', $file);
$this->files[] = $file;
}
/**
* @return array
*/
public function getFiles()
{
return $this->files;
}
}

View file

@ -0,0 +1,69 @@
<?php
namespace Drupal\Console\Core\Utils;
class KeyValueStorage
{
/**
* @var array
*/
protected $data = [];
/**
* Checks if the container has the given key.
*
* @param string $key
* The key to check.
*
* @return boolean
*/
public function has($key)
{
return array_key_exists($key, $this->data);
}
/**
* Gets the given key from the container, or returns the default if it does
* not exist.
*
* @param string $key
* The key to get.
* @param mixed $default
* Default value to return.
*
* @return mixed
*/
public function get($key, $default = null)
{
return $this->has($key) ? $this->data[$key] : $default;
}
/**
* Sets the given key in the container.
*
* @param mixed $key
* The key to set
* @param mixed $value
* The value.
*/
public function set($key, $value = null)
{
$this->data[$key] = $value;
}
/**
* Removes the given key from the container.
*
* @param string $key The key to forget.
*
* @return void
*/
public function remove($key)
{
unset($this->data[$key]);
}
}

View file

@ -0,0 +1,112 @@
<?php
namespace Drupal\Console\Core\Utils;
/**
* Class MessageParser
*
* @package Drupal\Console\Core\Utils
*/
class MessageManager
{
/**
* @var array
*/
protected $messages = [];
/**
* @param $type
* @param $message
* @param $code
* @param $showBy
* @param $removeBy
*/
private function add($type, $message, $code, $showBy, $removeBy)
{
$this->messages[] = [
'type' =>$type,
'message' => $message,
'code' => $code,
'showBy' => $showBy,
'removeBy' => $removeBy,
];
}
/**
* @param $message
* @param $code
* @param $showBy
* @param $removeBy
*/
public function error($message, $code = 0, $showBy = 'all', $removeBy = null)
{
$this->add('error', $message, $code, $showBy, $removeBy);
}
/**
* @param $message
* @param $code
* @param $showBy
* @param $removeBy
*/
public function warning($message, $code = 0, $showBy = 'all', $removeBy = null)
{
$this->add('warning', $message, $code, $showBy, $removeBy);
}
/**
* @param $message
* @param $code
* @param $showBy
* @param $removeBy
*/
public function info($message, $code = 0, $showBy = 'all', $removeBy = null)
{
$this->add('info', $message, $code, $showBy, $removeBy);
}
/**
* @param $message
* @param $code
* @param $showBy
* @param $removeBy
*/
public function listing(array $message, $code = 0, $showBy = 'all', $removeBy = null)
{
$this->add('listing', $message, $code, $showBy, $removeBy);
}
/**
* @param $message
* @param $code
* @param $showBy
* @param $removeBy
*/
public function comment($message, $code = 0, $showBy = 'all', $removeBy = null)
{
$this->add('comment', $message, $code, $showBy, $removeBy);
}
/**
* @return array
*/
public function getMessages()
{
return $this->messages;
}
public function remove($removeBy = null)
{
$this->messages = array_filter(
$this->messages,
function ($message) use ($removeBy) {
if (is_null($message['removeBy'])) {
return true;
}
return !($message['removeBy'] == $removeBy);
}
);
}
}

View file

@ -0,0 +1,504 @@
<?php
/**
* @file
* Contains Drupal\Console\Core\NestedArray.
*/
namespace Drupal\Console\Core\Utils;
/**
* Class NestedArray
*
* @package Drupal\Console\Core\Utils
*/
class NestedArray
{
/**
* Based on drupal class Drupal\Component\Utility\NestedArray
*
* Retrieves a value from a nested array with variable depth.
*
* This helper function should be used when the depth of the array element
* being retrieved may vary (that is, the number of parent keys is variable).
* It is primarily used for form structures and renderable arrays.
*
* Without this helper function the only way to get a nested array value with
* variable depth in one line would be using eval(), which should be avoided:
*
* @code
* // Do not do this! Avoid eval().
* // May also throw a PHP notice, if the variable array keys do not exist.
* eval('$value = $array[\'' . implode("']['", $parents) . "'];");
* @endcode
*
* Instead, use this helper function:
* @code
* $value = NestedArray::getValue($form, $parents);
* @endcode
*
* A return value of NULL is ambiguous, and can mean either that the requested
* key does not exist, or that the actual value is NULL. If it is required to
* know whether the nested array key actually exists, pass a third argument
* that is altered by reference:
* @code
* $key_exists = NULL;
* $value = NestedArray::getValue($form, $parents, $key_exists);
* if ($key_exists) {
* // Do something with $value.
* }
* @endcode
*
* However if the number of array parent keys is static, the value should
* always be retrieved directly rather than calling this function.
* For instance:
* @code
* $value = $form['signature_settings']['signature'];
* @endcode
*
* @param array $array
* The array from which to get the value.
* @param array $parents
* An array of parent keys of the value, starting with the outermost key.
* @param bool $key_exists
* (optional) If given, an already defined variable that is altered by
* reference.
*
* @return mixed
* The requested nested value. Possibly NULL if the value is NULL or not all
* nested parent keys exist. $key_exists is altered by reference and is a
* Boolean that indicates whether all nested parent keys exist (TRUE) or not
* (FALSE). This allows to distinguish between the two possibilities when
* NULL is returned.
*
* @see NestedArray::setValue()
* @see NestedArray::unsetValue()
*/
public static function &getValue(array &$array, array $parents, &$key_exists = null)
{
$ref = &$array;
foreach ($parents as $parent) {
if (is_array($ref) && array_key_exists($parent, $ref)) {
$ref = &$ref[$parent];
} else {
$key_exists = false;
$null = null;
return $null;
}
}
$key_exists = true;
return $ref;
}
/**
* Sets a value in a nested array with variable depth.
*
* This helper function should be used when the depth of the array element you
* are changing may vary (that is, the number of parent keys is variable). It
* is primarily used for form structures and renderable arrays.
*
* Example:
*
* @code
* // Assume you have a 'signature' element somewhere in a form. It might be:
* $form['signature_settings']['signature'] = array(
* '#type' => 'text_format',
* '#title' => t('Signature'),
* );
* // Or, it might be further nested:
* $form['signature_settings']['user']['signature'] = array(
* '#type' => 'text_format',
* '#title' => t('Signature'),
* );
* @endcode
*
* To deal with the situation, the code needs to figure out the route to the
* element, given an array of parents that is either
* @code array('signature_settings', 'signature') @endcode
* in the first case or
* @code array('signature_settings', 'user', 'signature') @endcode
* in the second case.
*
* Without this helper function the only way to set the signature element in
* one line would be using eval(), which should be avoided:
* @code
* // Do not do this! Avoid eval().
* eval('$form[\'' . implode("']['", $parents) . '\'] = $element;');
* @endcode
*
* Instead, use this helper function:
* @code
* NestedArray::setValue($form, $parents, $element);
* @endcode
*
* However if the number of array parent keys is static, the value should
* always be set directly rather than calling this function. For instance,
* for the first example we could just do:
* @code
* $form['signature_settings']['signature'] = $element;
* @endcode
*
* @param array $array
* A reference to the array to modify.
* @param array $parents
* An array of parent keys, starting with the outermost key.
* @param mixed $value
* The value to set.
* @param bool $force
* (optional) If TRUE, the value is forced into the structure even if it
* requires the deletion of an already existing non-array parent value. If
* FALSE, PHP throws an error if trying to add into a value that is not an
* array. Defaults to FALSE.
*
* @see NestedArray::unsetValue()
* @see NestedArray::getValue()
*/
public static function setValue(array &$array, array $parents, $value, $force = false)
{
$ref = &$array;
foreach ($parents as $parent) {
// PHP auto-creates container arrays and NULL entries without error if $ref
// is NULL, but throws an error if $ref is set, but not an array.
if ($force && isset($ref) && !is_array($ref)) {
$ref = [];
}
$ref = &$ref[$parent];
}
$ref = $value;
}
/**
* Replace a YAML key maintaining values
*
* @param array $array
* @param array $parents
* @param $new_key
*/
public static function replaceKey(array &$array, array $parents, $new_key)
{
$ref = &$array;
foreach ($parents as $parent) {
$father = &$ref;
$key = $parent;
$ref = &$ref[$parent];
}
$father[$new_key] = $father[$key];
unset($father[$key]);
}
/**
* @param $array1
* @param $array2
* @param bool $negate if Negate is true only if values are equal are returned.
* @param $statistics mixed array
* @return array
*/
public function arrayDiff($array1, $array2, $negate = false, &$statistics)
{
$result = [];
foreach ($array1 as $key => $val) {
if (isset($array2[$key])) {
if (is_array($val) && $array2[$key]) {
$result[$key] = $this->arrayDiff($val, $array2[$key], $negate, $statistics);
if (empty($result[$key])) {
unset($result[$key]);
}
} else {
$statistics['total'] += 1;
if ($val == $array2[$key] && $negate) {
$result[$key] = $array2[$key];
$statistics['equal'] += 1;
} elseif ($val != $array2[$key] && $negate) {
$statistics['diff'] += 1;
} elseif ($val != $array2[$key] && !$negate) {
$result[$key] = $array2[$key];
$statistics['diff'] += 1;
} elseif ($val == $array2[$key] && !$negate) {
$result[$key] = $array2[$key];
$statistics['equal'] += 1;
}
}
} else {
if (is_array($val)) {
$statistics['diff'] += count($val, COUNT_RECURSIVE);
$statistics['total'] += count($val, COUNT_RECURSIVE);
} else {
$statistics['diff'] +=1;
$statistics['total'] += 1;
}
}
}
return $result;
}
/**
* Flat a yaml file
*
* @param array $array
* @param array $flatten_array
* @param string $key_flatten
*/
public function yamlFlattenArray(array &$array, &$flatten_array, &$key_flatten = '')
{
foreach ($array as $key => $value) {
if (!empty($key_flatten)) {
$key_flatten.= '.';
}
$key_flatten.= $key;
if (is_array($value)) {
$this->yamlFlattenArray($value, $flatten_array, $key_flatten);
} else {
if (!empty($value)) {
$flatten_array[$key_flatten] = $value;
$key_flatten = substr($key_flatten, 0, strrpos($key_flatten, "."));
} else {
// Return to previous key
$key_flatten = substr($key_flatten, 0, strrpos($key_flatten, "."));
}
}
}
// Start again with flatten key after recursive call
$key_flatten = substr($key_flatten, 0, strrpos($key_flatten, "."));
}
/**
* @param array $array
* @param array $split_array
* @param int $indent_level
* @param array $key_flatten
* @param int $key_level
* @param bool $exclude_parents_key
*/
public function yamlSplitArray(array &$array, array &$split_array, $indent_level = '', &$key_flatten, &$key_level, $exclude_parents_key)
{
foreach ($array as $key => $value) {
if (!$exclude_parents_key && !empty($key_flatten)) {
$key_flatten.= '.';
}
if ($exclude_parents_key) {
$key_flatten = $key;
} else {
$key_flatten .= $key;
}
if ($key_level == $indent_level) {
if (!empty($value)) {
$split_array[$key_flatten] = $value;
if (!$exclude_parents_key) {
$key_flatten = substr($key_flatten, 0, strrpos($key_flatten, "."));
}
}
} else {
if (is_array($value)) {
$key_level++;
$this->yamlSplitArray($value, $split_array, $indent_level, $key_flatten, $key_level, $exclude_parents_key);
}
}
}
// Start again with flatten key after recursive call
if (!$exclude_parents_key) {
$key_flatten = substr($key_flatten, 0, strrpos($key_flatten, "."));
}
$key_level--;
}
/**
* Unsets a value in a nested array with variable depth.
*
* This helper function should be used when the depth of the array element you
* are changing may vary (that is, the number of parent keys is variable). It
* is primarily used for form structures and renderable arrays.
*
* Example:
*
* @code
* // Assume you have a 'signature' element somewhere in a form. It might be:
* $form['signature_settings']['signature'] = array(
* '#type' => 'text_format',
* '#title' => t('Signature'),
* );
* // Or, it might be further nested:
* $form['signature_settings']['user']['signature'] = array(
* '#type' => 'text_format',
* '#title' => t('Signature'),
* );
* @endcode
*
* To deal with the situation, the code needs to figure out the route to the
* element, given an array of parents that is either
* @code array('signature_settings', 'signature') @endcode
* in the first case or
* @code array('signature_settings', 'user', 'signature') @endcode
* in the second case.
*
* Without this helper function the only way to unset the signature element in
* one line would be using eval(), which should be avoided:
* @code
* // Do not do this! Avoid eval().
* eval('unset($form[\'' . implode("']['", $parents) . '\']);');
* @endcode
*
* Instead, use this helper function:
* @code
* NestedArray::unset_nested_value($form, $parents, $element);
* @endcode
*
* However if the number of array parent keys is static, the value should
* always be set directly rather than calling this function. For instance, for
* the first example we could just do:
* @code
* unset($form['signature_settings']['signature']);
* @endcode
*
* @param array $array
* A reference to the array to modify.
* @param array $parents
* An array of parent keys, starting with the outermost key and including
* the key to be unset.
* @param bool $key_existed
* (optional) If given, an already defined variable that is altered by
* reference.
*
* @see NestedArray::setValue()
* @see NestedArray::getValue()
*/
public static function unsetValue(array &$array, array $parents, &$key_existed = null)
{
$unset_key = array_pop($parents);
$ref = &self::getValue($array, $parents, $key_existed);
if ($key_existed && is_array($ref) && array_key_exists($unset_key, $ref)) {
$key_existed = true;
unset($ref[$unset_key]);
} else {
$key_existed = false;
}
}
/**
* Determines whether a nested array contains the requested keys.
*
* This helper function should be used when the depth of the array element to
* be checked may vary (that is, the number of parent keys is variable). See
* NestedArray::setValue() for details. It is primarily used for form
* structures and renderable arrays.
*
* If it is required to also get the value of the checked nested key, use
* NestedArray::getValue() instead.
*
* If the number of array parent keys is static, this helper function is
* unnecessary and the following code can be used instead:
*
* @code
* $value_exists = isset($form['signature_settings']['signature']);
* $key_exists = array_key_exists('signature', $form['signature_settings']);
* @endcode
*
* @param array $array
* The array with the value to check for.
* @param array $parents
* An array of parent keys of the value, starting with the outermost key.
*
* @return bool
* TRUE if all the parent keys exist, FALSE otherwise.
*
* @see NestedArray::getValue()
*/
public static function keyExists(array $array, array $parents)
{
// Although this function is similar to PHP's array_key_exists(), its
// arguments should be consistent with getValue().
$key_exists = null;
self::getValue($array, $parents, $key_exists);
return $key_exists;
}
/**
* Merges multiple arrays, recursively, and returns the merged array.
*
* This function is similar to PHP's array_merge_recursive() function, but it
* handles non-array values differently. When merging values that are not both
* arrays, the latter value replaces the former rather than merging with it.
*
* Example:
*
* @code
* $link_options_1 = array('fragment' => 'x', 'attributes' => array('title' => t('X'), 'class' => array('a', 'b')));
* $link_options_2 = array('fragment' => 'y', 'attributes' => array('title' => t('Y'), 'class' => array('c', 'd')));
*
* // This results in array('fragment' => array('x', 'y'), 'attributes' => array('title' => array(t('X'), t('Y')), 'class' => array('a', 'b', 'c', 'd'))).
* $incorrect = array_merge_recursive($link_options_1, $link_options_2);
*
* // This results in array('fragment' => 'y', 'attributes' => array('title' => t('Y'), 'class' => array('a', 'b', 'c', 'd'))).
* $correct = NestedArray::mergeDeep($link_options_1, $link_options_2);
* @endcode
*
* @param array ...
* Arrays to merge.
*
* @return array
* The merged array.
*
* @see NestedArray::mergeDeepArray()
*/
public static function mergeDeep()
{
return self::mergeDeepArray(func_get_args());
}
/**
* Merges multiple arrays, recursively, and returns the merged array.
*
* This function is equivalent to NestedArray::mergeDeep(), except the
* input arrays are passed as a single array parameter rather than a variable
* parameter list.
*
* The following are equivalent:
* - NestedArray::mergeDeep($a, $b);
* - NestedArray::mergeDeepArray(array($a, $b));
*
* The following are also equivalent:
* - call_user_func_array('NestedArray::mergeDeep', $arrays_to_merge);
* - NestedArray::mergeDeepArray($arrays_to_merge);
*
* @param array $arrays
* An arrays of arrays to merge.
* @param bool $preserve_integer_keys
* (optional) If given, integer keys will be preserved and merged instead of
* appended. Defaults to FALSE.
*
* @return array
* The merged array.
*
* @see NestedArray::mergeDeep()
*/
public static function mergeDeepArray(array $arrays, $preserve_integer_keys = false)
{
$result = [];
foreach ($arrays as $array) {
foreach ($array as $key => $value) {
// Renumber integer keys as array_merge_recursive() does unless
// $preserve_integer_keys is set to TRUE. Note that PHP automatically
// converts array keys that are integer strings (e.g., '1') to integers.
if (is_integer($key) && !$preserve_integer_keys) {
$result[] = $value;
}
// Recurse when both values are arrays.
elseif (isset($result[$key]) && is_array($result[$key]) && is_array($value)) {
$result[$key] = self::mergeDeepArray([$result[$key], $value], $preserve_integer_keys);
}
// Otherwise, use the latter value, overriding any previous value.
else {
$result[$key] = $value;
}
}
}
return $result;
}
}

View file

@ -0,0 +1,170 @@
<?php
namespace Drupal\Console\Core\Utils;
use Symfony\Component\Yaml\Parser;
/**
* Class RequirementChecker
*
* @package Drupal\Console\Core\Utils
*/
class RequirementChecker
{
/**
* @var Parser
*/
protected $parser;
/**
* @var array
*/
protected $requirements = [];
/**
* @var array
*/
protected $checkResult = [];
/**
* @var bool
*/
protected $valid = true;
/**
* @var bool
*/
protected $overwritten = false;
/**
* RequirementChecker constructor.
*/
public function __construct()
{
$this->parser = new Parser();
}
/**
*
*/
private function checkPHPVersion()
{
$requiredPHP = $this->requirements['requirements']['php']['required'];
$currentPHP = phpversion();
$this->checkResult['php']['required'] = $requiredPHP;
$this->checkResult['php']['current'] = $currentPHP;
$this->valid = (version_compare($currentPHP, $requiredPHP) >= 0);
$this->checkResult['php']['valid'] = $this->valid;
}
/**
* checkRequiredExtensions
*/
private function checkRequiredExtensions()
{
$this->checkResult['extensions']['required']['missing'] = [];
foreach ($this->requirements['requirements']['extensions']['required'] as $extension) {
if (!extension_loaded($extension)) {
$this->checkResult['extensions']['required']['missing'][] = $extension;
$this->valid = false;
}
}
}
/**
* checkRecommendedExtensions
*/
private function checkRecommendedExtensions()
{
$this->checkResult['extensions']['recommended']['missing'] = [];
foreach ($this->requirements['requirements']['extensions']['recommended'] as $extension) {
if (!extension_loaded($extension)) {
$this->checkResult['extensions']['recommended']['missing'][] = $extension;
}
}
}
/**
* checkRequiredConfigurations
*/
private function checkRequiredConfigurations()
{
$this->checkResult['configurations']['required']['overwritten'] = [];
$this->checkResult['configurations']['required']['missing'] = [];
foreach ($this->requirements['requirements']['configurations']['required'] as $configuration) {
$defaultValue = null;
if (is_array($configuration)) {
$defaultValue = current($configuration);
$configuration = key($configuration);
}
if (!ini_get($configuration)) {
if ($defaultValue) {
ini_set($configuration, $defaultValue);
$this->checkResult['configurations']['required']['overwritten'] = [
$configuration => $defaultValue
];
$this->overwritten = true;
continue;
}
$this->valid = false;
$this->checkResult['configurations']['required']['missing'][] = $configuration;
}
}
}
/**
* @param $files
* @return array
*/
public function validate($files)
{
if (!is_array($files)) {
$files = [$files];
}
foreach ($files as $file) {
if (file_exists($file)) {
$this->requirements = array_merge(
$this->requirements,
$this->parser->parse(
file_get_contents($file)
)
);
}
}
if (!$this->checkResult) {
$this->checkPHPVersion();
$this->checkRequiredExtensions();
$this->checkRecommendedExtensions();
$this->checkRequiredConfigurations();
}
return $this->checkResult;
}
/**
* @return array
*/
public function getCheckResult()
{
return $this->checkResult;
}
/**
* @return boolean
*/
public function isOverwritten()
{
return $this->overwritten;
}
/**
* @return bool
*/
public function isValid()
{
return $this->valid;
}
}

View file

@ -0,0 +1,105 @@
<?php
namespace Drupal\Console\Core\Utils;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Drupal\Console\Core\Style\DrupalStyle;
/**
* Class ShellProcess
*
* @package Drupal\Console\Core\Utils
*/
class ShellProcess
{
/**
* @var string
*/
protected $appRoot;
/**
* @var TranslatorManagerInterface
*/
protected $translator;
/**
* @var ShellProcess
*/
private $process;
/**
* @var DrupalStyle
*/
private $io;
/**
* Process constructor.
*
* @param string $appRoot
* @param TranslatorManagerInterface $translator
*/
public function __construct($appRoot, $translator)
{
$this->appRoot = $appRoot;
$this->translator = $translator;
$output = new ConsoleOutput();
$input = new ArrayInput([]);
$this->io = new DrupalStyle($input, $output);
}
/**
* @param string $command
* @param string $workingDirectory
*
* @throws ProcessFailedException
*
* @return Process
*/
public function exec($command, $workingDirectory=null)
{
if (!$workingDirectory || $workingDirectory==='') {
$workingDirectory = $this->appRoot;
}
if (realpath($workingDirectory)) {
$this->io->comment(
$this->translator->trans('commands.exec.messages.working-directory') .': ',
false
);
$this->io->writeln(realpath($workingDirectory));
}
$this->io->comment(
$this->translator->trans('commands.exec.messages.executing-command') .': ',
false
);
$this->io->writeln($command);
$this->process = new Process($command);
$this->process->setWorkingDirectory($workingDirectory);
$this->process->enableOutput();
$this->process->setTimeout(null);
$this->process->run(
function ($type, $buffer) {
$this->io->write($buffer);
}
);
if (!$this->process->isSuccessful()) {
throw new ProcessFailedException($this->process);
}
return $this->process->isSuccessful();
}
/**
* @return string
*/
public function getOutput()
{
return $this->process->getOutput();
}
}

View file

@ -0,0 +1,134 @@
<?php
/**
* @file
* Contains Drupal\Console\Core\Command\ShowFileHelper.
*/
namespace Drupal\Console\Core\Utils;
use Drupal\Console\Core\Style\DrupalStyle;
/**
* Class ShowFileHelper
*
* @package Drupal\Console\Core\Utils
*/
class ShowFile
{
/**
* @var string
*/
protected $root;
/**
* @var TranslatorManagerInterface
*/
protected $translator;
/**
* ShowFile constructor.
*
* @param string $root
* @param TranslatorManagerInterface $translator
*/
public function __construct(
$root,
TranslatorManagerInterface $translator
) {
$this->root = $root;
$this->translator = $translator;
}
/**
* @param DrupalStyle $io
* @param string $files
* @param boolean $showPath
*/
public function generatedFiles($io, $files, $showPath = true)
{
$pathKey = null;
$path = null;
if ($showPath) {
$pathKey = 'application.messages.path';
$path = $this->root;
}
$this->showMMultiple(
$io,
$files,
'application.messages.files.generated',
$pathKey,
$path
);
}
/**
* @param DrupalStyle $io
* @param array $files
* @param boolean $showPath
*/
public function copiedFiles($io, $files, $showPath = true)
{
$pathKey = null;
$path = null;
if ($showPath) {
$pathKey = 'application.user.messages.path';
$path = rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\').'/.console/';
}
$this->showMMultiple(
$io,
$files,
'application.messages.files.copied',
$pathKey,
$path
);
}
/**
* @param DrupalStyle $io
* @param array $files
* @param string $headerKey
* @param string $pathKey
* @param string $path
*/
private function showMMultiple($io, $files, $headerKey, $pathKey, $path)
{
if (!$files) {
return;
}
$io->writeln($this->translator->trans($headerKey));
if ($pathKey) {
$io->info(
sprintf('%s:', $this->translator->trans($pathKey)),
false
);
}
if ($path) {
$io->comment($path, false);
}
$io->newLine();
$index = 1;
foreach ($files as $file) {
$this->showSingle($io, $file, $index);
++$index;
}
}
/**
* @param DrupalStyle $io
* @param string $file
* @param int $index
*/
private function showSingle(DrupalStyle $io, $file, $index)
{
$io->info(
sprintf('%s -', $index),
false
);
$io->comment($file, false);
$io->newLine();
}
}

View file

@ -0,0 +1,159 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Utils\StringConverter
*/
namespace Drupal\Console\Core\Utils;
/**
* Class StringConverter
*
* @package Drupal\Console\Core\Utils
*/
class StringConverter
{
// This REGEX captures all uppercase letters after the first character
const REGEX_UPPER_CASE_LETTERS = '/(?<=\\w)(?=[A-Z])/';
// This REGEX captures non alphanumeric characters and non underscores
const REGEX_MACHINE_NAME_CHARS = '@[^a-z0-9_]+@';
// This REGEX captures
const REGEX_CAMEL_CASE_UNDER = '/([a-z])([A-Z])/';
// This REGEX captures spaces around words
const REGEX_SPACES = '/\s\s+/';
// This REGEX forces max length to 32
const MAX_MACHINE_NAME = 32;
/**
* Replaces non alphanumeric characters with underscores.
*
* @param String $name User input
*
* @return String $machine_name User input in machine-name format
*/
public function createMachineName($name)
{
$machine_name = preg_replace(self::REGEX_MACHINE_NAME_CHARS, '_', strtolower($name));
$machine_name = trim($machine_name, '_');
if (strlen($machine_name) > self::MAX_MACHINE_NAME) {
$machine_name = substr($machine_name, 0, self::MAX_MACHINE_NAME);
}
return $machine_name;
}
/**
* Converts camel-case strings to machine-name format.
*
* @param String $name User input
*
* @return String $machine_name User input in machine-name format
*/
public function camelCaseToMachineName($name)
{
$machine_name = preg_replace(self::REGEX_UPPER_CASE_LETTERS, '_$1', $name);
$machine_name = preg_replace(self::REGEX_MACHINE_NAME_CHARS, '_', strtolower($machine_name));
$machine_name = trim($machine_name, '_');
return $machine_name;
}
/**
* Converts camel-case strings to under-score format.
*
* @param String $camel_case User input
*
* @return String
*/
public function camelCaseToUnderscore($camel_case)
{
return strtolower(preg_replace(self::REGEX_CAMEL_CASE_UNDER, '$1_$2', $camel_case));
}
/**
* Converts camel-case strings to human readable format.
*
* @param String $camel_case User input
*
* @return String
*/
public function camelCaseToHuman($camel_case)
{
return ucfirst(strtolower(preg_replace(self::REGEX_CAMEL_CASE_UNDER, '$1 $2', $camel_case)));
}
/**
* @param $human
* @return mixed
*/
public function humanToCamelCase($human)
{
return str_replace(' ', '', ucwords($human));
}
/**
* Converts My Name to my name. For permissions.
*
* @param String $permission User input
*
* @return String
*/
public function camelCaseToLowerCase($permission)
{
return strtolower(preg_replace(self::REGEX_SPACES, ' ', $permission));
}
/**
* Convert the first character of upper case. For permissions.
*
* @param String $permission_title User input
*
* @return String
*/
public function anyCaseToUcFirst($permission_title)
{
return ucfirst(preg_replace(self::REGEX_SPACES, ' ', $permission_title));
}
/**
* @param $className
* @return string
*/
public function removeSuffix($className)
{
$suffixes = [
'Form',
'Controller',
'Service',
'Command'
];
if (strlen($className) == 0) {
return $className;
}
foreach ($suffixes as $suffix) {
$length = strlen($suffix);
if (strlen($className) <= $length) {
continue;
}
if (substr($className, -$length) === $suffix) {
return substr($className, 0, -$length);
}
}
return $className;
}
/**
* @param $input
* @return string
*/
public function underscoreToCamelCase($input)
{
return lcfirst(str_replace('_', '', ucwords($input, '_')));
}
}

View file

@ -0,0 +1,247 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Utils\TranslatorManager.
*/
namespace Drupal\Console\Core\Utils;
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Loader\YamlFileLoader;
use Symfony\Component\Translation\Loader\ArrayLoader;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Yaml\Parser;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Yaml\Exception\ParseException;
/**
* Class TranslatorManager
*
* @package Drupal\Console\Core\Utils
*/
class TranslatorManager implements TranslatorManagerInterface
{
/**
* @var string
*/
protected $language;
/**
* @var Translator
*/
protected $translator;
/**
* @var Parser
*/
protected $parser;
/**
* @var Filesystem
*/
protected $filesystem;
/**
* @var string
*/
protected $coreLanguageRoot;
/**
* Translator constructor.
*/
public function __construct()
{
$this->parser = new Parser();
$this->filesystem = new Filesystem();
}
/**
* @param $resource
* @param string $name
*/
private function addResource($resource, $name = 'yaml')
{
$this->translator->addResource(
$name,
$resource,
$this->language
);
}
/**
* @param $loader
* @param string $name
*/
private function addLoader($loader, $name = 'yaml')
{
$this->translator->addLoader(
$name,
$loader
);
}
/**
* @param $language
* @param $directoryRoot
*
* @return array
*/
private function buildCoreLanguageDirectory(
$language,
$directoryRoot
) {
$coreLanguageDirectory =
$directoryRoot .
sprintf(
DRUPAL_CONSOLE_LANGUAGE,
$language
);
if (!is_dir($coreLanguageDirectory)) {
return $this->buildCoreLanguageDirectory('en', $directoryRoot);
}
if (!$this->coreLanguageRoot) {
$this->coreLanguageRoot = $directoryRoot;
}
return [$language, $coreLanguageDirectory];
}
/**
* {@inheritdoc}
*/
public function loadCoreLanguage($language, $directoryRoot)
{
$coreLanguageDirectory = $this->buildCoreLanguageDirectory(
$language,
$directoryRoot
);
$this->loadResource(
$coreLanguageDirectory[0],
$coreLanguageDirectory[1]
);
return $this;
}
/**
* {@inheritdoc}
*/
public function changeCoreLanguage($language)
{
return $this->loadCoreLanguage($language, $this->coreLanguageRoot);
}
/**
* {@inheritdoc}
*/
public function loadResource($language, $directoryRoot)
{
if (!is_dir($directoryRoot)) {
return;
}
$this->language = $language;
$this->translator = new Translator($this->language);
$this->addLoader(new ArrayLoader(), 'array');
$this->addLoader(new YamlFileLoader(), 'yaml');
/* @TODO fallback to en */
$finder = new Finder();
$finder->files()
->name('*.yml')
->in($directoryRoot);
foreach ($finder as $file) {
$resource = $directoryRoot.'/'.$file->getBasename();
$filename = $file->getBasename('.yml');
// Handle application file different than commands
if ($filename == 'application') {
try {
$this->loadTranslationByFile($resource, 'application');
} catch (ParseException $e) {
echo 'application.yml'.' '.$e->getMessage();
}
continue;
}
$key = 'commands.'.$filename;
try {
$this->loadTranslationByFile($resource, $key);
} catch (ParseException $e) {
echo $key.'.yml '.$e->getMessage();
}
}
return;
}
/**
* Load yml translation where filename is part of translation key.
*
* @param $resource
* @param $resourceKey
*/
protected function loadTranslationByFile($resource, $resourceKey = null)
{
$resourceParsed = $this->parser->parse(file_get_contents($resource));
if ($resourceKey) {
$parents = explode('.', $resourceKey);
$resourceArray = [];
$this->setResourceArray($parents, $resourceArray, $resourceParsed);
$resourceParsed = $resourceArray;
}
$this->addResource($resourceParsed, 'array');
}
/**
* @param $parents
* @param $parentsArray
* @param $resource
*
* @return mixed
*/
private function setResourceArray($parents, &$parentsArray, $resource)
{
$ref = &$parentsArray;
foreach ($parents as $parent) {
$ref[$parent] = [];
$previous = &$ref;
$ref = &$ref[$parent];
}
$previous[$parent] = $resource;
return $parentsArray;
}
/**
* {@inheritdoc}
*/
public function getTranslator()
{
return $this->translator;
}
/**
* {@inheritdoc}
*/
public function getLanguage()
{
return $this->language;
}
/**
* {@inheritdoc}
*/
public function trans($key)
{
return $this->translator->trans($key);
}
}

View file

@ -0,0 +1,52 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Utils\TranslatorManagerInterface.
*/
namespace Drupal\Console\Core\Utils;
use Symfony\Component\Translation\Translator;
interface TranslatorManagerInterface
{
/**
* @param $language
* @param $directoryRoot
* @return $this
*/
public function loadCoreLanguage($language, $directoryRoot);
/**
* @param $language
* @return $this
*/
public function changeCoreLanguage($language);
/**
* @param $language
* @param $directoryRoot
*
* @return void
*/
public function loadResource($language, $directoryRoot);
/**
* @return Translator
*/
public function getTranslator();
/**
* @return string
*/
public function getLanguage();
/**
* @param $key
*
* @return string
*/
public function trans($key);
}

View file

@ -0,0 +1,270 @@
<?php
/**
* @file
* Contains \Drupal\Console\Core\Utils\TwigRenderer.
*/
namespace Drupal\Console\Core\Utils;
/**
* Class TwigRenderer
*
* @package Drupal\Console\Core\Utils
*/
class TwigRenderer
{
/**
* @var TranslatorManagerInterface
*/
protected $translator;
/**
* @var \Twig_Environment
*/
protected $engine;
/**
* @var array
*/
protected $skeletonDirs;
/**
* @var StringConverter
*/
protected $stringConverter;
/**
* TwigRenderer constructor.
*
* @param TranslatorManagerInterface $translator
* @param StringConverter $stringConverter
*/
public function __construct(
TranslatorManagerInterface $translator,
StringConverter $stringConverter
) {
$this->translator = $translator;
$this->stringConverter = $stringConverter;
}
/**
* @param array $skeletonDirs
*/
public function setSkeletonDirs(array $skeletonDirs)
{
foreach ($skeletonDirs as $skeletonDir) {
$this->addSkeletonDir($skeletonDir);
}
}
/**
* @param $skeletonDir
*/
public function addSkeletonDir($skeletonDir)
{
if (is_dir($skeletonDir)) {
$this->skeletonDirs[] = $skeletonDir;
}
}
/**
* @return array
*/
public function getSkeletonDirs()
{
if (!$this->skeletonDirs) {
$this->skeletonDirs[] = __DIR__ . '/../../templates';
}
return $this->skeletonDirs;
}
/**
* @param string $template
* @param array $parameters
*
* @return string
*/
public function render($template, $parameters = [])
{
if (!$this->engine) {
$this->engine = new \Twig_Environment(
new \Twig_Loader_Filesystem($this->getSkeletonDirs()), [
'debug' => true,
'cache' => false,
'strict_variables' => true,
'autoescape' => false,
]
);
$this->engine->addFunction($this->getServicesAsParameters());
$this->engine->addFunction($this->getServicesAsParametersKeys());
$this->engine->addFunction($this->getArgumentsFromRoute());
$this->engine->addFunction($this->getServicesClassInitialization());
$this->engine->addFunction($this->getServicesClassInjection());
$this->engine->addFunction($this->getTagsAsArray());
$this->engine->addFunction($this->getTranslationAsYamlComment());
$this->engine->addFilter($this->createMachineName());
}
return $this->engine->render($template, $parameters);
}
/**
* @return \Twig_SimpleFunction
*/
public function getServicesAsParameters()
{
$servicesAsParameters = new \Twig_SimpleFunction(
'servicesAsParameters', function ($services) {
$returnValues = [];
foreach ($services as $service) {
$returnValues[] = sprintf('%s $%s', $service['short'], $service['machine_name']);
}
return $returnValues;
}
);
return $servicesAsParameters;
}
/**
* @return \Twig_SimpleFunction
*/
public function getServicesAsParametersKeys()
{
$servicesAsParametersKeys = new \Twig_SimpleFunction(
'servicesAsParametersKeys', function ($services) {
$returnValues = [];
foreach ($services as $service) {
$returnValues[] = sprintf('\'@%s\'', $service['name']);
}
return $returnValues;
}
);
return $servicesAsParametersKeys;
}
/**
* @return \Twig_SimpleFunction
*/
public function getArgumentsFromRoute()
{
$argumentsFromRoute = new \Twig_SimpleFunction(
'argumentsFromRoute', function ($route) {
$returnValues = '';
preg_match_all('/{(.*?)}/', $route, $returnValues);
$returnValues = array_map(
function ($value) {
return sprintf('$%s', $value);
}, $returnValues[1]
);
return $returnValues;
}
);
return $argumentsFromRoute;
}
/**
* @return \Twig_SimpleFunction
*/
public function getServicesClassInitialization()
{
$returnValue = new \Twig_SimpleFunction(
'serviceClassInitialization', function ($services) {
$returnValues = [];
foreach ($services as $service) {
$returnValues[] = sprintf(' $this->%s = $%s;', $service['camel_case_name'], $service['machine_name']);
}
return implode(PHP_EOL, $returnValues);
}
);
return $returnValue;
}
/**
* @return \Twig_SimpleFunction
*/
public function getServicesClassInjection()
{
$returnValue = new \Twig_SimpleFunction(
'serviceClassInjection', function ($services) {
$returnValues = [];
foreach ($services as $service) {
$returnValues[] = sprintf(' $container->get(\'%s\')', $service['name']);
}
return implode(','.PHP_EOL, $returnValues);
}
);
return $returnValue;
}
/**
* @return \Twig_SimpleFunction
*/
public function getTagsAsArray()
{
$returnValue = new \Twig_SimpleFunction(
'tagsAsArray', function ($tags) {
$returnValues = [];
foreach ($tags as $key => $value) {
$returnValues[] = sprintf('%s: %s', $key, $value);
}
return $returnValues;
}
);
return $returnValue;
}
/**
* @return \Twig_SimpleFunction
*/
public function getTranslationAsYamlComment()
{
$returnValue = new \Twig_SimpleFunction(
'yaml_comment', function (\Twig_Environment $environment, $context, $key) {
$message = $this->translator->trans($key);
$messages = explode("\n", $message);
$returnValues = [];
foreach ($messages as $message) {
$returnValues[] = '# '.$message;
}
$message = implode("\n", $returnValues);
$template = $environment->createTemplate($message);
return $template->render($context);
}, [
'needs_environment' => true,
'needs_context' => true,
]
);
return $returnValue;
}
/**
* @return \Twig_SimpleFilter
*/
public function createMachineName()
{
return new \Twig_SimpleFilter(
'machine_name', function ($var) {
return $this->stringConverter->createMachineName($var);
}
);
}
}

View file

@ -0,0 +1,24 @@
<?php
use Webmozart\PathUtil\Path;
/**
* @param string $path
* @return null|string
*/
function calculateRealPath($path)
{
if (!$path) {
return null;
}
if (strpos($path, 'phar://')===0) {
return $path;
}
if (realpath($path)) {
return $path;
}
return Path::canonicalize($path);
}

View file

@ -0,0 +1,7 @@
# Drupal console autocompletion
function __complete_drupal
drupal complete | command awk '{ print $1 }'
end
complete -x -c drupal -a "(__complete_drupal)"

View file

@ -0,0 +1,10 @@
#!/usr/bin/env bash
# Enable auto-completion.
if HOOK=$({{executable}} _completion -g -p {{executable}}); then
# See https://github.com/stecman/symfony-console-completion/#zero-config-use
eval $(echo "$HOOK")
echo "$HOOK" | source /dev/stdin
source <(echo "$HOOK") 2>/dev/null
fi

View file

@ -0,0 +1,25 @@
/`
+o/`
-oooo/.
.+oooooo/-
./oooooo+//::`
`.:+ooooo/-`
.:+ooooooo+. `...`
./+ooooooooo/ ./oooooo+-
-+ooooooooooo+` -oooooooooo/ `
`/ooooooooooooo/ +ooooooooooo. .+.
`+oooooooooooooo+ /ooooooooooo. -oo/`
+oooooooooooooooo- `/oooooooo+. +ooo+`
:oooooooooooooooo+/` `-////:. `+ooooo+`
+oooooooooooo+:.` `:+ooooooo:
ooooooooooo/` .:+oooooooooo+
ooooooooo+` `.-::--` :oooooooooooo
/ooooooo/ -+oooooooo+:` -oooooooooo+
.oooooo+` `+oooooooooooo+. /ooooooooo-
:ooooo: /oooooooooooooo+` .oooooooo/
/oooo- +ooooooooooooooo. `ooooooo/
:ooo: :oooooooooooooo+ .oooooo:
`/oo` :oooooooooooo+` /oooo/.
./+` .:+ooooooo/- :ooo/.
`-` `..... `/o/-`
`-:.`

View file

@ -0,0 +1,52 @@
.,.
.cd:..
.xXd,,'..
.lXWx;;;,,..
.,dXWXo;;;;;,,..
.;dKWWKx:;;;;;;;,,'..
.;oOXNXKOo;;;;;;;;;;;;,,,'..
.:dOXWMMN0Okl;;;;;;;;;;;;;;;;,,,'..
.,lk0NMMMMMMNKOxc;;;;;;;;;;;;;;;;;;;;,,,'..
.'cx0XWMMMMMMMWX0kd:;;;;;;;;;;;;;;;;;;;;;;;;;,,,..
.'cx0NMMMMMMMMMWX0Oxl;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,,'..
.;d0NMMMMMMMMMMWX0Oxl:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,,...
.:kXWMMMMMMMMMWNK0kdl:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,'..
.cONMMMMMMMMMWNX0Okoc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,'.
.;kNMMMMMMMMWNX0Okdl:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,'..
.oXMMMMMMWWXK0Oxdl:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,'..
,oKWWWWNXKK0kxoc:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,'..
'lOO0000OOxdlc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,'''.
.,lxkxxdolc:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,''''..
.,;;;::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,,'''''..
.,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,'''''''.
.';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,,'''''''..
.',;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,,'''''''''..
.,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,,''''''''''..
',;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,,''''''''''''.
,,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,,''''''''''''''.
,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,,'''''''''''''''.
,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,,''''''''''''''''''
,;;;;;;;;;;;;;;;;;;;;;;;;;;;cldxkkOkkxxdlc;;;;;;;;;;;;;;;;;;;;;;;;,,''''''''''',''''''''
,;;;;;;;;;;;;;;;;;;;;;;;:ox0XWMMMMMMMMMWNX0kxdc;;;;;;;;;;;;;;;;,,,'''''''';cdk00Okl,''''
,;;;;;;;;;;;;;;;;;;;;;cxKWMMMMMMMMMMMMMMMMMMMWN0xl;;;;;;;;;;,,,'''''''';lkKWMMMMMMW0c'''
',;;;;;;;;;;;;;;;;;;:dKWMMMMMMMMMMMMMMMMMMMMMMMMMN0xl;;;;;,,'''''''';okXWMMMMMMMMMMM0:'.
.,;;;;;;;;;;;;;;;;;:kNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0xl;''''''',:oOXWMMMMMMMMMMMMMMNd'.
.',;;;;;;;;;;;;;;;;xWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0xolccoxONMMMMMMMMMMMMMMMMMMWd'.
.,;;;;;;;;;;;;;;;oXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNWMMMMMMMMMMMMMMMMMMMMMMXl..
.',;;;;;;;;;;;;;;xNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0OOOKNMMMMMMMMMMMMMMMMMMMM0;.
.',;;;;;;;;;;;;;dNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWN0xl:,''',cxXWMMMMMMMMMMMMMMMMWd.
.',;;;;;;;;;;;;lKMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKko:,'''''''''':dKWMMMMMMMMMMMMMWk,
.',;;;;;;;;;;;;dXMMMMMMMMMMMMMMMMMMMMMMMMWX0xl;'''',;:::;,''''';oKWMMMMMMMMMMWO,
..',,;;;;;;;;;;o0NMMMMMMMMMMMMMMMMMMN0xdo:,''',cdO0XXXXK0kl,'''';o0WMMMMMMMNd,
.''',,,,,,,,,,;lk0XWMMMMMMMMWNX0ko:,'''''';oONN0xdoodx0NNx,''''';lOXWWWXkc.
..'''''''''''''',:lloodddoolc;'''''''''',xN0dc,'''''',oK0:''''''',:clc;..
...''''''''''''''''''''''''''''''''''''':c,''''''''''';;''''''''''''..
..''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''...
...'''''''''''''''''''''',lxdc,'''''''''''''''''',:oxkl''''''..
...''''''''''''''''''':kNMNK0OxdollcccclllodxO0XX0d;'''..
..'''''''''''''''''',cxOKXXNWMMWWWWWWWWNXKOxo:'''..
...'.'''''''''''''''',;:clooodddoollc:,'''...
....'''''''''''''''''''''''''''.....
....'..''''''''''''........
Originally from: https://gist.github.com/ericjsilva/aef0808c61c213a2e578

View file

@ -0,0 +1,16 @@
Art by Morfina
__
'. \
'- \
/ /_ .---.
/ | \\,.\/--.// )
| \// )/ /
\ ' ^ ^ / )____.----.. 6
'.____. .___/ \._)
.\/. )
'\ /
_/ \/ ). ) (
/# .! | /\ /
\ C// # /'-----''/ # /
. 'C/ | | | | |mrf ,
\), .. .'OOO-'. ..'OOO'OOO-'. ..\(,

Some files were not shown because too many files have changed in this diff Show more