Initial Drupal 11 with DDEV setup
This commit is contained in:
297
.ddev/config.yaml
Normal file
297
.ddev/config.yaml
Normal file
@ -0,0 +1,297 @@
|
||||
name: drupal11-ddev
|
||||
type: drupal11
|
||||
docroot: web
|
||||
php_version: "8.3"
|
||||
webserver_type: nginx-fpm
|
||||
xdebug_enabled: false
|
||||
additional_hostnames: []
|
||||
additional_fqdns: []
|
||||
database:
|
||||
type: mariadb
|
||||
version: "10.11"
|
||||
use_dns_when_possible: true
|
||||
composer_version: "2"
|
||||
web_environment: []
|
||||
corepack_enable: true
|
||||
|
||||
# Key features of DDEV's config.yaml:
|
||||
|
||||
# name: <projectname> # Name of the project, automatically provides
|
||||
# http://projectname.ddev.site and https://projectname.ddev.site
|
||||
# If the name is omitted, the project will take the name of the enclosing directory,
|
||||
# which is useful if you want to have a copy of the project side by side with this one.
|
||||
|
||||
# type: <projecttype> # backdrop, cakephp, craftcms, drupal, drupal6, drupal7, drupal8, drupal9, drupal10, drupal11, generic, laravel, magento, magento2, php, shopware6, silverstripe, symfony, typo3, wordpress
|
||||
# See https://docs.ddev.com/en/stable/users/quickstart/ for more
|
||||
# information on the different project types
|
||||
|
||||
# docroot: <relative_path> # Relative path to the directory containing index.php.
|
||||
|
||||
# php_version: "8.3" # PHP version to use, "5.6" through "8.4"
|
||||
|
||||
# You can explicitly specify the webimage but this
|
||||
# is not recommended, as the images are often closely tied to DDEV's' behavior,
|
||||
# so this can break upgrades.
|
||||
|
||||
# webimage: <docker_image>
|
||||
# It’s unusual to change this option, and we don’t recommend it without Docker experience and a good reason.
|
||||
# Typically, this means additions to the existing web image using a .ddev/web-build/Dockerfile.*
|
||||
|
||||
# database:
|
||||
# type: <dbtype> # mysql, mariadb, postgres
|
||||
# version: <version> # database version, like "10.11" or "8.0"
|
||||
# MariaDB versions can be 5.5-10.8, 10.11, 11.4, 11.8
|
||||
# MySQL versions can be 5.5-8.0, 8.4
|
||||
# PostgreSQL versions can be 9-17
|
||||
|
||||
# router_http_port: <port> # Port to be used for http (defaults to global configuration, usually 80)
|
||||
# router_https_port: <port> # Port for https (defaults to global configuration, usually 443)
|
||||
|
||||
# xdebug_enabled: false # Set to true to enable Xdebug and "ddev start" or "ddev restart"
|
||||
# Note that for most people the commands
|
||||
# "ddev xdebug" to enable Xdebug and "ddev xdebug off" to disable it work better,
|
||||
# as leaving Xdebug enabled all the time is a big performance hit.
|
||||
|
||||
# xhgui_http_port: "8143"
|
||||
# xhgui_https_port: "8142"
|
||||
# The XHGui ports can be changed from the default 8143 and 8142
|
||||
# Very rarely used
|
||||
|
||||
# host_xhgui_port: "8142"
|
||||
# Can be used to change the host binding port of the XHGui
|
||||
# application. Rarely used; only when port conflict and
|
||||
# bind_all_ports is used (normally with router disabled)
|
||||
|
||||
# xhprof_mode: [prepend|xhgui|global]
|
||||
# Set to "xhgui" to enable XHGui features
|
||||
# "xhgui" will become default in a future major release
|
||||
|
||||
# webserver_type: nginx-fpm, apache-fpm, generic
|
||||
|
||||
# timezone: Europe/Berlin
|
||||
# If timezone is unset, DDEV will attempt to derive it from the host system timezone
|
||||
# using the $TZ environment variable or the /etc/localtime symlink.
|
||||
# This is the timezone used in the containers and by PHP;
|
||||
# it can be set to any valid timezone,
|
||||
# see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||
# For example Europe/Dublin or MST7MDT
|
||||
|
||||
# composer_root: <relative_path>
|
||||
# Relative path to the Composer root directory from the project root. This is
|
||||
# the directory which contains the composer.json and where all Composer related
|
||||
# commands are executed.
|
||||
|
||||
# composer_version: "2"
|
||||
# You can set it to "" or "2" (default) for Composer v2 or "1" for Composer v1
|
||||
# to use the latest major version available at the time your container is built.
|
||||
# It is also possible to use each other Composer version channel. This includes:
|
||||
# - 2.2 (latest Composer LTS version)
|
||||
# - stable
|
||||
# - preview
|
||||
# - snapshot
|
||||
# Alternatively, an explicit Composer version may be specified, for example "2.2.18".
|
||||
# To reinstall Composer after the image was built, run "ddev debug rebuild".
|
||||
|
||||
# nodejs_version: "22"
|
||||
# change from the default system Node.js version to any other version.
|
||||
# See https://docs.ddev.com/en/stable/users/configuration/config/#nodejs_version for more information
|
||||
# and https://www.npmjs.com/package/n#specifying-nodejs-versions for the full documentation,
|
||||
# Note that using of 'ddev nvm' is discouraged because "nodejs_version" is much easier to use,
|
||||
# can specify any version, and is more robust than using 'nvm'.
|
||||
|
||||
# corepack_enable: false
|
||||
# Change to 'true' to 'corepack enable' and gain access to latest versions of yarn/pnpm
|
||||
|
||||
# additional_hostnames:
|
||||
# - somename
|
||||
# - someothername
|
||||
# would provide http and https URLs for "somename.ddev.site"
|
||||
# and "someothername.ddev.site".
|
||||
|
||||
# additional_fqdns:
|
||||
# - example.com
|
||||
# - sub1.example.com
|
||||
# would provide http and https URLs for "example.com" and "sub1.example.com"
|
||||
# Please take care with this because it can cause great confusion.
|
||||
|
||||
# upload_dirs: "custom/upload/dir"
|
||||
#
|
||||
# upload_dirs:
|
||||
# - custom/upload/dir
|
||||
# - ../private
|
||||
#
|
||||
# would set the destination paths for ddev import-files to <docroot>/custom/upload/dir
|
||||
# When Mutagen is enabled this path is bind-mounted so that all the files
|
||||
# in the upload_dirs don't have to be synced into Mutagen.
|
||||
|
||||
# disable_upload_dirs_warning: false
|
||||
# If true, turns off the normal warning that says
|
||||
# "You have Mutagen enabled and your 'php' project type doesn't have upload_dirs set"
|
||||
|
||||
# ddev_version_constraint: ""
|
||||
# Example:
|
||||
# ddev_version_constraint: ">= 1.24.8"
|
||||
# This will enforce that the running ddev version is within this constraint.
|
||||
# See https://github.com/Masterminds/semver#checking-version-constraints for
|
||||
# supported constraint formats
|
||||
|
||||
# working_dir:
|
||||
# web: /var/www/html
|
||||
# db: /home
|
||||
# would set the default working directory for the web and db services.
|
||||
# These values specify the destination directory for ddev ssh and the
|
||||
# directory in which commands passed into ddev exec are run.
|
||||
|
||||
# omit_containers: [db, ddev-ssh-agent]
|
||||
# Currently only these containers are supported. Some containers can also be
|
||||
# omitted globally in the ~/.ddev/global_config.yaml. Note that if you omit
|
||||
# the "db" container, several standard features of DDEV that access the
|
||||
# database container will be unusable. In the global configuration it is also
|
||||
# possible to omit ddev-router, but not here.
|
||||
|
||||
# performance_mode: "global"
|
||||
# DDEV offers performance optimization strategies to improve the filesystem
|
||||
# performance depending on your host system. Should be configured globally.
|
||||
#
|
||||
# If set, will override the global config. Possible values are:
|
||||
# - "global": uses the value from the global config.
|
||||
# - "none": disables performance optimization for this project.
|
||||
# - "mutagen": enables Mutagen for this project.
|
||||
# - "nfs": enables NFS for this project.
|
||||
#
|
||||
# See https://docs.ddev.com/en/stable/users/install/performance/#nfs
|
||||
# See https://docs.ddev.com/en/stable/users/install/performance/#mutagen
|
||||
|
||||
# fail_on_hook_fail: False
|
||||
# Decide whether 'ddev start' should be interrupted by a failing hook
|
||||
|
||||
# host_https_port: "59002"
|
||||
# The host port binding for https can be explicitly specified. It is
|
||||
# dynamic unless otherwise specified.
|
||||
# This is not used by most people, most people use the *router* instead
|
||||
# of the localhost port.
|
||||
|
||||
# host_webserver_port: "59001"
|
||||
# The host port binding for the ddev-webserver can be explicitly specified. It is
|
||||
# dynamic unless otherwise specified.
|
||||
# This is not used by most people, most people use the *router* instead
|
||||
# of the localhost port.
|
||||
|
||||
# host_db_port: "59002"
|
||||
# The host port binding for the ddev-dbserver can be explicitly specified. It is dynamic
|
||||
# unless explicitly specified.
|
||||
|
||||
# mailpit_http_port: "8025"
|
||||
# mailpit_https_port: "8026"
|
||||
# The Mailpit ports can be changed from the default 8025 and 8026
|
||||
|
||||
# host_mailpit_port: "8025"
|
||||
# The mailpit port is not normally bound on the host at all, instead being routed
|
||||
# through ddev-router, but it can be bound directly to localhost if specified here.
|
||||
|
||||
# webimage_extra_packages: [php7.4-tidy, php-bcmath]
|
||||
# Extra Debian packages that are needed in the webimage can be added here
|
||||
|
||||
# dbimage_extra_packages: [telnet,netcat]
|
||||
# Extra Debian packages that are needed in the dbimage can be added here
|
||||
|
||||
# use_dns_when_possible: true
|
||||
# If the host has internet access and the domain configured can
|
||||
# successfully be looked up, DNS will be used for hostname resolution
|
||||
# instead of editing /etc/hosts
|
||||
# Defaults to true
|
||||
|
||||
# project_tld: ddev.site
|
||||
# The top-level domain used for project URLs
|
||||
# The default "ddev.site" allows DNS lookup via a wildcard
|
||||
# If you prefer you can change this to "ddev.local" to preserve
|
||||
# pre-v1.9 behavior.
|
||||
|
||||
# ngrok_args: --basic-auth username:pass1234
|
||||
# Provide extra flags to the "ngrok http" command, see
|
||||
# https://ngrok.com/docs/agent/config/v3/#agent-configuration or run "ngrok http -h"
|
||||
|
||||
# disable_settings_management: false
|
||||
# If true, DDEV will not create CMS-specific settings files like
|
||||
# Drupal's settings.php/settings.ddev.php or TYPO3's additional.php
|
||||
# In this case the user must provide all such settings.
|
||||
|
||||
# You can inject environment variables into the web container with:
|
||||
# web_environment:
|
||||
# - SOMEENV=somevalue
|
||||
# - SOMEOTHERENV=someothervalue
|
||||
|
||||
# no_project_mount: false
|
||||
# (Experimental) If true, DDEV will not mount the project into the web container;
|
||||
# the user is responsible for mounting it manually or via a script.
|
||||
# This is to enable experimentation with alternate file mounting strategies.
|
||||
# For advanced users only!
|
||||
|
||||
# bind_all_interfaces: false
|
||||
# If true, host ports will be bound on all network interfaces,
|
||||
# not the localhost interface only. This means that ports
|
||||
# will be available on the local network if the host firewall
|
||||
# allows it.
|
||||
|
||||
# default_container_timeout: 120
|
||||
# The default time that DDEV waits for all containers to become ready can be increased from
|
||||
# the default 120. This helps in importing huge databases, for example.
|
||||
|
||||
#web_extra_exposed_ports:
|
||||
#- name: nodejs
|
||||
# container_port: 3000
|
||||
# http_port: 2999
|
||||
# https_port: 3000
|
||||
#- name: something
|
||||
# container_port: 4000
|
||||
# https_port: 4000
|
||||
# http_port: 3999
|
||||
# Allows a set of extra ports to be exposed via ddev-router
|
||||
# Fill in all three fields even if you don’t intend to use the https_port!
|
||||
# If you don’t add https_port, then it defaults to 0 and ddev-router will fail to start.
|
||||
#
|
||||
# The port behavior on the ddev-webserver must be arranged separately, for example
|
||||
# using web_extra_daemons.
|
||||
# For example, with a web app on port 3000 inside the container, this config would
|
||||
# expose that web app on https://<project>.ddev.site:9999 and http://<project>.ddev.site:9998
|
||||
# web_extra_exposed_ports:
|
||||
# - name: myapp
|
||||
# container_port: 3000
|
||||
# http_port: 9998
|
||||
# https_port: 9999
|
||||
|
||||
#web_extra_daemons:
|
||||
#- name: "http-1"
|
||||
# command: "/var/www/html/node_modules/.bin/http-server -p 3000"
|
||||
# directory: /var/www/html
|
||||
#- name: "http-2"
|
||||
# command: "/var/www/html/node_modules/.bin/http-server /var/www/html/sub -p 3000"
|
||||
# directory: /var/www/html
|
||||
|
||||
# override_config: false
|
||||
# By default, config.*.yaml files are *merged* into the configuration
|
||||
# But this means that some things can't be overridden
|
||||
# For example, if you have 'use_dns_when_possible: true'' you can't override it with a merge
|
||||
# and you can't erase existing hooks or all environment variables.
|
||||
# However, with "override_config: true" in a particular config.*.yaml file,
|
||||
# 'use_dns_when_possible: false' can override the existing values, and
|
||||
# hooks:
|
||||
# post-start: []
|
||||
# or
|
||||
# web_environment: []
|
||||
# or
|
||||
# additional_hostnames: []
|
||||
# can have their intended affect. 'override_config' affects only behavior of the
|
||||
# config.*.yaml file it exists in.
|
||||
|
||||
# Many DDEV commands can be extended to run tasks before or after the
|
||||
# DDEV command is executed, for example "post-start", "post-import-db",
|
||||
# "pre-composer", "post-composer"
|
||||
# See https://docs.ddev.com/en/stable/users/extend/custom-commands/ for more
|
||||
# information on the commands that can be extended and the tasks you can define
|
||||
# for them. Example:
|
||||
#hooks:
|
||||
# post-import-db:
|
||||
# - exec: drush sql:sanitize
|
||||
# - exec: drush updatedb
|
||||
# - exec: drush cache:rebuild
|
||||
17
.editorconfig
Normal file
17
.editorconfig
Normal file
@ -0,0 +1,17 @@
|
||||
# Drupal editor configuration normalization
|
||||
# @see http://editorconfig.org/
|
||||
|
||||
# This is the top-most .editorconfig file; do not search in parent directories.
|
||||
root = true
|
||||
|
||||
# All files.
|
||||
[*]
|
||||
end_of_line = LF
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[composer.{json,lock}]
|
||||
indent_size = 4
|
||||
65
.gitattributes
vendored
Normal file
65
.gitattributes
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
# Drupal git normalization
|
||||
# @see https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
|
||||
# @see https://www.drupal.org/node/1542048
|
||||
|
||||
# Normally these settings would be done with macro attributes for improved
|
||||
# readability and easier maintenance. However macros can only be defined at the
|
||||
# repository root directory. Drupal avoids making any assumptions about where it
|
||||
# is installed.
|
||||
|
||||
# Define text file attributes.
|
||||
# - Treat them as text.
|
||||
# - Ensure no CRLF line-endings, neither on checkout nor on checkin.
|
||||
# - Detect whitespace errors.
|
||||
# - Exposed by default in `git diff --color` on the CLI.
|
||||
# - Validate with `git diff --check`.
|
||||
# - Deny applying with `git apply --whitespace=error-all`.
|
||||
# - Fix automatically with `git apply --whitespace=fix`.
|
||||
|
||||
*.config text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.css text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.dist text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.engine text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
|
||||
*.html text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=html
|
||||
*.inc text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
|
||||
*.install text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
|
||||
*.js text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.json text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.lock text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.map text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.md text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.module text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
|
||||
*.php text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
|
||||
*.po text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.profile text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
|
||||
*.script text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.sh text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
|
||||
*.sql text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.svg text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.theme text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
|
||||
*.twig text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.txt text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.xml text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
*.yml text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
|
||||
|
||||
# PHPStan's baseline uses tabs instead of spaces.
|
||||
core/.phpstan-baseline.php text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tabwidth=2 diff=php linguist-language=php
|
||||
|
||||
# Define binary file attributes.
|
||||
# - Do not treat them as text.
|
||||
# - Include binary diff in patches instead of "binary files differ."
|
||||
*.avif -text diff
|
||||
*.eot -text diff
|
||||
*.exe -text diff
|
||||
*.gif -text diff
|
||||
*.gz -text diff
|
||||
*.ico -text diff
|
||||
*.jpeg -text diff
|
||||
*.jpg -text diff
|
||||
*.otf -text diff
|
||||
*.phar -text diff
|
||||
*.png -text diff
|
||||
*.svgz -text diff
|
||||
*.ttf -text diff
|
||||
*.woff -text diff
|
||||
*.woff2 -text diff
|
||||
106
composer.json
Normal file
106
composer.json
Normal file
@ -0,0 +1,106 @@
|
||||
{
|
||||
"name": "drupal/recommended-project",
|
||||
"description": "Project template for Drupal projects with a relocated document root",
|
||||
"type": "project",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"support": {
|
||||
"docs": "https://www.drupal.org/docs/user_guide/en/index.html",
|
||||
"chat": "https://www.drupal.org/node/314178"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "composer",
|
||||
"url": "https://packages.drupal.org/8"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"composer/installers": "^2.3",
|
||||
"drupal/core-composer-scaffold": "^11.2",
|
||||
"drupal/core-project-message": "^11.2",
|
||||
"drupal/core-recipe-unpack": "^11.2",
|
||||
"drupal/core-recommended": "^11.2",
|
||||
"drush/drush": "^13.6"
|
||||
},
|
||||
"conflict": {
|
||||
"drupal/drupal": "*"
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true,
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"composer/installers": true,
|
||||
"drupal/core-composer-scaffold": true,
|
||||
"drupal/core-recipe-unpack": true,
|
||||
"drupal/core-project-message": true,
|
||||
"phpstan/extension-installer": true,
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true,
|
||||
"php-http/discovery": true,
|
||||
"php-tuf/composer-integration": true
|
||||
},
|
||||
"sort-packages": true
|
||||
},
|
||||
"extra": {
|
||||
"drupal-scaffold": {
|
||||
"locations": {
|
||||
"web-root": "web/"
|
||||
}
|
||||
},
|
||||
"installer-paths": {
|
||||
"web/core": [
|
||||
"type:drupal-core"
|
||||
],
|
||||
"web/libraries/{$name}": [
|
||||
"type:drupal-library"
|
||||
],
|
||||
"web/modules/contrib/{$name}": [
|
||||
"type:drupal-module"
|
||||
],
|
||||
"web/profiles/contrib/{$name}": [
|
||||
"type:drupal-profile"
|
||||
],
|
||||
"web/themes/contrib/{$name}": [
|
||||
"type:drupal-theme"
|
||||
],
|
||||
"drush/Commands/contrib/{$name}": [
|
||||
"type:drupal-drush"
|
||||
],
|
||||
"web/modules/custom/{$name}": [
|
||||
"type:drupal-custom-module"
|
||||
],
|
||||
"web/profiles/custom/{$name}": [
|
||||
"type:drupal-custom-profile"
|
||||
],
|
||||
"web/themes/custom/{$name}": [
|
||||
"type:drupal-custom-theme"
|
||||
],
|
||||
"recipes/{$name}": [
|
||||
"type:drupal-recipe"
|
||||
]
|
||||
},
|
||||
"drupal-core-project-message": {
|
||||
"include-keys": [
|
||||
"homepage",
|
||||
"support"
|
||||
],
|
||||
"post-create-project-cmd-message": [
|
||||
"<bg=blue;fg=white> </>",
|
||||
"<bg=blue;fg=white> Congratulations, you’ve installed the Drupal codebase </>",
|
||||
"<bg=blue;fg=white> from the drupal/recommended-project template! </>",
|
||||
"<bg=blue;fg=white> </>",
|
||||
"",
|
||||
"<bg=yellow;fg=black>Next steps</>:",
|
||||
" * Install the site: https://www.drupal.org/docs/installing-drupal",
|
||||
" * Read the user guide: https://www.drupal.org/docs/user_guide/en/index.html",
|
||||
" * Get support: https://www.drupal.org/support",
|
||||
" * Get involved with the Drupal community:",
|
||||
" https://www.drupal.org/getting-involved",
|
||||
" * Remove the plugin that prints this message:",
|
||||
" composer remove drupal/core-project-message"
|
||||
]
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"drupal/devel": "^5.4"
|
||||
}
|
||||
}
|
||||
6582
composer.lock
generated
Normal file
6582
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
9
recipes/README.txt
Normal file
9
recipes/README.txt
Normal file
@ -0,0 +1,9 @@
|
||||
Recipes allow the automation of Drupal module and theme installation and
|
||||
configuration.
|
||||
|
||||
WHAT TO PLACE IN THIS DIRECTORY?
|
||||
--------------------------------
|
||||
|
||||
Placing downloaded and custom recipes in this directory separates downloaded and
|
||||
custom recipes from Drupal core's recipes. This allows Drupal core to be updated
|
||||
without overwriting these files.
|
||||
19
vendor/asm89/stack-cors/LICENSE
vendored
Normal file
19
vendor/asm89/stack-cors/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2013-2017 Alexander <iam.asm89@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
85
vendor/asm89/stack-cors/README.md
vendored
Normal file
85
vendor/asm89/stack-cors/README.md
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
# Stack/Cors
|
||||
|
||||
Library and middleware enabling cross-origin resource sharing for your
|
||||
http-{foundation,kernel} using application. It attempts to implement the
|
||||
[W3C Recommendation] for cross-origin resource sharing.
|
||||
|
||||
[W3C Recommendation]: http://www.w3.org/TR/cors/
|
||||
|
||||
Build status: 
|
||||
|
||||
## Installation
|
||||
|
||||
Require `asm89/stack-cors` using composer.
|
||||
|
||||
## Usage
|
||||
|
||||
This package can be used as a library or as [stack middleware].
|
||||
|
||||
[stack middleware]: http://stackphp.com/
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Description | Default value |
|
||||
|------------------------|------------------------------------------------------------|---------------|
|
||||
| `allowedMethods` | Matches the request method. | `[]` |
|
||||
| `allowedOrigins` | Matches the request origin. | `[]` |
|
||||
| `allowedOriginsPatterns` | Matches the request origin with `preg_match`. | `[]` |
|
||||
| `allowedHeaders` | Sets the Access-Control-Allow-Headers response header. | `[]` |
|
||||
| `exposedHeaders` | Sets the Access-Control-Expose-Headers response header. | `false` |
|
||||
| `maxAge` | Sets the Access-Control-Max-Age response header.<br/>Set to `null` to omit the header/use browser default. | `0` |
|
||||
| `supportsCredentials` | Sets the Access-Control-Allow-Credentials header. | `false` |
|
||||
|
||||
The _allowedMethods_ and _allowedHeaders_ options are case-insensitive.
|
||||
|
||||
You don't need to provide both _allowedOrigins_ and _allowedOriginsPatterns_. If one of the strings passed matches, it is considered a valid origin.
|
||||
|
||||
If `['*']` is provided to _allowedMethods_, _allowedOrigins_ or _allowedHeaders_ all methods / origins / headers are allowed.
|
||||
|
||||
If _supportsCredentials_ is `true`, you must [explicitly set](https://fetch.spec.whatwg.org/#cors-protocol-and-credentials) `allowedHeaders` for any headers which are not CORS safelisted.
|
||||
|
||||
### Example: using the library
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Asm89\Stack\CorsService;
|
||||
|
||||
$cors = new CorsService([
|
||||
'allowedHeaders' => ['x-allowed-header', 'x-other-allowed-header'],
|
||||
'allowedMethods' => ['DELETE', 'GET', 'POST', 'PUT'],
|
||||
'allowedOrigins' => ['http://localhost'],
|
||||
'allowedOriginsPatterns' => ['/localhost:\d/'],
|
||||
'exposedHeaders' => false,
|
||||
'maxAge' => 600,
|
||||
'supportsCredentials' => true,
|
||||
]);
|
||||
|
||||
$cors->addActualRequestHeaders(Response $response, $origin);
|
||||
$cors->handlePreflightRequest(Request $request);
|
||||
$cors->isActualRequestAllowed(Request $request);
|
||||
$cors->isCorsRequest(Request $request);
|
||||
$cors->isPreflightRequest(Request $request);
|
||||
```
|
||||
|
||||
## Example: using the stack middleware
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Asm89\Stack\Cors;
|
||||
|
||||
$app = new Cors($app, [
|
||||
// you can use ['*'] to allow any headers
|
||||
'allowedHeaders' => ['x-allowed-header', 'x-other-allowed-header'],
|
||||
// you can use ['*'] to allow any methods
|
||||
'allowedMethods' => ['DELETE', 'GET', 'POST', 'PUT'],
|
||||
// you can use ['*'] to allow requests from any origin
|
||||
'allowedOrigins' => ['localhost'],
|
||||
// you can enter regexes that are matched to the origin request header
|
||||
'allowedOriginsPatterns' => ['/localhost:\d/'],
|
||||
'exposedHeaders' => false,
|
||||
'maxAge' => 600,
|
||||
'supportsCredentials' => false,
|
||||
]);
|
||||
```
|
||||
45
vendor/asm89/stack-cors/composer.json
vendored
Normal file
45
vendor/asm89/stack-cors/composer.json
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "asm89/stack-cors",
|
||||
"description": "Cross-origin resource sharing library and stack middleware",
|
||||
"keywords": ["stack", "cors"],
|
||||
"homepage": "https://github.com/asm89/stack-cors",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alexander",
|
||||
"email": "iam.asm89@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.3|^8.0",
|
||||
"symfony/http-foundation": "^5.3|^6|^7",
|
||||
"symfony/http-kernel": "^5.3|^6|^7"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Asm89\\Stack\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Asm89\\Stack\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": "phpunit",
|
||||
"check-style": "phpcs -p --standard=PSR12 --exclude=Generic.Files.LineLength --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 src",
|
||||
"fix-style": "phpcbf -p --standard=PSR12 --exclude=Generic.Files.LineLength --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 src"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.2-dev"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "beta",
|
||||
"prefer-stable": true
|
||||
}
|
||||
61
vendor/asm89/stack-cors/src/Cors.php
vendored
Normal file
61
vendor/asm89/stack-cors/src/Cors.php
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of asm89/stack-cors.
|
||||
*
|
||||
* (c) Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Asm89\Stack;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class Cors implements HttpKernelInterface
|
||||
{
|
||||
/**
|
||||
* @var \Symfony\Component\HttpKernel\HttpKernelInterface
|
||||
*/
|
||||
private $app;
|
||||
|
||||
/**
|
||||
* @var \Asm89\Stack\CorsService
|
||||
*/
|
||||
private $cors;
|
||||
|
||||
private $defaultOptions = [
|
||||
'allowedHeaders' => [],
|
||||
'allowedMethods' => [],
|
||||
'allowedOrigins' => [],
|
||||
'allowedOriginsPatterns' => [],
|
||||
'exposedHeaders' => [],
|
||||
'maxAge' => 0,
|
||||
'supportsCredentials' => false,
|
||||
];
|
||||
|
||||
public function __construct(HttpKernelInterface $app, array $options = [])
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->cors = new CorsService(array_merge($this->defaultOptions, $options));
|
||||
}
|
||||
|
||||
public function handle(Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = true): Response
|
||||
{
|
||||
if ($this->cors->isPreflightRequest($request)) {
|
||||
$response = $this->cors->handlePreflightRequest($request);
|
||||
return $this->cors->varyHeader($response, 'Access-Control-Request-Method');
|
||||
}
|
||||
|
||||
$response = $this->app->handle($request, $type, $catch);
|
||||
|
||||
if ($request->getMethod() === 'OPTIONS') {
|
||||
$this->cors->varyHeader($response, 'Access-Control-Request-Method');
|
||||
}
|
||||
|
||||
return $this->cors->addActualRequestHeaders($response, $request);
|
||||
}
|
||||
}
|
||||
228
vendor/asm89/stack-cors/src/CorsService.php
vendored
Normal file
228
vendor/asm89/stack-cors/src/CorsService.php
vendored
Normal file
@ -0,0 +1,228 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of asm89/stack-cors.
|
||||
*
|
||||
* (c) Alexander <iam.asm89@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Asm89\Stack;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class CorsService
|
||||
{
|
||||
private $options;
|
||||
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
$this->options = $this->normalizeOptions($options);
|
||||
}
|
||||
|
||||
private function normalizeOptions(array $options = []): array
|
||||
{
|
||||
$options += [
|
||||
'allowedOrigins' => [],
|
||||
'allowedOriginsPatterns' => [],
|
||||
'supportsCredentials' => false,
|
||||
'allowedHeaders' => [],
|
||||
'exposedHeaders' => [],
|
||||
'allowedMethods' => [],
|
||||
'maxAge' => 0,
|
||||
];
|
||||
|
||||
// normalize array('*') to true
|
||||
if (in_array('*', $options['allowedOrigins'])) {
|
||||
$options['allowedOrigins'] = true;
|
||||
}
|
||||
if (in_array('*', $options['allowedHeaders'])) {
|
||||
$options['allowedHeaders'] = true;
|
||||
} else {
|
||||
$options['allowedHeaders'] = array_map('strtolower', $options['allowedHeaders']);
|
||||
}
|
||||
|
||||
if (in_array('*', $options['allowedMethods'])) {
|
||||
$options['allowedMethods'] = true;
|
||||
} else {
|
||||
$options['allowedMethods'] = array_map('strtoupper', $options['allowedMethods']);
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use isOriginAllowed
|
||||
*/
|
||||
public function isActualRequestAllowed(Request $request): bool
|
||||
{
|
||||
return $this->isOriginAllowed($request);
|
||||
}
|
||||
|
||||
public function isCorsRequest(Request $request): bool
|
||||
{
|
||||
return $request->headers->has('Origin');
|
||||
}
|
||||
|
||||
public function isPreflightRequest(Request $request): bool
|
||||
{
|
||||
return $request->getMethod() === 'OPTIONS' && $request->headers->has('Access-Control-Request-Method');
|
||||
}
|
||||
|
||||
public function handlePreflightRequest(Request $request): Response
|
||||
{
|
||||
$response = new Response();
|
||||
|
||||
$response->setStatusCode(204);
|
||||
|
||||
return $this->addPreflightRequestHeaders($response, $request);
|
||||
}
|
||||
|
||||
public function addPreflightRequestHeaders(Response $response, Request $request): Response
|
||||
{
|
||||
$this->configureAllowedOrigin($response, $request);
|
||||
|
||||
if ($response->headers->has('Access-Control-Allow-Origin')) {
|
||||
$this->configureAllowCredentials($response, $request);
|
||||
|
||||
$this->configureAllowedMethods($response, $request);
|
||||
|
||||
$this->configureAllowedHeaders($response, $request);
|
||||
|
||||
$this->configureMaxAge($response, $request);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function isOriginAllowed(Request $request): bool
|
||||
{
|
||||
if ($this->options['allowedOrigins'] === true) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$request->headers->has('Origin')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$origin = $request->headers->get('Origin');
|
||||
|
||||
if (in_array($origin, $this->options['allowedOrigins'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($this->options['allowedOriginsPatterns'] as $pattern) {
|
||||
if (preg_match($pattern, $origin)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function addActualRequestHeaders(Response $response, Request $request): Response
|
||||
{
|
||||
$this->configureAllowedOrigin($response, $request);
|
||||
|
||||
if ($response->headers->has('Access-Control-Allow-Origin')) {
|
||||
$this->configureAllowCredentials($response, $request);
|
||||
|
||||
$this->configureExposedHeaders($response, $request);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function configureAllowedOrigin(Response $response, Request $request)
|
||||
{
|
||||
if ($this->options['allowedOrigins'] === true && !$this->options['supportsCredentials']) {
|
||||
// Safe+cacheable, allow everything
|
||||
$response->headers->set('Access-Control-Allow-Origin', '*');
|
||||
} elseif ($this->isSingleOriginAllowed()) {
|
||||
// Single origins can be safely set
|
||||
$response->headers->set('Access-Control-Allow-Origin', array_values($this->options['allowedOrigins'])[0]);
|
||||
} else {
|
||||
// For dynamic headers, set the requested Origin header when set and allowed
|
||||
if ($this->isCorsRequest($request) && $this->isOriginAllowed($request)) {
|
||||
$response->headers->set('Access-Control-Allow-Origin', $request->headers->get('Origin'));
|
||||
}
|
||||
|
||||
$this->varyHeader($response, 'Origin');
|
||||
}
|
||||
}
|
||||
|
||||
private function isSingleOriginAllowed(): bool
|
||||
{
|
||||
if ($this->options['allowedOrigins'] === true || !empty($this->options['allowedOriginsPatterns'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return count($this->options['allowedOrigins']) === 1;
|
||||
}
|
||||
|
||||
private function configureAllowedMethods(Response $response, Request $request)
|
||||
{
|
||||
if ($this->options['allowedMethods'] === true) {
|
||||
$allowMethods = strtoupper($request->headers->get('Access-Control-Request-Method'));
|
||||
$this->varyHeader($response, 'Access-Control-Request-Method');
|
||||
} else {
|
||||
$allowMethods = implode(', ', $this->options['allowedMethods']);
|
||||
}
|
||||
|
||||
$response->headers->set('Access-Control-Allow-Methods', $allowMethods);
|
||||
}
|
||||
|
||||
private function configureAllowedHeaders(Response $response, Request $request)
|
||||
{
|
||||
if ($this->options['allowedHeaders'] === true) {
|
||||
$allowHeaders = $request->headers->get('Access-Control-Request-Headers');
|
||||
$this->varyHeader($response, 'Access-Control-Request-Headers');
|
||||
} else {
|
||||
$allowHeaders = implode(', ', $this->options['allowedHeaders']);
|
||||
}
|
||||
$response->headers->set('Access-Control-Allow-Headers', $allowHeaders);
|
||||
}
|
||||
|
||||
private function configureAllowCredentials(Response $response, Request $request)
|
||||
{
|
||||
if ($this->options['supportsCredentials']) {
|
||||
$response->headers->set('Access-Control-Allow-Credentials', 'true');
|
||||
}
|
||||
}
|
||||
|
||||
private function configureExposedHeaders(Response $response, Request $request)
|
||||
{
|
||||
if ($this->options['exposedHeaders']) {
|
||||
$response->headers->set('Access-Control-Expose-Headers', implode(', ', $this->options['exposedHeaders']));
|
||||
}
|
||||
}
|
||||
|
||||
private function configureMaxAge(Response $response, Request $request)
|
||||
{
|
||||
if ($this->options['maxAge'] !== null) {
|
||||
$response->headers->set('Access-Control-Max-Age', (int) $this->options['maxAge']);
|
||||
}
|
||||
}
|
||||
|
||||
public function varyHeader(Response $response, $header): Response
|
||||
{
|
||||
$vary = $response->getVary();
|
||||
if (!in_array($header, $vary, true)) {
|
||||
if (count($response->headers->all('Vary')) === 1) {
|
||||
$response->setVary($response->headers->get('Vary') . ', ' . $header, true);
|
||||
} else {
|
||||
$response->setVary($header, false);
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function isSameHost(Request $request): bool
|
||||
{
|
||||
return $request->headers->get('Origin') === $request->getSchemeAndHttpHost();
|
||||
}
|
||||
}
|
||||
22
vendor/autoload.php
vendored
Normal file
22
vendor/autoload.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
if (PHP_VERSION_ID < 50600) {
|
||||
if (!headers_sent()) {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||
if (!ini_get('display_errors')) {
|
||||
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||
fwrite(STDERR, $err);
|
||||
} elseif (!headers_sent()) {
|
||||
echo $err;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException($err);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit9d559ab354f63dc7e9a3fc1a03ad7d46::getLoader();
|
||||
119
vendor/bin/dcg
vendored
Executable file
119
vendor/bin/dcg
vendored
Executable file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../chi-teck/drupal-code-generator/bin/dcg)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/chi-teck/drupal-code-generator/bin/dcg');
|
||||
}
|
||||
}
|
||||
|
||||
return include __DIR__ . '/..'.'/chi-teck/drupal-code-generator/bin/dcg';
|
||||
37
vendor/bin/drush
vendored
Executable file
37
vendor/bin/drush
vendored
Executable file
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Support bash to support `source` with fallback on $0 if this does not run with bash
|
||||
# https://stackoverflow.com/a/35006505/6512
|
||||
selfArg="$BASH_SOURCE"
|
||||
if [ -z "$selfArg" ]; then
|
||||
selfArg="$0"
|
||||
fi
|
||||
|
||||
self=$(realpath "$selfArg" 2> /dev/null)
|
||||
if [ -z "$self" ]; then
|
||||
self="$selfArg"
|
||||
fi
|
||||
|
||||
dir=$(cd "${self%[/\\]*}" > /dev/null; cd '../drush/drush' && pwd)
|
||||
|
||||
if [ -d /proc/cygdrive ]; then
|
||||
case $(which php) in
|
||||
$(readlink -n /proc/cygdrive)/*)
|
||||
# We are in Cygwin using Windows php, so the path must be translated
|
||||
dir=$(cygpath -m "$dir");
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
export COMPOSER_RUNTIME_BIN_DIR="$(cd "${self%[/\\]*}" > /dev/null; pwd)"
|
||||
|
||||
# If bash is sourcing this file, we have to source the target as well
|
||||
bashSource="$BASH_SOURCE"
|
||||
if [ -n "$bashSource" ]; then
|
||||
if [ "$bashSource" != "$0" ]; then
|
||||
source "${dir}/drush" "$@"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
exec "${dir}/drush" "$@"
|
||||
119
vendor/bin/drush.php
vendored
Executable file
119
vendor/bin/drush.php
vendored
Executable file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../drush/drush/drush.php)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/drush/drush/drush.php');
|
||||
}
|
||||
}
|
||||
|
||||
return include __DIR__ . '/..'.'/drush/drush/drush.php';
|
||||
119
vendor/bin/patch-type-declarations
vendored
Executable file
119
vendor/bin/patch-type-declarations
vendored
Executable file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../symfony/error-handler/Resources/bin/patch-type-declarations)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/symfony/error-handler/Resources/bin/patch-type-declarations');
|
||||
}
|
||||
}
|
||||
|
||||
return include __DIR__ . '/..'.'/symfony/error-handler/Resources/bin/patch-type-declarations';
|
||||
119
vendor/bin/php-parse
vendored
Executable file
119
vendor/bin/php-parse
vendored
Executable file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../nikic/php-parser/bin/php-parse)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/nikic/php-parser/bin/php-parse');
|
||||
}
|
||||
}
|
||||
|
||||
return include __DIR__ . '/..'.'/nikic/php-parser/bin/php-parse';
|
||||
119
vendor/bin/psysh
vendored
Executable file
119
vendor/bin/psysh
vendored
Executable file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../psy/psysh/bin/psysh)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/psy/psysh/bin/psysh');
|
||||
}
|
||||
}
|
||||
|
||||
return include __DIR__ . '/..'.'/psy/psysh/bin/psysh';
|
||||
119
vendor/bin/robo
vendored
Executable file
119
vendor/bin/robo
vendored
Executable file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../consolidation/robo/robo)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/consolidation/robo/robo');
|
||||
}
|
||||
}
|
||||
|
||||
return include __DIR__ . '/..'.'/consolidation/robo/robo';
|
||||
119
vendor/bin/var-dump-server
vendored
Executable file
119
vendor/bin/var-dump-server
vendored
Executable file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../symfony/var-dumper/Resources/bin/var-dump-server)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server');
|
||||
}
|
||||
}
|
||||
|
||||
return include __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server';
|
||||
119
vendor/bin/yaml-cli
vendored
Executable file
119
vendor/bin/yaml-cli
vendored
Executable file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../grasmash/yaml-cli/bin/yaml-cli)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/grasmash/yaml-cli/bin/yaml-cli');
|
||||
}
|
||||
}
|
||||
|
||||
return include __DIR__ . '/..'.'/grasmash/yaml-cli/bin/yaml-cli';
|
||||
119
vendor/bin/yaml-lint
vendored
Executable file
119
vendor/bin/yaml-lint
vendored
Executable file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Proxy PHP file generated by Composer
|
||||
*
|
||||
* This file includes the referenced bin path (../symfony/yaml/Resources/bin/yaml-lint)
|
||||
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||
*
|
||||
* @generated
|
||||
*/
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BinProxyWrapper
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
public function stream_read($count)
|
||||
{
|
||||
$data = fread($this->handle, $count);
|
||||
|
||||
if ($this->position === 0) {
|
||||
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||
}
|
||||
|
||||
$this->position += strlen($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function stream_cast($castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
public function stream_close()
|
||||
{
|
||||
fclose($this->handle);
|
||||
}
|
||||
|
||||
public function stream_lock($operation)
|
||||
{
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function stream_eof()
|
||||
{
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/symfony/yaml/Resources/bin/yaml-lint');
|
||||
}
|
||||
}
|
||||
|
||||
return include __DIR__ . '/..'.'/symfony/yaml/Resources/bin/yaml-lint';
|
||||
8
vendor/chi-teck/drupal-code-generator/.github/dependabot.yml
vendored
Normal file
8
vendor/chi-teck/drupal-code-generator/.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: composer
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "22:00"
|
||||
open-pull-requests-limit: 10
|
||||
71
vendor/chi-teck/drupal-code-generator/.github/workflows/tests.yml
vendored
Normal file
71
vendor/chi-teck/drupal-code-generator/.github/workflows/tests.yml
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ 3.x, 4.x ]
|
||||
pull_request:
|
||||
branches: [ 3.x, 4.x ]
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
DCG_TMP_DIR: /dev/shm
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php:
|
||||
- "8.3"
|
||||
drupal:
|
||||
- "11.x"
|
||||
dependency-mode:
|
||||
- prefer-stable
|
||||
- prefer-lowest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Upgrade sqlite3
|
||||
run: |
|
||||
wget https://www.sqlite.org/2024/sqlite-autoconf-3450300.tar.gz -O /tmp/sqlite.tar.gz
|
||||
tar -xzf /tmp/sqlite.tar.gz -C /tmp
|
||||
cd /tmp/sqlite-autoconf-3450300
|
||||
./configure CFLAGS="-DSQLITE_ENABLE_COLUMN_METADATA=1" --prefix=/usr/local
|
||||
make && sudo make install
|
||||
sudo ldconfig
|
||||
|
||||
- name: Install PHP with extensions
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
ini-values: zend.assertions=1
|
||||
tools: composer:v2
|
||||
|
||||
- name: Install Symfony CLI
|
||||
run: |
|
||||
echo 'deb [trusted=yes] https://repo.symfony.com/apt/ /' | sudo tee /etc/apt/sources.list.d/symfony-cli.list
|
||||
sudo apt update && sudo apt install symfony-cli
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --ansi
|
||||
|
||||
- name: Update dependencies
|
||||
run: composer update --${{ matrix.dependency-mode }} --ansi
|
||||
|
||||
- name: Run lint
|
||||
run: ./scripts/lint.sh
|
||||
|
||||
- name: Run unit tests
|
||||
run: ./scripts/unit-tests.sh
|
||||
|
||||
- name: Run functional tests
|
||||
env:
|
||||
DCG_DRUPAL_VERSION: ${{ matrix.drupal }}
|
||||
run: ./scripts/functional-tests.sh
|
||||
|
||||
- name: Run SUT tests
|
||||
env:
|
||||
DCG_DRUPAL_VERSION: ${{ matrix.drupal }}
|
||||
run: ./scripts/sut-tests.sh
|
||||
63
vendor/chi-teck/drupal-code-generator/.phpstorm.meta.php
vendored
Normal file
63
vendor/chi-teck/drupal-code-generator/.phpstorm.meta.php
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
<?php /** @noinspection ALL */
|
||||
|
||||
namespace PHPSTORM_META {
|
||||
|
||||
use DrupalCodeGenerator\Helper\Dumper\DumperInterface;
|
||||
|
||||
override(
|
||||
\Symfony\Component\Console\Helper\HelperSet::get(0),
|
||||
map([
|
||||
'service_info' => \DrupalCodeGenerator\Helper\Drupal\ServiceInfo::class,
|
||||
'module_info' => \DrupalCodeGenerator\Helper\Drupal\ModuleInfo::class,
|
||||
'theme_info' => \DrupalCodeGenerator\Helper\Drupal\ThemeInfo::class,
|
||||
'hook_info' => \DrupalCodeGenerator\Helper\Drupal\HookInfo::class,
|
||||
'route_info' => \DrupalCodeGenerator\Helper\Drupal\RouteInfo::class,
|
||||
'permission_info' => \DrupalCodeGenerator\Helper\Drupal\PermissionInfo::class,
|
||||
'config_info' => \DrupalCodeGenerator\Helper\Drupal\ConfigInfo::class,
|
||||
'dry_dumper' => \DrupalCodeGenerator\Helper\Dumper\DumperInterface::class,
|
||||
'filesytem_dumper' => \DrupalCodeGenerator\Helper\Dumper\DumperInterface::class,
|
||||
'renderer' => \DrupalCodeGenerator\Helper\Renderer\RendererInterface::class,
|
||||
'question' => \DrupalCodeGenerator\Helper\QuestionHelper::class,
|
||||
'assets_table_printer' => \DrupalCodeGenerator\Helper\Printer\PrinterInterface::class,
|
||||
'assets_list_printer' => \DrupalCodeGenerator\Helper\Printer\PrinterInterface::class,
|
||||
]),
|
||||
);
|
||||
|
||||
override(
|
||||
\Symfony\Component\Console\Command\Command::getHelper(0),
|
||||
map([
|
||||
'service_info' => \DrupalCodeGenerator\Helper\Drupal\ServiceInfo::class,
|
||||
'module_info' => \DrupalCodeGenerator\Helper\Drupal\ModuleInfo::class,
|
||||
'theme_info' => \DrupalCodeGenerator\Helper\Drupal\ThemeInfo::class,
|
||||
'hook_info' => \DrupalCodeGenerator\Helper\Drupal\HookInfo::class,
|
||||
'route_info' => \DrupalCodeGenerator\Helper\Drupal\RouteInfo::class,
|
||||
'permission_info' => \DrupalCodeGenerator\Helper\Drupal\PermissionInfo::class,
|
||||
'config_info' => \DrupalCodeGenerator\Helper\Drupal\ConfigInfo::class,
|
||||
'dry_dumper' => \DrupalCodeGenerator\Helper\Dumper\DumperInterface::class,
|
||||
'filesytem_dumper' => \DrupalCodeGenerator\Helper\Dumper\DumperInterface::class,
|
||||
'renderer' => \DrupalCodeGenerator\Helper\Renderer\RendererInterface::class,
|
||||
'question' => \DrupalCodeGenerator\Helper\QuestionHelper::class,
|
||||
'assets_table_printer' => \DrupalCodeGenerator\Helper\Printer\PrinterInterface::class,
|
||||
'assets_list_printer' => \DrupalCodeGenerator\Helper\Printer\PrinterInterface::class,
|
||||
])
|
||||
);
|
||||
|
||||
override(
|
||||
\Symfony\Component\DependencyInjection\ContainerInterface::get(0),
|
||||
map([
|
||||
'class_resolver' => \Drupal\Core\DependencyInjection\ClassResolverInterface::class,
|
||||
'entity_field.manager' => \Drupal\Core\Entity\EntityFieldManagerInterface::class,
|
||||
'entity_type.bundle.info' => \Drupal\Core\Entity\EntityTypeBundleInfoInterface::class,
|
||||
'entity_type.manager' => \Drupal\Core\Entity\EntityTypeManagerInterface::class,
|
||||
'event_dispatcher' => \Symfony\Contracts\EventDispatcher\EventDispatcherInterface::class,
|
||||
'extension.list.module' => \Drupal\Core\Extension\ModuleExtensionList::class,
|
||||
'kernel' => \Drupal\Core\DrupalKernelInterface::class,
|
||||
'library.discovery' => \Drupal\Core\Asset\LibraryDiscovery::class,
|
||||
'module_handler' => \Drupal\Core\Extension\ModuleHandlerInterface::class,
|
||||
'theme_handler' => \Drupal\Core\Extension\ThemeHandlerInterface::class,
|
||||
])
|
||||
);
|
||||
|
||||
override(\Drupal\Core\Routing\RouteProviderInterface::getAllRoutes(), map(['' => \ArrayIterator::class]));
|
||||
|
||||
}
|
||||
339
vendor/chi-teck/drupal-code-generator/LICENSE.txt
vendored
Normal file
339
vendor/chi-teck/drupal-code-generator/LICENSE.txt
vendored
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
40
vendor/chi-teck/drupal-code-generator/README.md
vendored
Normal file
40
vendor/chi-teck/drupal-code-generator/README.md
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
# Drupal Code Generator
|
||||
|
||||
[](https://github.com/Chi-teck/drupal-code-generator/actions?query=workflow%3ATests)
|
||||
[](//packagist.org/packages/chi-teck/drupal-code-generator)
|
||||
[](https://php.net/)
|
||||
|
||||
A command line code generator for Drupal.
|
||||
|
||||
## Installation
|
||||
```
|
||||
composer require chi-teck/drupal-code-generator --dev
|
||||
```
|
||||
|
||||
Optionally, generate shell completions for DCG executable.
|
||||
```
|
||||
./vendor/bin/dcg completion bash >> ~/.bash_completion
|
||||
```
|
||||
|
||||
## Usage
|
||||
```shell
|
||||
# Display navigation.
|
||||
./vendor/bin/dcg
|
||||
|
||||
# Call generator directly.
|
||||
./vendor/bin/dcg plugin:field:widget
|
||||
|
||||
# Generate code non-interactively.
|
||||
./vendor/bin/dcg config-form -a Example -a example -a SettingsForm -a No
|
||||
```
|
||||
|
||||
## Compatibility
|
||||
DCG|PHP|Symfony|Twig|Drupal|Drush
|
||||
:-:|:-:|:-:|:-:|:-:|:-:
|
||||
1|7.1 - 7.4|3, 4|1, 2|7, 8|9, 10
|
||||
2|7.4+|4, 5|2, 3|7, 9|11
|
||||
3|8.1+|6|3|10|12
|
||||
4|8.3+|7|3|11|13
|
||||
|
||||
## License
|
||||
GNU General Public License, version 2 or later.
|
||||
38
vendor/chi-teck/drupal-code-generator/bin/dcg
vendored
Executable file
38
vendor/chi-teck/drupal-code-generator/bin/dcg
vendored
Executable file
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\BootstrapHandler;
|
||||
|
||||
$dcg_exit = static function(string $message): never {
|
||||
\fwrite(\STDERR, "\e[0;41m [ERROR] $message \e[0m" . \PHP_EOL);
|
||||
exit(1);
|
||||
};
|
||||
|
||||
// __DIR__ cannot be used here as it contains a path with symlinks resolved.
|
||||
$dcg_path = \str_starts_with($argv[0], '/') ?
|
||||
$argv[0] : \getcwd() . '/' . $argv[0];
|
||||
|
||||
// DCG is installed as Composer package.
|
||||
$autoload_dir = \dirname($dcg_path) . '/..';
|
||||
if (!\file_exists($autoload_dir . '/autoload.php')) {
|
||||
// DCG is installed as Composer project.
|
||||
$autoload_dir = $autoload_dir . '/vendor';
|
||||
}
|
||||
|
||||
if (!\file_exists($autoload_dir . '/autoload.php')) {
|
||||
$dcg_exit('Could not locate class loader.');
|
||||
}
|
||||
|
||||
$class_loader = require $autoload_dir . '/autoload.php';
|
||||
$bootstrap_handler = new BootstrapHandler($class_loader);
|
||||
try {
|
||||
$container = $bootstrap_handler->bootstrap();
|
||||
}
|
||||
catch (\Exception $exception) {
|
||||
$dcg_exit($exception->getMessage());
|
||||
}
|
||||
|
||||
Application::create($container)->run();
|
||||
54
vendor/chi-teck/drupal-code-generator/composer.json
vendored
Normal file
54
vendor/chi-teck/drupal-code-generator/composer.json
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "chi-teck/drupal-code-generator",
|
||||
"description": "Drupal code generator",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"bin": [
|
||||
"bin/dcg"
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"DrupalCodeGenerator\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"DrupalCodeGenerator\\Tests\\Unit\\": "tests/unit",
|
||||
"DrupalCodeGenerator\\Tests\\Functional\\": "tests/functional"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.3.0",
|
||||
"ext-json": "*",
|
||||
"psr/event-dispatcher": "^1.0",
|
||||
"psr/log": "^3.0",
|
||||
"symfony/console": "^7.1",
|
||||
"symfony/dependency-injection": "^7.1",
|
||||
"symfony/filesystem": "^7.1",
|
||||
"symfony/string": "^7.0",
|
||||
"twig/twig": "^3.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-simplexml": "*",
|
||||
"chi-teck/drupal-coder-extension": "^2.0.0-rc2",
|
||||
"drupal/coder": "8.3.24",
|
||||
"drupal/core": "11.x-dev",
|
||||
"phpspec/prophecy-phpunit": "^2.2",
|
||||
"phpunit/phpunit": "^10.5",
|
||||
"squizlabs/php_codesniffer": "^3.9",
|
||||
"symfony/var-dumper": "^7.1",
|
||||
"symfony/yaml": "^7.1",
|
||||
"vimeo/psalm": "^5.24.0"
|
||||
},
|
||||
"conflict": {
|
||||
"squizlabs/php_codesniffer": "<3.6",
|
||||
"nikic/php-parser": "<4.17"
|
||||
},
|
||||
"minimum-stability": "RC",
|
||||
"prefer-stable": true
|
||||
}
|
||||
21
vendor/chi-teck/drupal-code-generator/psalm-autoloader.php
vendored
Normal file
21
vendor/chi-teck/drupal-code-generator/psalm-autoloader.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
/** @var \Composer\Autoload\ClassLoader $autoloader */
|
||||
$autoloader = require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
$modules = [
|
||||
'comment',
|
||||
'file',
|
||||
'node',
|
||||
'taxonomy',
|
||||
'user',
|
||||
];
|
||||
foreach ($modules as $module) {
|
||||
$autoloader->addPsr4(
|
||||
\sprintf('Drupal\%s\\', $module),
|
||||
\sprintf('vendor/drupal/core/modules/%s/src', $module),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
33
vendor/chi-teck/drupal-code-generator/psalm.xml
vendored
Normal file
33
vendor/chi-teck/drupal-code-generator/psalm.xml
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
checkForThrowsInGlobalScope="true"
|
||||
ensureArrayStringOffsetsExist="true"
|
||||
findUnusedPsalmSuppress="true"
|
||||
findUnusedBaselineEntry="true"
|
||||
findUnusedCode="false"
|
||||
sealAllMethods="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
errorLevel="2"
|
||||
autoloader="psalm-autoloader.php"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="src"/>
|
||||
<ignoreFiles>
|
||||
<!-- Psalm reports issues about vendors by some reason. -->
|
||||
<directory name="vendor"/>
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
<issueHandlers>
|
||||
<PossiblyNullArgument>
|
||||
<errorLevel type="suppress">
|
||||
<referencedFunction name="/__construct/"/>
|
||||
</errorLevel>
|
||||
</PossiblyNullArgument>
|
||||
<!-- @see https://github.com/vimeo/psalm/issues/8765 -->
|
||||
<PossiblyUndefinedVariable errorLevel="suppress"/>
|
||||
<PropertyNotSetInConstructor errorLevel="suppress"/>
|
||||
<RiskyTruthyFalsyComparison errorLevel="suppress"/>
|
||||
</issueHandlers>
|
||||
</psalm>
|
||||
1
vendor/chi-teck/drupal-code-generator/resources/service-meta.json
vendored
Normal file
1
vendor/chi-teck/drupal-code-generator/resources/service-meta.json
vendored
Normal file
File diff suppressed because one or more lines are too long
148
vendor/chi-teck/drupal-code-generator/src/Application.php
vendored
Normal file
148
vendor/chi-teck/drupal-code-generator/src/Application.php
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator;
|
||||
|
||||
use Composer\InstalledVersions;
|
||||
use DrupalCodeGenerator\Command\Navigation;
|
||||
use DrupalCodeGenerator\Event\GeneratorInfo;
|
||||
use DrupalCodeGenerator\Event\GeneratorInfoAlter;
|
||||
use DrupalCodeGenerator\Helper\Drupal\ConfigInfo;
|
||||
use DrupalCodeGenerator\Helper\Drupal\HookInfo;
|
||||
use DrupalCodeGenerator\Helper\Drupal\ModuleInfo;
|
||||
use DrupalCodeGenerator\Helper\Drupal\PermissionInfo;
|
||||
use DrupalCodeGenerator\Helper\Drupal\RouteInfo;
|
||||
use DrupalCodeGenerator\Helper\Drupal\ServiceInfo;
|
||||
use DrupalCodeGenerator\Helper\Drupal\ThemeInfo;
|
||||
use DrupalCodeGenerator\Helper\Dumper\DryDumper;
|
||||
use DrupalCodeGenerator\Helper\Dumper\FileSystemDumper;
|
||||
use DrupalCodeGenerator\Helper\Printer\ListPrinter;
|
||||
use DrupalCodeGenerator\Helper\Printer\TablePrinter;
|
||||
use DrupalCodeGenerator\Helper\QuestionHelper;
|
||||
use DrupalCodeGenerator\Helper\Renderer\TwigRenderer;
|
||||
use DrupalCodeGenerator\Twig\TwigEnvironment;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Console\Application as BaseApplication;
|
||||
use Symfony\Component\Console\Helper\HelperSet;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\Filesystem\Filesystem as SymfonyFileSystem;
|
||||
use Twig\Loader\FilesystemLoader as TemplateLoader;
|
||||
|
||||
/**
|
||||
* DCG console application.
|
||||
*
|
||||
* @psalm-suppress DeprecatedInterface
|
||||
* @psalm-suppress DeprecatedTrait
|
||||
*
|
||||
* @todo Use Drupal replacement for ContainerAwareInterface when it's available.
|
||||
* @see https://www.drupal.org/project/drupal/issues/3397522
|
||||
*/
|
||||
final class Application extends BaseApplication implements EventDispatcherInterface {
|
||||
|
||||
/**
|
||||
* Path to DCG root directory.
|
||||
*/
|
||||
public const string ROOT = __DIR__ . '/..';
|
||||
|
||||
/**
|
||||
* DCG version.
|
||||
*
|
||||
* @deprecated Use \DrupalCodeGenerator\Application->getVersion() instead.
|
||||
*/
|
||||
public const string VERSION = 'unknown';
|
||||
|
||||
/**
|
||||
* DCG API version.
|
||||
*/
|
||||
public const int API = 3;
|
||||
|
||||
/**
|
||||
* Path to templates directory.
|
||||
*/
|
||||
public const string TEMPLATE_PATH = self::ROOT . '/templates';
|
||||
|
||||
/**
|
||||
* {@selfdoc}
|
||||
*/
|
||||
private ContainerInterface $container;
|
||||
|
||||
/**
|
||||
* Creates the application.
|
||||
*
|
||||
* @psalm-suppress ArgumentTypeCoercion
|
||||
*/
|
||||
public static function create(ContainerInterface $container): self {
|
||||
$application = new self(
|
||||
'Drupal Code Generator',
|
||||
InstalledVersions::getPrettyVersion('chi-teck/drupal-code-generator'),
|
||||
);
|
||||
$application->container = $container;
|
||||
|
||||
$file_system = new SymfonyFileSystem();
|
||||
$template_loader = new TemplateLoader();
|
||||
$template_loader->addPath(self::TEMPLATE_PATH . '/_lib', 'lib');
|
||||
$application->setHelperSet(
|
||||
new HelperSet([
|
||||
new QuestionHelper(),
|
||||
new DryDumper($file_system),
|
||||
new FileSystemDumper($file_system),
|
||||
new TwigRenderer(new TwigEnvironment($template_loader)),
|
||||
new ListPrinter(),
|
||||
new TablePrinter(),
|
||||
new ModuleInfo($container->get('module_handler'), $container->get('extension.list.module')),
|
||||
new ThemeInfo($container->get('theme_handler')),
|
||||
new ServiceInfo($container),
|
||||
new HookInfo($container->get('module_handler')),
|
||||
new RouteInfo($container->get('router.route_provider')),
|
||||
new ConfigInfo($container->get('config.factory')),
|
||||
new PermissionInfo($container->get('user.permissions')),
|
||||
]),
|
||||
);
|
||||
|
||||
$generator_factory = new GeneratorFactory(
|
||||
$container->get('class_resolver'),
|
||||
);
|
||||
|
||||
$core_generators = $generator_factory->getGenerators();
|
||||
$user_generators = [];
|
||||
$application->dispatch(new GeneratorInfo($user_generators));
|
||||
|
||||
$all_generators = \array_merge($core_generators, $user_generators);
|
||||
$application->addCommands(
|
||||
$application->dispatch(new GeneratorInfoAlter($all_generators))->generators,
|
||||
);
|
||||
|
||||
$application->add(new Navigation());
|
||||
$application->setDefaultCommand('navigation');
|
||||
|
||||
/** @var \DrupalCodeGenerator\Application $application */
|
||||
$application = $application->dispatch($application);
|
||||
return $application;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Drupal container.
|
||||
*/
|
||||
public function getContainer(): ContainerInterface {
|
||||
return $this->container;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @template T as object
|
||||
* @psalm-param T $event
|
||||
* @psalm-return T
|
||||
*
|
||||
* @todo Remove this once Symfony drops support for event-dispatcher-contracts v2.
|
||||
* @see \Symfony\Contracts\EventDispatcher\EventDispatcherInterface::dispatch()
|
||||
* @psalm-suppress UnusedPsalmSuppress
|
||||
* @psalm-suppress InvalidReturnType
|
||||
* @psalm-suppress InvalidReturnStatement
|
||||
*/
|
||||
public function dispatch(object $event): object {
|
||||
return $this->container->get('event_dispatcher')->dispatch($event);
|
||||
}
|
||||
|
||||
}
|
||||
175
vendor/chi-teck/drupal-code-generator/src/Asset/Asset.php
vendored
Normal file
175
vendor/chi-teck/drupal-code-generator/src/Asset/Asset.php
vendored
Normal file
@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Asset;
|
||||
|
||||
use DrupalCodeGenerator\Asset\Resolver\PreserveResolver;
|
||||
use DrupalCodeGenerator\Asset\Resolver\ReplaceResolver;
|
||||
use DrupalCodeGenerator\Asset\Resolver\ResolverDefinition;
|
||||
use DrupalCodeGenerator\Asset\Resolver\ResolverInterface;
|
||||
use DrupalCodeGenerator\InputOutput\IO;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
|
||||
/**
|
||||
* Base class for assets.
|
||||
*/
|
||||
abstract class Asset implements \Stringable {
|
||||
|
||||
/**
|
||||
* Indicates that the asset can be updated but never created.
|
||||
*/
|
||||
private bool $virtual = FALSE;
|
||||
|
||||
/**
|
||||
* Asset mode.
|
||||
*
|
||||
* @psalm-var int<0, 511>
|
||||
*/
|
||||
private int $mode = 0444;
|
||||
|
||||
/**
|
||||
* Template variables.
|
||||
*
|
||||
* @psalm-var array<string, mixed>
|
||||
*/
|
||||
private array $vars = [];
|
||||
|
||||
/**
|
||||
* Content resolver.
|
||||
*/
|
||||
protected ?ResolverInterface $resolver = NULL;
|
||||
|
||||
/**
|
||||
* Resolver definition.
|
||||
*/
|
||||
protected ResolverDefinition $resolverDefinition;
|
||||
|
||||
/**
|
||||
* Asset constructor.
|
||||
*/
|
||||
public function __construct(protected readonly string $path) {
|
||||
// @todo Test this.
|
||||
match (TRUE) {
|
||||
$this instanceof Directory,
|
||||
$this instanceof File,
|
||||
$this instanceof Symlink => NULL,
|
||||
default => throw new \LogicException(\sprintf('%s class is internal for extension.', self::class)),
|
||||
};
|
||||
$this->resolverDefinition = new ResolverDefinition(ReplaceResolver::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the asset path.
|
||||
*/
|
||||
final public function getPath(): string {
|
||||
return $this->replaceTokens($this->path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the asset mode.
|
||||
*
|
||||
* @psalm-return int<0, 511>
|
||||
*/
|
||||
final public function getMode(): int {
|
||||
return $this->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the asset vars.
|
||||
*
|
||||
* @psalm-return array<string, mixed>
|
||||
*/
|
||||
final public function getVars(): array {
|
||||
return $this->vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the asset is virtual.
|
||||
*
|
||||
* Virtual assets should not cause creating new directories, files or symlinks
|
||||
* on file system. They meant to be used by resolvers to update existing
|
||||
* objects.
|
||||
*/
|
||||
final public function isVirtual(): bool {
|
||||
return $this->virtual;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the asset resolver.
|
||||
*/
|
||||
public function getResolver(IO $io): ResolverInterface {
|
||||
return $this->resolver ?? $this->resolverDefinition->createResolver($io);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for asset mode.
|
||||
*
|
||||
* @psalm-param int<0, 511> $mode
|
||||
*/
|
||||
final public function mode(int $mode): static {
|
||||
/** @psalm-suppress DocblockTypeContradiction */
|
||||
if ($mode < 0000 || $mode > 0777) {
|
||||
throw new \InvalidArgumentException('Incorrect mode value.');
|
||||
}
|
||||
$this->mode = $mode;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the asset vars.
|
||||
*
|
||||
* @psalm-param array<string, mixed> $vars
|
||||
*/
|
||||
final public function vars(array $vars): static {
|
||||
$this->vars = $vars;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the asset "virtual".
|
||||
*/
|
||||
final public function setVirtual(bool $virtual): static {
|
||||
$this->virtual = $virtual;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that existing asset should be replaced.
|
||||
*/
|
||||
final public function replaceIfExists(): static {
|
||||
$this->resolverDefinition = new ResolverDefinition(ReplaceResolver::class);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that existing asset should be preserved.
|
||||
*/
|
||||
final public function preserveIfExists(): static {
|
||||
$this->resolverDefinition = new ResolverDefinition(PreserveResolver::class);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for asset resolver.
|
||||
*/
|
||||
final public function resolver(ResolverInterface $resolver): static {
|
||||
$this->resolver = $resolver;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the magic __toString() method.
|
||||
*/
|
||||
final public function __toString(): string {
|
||||
return $this->getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all tokens in a given string with appropriate values.
|
||||
*/
|
||||
final protected function replaceTokens(string $input): string {
|
||||
return Utils::replaceTokens($input, $this->vars);
|
||||
}
|
||||
|
||||
}
|
||||
198
vendor/chi-teck/drupal-code-generator/src/Asset/AssetCollection.php
vendored
Normal file
198
vendor/chi-teck/drupal-code-generator/src/Asset/AssetCollection.php
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Asset;
|
||||
|
||||
/**
|
||||
* Asset collection.
|
||||
*
|
||||
* @template-implements \ArrayAccess<string,\DrupalCodeGenerator\Asset\Asset>
|
||||
* @template-implements \IteratorAggregate<string,\DrupalCodeGenerator\Asset\Asset>
|
||||
*/
|
||||
final class AssetCollection implements \ArrayAccess, \IteratorAggregate, \Countable, \Stringable {
|
||||
|
||||
/**
|
||||
* AssetCollection constructor.
|
||||
*
|
||||
* @param \DrupalCodeGenerator\Asset\Asset[] $assets
|
||||
* Assets.
|
||||
*/
|
||||
public function __construct(private array $assets = []) {}
|
||||
|
||||
/**
|
||||
* Creates a directory asset.
|
||||
*/
|
||||
public function addDirectory(string $path): Directory {
|
||||
$directory = new Directory($path);
|
||||
$this->assets[] = $directory;
|
||||
return $directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file asset.
|
||||
*/
|
||||
public function addFile(string $path, ?string $template = NULL): File {
|
||||
$file = new File($path);
|
||||
if ($template) {
|
||||
$file->template($template);
|
||||
}
|
||||
$this->assets[] = $file;
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a symlink asset.
|
||||
*
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function addSymlink(string $path, string $target): Symlink {
|
||||
$symlink = new Symlink($path, $target);
|
||||
$this->assets[] = $symlink;
|
||||
return $symlink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an asset for configuration schema file.
|
||||
*/
|
||||
public function addSchemaFile(string $path = 'config/schema/{machine_name}.schema.yml'): File {
|
||||
return $this->addFile($path)
|
||||
->appendIfExists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an asset for service file.
|
||||
*/
|
||||
public function addServicesFile(string $path = '{machine_name}.services.yml'): File {
|
||||
return $this->addFile($path)
|
||||
->appendIfExists(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @psalm-param \DrupalCodeGenerator\Asset\Asset $value
|
||||
*/
|
||||
public function offsetSet(mixed $offset, mixed $value): void {
|
||||
match (TRUE) {
|
||||
$value instanceof Directory,
|
||||
$value instanceof File,
|
||||
$value instanceof Symlink => NULL,
|
||||
default => throw new \InvalidArgumentException('Unsupported asset type.'),
|
||||
};
|
||||
if ($offset === NULL) {
|
||||
$this->assets[] = $value;
|
||||
}
|
||||
else {
|
||||
$this->assets[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetGet(mixed $offset): ?Asset {
|
||||
return $this->assets[$offset] ?? NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetUnset(mixed $offset): void {
|
||||
unset($this->assets[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function offsetExists(mixed $offset): bool {
|
||||
return isset($this->assets[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIterator(): \ArrayIterator {
|
||||
return new \ArrayIterator($this->assets);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @psalm-return int<0, max>
|
||||
*/
|
||||
public function count(): int {
|
||||
return \count($this->assets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of directory assets.
|
||||
*/
|
||||
public function getDirectories(): self {
|
||||
return $this->getFiltered(
|
||||
static fn (Asset $asset): bool => $asset instanceof Directory,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of file assets.
|
||||
*/
|
||||
public function getFiles(): self {
|
||||
return $this->getFiltered(
|
||||
static fn (Asset $asset): bool => $asset instanceof File,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of symlink assets.
|
||||
*/
|
||||
public function getSymlinks(): self {
|
||||
return $this->getFiltered(
|
||||
static fn (Asset $asset): bool => $asset instanceof Symlink,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of sorted assets.
|
||||
*/
|
||||
public function getSorted(): self {
|
||||
$sorter = static function (Asset $a, Asset $b): int {
|
||||
$name_a = (string) $a;
|
||||
$name_b = (string) $b;
|
||||
|
||||
// Top level assets should go first.
|
||||
$result = \strcasecmp(\dirname($name_a), \dirname($name_b));
|
||||
if ($result === 0) {
|
||||
$result = \strcasecmp($name_a, $name_b);
|
||||
}
|
||||
return $result;
|
||||
};
|
||||
|
||||
$assets = $this->assets;
|
||||
\usort($assets, $sorter);
|
||||
return new self($assets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the asset collection.
|
||||
*/
|
||||
public function getFiltered(callable $filter): self {
|
||||
$iterator = new \CallbackFilterIterator($this->getIterator(), $filter);
|
||||
$assets = \iterator_to_array($iterator);
|
||||
$str_keys = \array_filter(\array_keys($assets), 'is_string');
|
||||
// Reindex if it's not an associative array.
|
||||
return new self(\count($str_keys) > 0 ? $assets : \array_values($assets));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString(): string {
|
||||
$output = '';
|
||||
foreach ($this->getSorted() as $asset) {
|
||||
$output .= '• ' . $asset . \PHP_EOL;
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
8
vendor/chi-teck/drupal-code-generator/src/Asset/Assets.php
vendored
Normal file
8
vendor/chi-teck/drupal-code-generator/src/Asset/Assets.php
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Asset;
|
||||
|
||||
// @todo Is it still needed?
|
||||
\class_alias(AssetCollection::class, '\DrupalCodeGenerator\Asset\Assets');
|
||||
32
vendor/chi-teck/drupal-code-generator/src/Asset/Directory.php
vendored
Normal file
32
vendor/chi-teck/drupal-code-generator/src/Asset/Directory.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Asset;
|
||||
|
||||
use DrupalCodeGenerator\Asset\Resolver\PreserveResolver;
|
||||
use DrupalCodeGenerator\Asset\Resolver\ResolverDefinition;
|
||||
|
||||
/**
|
||||
* Simple data structure to represent a directory being created.
|
||||
*/
|
||||
final class Directory extends Asset {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(string $path) {
|
||||
parent::__construct($path);
|
||||
$this->mode(0755);
|
||||
// Recreating existing directories makes no sense.
|
||||
$this->resolverDefinition = new ResolverDefinition(PreserveResolver::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Named constructor.
|
||||
*/
|
||||
public static function create(string $path): self {
|
||||
return new self($path);
|
||||
}
|
||||
|
||||
}
|
||||
131
vendor/chi-teck/drupal-code-generator/src/Asset/File.php
vendored
Normal file
131
vendor/chi-teck/drupal-code-generator/src/Asset/File.php
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Asset;
|
||||
|
||||
use DrupalCodeGenerator\Asset\Resolver\AppendResolver;
|
||||
use DrupalCodeGenerator\Asset\Resolver\PrependResolver;
|
||||
use DrupalCodeGenerator\Asset\Resolver\ResolverDefinition;
|
||||
use DrupalCodeGenerator\Helper\Renderer\RendererInterface;
|
||||
|
||||
/**
|
||||
* A data structure to represent a file being generated.
|
||||
*/
|
||||
final class File extends Asset implements RenderableInterface {
|
||||
|
||||
/**
|
||||
* Asset content.
|
||||
*/
|
||||
private string $content = '';
|
||||
|
||||
/**
|
||||
* Template to render main content.
|
||||
*/
|
||||
private ?string $template = NULL;
|
||||
|
||||
/**
|
||||
* The template string to render.
|
||||
*/
|
||||
private ?string $inlineTemplate = NULL;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(string $path) {
|
||||
parent::__construct($path);
|
||||
$this->mode(0644);
|
||||
}
|
||||
|
||||
/**
|
||||
* Named constructor.
|
||||
*/
|
||||
public static function create(string $path): self {
|
||||
return new self($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the asset content.
|
||||
*/
|
||||
public function getContent(): string {
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the asset content.
|
||||
*/
|
||||
public function content(string $content): self {
|
||||
$this->content = $content;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the asset template.
|
||||
*
|
||||
* Templates with 'twig' extension are processed with Twig template engine.
|
||||
*/
|
||||
public function template(string $template): self {
|
||||
if ($this->inlineTemplate) {
|
||||
throw new \LogicException('A file cannot have both inline and regular templates.');
|
||||
}
|
||||
$this->template = $template;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the asset inline template.
|
||||
*/
|
||||
public function inlineTemplate(string $inline_template): self {
|
||||
if ($this->template) {
|
||||
throw new \LogicException('A file cannot have both inline and regular templates.');
|
||||
}
|
||||
$this->inlineTemplate = $inline_template;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the "prepend" resolver.
|
||||
*/
|
||||
public function prependIfExists(): self {
|
||||
$this->resolverDefinition = new ResolverDefinition(PrependResolver::class);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the "append" resolver.
|
||||
*
|
||||
* @psalm-param int<0, max> $header_size
|
||||
*/
|
||||
public function appendIfExists(int $header_size = 0): self {
|
||||
$this->resolverDefinition = new ResolverDefinition(AppendResolver::class, $header_size);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function render(RendererInterface $renderer): void {
|
||||
if ($this->inlineTemplate) {
|
||||
$content = $renderer->renderInline($this->inlineTemplate, $this->getVars());
|
||||
$this->content($content);
|
||||
}
|
||||
elseif ($this->template) {
|
||||
$template = $this->replaceTokens($this->template);
|
||||
$content = $renderer->render($template, $this->getVars());
|
||||
$this->content($content);
|
||||
}
|
||||
// It's OK that the file has no templates as consumers may set rendered
|
||||
// content directly through `content()` method.
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the asset is a PHP script.
|
||||
*/
|
||||
public function isPhp(): bool {
|
||||
return \in_array(
|
||||
\pathinfo($this->getPath(), \PATHINFO_EXTENSION),
|
||||
['php', 'module', 'install', 'inc', 'theme'],
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
19
vendor/chi-teck/drupal-code-generator/src/Asset/RenderableInterface.php
vendored
Normal file
19
vendor/chi-teck/drupal-code-generator/src/Asset/RenderableInterface.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Asset;
|
||||
|
||||
use DrupalCodeGenerator\Helper\Renderer\RendererInterface;
|
||||
|
||||
/**
|
||||
* An interface for renderable assets.
|
||||
*/
|
||||
interface RenderableInterface {
|
||||
|
||||
/**
|
||||
* Renders the asset.
|
||||
*/
|
||||
public function render(RendererInterface $renderer): void;
|
||||
|
||||
}
|
||||
48
vendor/chi-teck/drupal-code-generator/src/Asset/Resolver/AppendResolver.php
vendored
Normal file
48
vendor/chi-teck/drupal-code-generator/src/Asset/Resolver/AppendResolver.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Asset\Resolver;
|
||||
|
||||
use DrupalCodeGenerator\Asset\Asset;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
use DrupalCodeGenerator\InputOutput\IO;
|
||||
|
||||
final class AppendResolver implements ResolverInterface, ResolverFactoryInterface {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*
|
||||
* @psalm-param int<0, max> $headerSize
|
||||
*/
|
||||
public function __construct(private readonly int $headerSize = 0) {
|
||||
/** @psalm-suppress DocblockTypeContradiction */
|
||||
if ($headerSize < 0) {
|
||||
throw new \InvalidArgumentException('Header size must be greater than or equal to 0.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createResolver(IO $io, mixed $options): self {
|
||||
return new self($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Asset $asset, string $path): File {
|
||||
if (!$asset instanceof File) {
|
||||
throw new \InvalidArgumentException('Wrong asset type.');
|
||||
}
|
||||
$new_content = $asset->getContent();
|
||||
// Remove header from existing content.
|
||||
if ($this->headerSize > 0) {
|
||||
$new_content = \implode("\n", \array_slice(\explode("\n", $new_content), $this->headerSize));
|
||||
}
|
||||
$existing_content = \file_get_contents($path);
|
||||
return clone $asset->content($existing_content . "\n" . $new_content);
|
||||
}
|
||||
|
||||
}
|
||||
24
vendor/chi-teck/drupal-code-generator/src/Asset/Resolver/PrependResolver.php
vendored
Normal file
24
vendor/chi-teck/drupal-code-generator/src/Asset/Resolver/PrependResolver.php
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Asset\Resolver;
|
||||
|
||||
use DrupalCodeGenerator\Asset\Asset;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
|
||||
final class PrependResolver implements ResolverInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Asset $asset, string $path): File {
|
||||
if (!$asset instanceof File) {
|
||||
throw new \InvalidArgumentException('Wrong asset type.');
|
||||
}
|
||||
$new_content = $asset->getContent();
|
||||
$existing_content = \file_get_contents($path);
|
||||
return clone $asset->content($new_content . "\n" . $existing_content);
|
||||
}
|
||||
|
||||
}
|
||||
20
vendor/chi-teck/drupal-code-generator/src/Asset/Resolver/PreserveResolver.php
vendored
Normal file
20
vendor/chi-teck/drupal-code-generator/src/Asset/Resolver/PreserveResolver.php
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Asset\Resolver;
|
||||
|
||||
use DrupalCodeGenerator\Asset\Asset;
|
||||
|
||||
final class PreserveResolver implements ResolverInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @psalm-return null
|
||||
*/
|
||||
public function resolve(Asset $asset, string $path): ?Asset {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
39
vendor/chi-teck/drupal-code-generator/src/Asset/Resolver/ReplaceResolver.php
vendored
Normal file
39
vendor/chi-teck/drupal-code-generator/src/Asset/Resolver/ReplaceResolver.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Asset\Resolver;
|
||||
|
||||
use DrupalCodeGenerator\Asset\Asset;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
use DrupalCodeGenerator\Asset\Symlink;
|
||||
use DrupalCodeGenerator\InputOutput\IO;
|
||||
|
||||
final class ReplaceResolver implements ResolverInterface, ResolverFactoryInterface {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(private readonly IO $io) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createResolver(IO $io, mixed $options): self {
|
||||
return new self($io);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve(Asset $asset, string $path): NULL|File|Symlink {
|
||||
if (!$asset instanceof File && !$asset instanceof Symlink) {
|
||||
throw new \InvalidArgumentException('Wrong asset type.');
|
||||
}
|
||||
$replace = $this->io->getInput()->getOption('replace') ||
|
||||
$this->io->getInput()->getOption('dry-run') ||
|
||||
$this->io->confirm("The file <comment>$path</comment> already exists. Would you like to replace it?");
|
||||
return $replace ? clone $asset : NULL;
|
||||
}
|
||||
|
||||
}
|
||||
34
vendor/chi-teck/drupal-code-generator/src/Asset/Resolver/ResolverDefinition.php
vendored
Normal file
34
vendor/chi-teck/drupal-code-generator/src/Asset/Resolver/ResolverDefinition.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Asset\Resolver;
|
||||
|
||||
use DrupalCodeGenerator\InputOutput\IO;
|
||||
|
||||
final class ResolverDefinition {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*
|
||||
* @psalm-param class-string<\DrupalCodeGenerator\Asset\Resolver\ResolverInterface> $className
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $className,
|
||||
public readonly mixed $options = NULL,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Creates asset resolver.
|
||||
*/
|
||||
public function createResolver(IO $io): ResolverInterface {
|
||||
if (\is_subclass_of($this->className, ResolverFactoryInterface::class)) {
|
||||
$resolver = $this->className::createResolver($io, $this->options);
|
||||
}
|
||||
else {
|
||||
$resolver = new $this->className();
|
||||
}
|
||||
return $resolver;
|
||||
}
|
||||
|
||||
}
|
||||
19
vendor/chi-teck/drupal-code-generator/src/Asset/Resolver/ResolverFactoryInterface.php
vendored
Normal file
19
vendor/chi-teck/drupal-code-generator/src/Asset/Resolver/ResolverFactoryInterface.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Asset\Resolver;
|
||||
|
||||
use DrupalCodeGenerator\InputOutput\IO;
|
||||
|
||||
/**
|
||||
* Interface for classes capable of creating resolvers.
|
||||
*/
|
||||
interface ResolverFactoryInterface {
|
||||
|
||||
/**
|
||||
* Creates a resolver.
|
||||
*/
|
||||
public static function createResolver(IO $io, mixed $options): ResolverInterface;
|
||||
|
||||
}
|
||||
27
vendor/chi-teck/drupal-code-generator/src/Asset/Resolver/ResolverInterface.php
vendored
Normal file
27
vendor/chi-teck/drupal-code-generator/src/Asset/Resolver/ResolverInterface.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Asset\Resolver;
|
||||
|
||||
use DrupalCodeGenerator\Asset\Asset;
|
||||
|
||||
/**
|
||||
* Interface resolver.
|
||||
*
|
||||
* A resolver is called when the asset with the same path already exists in the
|
||||
* file system. The purpose of the resolver is to merge the existing asset with
|
||||
* the one provided by a generator.
|
||||
*/
|
||||
interface ResolverInterface {
|
||||
|
||||
/**
|
||||
* Resolves an asset.
|
||||
*
|
||||
* Returns the resolved asset or NULL if existing asset is up-to-date.
|
||||
*
|
||||
* @throw \InvalidArgumentException
|
||||
*/
|
||||
public function resolve(Asset $asset, string $path): ?Asset;
|
||||
|
||||
}
|
||||
40
vendor/chi-teck/drupal-code-generator/src/Asset/Symlink.php
vendored
Normal file
40
vendor/chi-teck/drupal-code-generator/src/Asset/Symlink.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Asset;
|
||||
|
||||
/**
|
||||
* Simple data structure to represent a symlink being generated.
|
||||
*/
|
||||
final class Symlink extends Asset {
|
||||
|
||||
/**
|
||||
* Symlink target.
|
||||
*/
|
||||
private readonly string $target;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(string $path, string $target) {
|
||||
parent::__construct($path);
|
||||
$this->target = $target;
|
||||
$this->mode(0644);
|
||||
}
|
||||
|
||||
/**
|
||||
* Named constructor.
|
||||
*/
|
||||
public static function create(string $path, string $target): self {
|
||||
return new self($path, $target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for symlink target.
|
||||
*/
|
||||
public function getTarget(): string {
|
||||
return $this->replaceTokens($this->target);
|
||||
}
|
||||
|
||||
}
|
||||
25
vendor/chi-teck/drupal-code-generator/src/Attribute/Generator.php
vendored
Normal file
25
vendor/chi-teck/drupal-code-generator/src/Attribute/Generator.php
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Attribute;
|
||||
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
|
||||
/**
|
||||
* Generator definition.
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_CLASS)]
|
||||
final class Generator {
|
||||
|
||||
public function __construct(
|
||||
public readonly string $name,
|
||||
public readonly string $description = '',
|
||||
public readonly array $aliases = [],
|
||||
public readonly bool $hidden = FALSE,
|
||||
public readonly ?string $templatePath = NULL,
|
||||
public readonly GeneratorType $type = GeneratorType::OTHER,
|
||||
public readonly ?string $label = NULL,
|
||||
) {}
|
||||
|
||||
}
|
||||
57
vendor/chi-teck/drupal-code-generator/src/BootstrapHandler.php
vendored
Normal file
57
vendor/chi-teck/drupal-code-generator/src/BootstrapHandler.php
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Composer\InstalledVersions;
|
||||
use Drupal\Core\DrupalKernel;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Provides a handler to bootstrap Drupal.
|
||||
*/
|
||||
final class BootstrapHandler {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(private readonly ClassLoader $classLoader) {}
|
||||
|
||||
/**
|
||||
* Bootstraps Drupal.
|
||||
*/
|
||||
public function bootstrap(): ContainerInterface {
|
||||
self::assertInstallation();
|
||||
|
||||
$root_package = InstalledVersions::getRootPackage();
|
||||
\chdir($root_package['install_path']);
|
||||
$request = Request::createFromGlobals();
|
||||
$kernel = DrupalKernel::createFromRequest($request, $this->classLoader, 'prod');
|
||||
$kernel->boot();
|
||||
$kernel->preHandle($request);
|
||||
// Cancel Drupal error handler to get all errors in STDOUT.
|
||||
\restore_error_handler();
|
||||
\error_reporting(\E_ALL);
|
||||
return $kernel->getContainer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts Drupal instance.
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
private static function assertInstallation(): void {
|
||||
$preflight = \defined('Drupal::VERSION') &&
|
||||
\version_compare(\Drupal::VERSION, '10.0.0-dev', '>=') &&
|
||||
\class_exists(InstalledVersions::class) &&
|
||||
\class_exists(Request::class) &&
|
||||
\class_exists(DrupalKernel::class);
|
||||
if (!$preflight) {
|
||||
throw new \RuntimeException('Could not load Drupal.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
299
vendor/chi-teck/drupal-code-generator/src/Command/BaseGenerator.php
vendored
Normal file
299
vendor/chi-teck/drupal-code-generator/src/Command/BaseGenerator.php
vendored
Normal file
@ -0,0 +1,299 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command;
|
||||
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator as GeneratorDefinition;
|
||||
use DrupalCodeGenerator\Event\AssetPostProcess;
|
||||
use DrupalCodeGenerator\Event\AssetPreProcess;
|
||||
use DrupalCodeGenerator\Exception\ExceptionInterface;
|
||||
use DrupalCodeGenerator\Exception\SilentException;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Helper\Drupal\NullExtensionInfo;
|
||||
use DrupalCodeGenerator\InputOutput\DefaultOptions;
|
||||
use DrupalCodeGenerator\InputOutput\Interviewer;
|
||||
use DrupalCodeGenerator\InputOutput\IO;
|
||||
use DrupalCodeGenerator\InputOutput\IOAwareInterface;
|
||||
use DrupalCodeGenerator\InputOutput\IOAwareTrait;
|
||||
use DrupalCodeGenerator\Logger\ConsoleLogger;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
use Psr\Log\NullLogger;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\Helper;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Base class for code generators.
|
||||
*
|
||||
* @method \DrupalCodeGenerator\Application getApplication()
|
||||
* @method string getName()
|
||||
* @method \Symfony\Component\Console\Helper\HelperSet getHelperSet()
|
||||
*/
|
||||
abstract class BaseGenerator extends Command implements LabelInterface, IOAwareInterface, LoggerAwareInterface {
|
||||
|
||||
use IOAwareTrait;
|
||||
use LoggerAwareTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->logger = new NullLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure(): void {
|
||||
parent::configure();
|
||||
$definition = $this->getGeneratorDefinition();
|
||||
$this->setName($definition->name)
|
||||
->setDescription($definition->description)
|
||||
->setAliases($definition->aliases)
|
||||
->setHidden($definition->hidden);
|
||||
DefaultOptions::apply($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @psalm-suppress PossiblyNullReference
|
||||
*/
|
||||
protected function initialize(InputInterface $input, OutputInterface $output): void {
|
||||
parent::initialize($input, $output);
|
||||
|
||||
$logger = new ConsoleLogger($output);
|
||||
$question_helper = $this->getHelper('question');
|
||||
$io = new IO($input, $output, $question_helper);
|
||||
|
||||
$items = \iterator_to_array($this->getHelperSet());
|
||||
$items[] = $this;
|
||||
foreach ($items as $item) {
|
||||
if ($item instanceof IOAwareInterface) {
|
||||
$item->io($io);
|
||||
}
|
||||
if ($item instanceof LoggerAwareInterface) {
|
||||
$item->setLogger($logger);
|
||||
}
|
||||
}
|
||||
|
||||
$template_path = $this->getTemplatePath();
|
||||
if ($template_path !== NULL) {
|
||||
$this->getHelper('renderer')->registerTemplatePath($template_path);
|
||||
}
|
||||
|
||||
$this->logger->debug('PHP binary: {binary}', ['binary' => \PHP_BINARY]);
|
||||
/** @psalm-var array{PHP_SELF: string} $_SERVER */
|
||||
// @phpcs:ignore SlevomatCodingStandard.Variables.DisallowSuperGlobalVariable.DisallowedSuperGlobalVariable
|
||||
$this->logger->debug('DCG executable: {dcg}', ['dcg' => \realpath($_SERVER['PHP_SELF'])]);
|
||||
$this->logger->debug('Working directory: {directory}', ['directory' => $io->getWorkingDirectory()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @noinspection PhpMissingParentCallCommonInspection
|
||||
* @psalm-suppress PossiblyNullReference
|
||||
*
|
||||
* @psalm-return int<0, 1>
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int {
|
||||
|
||||
$this->logger->debug('Command: {command}', ['command' => static::class]);
|
||||
|
||||
try {
|
||||
$this->printHeader();
|
||||
|
||||
$vars = [];
|
||||
$assets = new AssetCollection();
|
||||
$this->generate($vars, $assets);
|
||||
$this->generateInfoFile($vars, $assets);
|
||||
|
||||
$vars = Utils::processVars($vars);
|
||||
$collected_vars = \preg_replace('/^Array/', '', \print_r($vars, TRUE));
|
||||
$this->logger->debug('Collected variables: {vars}', ['vars' => $collected_vars]);
|
||||
|
||||
foreach ($assets as $asset) {
|
||||
// Local asset variables take precedence over global ones.
|
||||
$asset->vars(\array_merge($vars, Utils::processVars($asset->getVars())));
|
||||
}
|
||||
|
||||
$this->render($assets);
|
||||
|
||||
// Destination passed through command line option takes precedence over
|
||||
// destination defined in a generator.
|
||||
$destination = $input->getOption('destination') ?: $this->getDestination($vars);
|
||||
$this->logger->debug('Destination directory: {directory}', ['directory' => $destination]);
|
||||
|
||||
$dumped_assets = $this->dump($assets, $destination);
|
||||
|
||||
$full_path = $input->getOption('full-path');
|
||||
$this->printSummary($dumped_assets, $full_path ? $destination . '/' : '');
|
||||
}
|
||||
catch (ExceptionInterface $exception) {
|
||||
if (!$exception instanceof SilentException) {
|
||||
$this->io()->getErrorStyle()->error($exception->getMessage());
|
||||
}
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$this->logger->debug('Memory usage: {memory}', ['memory' => Helper::formatMemory(\memory_get_peak_usage())]);
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates assets.
|
||||
*/
|
||||
abstract protected function generate(array &$vars, AssetCollection $assets): void;
|
||||
|
||||
/**
|
||||
* Gets generator definition.
|
||||
*/
|
||||
protected function getGeneratorDefinition(): GeneratorDefinition {
|
||||
$attributes = (new \ReflectionClass(static::class))->getAttributes(GeneratorDefinition::class);
|
||||
if (\count($attributes) === 0) {
|
||||
throw new \LogicException(\sprintf('Command %s does not have generator annotation.', static::class));
|
||||
}
|
||||
return $attributes[0]->newInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates interviewer.
|
||||
*/
|
||||
protected function createInterviewer(array &$vars): Interviewer {
|
||||
$extension_info = match ($this->getGeneratorDefinition()->type) {
|
||||
GeneratorType::MODULE, GeneratorType::MODULE_COMPONENT => $this->getHelper('module_info'),
|
||||
GeneratorType::THEME, GeneratorType::THEME_COMPONENT => $this->getHelper('theme_info'),
|
||||
default => new NullExtensionInfo(),
|
||||
};
|
||||
return new Interviewer(
|
||||
io: $this->io,
|
||||
vars: $vars,
|
||||
generatorDefinition: $this->getGeneratorDefinition(),
|
||||
serviceInfo: $this->getHelper('service_info'),
|
||||
extensionInfo: $extension_info,
|
||||
permissionInfo: $this->getHelper('permission_info'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render assets.
|
||||
*/
|
||||
protected function render(AssetCollection $assets): void {
|
||||
$renderer = $this->getHelper('renderer');
|
||||
foreach ($assets->getFiles() as $file) {
|
||||
/** @var \DrupalCodeGenerator\Asset\File $file */
|
||||
$renderer->renderAsset($file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps assets.
|
||||
*/
|
||||
protected function dump(AssetCollection $assets, string $destination): AssetCollection {
|
||||
$is_dry = $this->io()->getInput()->getOption('dry-run');
|
||||
|
||||
$pre_process_event = $this->getApplication()->dispatch(
|
||||
new AssetPreProcess($assets, $destination, $this->getName(), $is_dry),
|
||||
);
|
||||
$assets = $pre_process_event->assets;
|
||||
$destination = $pre_process_event->destination;
|
||||
|
||||
/** @var \DrupalCodeGenerator\Helper\Dumper\DumperInterface $dumper */
|
||||
$dumper = $this->getHelper($is_dry ? 'dry_dumper' : 'filesystem_dumper');
|
||||
$dumped_assets = $dumper->dump($assets, $destination);
|
||||
|
||||
$post_process_event = $this->getApplication()->dispatch(
|
||||
new AssetPostProcess($dumped_assets, $destination, $this->getName(), $is_dry),
|
||||
);
|
||||
return $post_process_event->assets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints header.
|
||||
*/
|
||||
protected function printHeader(): void {
|
||||
$this->io()->title(\sprintf('Welcome to %s generator!', $this->getAliases()[0] ?? $this->getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints summary.
|
||||
*/
|
||||
protected function printSummary(AssetCollection $dumped_assets, string $base_path): void {
|
||||
$printer_name = $this->io()->isVerbose() ? 'assets_table_printer' : 'assets_list_printer';
|
||||
/** @psalm-suppress UndefinedInterfaceMethod */
|
||||
$this->getHelper($printer_name)->printAssets($dumped_assets, $base_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLabel(): ?string {
|
||||
return $this->getGeneratorDefinition()->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns template path.
|
||||
*/
|
||||
final protected function getTemplatePath(): ?string {
|
||||
return $this->getGeneratorDefinition()->templatePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns destination for generated files.
|
||||
*
|
||||
* @todo Test this.
|
||||
*/
|
||||
protected function getDestination(array $vars): string {
|
||||
if (!isset($vars['machine_name'])) {
|
||||
return $this->io()->getWorkingDirectory();
|
||||
}
|
||||
$definition = $this->getGeneratorDefinition();
|
||||
$is_new = $definition->type->isNewExtension();
|
||||
return match ($definition->type) {
|
||||
GeneratorType::MODULE, GeneratorType::MODULE_COMPONENT =>
|
||||
$this->getHelper('module_info')->getDestination($vars['machine_name'], $is_new),
|
||||
GeneratorType::THEME, GeneratorType::THEME_COMPONENT =>
|
||||
$this->getHelper('theme_info')->getDestination($vars['machine_name'], $is_new),
|
||||
default => $this->io()->getWorkingDirectory(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates info file.
|
||||
*
|
||||
* @todo Test this.
|
||||
* @todo Generate info file for theme components.
|
||||
*/
|
||||
protected function generateInfoFile(array &$vars, AssetCollection $assets): void {
|
||||
if (\count($assets) === 0) {
|
||||
return;
|
||||
}
|
||||
if ($this->getGeneratorDefinition()->type !== GeneratorType::MODULE_COMPONENT) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @todo Throw an exception if machine name was not provided.
|
||||
/** @psalm-suppress PossiblyUndefinedStringArrayOffset */
|
||||
$vars['name'] ??= Utils::machine2human($vars['machine_name']);
|
||||
$info_template = <<< 'TWIG'
|
||||
name: '{{ name }}'
|
||||
type: module
|
||||
description: '@todo Add description.'
|
||||
package: '@todo Add package'
|
||||
core_version_requirement: ^10 || ^11
|
||||
|
||||
TWIG;
|
||||
$assets->addFile('{machine_name}.info.yml')
|
||||
->inlineTemplate($info_template)
|
||||
->preserveIfExists();
|
||||
}
|
||||
|
||||
}
|
||||
67
vendor/chi-teck/drupal-code-generator/src/Command/Composer.php
vendored
Normal file
67
vendor/chi-teck/drupal-code-generator/src/Command/Composer.php
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\Assets;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
|
||||
/**
|
||||
* A generator for composer.json file.
|
||||
*
|
||||
* @todo Clean-up
|
||||
* @todo Define destination automatically based on project type.
|
||||
*/
|
||||
#[Generator(
|
||||
name: 'composer',
|
||||
description: 'Generates a composer.json file',
|
||||
aliases: ['composer.json'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/_composer',
|
||||
type: GeneratorType::OTHER,
|
||||
label: 'composer.json',
|
||||
)]
|
||||
final class Composer extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, Assets $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
|
||||
// @see https://getcomposer.org/doc/04-schema.md#name
|
||||
// @todo Test this.
|
||||
$validator = static function (string $input): string {
|
||||
if (!\preg_match('#^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$#', $input)) {
|
||||
throw new \UnexpectedValueException("The package name \"$input\" is invalid, it should be lowercase and have a vendor name, a forward slash, and a package name.");
|
||||
}
|
||||
return $input;
|
||||
};
|
||||
$vars['project_name'] = $ir->ask('Project name', 'drupal/example', $validator);
|
||||
[, $vars['machine_name']] = \explode('/', $vars['project_name']);
|
||||
|
||||
$vars['description'] = $ir->ask('Description');
|
||||
|
||||
$type_choices = [
|
||||
'drupal-module',
|
||||
'drupal-custom-module',
|
||||
'drupal-theme',
|
||||
'drupal-custom-theme',
|
||||
'drupal-library',
|
||||
'drupal-profile',
|
||||
'drupal-custom-profile',
|
||||
'drupal-drush',
|
||||
];
|
||||
$vars['type'] = $ir->choice('Project type', \array_combine($type_choices, $type_choices));
|
||||
|
||||
$vars['drupal_org'] = match($vars['type']) {
|
||||
'drupal-custom-module', 'drupal-custom-theme', 'drupal-custom-profile' => FALSE,
|
||||
default => $ir->confirm('Will this project be hosted on drupal.org?'),
|
||||
};
|
||||
|
||||
$assets->addFile('composer.json', 'composer.twig');
|
||||
}
|
||||
|
||||
}
|
||||
52
vendor/chi-teck/drupal-code-generator/src/Command/Controller.php
vendored
Normal file
52
vendor/chi-teck/drupal-code-generator/src/Command/Controller.php
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\Assets;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
|
||||
#[Generator(
|
||||
name: 'controller',
|
||||
description: 'Generates a controller',
|
||||
templatePath: Application::TEMPLATE_PATH . '/_controller',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Controller extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, Assets $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
$vars['class'] = $ir->askClass(default: '{machine_name|camelize}Controller');
|
||||
|
||||
$vars['services'] = $ir->askServices(FALSE);
|
||||
|
||||
if ($ir->confirm('Would you like to create a route for this controller?')) {
|
||||
$unprefixed_class = Utils::camel2machine(Utils::removeSuffix($vars['class'], 'Controller'));
|
||||
// Route name like 'foo.foo' would look weird.
|
||||
if ($unprefixed_class === $vars['machine_name']) {
|
||||
$unprefixed_class = 'example';
|
||||
}
|
||||
$vars['route_name'] = $ir->ask('Route name', '{machine_name}.' . $unprefixed_class);
|
||||
$vars['unprefixed_route_name'] = \str_replace(
|
||||
'.', '_', Utils::removePrefix($vars['route_name'], $vars['machine_name'] . '.'),
|
||||
);
|
||||
$vars['route_path'] = $ir->ask('Route path', '/{machine_name|u2h}/{unprefixed_route_name|u2h}');
|
||||
$vars['route_title'] = $ir->ask('Route title', '{unprefixed_route_name|m2t}');
|
||||
$vars['route_permission'] = $ir->askPermission('Route permission', 'access content');
|
||||
$assets->addFile('{machine_name}.routing.yml', 'route.twig')->appendIfExists();
|
||||
}
|
||||
|
||||
$assets->addFile('src/Controller/{class}.php', 'controller.twig');
|
||||
}
|
||||
|
||||
}
|
||||
62
vendor/chi-teck/drupal-code-generator/src/Command/Drush/SymfonyCommand.php
vendored
Normal file
62
vendor/chi-teck/drupal-code-generator/src/Command/Drush/SymfonyCommand.php
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Drush;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
use DrupalCodeGenerator\Validator\RegExp;
|
||||
|
||||
#[Generator(
|
||||
name: 'drush:symfony-command',
|
||||
description: 'Generates Symfony console command',
|
||||
aliases: ['symfony-command'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Drush/_symfony-command',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class SymfonyCommand extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
|
||||
$command_name_validator = new RegExp('/^[a-z][a-z0-9-_:]*[a-z0-9]$/', 'The value is not correct command name.');
|
||||
$vars['command']['name'] = $ir->ask('Command name', '{machine_name}:example', $command_name_validator);
|
||||
|
||||
$vars['command']['description'] = $ir->ask('Command description');
|
||||
|
||||
$sub_names = \explode(':', $vars['command']['name']);
|
||||
$short_name = \array_pop($sub_names);
|
||||
|
||||
$alias_validator = new RegExp('/^[a-z0-9_-]+$/', 'The value is not correct alias name.');
|
||||
$vars['command']['alias'] = $ir->ask('Command alias', $short_name, $alias_validator);
|
||||
|
||||
$vars['class'] = $ir->askClass('Class', Utils::camelize($short_name) . 'Command');
|
||||
|
||||
if ($ir->confirm('Would you like to run the command with Drush')) {
|
||||
// Make service name using the following guides.
|
||||
// `foo:example` -> `foo.example` (not `foo:foo_example`)
|
||||
// `foo` -> `foo.foo` (not `foo`)
|
||||
$service_name = Utils::removePrefix($vars['command']['name'], $vars['machine_name'] . ':');
|
||||
if (!$service_name) {
|
||||
$service_name = $vars['command']['name'];
|
||||
}
|
||||
$vars['service_name'] = $vars['machine_name'] . '.' . \str_replace(':', '_', $service_name);
|
||||
|
||||
$vars['services'] = $ir->askServices(FALSE);
|
||||
$assets->addServicesFile('drush.services.yml')->template('services.twig');
|
||||
}
|
||||
$assets->addFile('src/Command/{class}.php', 'command.twig');
|
||||
}
|
||||
|
||||
}
|
||||
83
vendor/chi-teck/drupal-code-generator/src/Command/Entity/ConfigurationEntity.php
vendored
Normal file
83
vendor/chi-teck/drupal-code-generator/src/Command/Entity/ConfigurationEntity.php
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Entity;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\Asset;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
use DrupalCodeGenerator\Asset\Resolver\ResolverInterface;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
|
||||
#[Generator(
|
||||
name: 'entity:configuration',
|
||||
description: 'Generates configuration entity',
|
||||
aliases: ['config-entity'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Entity/_configuration-entity',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class ConfigurationEntity extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
|
||||
$vars['entity_type_label'] = $ir->ask('Entity type label', '{name}');
|
||||
$vars['entity_type_id'] = $ir->ask('Entity type ID', '{entity_type_label|h2m}');
|
||||
$vars['class_prefix'] = '{entity_type_id|camelize}';
|
||||
|
||||
$assets->addFile('src/{class_prefix}ListBuilder.php', 'src/ExampleListBuilder.php.twig');
|
||||
$assets->addFile('src/Form/{class_prefix}Form.php', 'src/Form/ExampleForm.php.twig');
|
||||
$assets->addFile('src/{class_prefix}Interface.php', 'src/ExampleInterface.php.twig');
|
||||
$assets->addFile('src/Entity/{class_prefix}.php', 'src/Entity/Example.php.twig');
|
||||
$assets->addFile('{machine_name}.routing.yml', 'model.routing.yml.twig')
|
||||
->appendIfExists();
|
||||
$assets->addFile('{machine_name}.links.action.yml', 'model.links.action.yml.twig')
|
||||
->appendIfExists();
|
||||
$assets->addFile('{machine_name}.links.menu.yml', 'model.links.menu.yml.twig')
|
||||
->appendIfExists();
|
||||
$assets->addFile('{machine_name}.permissions.yml', 'model.permissions.yml.twig')
|
||||
->appendIfExists();
|
||||
$assets->addFile('config/schema/{machine_name}.schema.yml', 'config/schema/model.schema.yml.twig')
|
||||
->appendIfExists();
|
||||
|
||||
$assets->addFile('{machine_name}.info.yml.twig')
|
||||
->setVirtual(TRUE)
|
||||
->resolver($this->getInfoResolver($vars));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns resolver for the module info file.
|
||||
*/
|
||||
private function getInfoResolver(array $vars): ResolverInterface {
|
||||
// Add 'configure' link to the info file if it exists.
|
||||
return new class ($vars) implements ResolverInterface {
|
||||
|
||||
public function __construct(private readonly array $vars) {}
|
||||
|
||||
public function resolve(Asset $asset, string $path): Asset {
|
||||
if (!$asset instanceof File) {
|
||||
throw new \InvalidArgumentException('Wrong asset type.');
|
||||
}
|
||||
$resolved = clone $asset;
|
||||
$existing_content = \file_get_contents($path);
|
||||
if (!\preg_match('/^configure: /m', $existing_content)) {
|
||||
/** @psalm-suppress PossiblyUndefinedStringArrayOffset */
|
||||
$content = "{$existing_content}configure: entity.{$this->vars['entity_type_id']}.collection\n";
|
||||
return $resolved->content($content);
|
||||
}
|
||||
return $resolved;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
167
vendor/chi-teck/drupal-code-generator/src/Command/Entity/ContentEntity.php
vendored
Normal file
167
vendor/chi-teck/drupal-code-generator/src/Command/Entity/ContentEntity.php
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Entity;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
|
||||
#[Generator(
|
||||
name: 'entity:content',
|
||||
description: 'Generates content entity',
|
||||
aliases: ['content-entity'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Entity/_content-entity',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class ContentEntity extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
|
||||
$vars['entity_type_label'] = $ir->ask('Entity type label', '{name}');
|
||||
// Make sure the default entity type ID is not like 'example_example'.
|
||||
// @todo Create a test for this.
|
||||
$default_entity_type_id = Utils::human2machine($vars['entity_type_label']) === $vars['machine_name'] ?
|
||||
$vars['machine_name'] : $vars['machine_name'] . '_' . Utils::human2machine($vars['entity_type_label']);
|
||||
$vars['entity_type_id'] = $ir->ask('Entity type ID', $default_entity_type_id);
|
||||
|
||||
$vars['entity_type_id_short'] = $vars['machine_name'] === $vars['entity_type_id'] ?
|
||||
$vars['entity_type_id'] : Utils::removePrefix($vars['entity_type_id'], $vars['machine_name'] . '_');
|
||||
|
||||
$vars['class'] = $ir->ask('Entity class', '{entity_type_label|camelize}');
|
||||
$vars['entity_base_path'] = $ir->ask('Entity base path', '/{entity_type_id_short|u2h}');
|
||||
$vars['fieldable'] = $ir->confirm('Make the entity type fieldable?');
|
||||
$vars['revisionable'] = $ir->confirm('Make the entity type revisionable?', FALSE);
|
||||
$vars['translatable'] = $ir->confirm('Make the entity type translatable?', FALSE);
|
||||
$vars['bundle'] = $ir->confirm('The entity type has bundle?', FALSE);
|
||||
$vars['canonical'] = $ir->confirm('Create canonical page?');
|
||||
$vars['template'] = $vars['canonical'] && $ir->confirm('Create entity template?');
|
||||
$vars['access_controller'] = $ir->confirm('Create CRUD permissions?', FALSE);
|
||||
|
||||
$vars['label_base_field'] = $ir->confirm('Add "label" base field?');
|
||||
$vars['status_base_field'] = $ir->confirm('Add "status" base field?');
|
||||
$vars['created_base_field'] = $ir->confirm('Add "created" base field?');
|
||||
$vars['changed_base_field'] = $ir->confirm('Add "changed" base field?');
|
||||
$vars['author_base_field'] = $ir->confirm('Add "author" base field?');
|
||||
$vars['description_base_field'] = $ir->confirm('Add "description" base field?');
|
||||
$vars['has_base_fields'] = $vars['label_base_field'] ||
|
||||
$vars['status_base_field'] ||
|
||||
$vars['created_base_field'] ||
|
||||
$vars['changed_base_field'] ||
|
||||
$vars['author_base_field'] ||
|
||||
$vars['description_base_field'];
|
||||
|
||||
$vars['permissions']['administer'] = $vars['bundle']
|
||||
? 'administer {entity_type_id} types' : 'administer {entity_type_id}';
|
||||
|
||||
if ($vars['access_controller']) {
|
||||
$vars['permissions']['view'] = 'view {entity_type_id}';
|
||||
$vars['permissions']['edit'] = 'edit {entity_type_id}';
|
||||
$vars['permissions']['delete'] = 'delete {entity_type_id}';
|
||||
$vars['permissions']['create'] = 'create {entity_type_id}';
|
||||
}
|
||||
|
||||
if ($vars['access_controller'] && $vars['revisionable']) {
|
||||
$vars['permissions']['view_revision'] = 'view {entity_type_id} revision';
|
||||
$vars['permissions']['revert_revision'] = 'revert {entity_type_id} revision';
|
||||
$vars['permissions']['delete_revision'] = 'delete {entity_type_id} revision';
|
||||
}
|
||||
|
||||
$vars['rest_configuration'] = $ir->confirm('Create REST configuration for the entity?', FALSE);
|
||||
|
||||
if (!\str_starts_with($vars['entity_base_path'], '/')) {
|
||||
$vars['entity_base_path'] = '/' . $vars['entity_base_path'];
|
||||
}
|
||||
|
||||
if (($vars['fieldable_no_bundle'] = $vars['fieldable'] && !$vars['bundle'])) {
|
||||
$vars['configure'] = 'entity.{entity_type_id}.settings';
|
||||
}
|
||||
elseif ($vars['bundle']) {
|
||||
$vars['configure'] = 'entity.{entity_type_id}_type.collection';
|
||||
}
|
||||
|
||||
$vars['template_name'] = '{entity_type_id|u2h}.html.twig';
|
||||
|
||||
// Contextual links need title suffix to be added to entity template.
|
||||
if ($vars['template']) {
|
||||
$assets->addFile('{machine_name}.links.contextual.yml', 'model.links.contextual.yml.twig')
|
||||
->appendIfExists();
|
||||
}
|
||||
$assets->addFile('{machine_name}.links.action.yml', 'model.links.action.yml.twig')
|
||||
->appendIfExists();
|
||||
$assets->addFile('{machine_name}.links.menu.yml', 'model.links.menu.yml.twig')
|
||||
->appendIfExists();
|
||||
$assets->addFile('{machine_name}.links.task.yml', 'model.links.task.yml.twig')
|
||||
->appendIfExists();
|
||||
$assets->addFile('{machine_name}.permissions.yml', 'model.permissions.yml.twig')
|
||||
->appendIfExists();
|
||||
|
||||
// Delete action plugins only registered for entity types that have
|
||||
// 'delete-multiple-confirm' form handler and 'delete-multiple-form' link
|
||||
// template.
|
||||
// @see \Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider::getDeleteMultipleFormRoute
|
||||
// @see \Drupal\Core\Action\Plugin\Action\Derivative\EntityDeleteActionDeriver
|
||||
$assets->addFile(
|
||||
'config/install/system.action.{entity_type_id}_delete_action.yml',
|
||||
'config/install/system.action.example_delete_action.yml.twig',
|
||||
);
|
||||
// Save action plugins only registered for entity types that implement
|
||||
// Drupal\Core\Entity\EntityChangedInterface.
|
||||
// @see \Drupal\Core\Action\Plugin\Action\Derivative\EntityChangedActionDeriver
|
||||
if ($vars['changed_base_field']) {
|
||||
$assets->addFile(
|
||||
'config/install/system.action.{entity_type_id}_save_action.yml',
|
||||
'config/install/system.action.example_save_action.yml.twig',
|
||||
);
|
||||
}
|
||||
|
||||
$assets->addFile('src/Entity/{class}.php', 'src/Entity/Example.php.twig');
|
||||
$assets->addFile('src/{class}Interface.php', 'src/ExampleInterface.php.twig');
|
||||
|
||||
if (!$vars['canonical']) {
|
||||
$assets->addFile('src/Routing/{class}HtmlRouteProvider.php', 'src/Routing/ExampleHtmlRouteProvider.php.twig');
|
||||
}
|
||||
|
||||
$assets->addFile('src/{class}ListBuilder.php', 'src/ExampleListBuilder.php.twig');
|
||||
$assets->addFile('src/Form/{class}Form.php', 'src/Form/ExampleForm.php.twig');
|
||||
|
||||
if ($vars['fieldable_no_bundle']) {
|
||||
$assets->addFile('{machine_name}.routing.yml', 'model.routing.yml.twig')
|
||||
->appendIfExists();
|
||||
$assets->addFile('src/Form/{class}SettingsForm.php', 'src/Form/ExampleSettingsForm.php.twig');
|
||||
}
|
||||
|
||||
if ($vars['template']) {
|
||||
$assets->addFile('templates/{entity_type_id|u2h}.html.twig', 'templates/model-example.html.twig.twig');
|
||||
$assets->addFile('{machine_name}.module', 'model.module.twig')
|
||||
->appendIfExists(9);
|
||||
}
|
||||
|
||||
if ($vars['access_controller']) {
|
||||
$assets->addFile('src/{class}AccessControlHandler.php', 'src/ExampleAccessControlHandler.php.twig');
|
||||
}
|
||||
|
||||
if ($vars['rest_configuration']) {
|
||||
$assets->addFile('config/optional/rest.resource.entity.{entity_type_id}.yml', 'config/optional/rest.resource.entity.example.yml.twig');
|
||||
}
|
||||
|
||||
if ($vars['bundle']) {
|
||||
$assets->addFile('config/schema/{machine_name}.entity_type.schema.yml', 'config/schema/model.entity_type.schema.yml.twig')
|
||||
->appendIfExists();
|
||||
$assets->addFile('src/{class}TypeListBuilder.php', 'src/ExampleTypeListBuilder.php.twig');
|
||||
$assets->addFile('src/Entity/{class}Type.php', 'src/Entity/ExampleType.php.twig');
|
||||
$assets->addFile('src/Form/{class}TypeForm.php', 'src/Form/ExampleTypeForm.php.twig');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
120
vendor/chi-teck/drupal-code-generator/src/Command/Entity/EntityBundleClass.php
vendored
Normal file
120
vendor/chi-teck/drupal-code-generator/src/Command/Entity/EntityBundleClass.php
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Entity;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Entity\ContentEntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\Exception\RuntimeException;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
#[Generator(
|
||||
name: 'entity:bundle-class',
|
||||
description: 'Generate a bundle class for a content entity.',
|
||||
aliases: ['bundle-class'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Entity/_entity-bundle-class',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class EntityBundleClass extends BaseGenerator implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly EntityTypeManagerInterface $entityTypeManager,
|
||||
private readonly EntityTypeBundleInfoInterface $bundleInfo,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container): self {
|
||||
return new self(
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('entity_type.bundle.info'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @psalm-suppress PossiblyInvalidArgument
|
||||
* @psalm-suppress PossiblyUndefinedStringArrayOffset
|
||||
* @psalm-suppress PossiblyInvalidArrayOffset
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
|
||||
$ir = $this->createInterviewer($vars);
|
||||
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
|
||||
/** @psalm-var array<string, \Drupal\Core\Entity\ContentEntityTypeInterface> $definitions */
|
||||
$definitions = \array_filter(
|
||||
$this->entityTypeManager->getDefinitions(),
|
||||
static fn (EntityTypeInterface $definition): bool => $definition->getGroup() === 'content',
|
||||
);
|
||||
|
||||
$entity_types = \array_map(
|
||||
static fn (ContentEntityTypeInterface $definition): string => (string) $definition->get('label'),
|
||||
$definitions,
|
||||
);
|
||||
$vars['entity_type_id'] = $ir->choice('Entity type', $entity_types);
|
||||
|
||||
// @todo Should this use 'original_class' instead?
|
||||
$vars['entity_class_fqn'] = $definitions[$vars['entity_type_id']]->get('class');
|
||||
$vars['entity_class'] = \array_slice(\explode('\\', $vars['entity_class_fqn']), -1)[0];
|
||||
$vars['namespace'] = 'Drupal\\\{machine_name}\Entity\\\{entity_class}';
|
||||
|
||||
$bundles = \array_map(
|
||||
static fn (array $bundle): string => (string) $bundle['label'],
|
||||
$this->bundleInfo->getBundleInfo($vars['entity_type_id']),
|
||||
);
|
||||
if (\count($bundles) === 0) {
|
||||
throw new RuntimeException(
|
||||
\sprintf('The "%s" entity type has no bundles.', $entity_types[$vars['entity_type_id']]),
|
||||
);
|
||||
}
|
||||
|
||||
// Skip the question if only 1 bundle exists.
|
||||
$bundle_ids = \count($bundles) === 1 ?
|
||||
\array_keys($bundles) : $ir->choice('Bundles, comma separated', $bundles, NULL, TRUE);
|
||||
|
||||
$vars['classes'] = [];
|
||||
$vars['classes_fqn'] = [];
|
||||
/** @psalm-var list<string> $bundle_ids */
|
||||
foreach ($bundle_ids as $bundle_id) {
|
||||
$vars['bundle_id'] = $bundle_id;
|
||||
$vars['class'] = $ir->ask(
|
||||
\sprintf('Class for "%s" bundle', $bundles[$bundle_id]),
|
||||
'{bundle_id|camelize}',
|
||||
);
|
||||
$assets->addFile('src/Entity/{entity_class}/{class}.php', 'bundle-class.twig')->vars($vars);
|
||||
// Track all bundle classes to generate hook_entity_bundle_info_alter().
|
||||
$vars['classes'][$bundle_id] = $vars['class'];
|
||||
$vars['classes_fqn'][$bundle_id] = '\\' . $vars['namespace'] . '\\' . $vars['class'];
|
||||
}
|
||||
|
||||
$vars['base_class'] = NULL;
|
||||
if ($ir->confirm('Use a base class?', FALSE)) {
|
||||
$vars['base_class'] = $ir->ask('Base class', '{entity_type_id|camelize}Base');
|
||||
$assets->addFile('src/Entity/{entity_class}/{base_class}.php', 'bundle-base-class.twig');
|
||||
}
|
||||
|
||||
// @todo Handle duplicated hooks.
|
||||
$assets->addFile('{machine_name}.module', 'module.twig')
|
||||
->appendIfExists(9);
|
||||
}
|
||||
|
||||
}
|
||||
273
vendor/chi-teck/drupal-code-generator/src/Command/Field.php
vendored
Normal file
273
vendor/chi-teck/drupal-code-generator/src/Command/Field.php
vendored
Normal file
@ -0,0 +1,273 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\Assets;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
use DrupalCodeGenerator\Validator\Required;
|
||||
use DrupalCodeGenerator\Validator\RequiredMachineName;
|
||||
|
||||
#[Generator(
|
||||
name: 'field',
|
||||
description: 'Generates a field',
|
||||
templatePath: Application::TEMPLATE_PATH . '/_field',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Field extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* Field sub-types.
|
||||
*/
|
||||
private const array SUB_TYPES = [
|
||||
'boolean' => [
|
||||
'label' => 'Boolean',
|
||||
'list' => FALSE,
|
||||
'random' => FALSE,
|
||||
'inline' => FALSE,
|
||||
'link' => FALSE,
|
||||
'data_type' => 'boolean',
|
||||
],
|
||||
'string' => [
|
||||
'label' => 'Text',
|
||||
'list' => TRUE,
|
||||
'random' => TRUE,
|
||||
'inline' => TRUE,
|
||||
'link' => FALSE,
|
||||
'data_type' => 'string',
|
||||
],
|
||||
'text' => [
|
||||
'label' => 'Text (long)',
|
||||
'list' => FALSE,
|
||||
'random' => TRUE,
|
||||
'inline' => FALSE,
|
||||
'link' => FALSE,
|
||||
'data_type' => 'string',
|
||||
],
|
||||
'integer' => [
|
||||
'label' => 'Integer',
|
||||
'list' => TRUE,
|
||||
'random' => FALSE,
|
||||
'inline' => TRUE,
|
||||
'link' => FALSE,
|
||||
'data_type' => 'integer',
|
||||
],
|
||||
'float' => [
|
||||
'label' => 'Float',
|
||||
'list' => TRUE,
|
||||
'random' => FALSE,
|
||||
'inline' => TRUE,
|
||||
'link' => FALSE,
|
||||
'data_type' => 'float',
|
||||
],
|
||||
'numeric' => [
|
||||
'label' => 'Numeric',
|
||||
'list' => TRUE,
|
||||
'random' => FALSE,
|
||||
'inline' => TRUE,
|
||||
'link' => FALSE,
|
||||
'data_type' => 'float',
|
||||
],
|
||||
'email' => [
|
||||
'label' => 'Email',
|
||||
'list' => TRUE,
|
||||
'random' => TRUE,
|
||||
'inline' => TRUE,
|
||||
'link' => TRUE,
|
||||
'data_type' => 'email',
|
||||
],
|
||||
'telephone' => [
|
||||
'label' => 'Telephone',
|
||||
'list' => TRUE,
|
||||
'random' => FALSE,
|
||||
'inline' => TRUE,
|
||||
'link' => TRUE,
|
||||
'data_type' => 'string',
|
||||
],
|
||||
'uri' => [
|
||||
'label' => 'Url',
|
||||
'list' => TRUE,
|
||||
'random' => TRUE,
|
||||
'inline' => TRUE,
|
||||
'link' => TRUE,
|
||||
'data_type' => 'uri',
|
||||
],
|
||||
'datetime' => [
|
||||
'label' => 'Date',
|
||||
'list' => TRUE,
|
||||
'random' => FALSE,
|
||||
'inline' => FALSE,
|
||||
'link' => FALSE,
|
||||
'data_type' => 'datetime_iso8601',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Date types.
|
||||
*/
|
||||
private const array DATE_TYPES = [
|
||||
'date' => 'Date only',
|
||||
'datetime' => 'Date and time',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, Assets $assets): void {
|
||||
|
||||
$ir = $this->createInterviewer($vars);
|
||||
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
|
||||
$vars['field_label'] = $ir->ask('Field label', 'Example', new Required());
|
||||
$vars['field_id'] = $ir->ask('Field ID', '{machine_name}_{field_label|h2m}', new RequiredMachineName());
|
||||
|
||||
$subfield_count_validator = static function (mixed $value): int {
|
||||
if (!(\is_int($value) || \ctype_digit($value)) || (int) $value <= 0) {
|
||||
throw new \UnexpectedValueException('The value should be greater than zero.');
|
||||
}
|
||||
return (int) $value;
|
||||
};
|
||||
|
||||
$vars['subfield_count'] = $ir->ask('How many sub-fields would you like to create?', '3', $subfield_count_validator);
|
||||
|
||||
$type_choices = \array_combine(
|
||||
\array_keys(self::SUB_TYPES),
|
||||
\array_column(self::SUB_TYPES, 'label'),
|
||||
);
|
||||
|
||||
// Indicates that at least one of sub-fields needs Random component.
|
||||
$vars['random'] = FALSE;
|
||||
|
||||
// Indicates that all sub-fields can be rendered inline.
|
||||
$vars['inline'] = TRUE;
|
||||
|
||||
// Indicates that at least one of sub-fields has limited allowed values.
|
||||
$vars['list'] = FALSE;
|
||||
|
||||
// Indicates that at least one of sub-fields is required.
|
||||
$vars['required'] = FALSE;
|
||||
|
||||
// Indicates that at least one of sub-fields is of email type.
|
||||
$vars['email'] = FALSE;
|
||||
|
||||
// Indicates that at least one of sub-fields can be rendered as a link.
|
||||
$vars['link'] = FALSE;
|
||||
|
||||
// Indicates that at least one of sub-fields is of datetime type.
|
||||
$vars['datetime'] = FALSE;
|
||||
|
||||
$vars['type_class'] = '{field_label|camelize}Item';
|
||||
$vars['widget_class'] = '{field_label|camelize}Widget';
|
||||
$vars['formatter_class'] = '{field_label|camelize}DefaultFormatter';
|
||||
|
||||
for ($i = 1; $i <= $vars['subfield_count']; $i++) {
|
||||
$this->io()->writeln(\sprintf('<fg=green>%s</>', \str_repeat('–', 50)));
|
||||
|
||||
$subfield = new \stdClass();
|
||||
|
||||
$subfield->name = $ir->ask("Label for sub-field #$i", "Value $i");
|
||||
$subfield->machineName = $ir->ask(
|
||||
"Machine name for sub-field #$i",
|
||||
Utils::human2machine($subfield->name),
|
||||
new RequiredMachineName(),
|
||||
);
|
||||
/** @var string $type */
|
||||
$type = $ir->choice("Type of sub-field #$i", $type_choices, 'Text');
|
||||
|
||||
$subfield->dateType = $type === 'datetime' ?
|
||||
$ir->choice("Date type for sub-field #$i", self::DATE_TYPES, 'Date only') : NULL;
|
||||
|
||||
$definition = self::SUB_TYPES[$type];
|
||||
if ($definition['list']) {
|
||||
$subfield->list = $ir->confirm("Limit allowed values for sub-field #$i?", FALSE);
|
||||
}
|
||||
$subfield->required = $ir->confirm("Make sub-field #$i required?", FALSE);
|
||||
|
||||
// Build sub-field vars.
|
||||
$vars['subfields'][$i] = [
|
||||
'name' => $subfield->name,
|
||||
'machine_name' => $subfield->machineName,
|
||||
'type' => $type,
|
||||
'data_type' => $definition['data_type'],
|
||||
'list' => $subfield->list ?? FALSE,
|
||||
'allowed_values_method' => 'allowed' . Utils::camelize($subfield->name, TRUE) . 'Values',
|
||||
'required' => $subfield->required,
|
||||
'link' => $definition['link'],
|
||||
];
|
||||
if ($subfield->dateType) {
|
||||
$vars['subfields'][$i]['date_type'] = $subfield->dateType;
|
||||
// Back to date type ID.
|
||||
$vars['subfields'][$i]['date_storage_format'] = $subfield->dateType === 'date' ? 'Y-m-d' : 'Y-m-d\TH:i:s';
|
||||
}
|
||||
|
||||
if ($definition['random']) {
|
||||
$vars['random'] = TRUE;
|
||||
}
|
||||
|
||||
if (!$definition['inline']) {
|
||||
$vars['inline'] = FALSE;
|
||||
}
|
||||
|
||||
if ($vars['subfields'][$i]['list']) {
|
||||
$vars['list'] = TRUE;
|
||||
}
|
||||
|
||||
if ($vars['subfields'][$i]['required']) {
|
||||
$vars['required'] = TRUE;
|
||||
}
|
||||
|
||||
if ($type === 'email') {
|
||||
$vars['email'] = TRUE;
|
||||
}
|
||||
|
||||
if ($definition['link']) {
|
||||
$vars['link'] = TRUE;
|
||||
}
|
||||
|
||||
if ($type === 'datetime') {
|
||||
$vars['datetime'] = TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->io()->writeln(\sprintf('<fg=green>%s</>', \str_repeat('–', 50)));
|
||||
|
||||
$vars['storage_settings'] = $ir->confirm('Would you like to create field storage settings form?', FALSE);
|
||||
$vars['instance_settings'] = $ir->confirm('Would you like to create field instance settings form?', FALSE);
|
||||
$vars['widget_settings'] = $ir->confirm('Would you like to create field widget settings form?', FALSE);
|
||||
$vars['formatter_settings'] = $ir->confirm('Would you like to create field formatter settings form?', FALSE);
|
||||
$vars['table_formatter'] = $ir->confirm('Would you like to create table formatter?', FALSE);
|
||||
$vars['key_value_formatter'] = $ir->confirm('Would you like to create key-value formatter?', FALSE);
|
||||
|
||||
$assets->addFile('src/Plugin/Field/FieldType/{type_class}.php', 'type.twig');
|
||||
|
||||
$assets->addFile('src/Plugin/Field/FieldWidget/{widget_class}.php', 'widget.twig');
|
||||
|
||||
$assets->addFile('src/Plugin/Field/FieldFormatter/{formatter_class}.php', 'default-formatter.twig');
|
||||
|
||||
$assets->addSchemaFile()->template('schema.twig');
|
||||
|
||||
$assets->addFile('{machine_name}.libraries.yml', 'libraries.twig')
|
||||
->appendIfExists();
|
||||
|
||||
$assets->addFile('css/{field_id|u2h}-widget.css', 'widget-css.twig');
|
||||
|
||||
if ($vars['table_formatter']) {
|
||||
$vars['table_formatter_class'] = '{field_label|camelize}TableFormatter';
|
||||
$assets->addFile('src/Plugin/Field/FieldFormatter/{table_formatter_class}.php', '/table-formatter.twig');
|
||||
}
|
||||
|
||||
if ($vars['key_value_formatter']) {
|
||||
$vars['key_value_formatter_class'] = '{field_label|camelize}KeyValueFormatter';
|
||||
$assets->addFile('src/Plugin/Field/FieldFormatter/{key_value_formatter_class}.php', 'key-value-formatter.twig');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
72
vendor/chi-teck/drupal-code-generator/src/Command/Form/Config.php
vendored
Normal file
72
vendor/chi-teck/drupal-code-generator/src/Command/Form/Config.php
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Form;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
|
||||
/**
|
||||
* Config form generator.
|
||||
*
|
||||
* @todo Clean-up.
|
||||
*/
|
||||
#[Generator(
|
||||
name: 'form:config',
|
||||
description: 'Generates a configuration form',
|
||||
aliases: ['config-form'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Form/_config',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Config extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
|
||||
$ir = $this->createInterviewer($vars);
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
|
||||
$vars['class'] = $ir->askClass(default: 'SettingsForm');
|
||||
$vars['raw_form_id'] = \preg_replace('/_form/', '', Utils::camel2machine($vars['class']));
|
||||
$vars['form_id'] = '{machine_name}_{raw_form_id}';
|
||||
|
||||
$vars['route'] = $ir->confirm('Would you like to create a route for this form?');
|
||||
if ($vars['route']) {
|
||||
$default_route_path = \str_replace('_', '-', '/admin/config/system/' . $vars['raw_form_id']);
|
||||
$vars['route_name'] = $ir->ask('Route name', '{machine_name}.' . $vars['raw_form_id']);
|
||||
$vars['route_path'] = $ir->ask('Route path', $default_route_path);
|
||||
$vars['route_title'] = $ir->ask('Route title', '{raw_form_id|m2h}');
|
||||
$vars['route_permission'] = $ir->askPermission('Route permission', 'administer site configuration');
|
||||
|
||||
$assets->addFile('{machine_name}.routing.yml')
|
||||
->template('routing.twig')
|
||||
->appendIfExists();
|
||||
|
||||
if ($vars['link'] = $ir->confirm('Would you like to create a menu link for this route?')) {
|
||||
|
||||
$vars['link_title'] = $ir->ask('Link title', $vars['route_title']);
|
||||
$vars['link_description'] = $ir->ask('Link description');
|
||||
// Try to guess parent menu item using route path.
|
||||
if (\preg_match('#^/admin/config/([^/]+)/[^/]+$#', $vars['route_path'], $matches)) {
|
||||
$vars['link_parent'] = $ir->ask('Parent menu item', 'system.admin_config_' . $matches[1]);
|
||||
}
|
||||
|
||||
$assets->addFile('{machine_name}.links.menu.yml')
|
||||
->template('links.menu.twig')
|
||||
->appendIfExists();
|
||||
}
|
||||
}
|
||||
|
||||
$assets->addFile('src/Form/{class}.php', 'form.twig');
|
||||
$assets->addSchemaFile()->template('schema.twig');
|
||||
}
|
||||
|
||||
}
|
||||
56
vendor/chi-teck/drupal-code-generator/src/Command/Form/Confirm.php
vendored
Normal file
56
vendor/chi-teck/drupal-code-generator/src/Command/Form/Confirm.php
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Form;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
|
||||
/**
|
||||
* Confirm form generator.
|
||||
*
|
||||
* @todo Clean-up.
|
||||
*/
|
||||
#[Generator(
|
||||
name: 'form:confirm',
|
||||
description: 'Generates a confirmation form',
|
||||
aliases: ['confirm-form'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Form/_confirm',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Confirm extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
|
||||
$vars['class'] = $ir->askClass(default: 'ExampleConfirmForm');
|
||||
$vars['raw_form_id'] = \preg_replace('/_form/', '', Utils::camel2machine($vars['class']));
|
||||
$vars['form_id'] = '{machine_name}_{raw_form_id}';
|
||||
|
||||
$vars['route'] = $ir->confirm('Would you like to create a route for this form?');
|
||||
if ($vars['route']) {
|
||||
$default_route_path = \str_replace('_', '-', '/' . $vars['machine_name'] . '/' . $vars['raw_form_id']);
|
||||
$vars['route_name'] = $ir->ask('Route name', '{machine_name}.' . $vars['raw_form_id']);
|
||||
$vars['route_path'] = $ir->ask('Route path', $default_route_path);
|
||||
$vars['route_title'] = $ir->ask('Route title', '{raw_form_id|m2t}');
|
||||
$vars['route_permission'] = $ir->askPermission('Route permission', 'administer site configuration');
|
||||
|
||||
$assets->addFile('{machine_name}.routing.yml')
|
||||
->template('routing.twig')
|
||||
->appendIfExists();
|
||||
}
|
||||
|
||||
$assets->addFile('src/Form/{class}.php', 'form.twig');
|
||||
}
|
||||
|
||||
}
|
||||
53
vendor/chi-teck/drupal-code-generator/src/Command/Form/Simple.php
vendored
Normal file
53
vendor/chi-teck/drupal-code-generator/src/Command/Form/Simple.php
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Form;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
|
||||
/**
|
||||
* A generator for a simple form.
|
||||
*/
|
||||
#[Generator(
|
||||
name: 'form:simple',
|
||||
description: 'Generates simple form',
|
||||
aliases: ['form'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Form/_simple',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Simple extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
|
||||
$vars['class'] = $ir->askClass(default: 'ExampleForm');
|
||||
$vars['raw_form_id'] = Utils::camel2machine(Utils::removeSuffix($vars['class'], 'Form'));
|
||||
$vars['form_id'] = '{machine_name}_{raw_form_id}';
|
||||
|
||||
$vars['route'] = $ir->confirm('Would you like to create a route for this form?');
|
||||
if ($vars['route']) {
|
||||
$vars['route_name'] = $ir->ask('Route name', '{machine_name}.' . $vars['raw_form_id']);
|
||||
$default_route_path = \str_replace('_', '-', '/' . $vars['machine_name'] . '/' . $vars['raw_form_id']);
|
||||
$vars['route_path'] = $ir->ask('Route path', $default_route_path);
|
||||
$vars['route_title'] = $ir->ask('Route title', '{raw_form_id|m2t}');
|
||||
$vars['route_permission'] = $ir->askPermission('Route permission', 'access content');
|
||||
$assets->addFile('{machine_name}.routing.yml')
|
||||
->template('routing.twig')
|
||||
->appendIfExists();
|
||||
}
|
||||
|
||||
$assets->addFile('src/Form/{class}.php', 'form.twig');
|
||||
}
|
||||
|
||||
}
|
||||
52
vendor/chi-teck/drupal-code-generator/src/Command/Hook.php
vendored
Normal file
52
vendor/chi-teck/drupal-code-generator/src/Command/Hook.php
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command;
|
||||
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Validator\Chained;
|
||||
use DrupalCodeGenerator\Validator\Choice;
|
||||
use DrupalCodeGenerator\Validator\Required;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
|
||||
#[Generator(
|
||||
name: 'hook',
|
||||
description: 'Generates a hook',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Hook extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
/** @var \DrupalCodeGenerator\Helper\Drupal\HookInfo $hook_info */
|
||||
$hook_info = $this->getHelper('hook_info');
|
||||
|
||||
$hook_templates = $hook_info->getHookTemplates();
|
||||
$available_hooks = \array_keys($hook_templates);
|
||||
|
||||
$ir = $this->createInterviewer($vars);
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
|
||||
$hook_question = new Question('Hook name');
|
||||
$validator = new Chained(
|
||||
new Required(),
|
||||
new Choice($available_hooks, 'The value is not correct hook name.'),
|
||||
);
|
||||
$hook_question->setValidator($validator);
|
||||
$hook_question->setAutocompleterValues($available_hooks);
|
||||
$vars['hook_name'] = $this->io()->askQuestion($hook_question);
|
||||
|
||||
$vars['file_type'] = $hook_info::getFileType($vars['hook_name']);
|
||||
|
||||
$assets->addFile('{machine_name}.{file_type}')
|
||||
->inlineTemplate($hook_templates[$vars['hook_name']])
|
||||
->appendIfExists(9);
|
||||
}
|
||||
|
||||
}
|
||||
30
vendor/chi-teck/drupal-code-generator/src/Command/InstallFile.php
vendored
Normal file
30
vendor/chi-teck/drupal-code-generator/src/Command/InstallFile.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
|
||||
#[Generator(
|
||||
name: 'install-file',
|
||||
description: 'Generates an install file',
|
||||
templatePath: Application::TEMPLATE_PATH . '/_install-file',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class InstallFile extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
$assets->addFile('{machine_name}.install', 'install.twig');
|
||||
}
|
||||
|
||||
}
|
||||
43
vendor/chi-teck/drupal-code-generator/src/Command/JavaScript.php
vendored
Normal file
43
vendor/chi-teck/drupal-code-generator/src/Command/JavaScript.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
|
||||
#[Generator(
|
||||
name: 'javascript',
|
||||
description: 'Generates Drupal JavaScript file',
|
||||
templatePath: Application::TEMPLATE_PATH . '/_javascript',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class JavaScript extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
|
||||
$vars['file_name_full'] = $ir->ask('File name', '{machine_name|u2h}.js');
|
||||
$vars['file_name'] = \pathinfo($vars['file_name_full'], \PATHINFO_FILENAME);
|
||||
$vars['behavior'] = Utils::camelize($vars['machine_name'], FALSE) . Utils::camelize($vars['file_name']);
|
||||
|
||||
if ($ir->confirm('Would you like to create a library for this file?')) {
|
||||
$vars['library'] = $ir->ask('Library name', '{file_name|h2u}');
|
||||
$assets->addFile('{machine_name}.libraries.yml', 'libraries.twig')
|
||||
->appendIfExists();
|
||||
}
|
||||
|
||||
$assets->addFile('js/{file_name_full}', 'javascript.twig');
|
||||
}
|
||||
|
||||
}
|
||||
17
vendor/chi-teck/drupal-code-generator/src/Command/LabelInterface.php
vendored
Normal file
17
vendor/chi-teck/drupal-code-generator/src/Command/LabelInterface.php
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command;
|
||||
|
||||
/**
|
||||
* Interface for generators that provide human-readable label.
|
||||
*/
|
||||
interface LabelInterface {
|
||||
|
||||
/**
|
||||
* Returns the human-readable command label.
|
||||
*/
|
||||
public function getLabel(): ?string;
|
||||
|
||||
}
|
||||
53
vendor/chi-teck/drupal-code-generator/src/Command/Layout.php
vendored
Normal file
53
vendor/chi-teck/drupal-code-generator/src/Command/Layout.php
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
|
||||
#[Generator(
|
||||
name: 'layout',
|
||||
description: 'Generates a layout',
|
||||
templatePath: Application::TEMPLATE_PATH . '/_layout',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Layout extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
|
||||
$vars['layout_name'] = $ir->ask('Layout name', 'Example');
|
||||
$vars['layout_machine_name'] = $ir->ask('Layout machine name', '{layout_name|h2m}');
|
||||
$vars['category'] = $ir->ask('Category', '{machine_name|m2h} Layouts');
|
||||
|
||||
$vars['js'] = $ir->confirm('Would you like to create JavaScript file for this layout?', FALSE);
|
||||
$vars['css'] = $ir->confirm('Would you like to create CSS file for this layout?', FALSE);
|
||||
|
||||
$assets->addFile('{machine_name}.layouts.yml', 'layouts.twig')
|
||||
->appendIfExists();
|
||||
|
||||
if ($vars['js'] || $vars['css']) {
|
||||
$assets->addFile('{machine_name}.libraries.yml', 'libraries.twig')
|
||||
->appendIfExists();
|
||||
}
|
||||
|
||||
$vars['layout_asset_name'] = '{layout_machine_name|u2h}';
|
||||
|
||||
$assets->addFile('layouts/{layout_machine_name}/{layout_asset_name}.html.twig', 'template.twig');
|
||||
if ($vars['js']) {
|
||||
$assets->addFile('layouts/{layout_machine_name}/{layout_asset_name}.js', 'javascript.twig');
|
||||
}
|
||||
if ($vars['css']) {
|
||||
$assets->addFile('layouts/{layout_machine_name}/{layout_asset_name}.css', 'styles.twig');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
115
vendor/chi-teck/drupal-code-generator/src/Command/Module.php
vendored
Normal file
115
vendor/chi-teck/drupal-code-generator/src/Command/Module.php
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Extension\Exception\UnknownExtensionException;
|
||||
use Drupal\Core\Extension\ModuleExtensionList;
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Validator\Required;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
#[Generator(
|
||||
name: 'module',
|
||||
description: 'Generates Drupal module',
|
||||
templatePath: Application::TEMPLATE_PATH . '/_module',
|
||||
type: GeneratorType::MODULE,
|
||||
)]
|
||||
final class Module extends BaseGenerator implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly ModuleExtensionList $moduleList,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container): self {
|
||||
return new self($container->get('extension.list.module'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
|
||||
$vars['name'] = $ir->askName();
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
|
||||
$vars['description'] = $ir->ask('Module description', validator: new Required());
|
||||
$vars['package'] = $ir->ask('Package', 'Custom');
|
||||
|
||||
$dependencies = $ir->ask('Dependencies (comma separated)');
|
||||
$vars['dependencies'] = $this->buildDependencies($dependencies);
|
||||
|
||||
$assets->addFile('{machine_name}/{machine_name}.info.yml', 'model.info.yml.twig');
|
||||
|
||||
if ($ir->confirm('Would you like to create module file?', FALSE)) {
|
||||
$assets->addFile('{machine_name}/{machine_name}.module', 'model.module.twig');
|
||||
}
|
||||
|
||||
if ($ir->confirm('Would you like to create install file?', FALSE)) {
|
||||
$assets->addFile('{machine_name}/{machine_name}.install', 'model.install.twig');
|
||||
}
|
||||
|
||||
if ($ir->confirm('Would you like to create README.md file?', FALSE)) {
|
||||
$assets->addFile('{machine_name}/README.md', 'README.md.twig');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds array of dependencies from comma-separated string.
|
||||
*/
|
||||
private function buildDependencies(?string $dependencies_encoded): array {
|
||||
|
||||
$dependencies = $dependencies_encoded ? \explode(',', $dependencies_encoded) : [];
|
||||
|
||||
foreach ($dependencies as &$dependency) {
|
||||
$dependency = \str_replace(' ', '_', \trim(\strtolower($dependency)));
|
||||
// Check if the module name is already prefixed.
|
||||
if (\str_contains($dependency, ':')) {
|
||||
continue;
|
||||
}
|
||||
// Dependencies should be namespaced in the format {project}:{name}.
|
||||
$project = $dependency;
|
||||
try {
|
||||
// The extension list is internal for extending not for instantiating.
|
||||
// @see \Drupal\Core\Extension\ExtensionList
|
||||
/** @psalm-suppress InternalMethod */
|
||||
$package = $this->moduleList->getExtensionInfo($dependency)['package'] ?? NULL;
|
||||
if ($package === 'Core') {
|
||||
$project = 'drupal';
|
||||
}
|
||||
}
|
||||
catch (UnknownExtensionException) {
|
||||
|
||||
}
|
||||
$dependency = $project . ':' . $dependency;
|
||||
}
|
||||
|
||||
$dependency_sorter = static function (string $a, string $b): int {
|
||||
// Core dependencies go first.
|
||||
$a_is_drupal = \str_starts_with($a, 'drupal:');
|
||||
$b_is_drupal = \str_starts_with($b, 'drupal:');
|
||||
if ($a_is_drupal xor $b_is_drupal) {
|
||||
return $a_is_drupal ? -1 : 1;
|
||||
}
|
||||
return $a <=> $b;
|
||||
};
|
||||
\uasort($dependencies, $dependency_sorter);
|
||||
|
||||
return $dependencies;
|
||||
}
|
||||
|
||||
}
|
||||
207
vendor/chi-teck/drupal-code-generator/src/Command/Navigation.php
vendored
Normal file
207
vendor/chi-teck/drupal-code-generator/src/Command/Navigation.php
vendored
Normal file
@ -0,0 +1,207 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command;
|
||||
|
||||
use DrupalCodeGenerator\InputOutput\DefaultOptions;
|
||||
use DrupalCodeGenerator\InputOutput\IOAwareInterface;
|
||||
use DrupalCodeGenerator\InputOutput\IOAwareTrait;
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||
|
||||
/**
|
||||
* Implements navigation command.
|
||||
*/
|
||||
#[AsCommand(name: 'navigation')]
|
||||
final class Navigation extends Command implements IOAwareInterface, LoggerAwareInterface {
|
||||
|
||||
use IOAwareTrait;
|
||||
use LoggerAwareTrait;
|
||||
|
||||
/**
|
||||
* Menu tree.
|
||||
*/
|
||||
private array $menuTree = [];
|
||||
|
||||
/**
|
||||
* Menu labels.
|
||||
*/
|
||||
private array $labels = [
|
||||
'misc:d7' => 'Drupal 7',
|
||||
'yml' => 'Yaml',
|
||||
'misc' => 'Miscellaneous',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function configure(): void {
|
||||
|
||||
// As the navigation is default command the help should be relevant to the
|
||||
// entire DCG application.
|
||||
$help = <<<'EOT'
|
||||
<info>dcg</info> Display navigation
|
||||
<info>dcg plugin:field:widget</info> Run a specific generator
|
||||
<info>dcg list</info> List all available generators
|
||||
|
||||
EOT;
|
||||
|
||||
$this
|
||||
->setName('navigation')
|
||||
->setDescription('Command line code generator')
|
||||
->setHelp($help)
|
||||
->setHidden();
|
||||
DefaultOptions::apply($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSynopsis($short = FALSE): string {
|
||||
return 'dcg [options] <generator>';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function initialize(InputInterface $input, OutputInterface $output): void {
|
||||
parent::initialize($input, $output);
|
||||
|
||||
// Build the menu structure.
|
||||
$this->menuTree = [];
|
||||
if (!$application = $this->getApplication()) {
|
||||
throw new \LogicException('Navigation command cannot work without application');
|
||||
}
|
||||
foreach ($application->all() as $command) {
|
||||
if ($command instanceof LabelInterface && !$command->isHidden()) {
|
||||
/** @var string $command_name */
|
||||
$command_name = $command->getName();
|
||||
self::arraySetNestedValue($this->menuTree, \explode(':', $command_name));
|
||||
// Collect command labels.
|
||||
if ($label = $command->getLabel()) {
|
||||
$this->labels[$command_name] = $label;
|
||||
}
|
||||
}
|
||||
}
|
||||
self::recursiveKsort($this->menuTree);
|
||||
|
||||
$style = new OutputFormatterStyle('white', 'blue', ['bold']);
|
||||
$output->getFormatter()->setStyle('title', $style);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int {
|
||||
if ($command_name = $this->selectGenerator($input, $output)) {
|
||||
if (!$application = $this->getApplication()) {
|
||||
throw new \LogicException('Navigation command cannot work without application');
|
||||
}
|
||||
return $application
|
||||
->find($command_name)
|
||||
->run($input, $output);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects a generator.
|
||||
*
|
||||
* Returns a generator selected by the user from a multilevel console menu or
|
||||
* null if user decided to exit the navigation.
|
||||
*/
|
||||
private function selectGenerator(InputInterface $input, OutputInterface $output, array $menu_trail = []): ?string {
|
||||
|
||||
// Narrow down the menu tree using menu trail.
|
||||
$active_menu_tree = $this->menuTree;
|
||||
foreach ($menu_trail as $active_menu_item) {
|
||||
$active_menu_tree = $active_menu_tree[$active_menu_item];
|
||||
}
|
||||
|
||||
// The $active_menu_tree can be either an array of menu items or TRUE if the
|
||||
// user has reached the final menu point.
|
||||
if ($active_menu_tree === TRUE) {
|
||||
return \implode(':', $menu_trail);
|
||||
}
|
||||
|
||||
$sub_menu_labels = $command_labels = [];
|
||||
foreach ($active_menu_tree as $menu_item => $subtree) {
|
||||
$command_name = $menu_trail ? (\implode(':', $menu_trail) . ':' . $menu_item) : $menu_item;
|
||||
$label = $this->labels[$command_name] ?? \str_replace(['-', '_'], ' ', \ucfirst($menu_item));
|
||||
\is_array($subtree)
|
||||
? $sub_menu_labels[$menu_item] = "<comment>$label</comment>"
|
||||
: $command_labels[$menu_item] = $label;
|
||||
}
|
||||
|
||||
// Generally the choices array consists of the following parts:
|
||||
// - Reference to the parent menu level.
|
||||
// - Sorted list of nested menu levels.
|
||||
// - Sorted list of commands.
|
||||
\natcasesort($sub_menu_labels);
|
||||
\natcasesort($command_labels);
|
||||
$choices = ['..' => '..'] + $sub_menu_labels + $command_labels;
|
||||
$question = new ChoiceQuestion('<title> Select generator </title>', \array_values($choices));
|
||||
|
||||
$answer_label = $this->getHelper('question')->ask($input, $output, $question);
|
||||
$answer = \array_search($answer_label, $choices);
|
||||
|
||||
if ($answer === '..') {
|
||||
// Exit the application if a user selected zero on the top menu level.
|
||||
if (\count($menu_trail) === 0) {
|
||||
return NULL;
|
||||
}
|
||||
// Level up.
|
||||
\array_pop($menu_trail);
|
||||
}
|
||||
else {
|
||||
// Level down.
|
||||
$menu_trail[] = $answer;
|
||||
}
|
||||
|
||||
return $this->selectGenerator($input, $output, $menu_trail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort multidimensional array by keys.
|
||||
*
|
||||
* @param array $array
|
||||
* An array being sorted.
|
||||
*/
|
||||
private static function recursiveKsort(array &$array): void {
|
||||
foreach ($array as &$value) {
|
||||
if (\is_array($value)) {
|
||||
self::recursiveKsort($value);
|
||||
}
|
||||
}
|
||||
\ksort($array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the property to true in nested array.
|
||||
*
|
||||
* @psalm-param list<string> $parents
|
||||
* An array of parent keys, starting with the outermost key.
|
||||
*
|
||||
* @see https://api.drupal.org/api/drupal/includes!common.inc/function/drupal_array_set_nested_value/7
|
||||
*/
|
||||
private static function arraySetNestedValue(array &$array, array $parents): void {
|
||||
$ref = &$array;
|
||||
foreach ($parents as $parent) {
|
||||
if (isset($ref) && !\is_array($ref)) {
|
||||
$ref = [];
|
||||
}
|
||||
// @todo Fix this.
|
||||
/** @psalm-suppress PossiblyNullArrayAccess */
|
||||
$ref = &$ref[$parent];
|
||||
}
|
||||
$ref ??= TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
60
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/ConfigEntityIds.php
vendored
Normal file
60
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/ConfigEntityIds.php
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use Drupal\Core\Config\Entity\ConfigEntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for configuration entity types.
|
||||
*/
|
||||
final class ConfigEntityIds {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly EntityTypeManagerInterface $entityTypeManager,
|
||||
private readonly \Closure $entityInterface,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
$entity_definitions = \array_filter(
|
||||
$this->entityTypeManager->getDefinitions(),
|
||||
static fn (EntityTypeInterface $entity_type): bool => $entity_type instanceof ConfigEntityTypeInterface,
|
||||
);
|
||||
\ksort($entity_definitions);
|
||||
|
||||
$definitions = [];
|
||||
foreach ($entity_definitions as $type => $entity_definition) {
|
||||
/** @psalm-var array<string, string> $ids */
|
||||
$ids = $this->entityTypeManager
|
||||
->getStorage($type)
|
||||
->getQuery()
|
||||
->accessCheck(FALSE)
|
||||
->execute();
|
||||
if (\count($ids) > 0) {
|
||||
$definitions[] = [
|
||||
'type' => $type,
|
||||
'label' => $entity_definition->getLabel(),
|
||||
'class' => Utils::addLeadingSlash($entity_definition->getClass()),
|
||||
'interface' => ($this->entityInterface)($entity_definition),
|
||||
'ids' => \array_values($ids),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return File::create('.phpstorm.meta.php/config_entity_ids.php')
|
||||
->template('config_entity_ids.php.twig')
|
||||
->vars(['definitions' => $definitions]);
|
||||
}
|
||||
|
||||
}
|
||||
31
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Configuration.php
vendored
Normal file
31
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Configuration.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
use DrupalCodeGenerator\Helper\Drupal\ConfigInfo;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for Drupal configuration.
|
||||
*/
|
||||
final class Configuration {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly ConfigInfo $configInfo,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
return File::create('.phpstorm.meta.php/configuration.php')
|
||||
->template('configuration.php.twig')
|
||||
->vars(['configs' => $this->configInfo->getConfigNames()]);
|
||||
}
|
||||
|
||||
}
|
||||
48
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Database.php
vendored
Normal file
48
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Database.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use Drupal\Core\Database\Connection;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for Drupal database.
|
||||
*/
|
||||
final class Database {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly Connection $connection,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
$driver = $this->connection->driver();
|
||||
$tables = [];
|
||||
// @todo Support PostgreSQL.
|
||||
if ($driver === 'mysql') {
|
||||
/** @psalm-suppress PossiblyNullReference */
|
||||
$tables = $this->connection->query('SHOW TABLES')->fetchCol();
|
||||
}
|
||||
elseif ($driver === 'sqlite') {
|
||||
$query = <<< 'SQL'
|
||||
SELECT name
|
||||
FROM sqlite_schema
|
||||
WHERE type ='table' AND name NOT LIKE 'sqlite_%'
|
||||
ORDER BY name
|
||||
SQL;
|
||||
/** @psalm-suppress PossiblyNullReference */
|
||||
$tables = $this->connection->query($query)->fetchCol();
|
||||
}
|
||||
return File::create('.phpstorm.meta.php/database.php')
|
||||
->template('database.php.twig')
|
||||
->vars(['tables' => $tables]);
|
||||
}
|
||||
|
||||
}
|
||||
35
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/DateFormats.php
vendored
Normal file
35
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/DateFormats.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for date formats.
|
||||
*/
|
||||
final class DateFormats {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly EntityTypeManagerInterface $entityTypeManager,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
$date_formats = $this->entityTypeManager
|
||||
->getStorage('date_format')
|
||||
->loadMultiple();
|
||||
$date_formats['custom'] = NULL;
|
||||
return File::create('.phpstorm.meta.php/date_formats.php')
|
||||
->template('date_formats.php.twig')
|
||||
->vars(['date_formats' => \array_keys($date_formats)]);
|
||||
}
|
||||
|
||||
}
|
||||
53
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/EntityBundles.php
vendored
Normal file
53
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/EntityBundles.php
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for entity bundles.
|
||||
*/
|
||||
final class EntityBundles {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly EntityTypeManagerInterface $entityTypeManager,
|
||||
private readonly EntityTypeBundleInfoInterface $entityTypeBundleInfo,
|
||||
private readonly \Closure $entityInterface,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
$definitions = [];
|
||||
$entity_definitions = $this->entityTypeManager->getDefinitions();
|
||||
\ksort($entity_definitions);
|
||||
$bundle_getters = [
|
||||
'node' => 'getType',
|
||||
'comment' => 'getTypeId',
|
||||
];
|
||||
foreach ($entity_definitions as $entity_type_id => $entity_definition) {
|
||||
$definitions[] = [
|
||||
'type' => $entity_type_id,
|
||||
'label' => $entity_definition->getLabel(),
|
||||
'class' => Utils::addLeadingSlash($entity_definition->getClass()),
|
||||
'interface' => ($this->entityInterface)($entity_definition),
|
||||
'bundle_getter' => $bundle_getters[$entity_type_id] ?? NULL,
|
||||
'bundles' => \array_keys($this->entityTypeBundleInfo->getBundleInfo($entity_type_id)),
|
||||
];
|
||||
}
|
||||
|
||||
return File::create('.phpstorm.meta.php/entity_bundles.php')
|
||||
->template('entity_bundles.php.twig')
|
||||
->vars(['definitions' => $definitions]);
|
||||
}
|
||||
|
||||
}
|
||||
45
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/EntityLinks.php
vendored
Normal file
45
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/EntityLinks.php
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for entity links.
|
||||
*/
|
||||
final class EntityLinks {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly EntityTypeManagerInterface $entityTypeManager,
|
||||
private readonly \Closure $entityInterface,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
$definitions = [];
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $entity_type => $definition) {
|
||||
$definitions[] = [
|
||||
'type' => $entity_type,
|
||||
'label' => $definition->getLabel(),
|
||||
'class' => Utils::addLeadingSlash($definition->getClass()),
|
||||
'interface' => ($this->entityInterface)($definition),
|
||||
'links' => \array_keys($definition->getLinkTemplates()),
|
||||
];
|
||||
}
|
||||
\asort($definitions);
|
||||
|
||||
return File::create('.phpstorm.meta.php/entity_links.php')
|
||||
->template('entity_links.php.twig')
|
||||
->vars(['definitions' => $definitions]);
|
||||
}
|
||||
|
||||
}
|
||||
54
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/EntityTypes.php
vendored
Normal file
54
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/EntityTypes.php
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for entity types.
|
||||
*/
|
||||
final class EntityTypes {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly EntityTypeManagerInterface $entityTypeManager,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
$normalized_definitions = [];
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $type => $definition) {
|
||||
$normalized_definitions[$type]['class'] = self::normalizeType($definition->getClass());
|
||||
$normalized_definitions[$type]['storage'] = self::normalizeType($definition->getStorageClass());
|
||||
$normalized_definitions[$type]['access_control'] = self::normalizeType($definition->getAccessControlClass());
|
||||
$normalized_definitions[$type]['list_builder'] = self::normalizeType($definition->getListBuilderClass());
|
||||
$normalized_definitions[$type]['view_builder'] = self::normalizeType($definition->getViewBuilderClass());
|
||||
}
|
||||
\ksort($normalized_definitions);
|
||||
return File::create('.phpstorm.meta.php/entity_types.php')
|
||||
->template('entity_types.php.twig')
|
||||
->vars(['definitions' => $normalized_definitions]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes handler type.
|
||||
*/
|
||||
private static function normalizeType(?string $class): ?string {
|
||||
if ($class === NULL) {
|
||||
return NULL;
|
||||
}
|
||||
$class = Utils::addLeadingSlash($class);
|
||||
/** @psalm-var class-string $interface */
|
||||
$interface = $class . 'Interface';
|
||||
return \is_a($class, $interface, TRUE) ? $interface : $class;
|
||||
}
|
||||
|
||||
}
|
||||
43
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Extensions.php
vendored
Normal file
43
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Extensions.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use Drupal\Core\Extension\Extension;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Extension\ThemeHandlerInterface;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for extensions.
|
||||
*/
|
||||
final class Extensions {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly ModuleHandlerInterface $moduleHandler,
|
||||
private readonly ThemeHandlerInterface $themeHandler,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
// Module handler also manages profiles.
|
||||
$module_extensions = \array_filter(
|
||||
$this->moduleHandler->getModuleList(),
|
||||
static fn (Extension $extension): bool => $extension->getType() === 'module',
|
||||
);
|
||||
$modules = \array_keys($module_extensions);
|
||||
$themes = \array_keys($this->themeHandler->listInfo());
|
||||
\sort($themes);
|
||||
|
||||
return File::create('.phpstorm.meta.php/extensions.php')
|
||||
->template('extensions.php.twig')
|
||||
->vars(['modules' => $modules, 'themes' => $themes]);
|
||||
}
|
||||
|
||||
}
|
||||
38
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/FieldDefinitions.php
vendored
Normal file
38
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/FieldDefinitions.php
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Field\FieldTypePluginManagerInterface;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for field definitions.
|
||||
*/
|
||||
final class FieldDefinitions {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly EntityTypeManagerInterface $entityTypeManager,
|
||||
private readonly FieldTypePluginManagerInterface $fieldTypePluginManager,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
$entity_types = \array_keys($this->entityTypeManager->getDefinitions());
|
||||
\sort($entity_types);
|
||||
$field_types = \array_keys($this->fieldTypePluginManager->getDefinitions());
|
||||
\sort($field_types);
|
||||
|
||||
return File::create('.phpstorm.meta.php/field_definitions.php')
|
||||
->template('field_definitions.php.twig')
|
||||
->vars(['entity_types' => $entity_types, 'field_types' => $field_types]);
|
||||
}
|
||||
|
||||
}
|
||||
50
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Fields.php
vendored
Normal file
50
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Fields.php
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use Drupal\Core\Entity\EntityFieldManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Entity\FieldableEntityInterface;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for entity fields.
|
||||
*/
|
||||
final class Fields {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly EntityTypeManagerInterface $entityTypeManager,
|
||||
private readonly EntityFieldManagerInterface $entityFieldManager,
|
||||
private readonly \Closure $entityInterface,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
$definitions = [];
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $entity_type => $definition) {
|
||||
if (!$definition->entityClassImplements(FieldableEntityInterface::class)) {
|
||||
continue;
|
||||
}
|
||||
$definitions[] = [
|
||||
'type' => $entity_type,
|
||||
'label' => $definition->getLabel(),
|
||||
'class' => Utils::addLeadingSlash($definition->getClass()),
|
||||
'interface' => ($this->entityInterface)($definition),
|
||||
'fields' => \array_keys($this->entityFieldManager->getFieldStorageDefinitions($entity_type)),
|
||||
];
|
||||
}
|
||||
|
||||
return File::create('.phpstorm.meta.php/fields.php')
|
||||
->template('fields.php.twig')
|
||||
->vars(['definitions' => $definitions]);
|
||||
}
|
||||
|
||||
}
|
||||
22
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/FileSystem.php
vendored
Normal file
22
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/FileSystem.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for Drupal filesystem helpers.
|
||||
*/
|
||||
final class FileSystem {
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
return File::create('.phpstorm.meta.php/file_system.php')
|
||||
->template('file_system.php.twig');
|
||||
}
|
||||
|
||||
}
|
||||
35
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Hooks.php
vendored
Normal file
35
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Hooks.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
use DrupalCodeGenerator\Helper\Drupal\HookInfo;
|
||||
use DrupalCodeGenerator\Helper\Drupal\ModuleInfo;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for Drupal hooks.
|
||||
*/
|
||||
final class Hooks {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly HookInfo $hookInfo,
|
||||
private readonly ModuleInfo $moduleInfo,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
$hooks = \array_keys($this->hookInfo->getHookTemplates());
|
||||
$modules = \array_keys($this->moduleInfo->getExtensions());
|
||||
return File::create('.phpstorm.meta.php/hooks.php')
|
||||
->template('hooks.php.twig')
|
||||
->vars(['hooks' => $hooks, 'modules' => $modules]);
|
||||
}
|
||||
|
||||
}
|
||||
22
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Miscellaneous.php
vendored
Normal file
22
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Miscellaneous.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for miscellaneous Drupal methods.
|
||||
*/
|
||||
final class Miscellaneous {
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
return File::create('.phpstorm.meta.php/miscellaneous.php')
|
||||
->template('miscellaneous.php.twig');
|
||||
}
|
||||
|
||||
}
|
||||
32
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Permissions.php
vendored
Normal file
32
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Permissions.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
use DrupalCodeGenerator\Helper\Drupal\PermissionInfo;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for permissions.
|
||||
*/
|
||||
final class Permissions {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly PermissionInfo $permissionInfo,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
$permissions = $this->permissionInfo->getPermissionNames();
|
||||
return File::create('.phpstorm.meta.php/permissions.php')
|
||||
->template('permissions.php.twig')
|
||||
->vars(['permissions' => $permissions]);
|
||||
}
|
||||
|
||||
}
|
||||
94
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/PhpStormMeta.php
vendored
Normal file
94
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/PhpStormMeta.php
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection as Assets;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
#[Generator(
|
||||
name: 'phpstorm-meta',
|
||||
description: 'Generates PhpStorm metadata',
|
||||
templatePath: Application::TEMPLATE_PATH . '/_phpstorm-meta',
|
||||
type: GeneratorType::OTHER,
|
||||
label: 'PhpStorm metadata',
|
||||
)]
|
||||
final class PhpStormMeta extends BaseGenerator implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly ContainerInterface $container,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container): self {
|
||||
return new self($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @noinspection PhpParamsInspection
|
||||
* @psalm-suppress ArgumentTypeCoercion
|
||||
*/
|
||||
protected function generate(array &$vars, Assets $assets): void {
|
||||
|
||||
$service = fn (string $name): object => $this->container->get($name);
|
||||
|
||||
$entity_interface = static function (EntityTypeInterface $definition): ?string {
|
||||
$class = Utils::addLeadingSlash($definition->getClass());
|
||||
// Most content entity types implement an interface which name follows
|
||||
// this pattern.
|
||||
$interface = \str_replace('\Entity\\', '\\', $class) . 'Interface';
|
||||
return $definition->entityClassImplements($interface) ? $interface : NULL;
|
||||
};
|
||||
|
||||
$assets[] = (new ConfigEntityIds($service('entity_type.manager'), $entity_interface))();
|
||||
$assets[] = (new Configuration($this->getHelper('config_info')))();
|
||||
$assets[] = (new Database($service('database')))();
|
||||
$assets[] = (new DateFormats($service('entity_type.manager')))();
|
||||
$assets[] = (new EntityBundles($service('entity_type.manager'), $service('entity_type.bundle.info'), $entity_interface))();
|
||||
$assets[] = (new EntityLinks($service('entity_type.manager'), $entity_interface))();
|
||||
$assets[] = (new EntityTypes($service('entity_type.manager')))();
|
||||
$assets[] = (new Extensions($service('module_handler'), $service('theme_handler')))();
|
||||
$assets[] = (new FieldDefinitions($service('entity_type.manager'), $service('plugin.manager.field.field_type')))();
|
||||
$assets[] = (new Fields($service('entity_type.manager'), $service('entity_field.manager'), $entity_interface))();
|
||||
$assets[] = (new FileSystem())();
|
||||
$assets[] = (new Hooks($this->getHelper('hook_info'), $this->getHelper('module_info')))();
|
||||
$assets[] = (new Miscellaneous())();
|
||||
$assets[] = (new Permissions($this->getHelper('permission_info')))();
|
||||
$assets[] = (new Plugins($this->getHelper('service_info')))();
|
||||
$assets[] = (new Roles($service('entity_type.manager')))();
|
||||
$assets[] = (new Routes($this->getHelper('route_info')))();
|
||||
$assets[] = (new Services($this->getHelper('service_info')))();
|
||||
$assets[] = (new Settings())();
|
||||
$assets[] = (new States($service('keyvalue'), $service('cron')))();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getDestination(array $vars): string {
|
||||
// Typically the root of the PhpStorm project is one level above of the
|
||||
// Drupal root.
|
||||
if (!\file_exists(\DRUPAL_ROOT . '/.idea') && \file_exists(\DRUPAL_ROOT . '/../.idea')) {
|
||||
return \DRUPAL_ROOT . '/..';
|
||||
}
|
||||
return \DRUPAL_ROOT;
|
||||
}
|
||||
|
||||
}
|
||||
68
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Plugins.php
vendored
Normal file
68
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Plugins.php
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use Drupal\Core\Plugin\DefaultPluginManager;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
use DrupalCodeGenerator\Helper\Drupal\ServiceInfo;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for plugins.
|
||||
*/
|
||||
final class Plugins {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly ServiceInfo $serviceInfo,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
$plugins = [];
|
||||
foreach ($this->serviceInfo->getServiceClasses() as $manager_id => $class) {
|
||||
/** @var class-string $class */
|
||||
if (!\is_subclass_of($class, DefaultPluginManager::class)) {
|
||||
continue;
|
||||
}
|
||||
/** @var \Drupal\Core\Plugin\DefaultPluginManager $manager */
|
||||
$manager = $this->serviceInfo->getService($manager_id);
|
||||
|
||||
$guessed_interface = $class . 'Interface';
|
||||
$interface = $manager instanceof $guessed_interface
|
||||
? $guessed_interface : NULL;
|
||||
|
||||
$plugin_ids = \array_keys($manager->getDefinitions());
|
||||
\sort($plugin_ids);
|
||||
|
||||
$plugins[] = [
|
||||
'manager_id' => $manager_id,
|
||||
'manager_class' => $class,
|
||||
'manager_interface' => $interface,
|
||||
'plugin_interface' => self::getPluginInterface($manager),
|
||||
'plugin_ids' => $plugin_ids,
|
||||
];
|
||||
}
|
||||
|
||||
return File::create('.phpstorm.meta.php/plugins.php')
|
||||
->template('plugins.php.twig')
|
||||
->vars(['plugins' => $plugins]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for protected 'pluginInterface' property.
|
||||
*/
|
||||
private static function getPluginInterface(DefaultPluginManager $manager): ?string {
|
||||
$interface = (new \ReflectionClass($manager))
|
||||
->getProperty('pluginInterface')
|
||||
->getValue($manager);
|
||||
return $interface ? Utils::addLeadingSlash($interface) : NULL;
|
||||
}
|
||||
|
||||
}
|
||||
33
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Roles.php
vendored
Normal file
33
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Roles.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for roles.
|
||||
*/
|
||||
final class Roles {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly EntityTypeManagerInterface $entityTypeManager,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
// @todo Create a helper for roles.
|
||||
$roles = $this->entityTypeManager->getStorage('user_role')->loadMultiple();
|
||||
return File::create('.phpstorm.meta.php/roles.php')
|
||||
->template('roles.php.twig')
|
||||
->vars(['roles' => \array_keys($roles)]);
|
||||
}
|
||||
|
||||
}
|
||||
60
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Routes.php
vendored
Normal file
60
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Routes.php
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
use DrupalCodeGenerator\Helper\Drupal\RouteInfo;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for routes.
|
||||
*/
|
||||
final class Routes {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly RouteInfo $routeInfo,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
$routes = $this->routeInfo->getRouteNames();
|
||||
$route_attributes = $this->getRouteAttributes();
|
||||
return File::create('.phpstorm.meta.php/routes.php')
|
||||
->template('routes.php.twig')
|
||||
->vars(['routes' => $routes, 'route_attributes' => $route_attributes]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds attributes suitable for Route autocompletion.
|
||||
*/
|
||||
private function getRouteAttributes(): array {
|
||||
|
||||
/** @psalm-var array{options: array, requirements: array, defaults: array} $route_attributes */
|
||||
$route_attributes = [
|
||||
'options' => [],
|
||||
'requirements' => [],
|
||||
'defaults' => [],
|
||||
];
|
||||
|
||||
foreach ($this->routeInfo->getRoutes() as $route) {
|
||||
$route_attributes['options'] += $route->getOptions();
|
||||
$route_attributes['requirements'] += $route->getRequirements();
|
||||
$route_attributes['defaults'] += $route->getDefaults();
|
||||
}
|
||||
|
||||
$is_internal = static fn (string $option_name): bool => \str_starts_with($option_name, '_');
|
||||
foreach ($route_attributes as $name => $attributes) {
|
||||
$route_attributes[$name] = \array_filter(\array_keys($route_attributes[$name]), $is_internal);
|
||||
\sort($route_attributes[$name]);
|
||||
}
|
||||
|
||||
return $route_attributes;
|
||||
}
|
||||
|
||||
}
|
||||
31
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Services.php
vendored
Normal file
31
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Services.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
use DrupalCodeGenerator\Helper\Drupal\ServiceInfo;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for services.
|
||||
*/
|
||||
final class Services {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly ServiceInfo $serviceInfo,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
return File::create('.phpstorm.meta.php/services.php')
|
||||
->template('services.php.twig')
|
||||
->vars(['services' => $this->serviceInfo->getServiceClasses()]);
|
||||
}
|
||||
|
||||
}
|
||||
24
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Settings.php
vendored
Normal file
24
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/Settings.php
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use Drupal\Core\Site\Settings as DrupalSettings;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for Drupal settings.
|
||||
*/
|
||||
final class Settings {
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
return File::create('.phpstorm.meta.php/settings.php')
|
||||
->template('settings.php.twig')
|
||||
->vars(['settings' => \array_keys(DrupalSettings::getAll())]);
|
||||
}
|
||||
|
||||
}
|
||||
35
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/States.php
vendored
Normal file
35
vendor/chi-teck/drupal-code-generator/src/Command/PhpStormMeta/States.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\PhpStormMeta;
|
||||
|
||||
use Drupal\Core\CronInterface;
|
||||
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
|
||||
use DrupalCodeGenerator\Asset\File;
|
||||
|
||||
/**
|
||||
* Generates PhpStorm meta-data for Drupal states.
|
||||
*/
|
||||
final class States {
|
||||
|
||||
/**
|
||||
* Constructs the object.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly KeyValueFactoryInterface $keyValueStore,
|
||||
private readonly CronInterface $cron,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generator callback.
|
||||
*/
|
||||
public function __invoke(): File {
|
||||
$this->cron->run();
|
||||
$states = \array_keys($this->keyValueStore->get('state')->getAll());
|
||||
return File::create('.phpstorm.meta.php/states.php')
|
||||
->template('states.php.twig')
|
||||
->vars(['states' => $states]);
|
||||
}
|
||||
|
||||
}
|
||||
78
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Action.php
vendored
Normal file
78
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Action.php
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Plugin;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Entity\ContentEntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Validator\RequiredMachineName;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
#[Generator(
|
||||
name: 'plugin:action',
|
||||
description: 'Generates action plugin',
|
||||
aliases: ['action'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Plugin/_action',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Action extends BaseGenerator implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly EntityTypeManagerInterface $entityTypeManager,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container): self {
|
||||
return new self($container->get('entity_type.manager'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['plugin_label'] = $ir->askPluginLabel('Action label');
|
||||
$vars['plugin_id'] = $ir->askPluginId();
|
||||
$vars['class'] = $ir->askPluginClass();
|
||||
|
||||
$vars['category'] = $ir->ask('Action category', 'Custom');
|
||||
|
||||
// @todo Create a helper for this.
|
||||
$definitions = \array_filter(
|
||||
$this->entityTypeManager->getDefinitions(),
|
||||
static fn (EntityTypeInterface $definition): bool => $definition instanceof ContentEntityTypeInterface,
|
||||
);
|
||||
$entity_type_question = new Question('Entity type to apply the action', 'node');
|
||||
$entity_type_question->setValidator(new RequiredMachineName());
|
||||
$entity_type_question->setAutocompleterValues(\array_keys($definitions));
|
||||
$vars['entity_type'] = $this->io()->askQuestion($entity_type_question);
|
||||
|
||||
$vars['configurable'] = $ir->confirm('Make the action configurable?', FALSE);
|
||||
$vars['services'] = $ir->askServices(FALSE);
|
||||
|
||||
$assets->addFile('src/Plugin/Action/{class}.php', 'action.twig');
|
||||
|
||||
if ($vars['configurable']) {
|
||||
$assets->addSchemaFile()->template('schema.twig');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
46
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Block.php
vendored
Normal file
46
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Block.php
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Plugin;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection as Assets;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
|
||||
#[Generator(
|
||||
name: 'plugin:block',
|
||||
description: 'Generates block plugin',
|
||||
aliases: ['block'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Plugin/_block',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Block extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, Assets $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
|
||||
$vars['plugin_label'] = $ir->askPluginLabel('Block admin label');
|
||||
$vars['plugin_id'] = $ir->askPluginId();
|
||||
$vars['class'] = $ir->askPluginClass(suffix: 'Block');
|
||||
|
||||
$vars['category'] = $ir->ask('Block category', 'Custom');
|
||||
$vars['configurable'] = $ir->confirm('Make the block configurable?', FALSE);
|
||||
$vars['services'] = $ir->askServices(FALSE);
|
||||
|
||||
$vars['access'] = $ir->confirm('Create access callback?', FALSE);
|
||||
|
||||
$assets->addFile('src/Plugin/Block/{class}.php', 'block.twig');
|
||||
if ($vars['configurable']) {
|
||||
$assets->addSchemaFile()->template('schema.twig');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
36
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Condition.php
vendored
Normal file
36
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Condition.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Plugin;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\Assets;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
|
||||
#[Generator(
|
||||
name: 'plugin:condition',
|
||||
description: 'Generates condition plugin',
|
||||
aliases: ['condition'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Plugin/_condition',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Condition extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, Assets $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['plugin_label'] = $ir->askPluginLabel();
|
||||
$vars['plugin_id'] = $ir->askPluginId();
|
||||
$vars['class'] = $ir->askPluginClass();
|
||||
$vars['services'] = $ir->askServices(FALSE);
|
||||
$assets->addFile('src/Plugin/Condition/{class}.php', 'condition.twig');
|
||||
$assets->addSchemaFile()->template('schema.twig');
|
||||
}
|
||||
|
||||
}
|
||||
66
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Constraint.php
vendored
Normal file
66
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Constraint.php
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Plugin;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\Assets;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Utils;
|
||||
use DrupalCodeGenerator\Validator\Chained;
|
||||
use DrupalCodeGenerator\Validator\RegExp;
|
||||
use DrupalCodeGenerator\Validator\Required;
|
||||
|
||||
/**
|
||||
* Constraint generator.
|
||||
*
|
||||
* @todo Clean-up.
|
||||
* @todo Create SUT test.
|
||||
*/
|
||||
#[Generator(
|
||||
name: 'plugin:constraint',
|
||||
description: 'Generates constraint plugin',
|
||||
aliases: ['constraint'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Plugin/_constraint',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Constraint extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, Assets $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
$vars['plugin_label'] = $ir->askPluginLabel();
|
||||
// Unlike other plugin types, constraint IDs use camel case.
|
||||
$validator = new Chained(
|
||||
new Required(),
|
||||
new RegExp('/^[a-z][a-z0-9_]*[a-z0-9]$/i', 'The value is not correct constraint ID.'),
|
||||
);
|
||||
$vars['plugin_id'] = $ir->ask('Plugin ID', '{name|camelize}{plugin_label|camelize}', $validator);
|
||||
$unprefixed_plugin_id = Utils::removePrefix($vars['plugin_id'], Utils::camelize($vars['machine_name']));
|
||||
$vars['class'] = $ir->askPluginClass(default: $unprefixed_plugin_id . 'Constraint');
|
||||
|
||||
$input_types = [
|
||||
'raw_value' => 'Raw value',
|
||||
'item' => 'Item',
|
||||
'item_list' => 'Item list',
|
||||
'entity' => 'Entity',
|
||||
];
|
||||
$vars['input_type'] = $ir->choice('Type of data to validate', $input_types);
|
||||
|
||||
$vars['services'] = $ir->askServices(FALSE);
|
||||
|
||||
$assets->addFile('src/Plugin/Validation/Constraint/{class}.php')
|
||||
->template('constraint.twig');
|
||||
|
||||
$assets->addFile('src/Plugin/Validation/Constraint/{class}Validator.php')
|
||||
->template('validator.twig');
|
||||
}
|
||||
|
||||
}
|
||||
86
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/EntityReferenceSelection.php
vendored
Normal file
86
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/EntityReferenceSelection.php
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Plugin;
|
||||
|
||||
use Drupal\comment\Plugin\EntityReferenceSelection\CommentSelection;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection;
|
||||
use Drupal\file\Plugin\EntityReferenceSelection\FileSelection;
|
||||
use Drupal\node\Plugin\EntityReferenceSelection\NodeSelection;
|
||||
use Drupal\taxonomy\Plugin\EntityReferenceSelection\TermSelection;
|
||||
use Drupal\user\Plugin\EntityReferenceSelection\UserSelection;
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\Assets;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
use DrupalCodeGenerator\Validator\RequiredMachineName;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
#[Generator(
|
||||
name: 'plugin:entity-reference-selection',
|
||||
description: 'Generates entity reference selection plugin',
|
||||
aliases: ['entity-reference-selection'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Plugin/_entity-reference-selection',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class EntityReferenceSelection extends BaseGenerator implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly EntityTypeManagerInterface $entityTypeManager,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container): self {
|
||||
return new self($container->get('entity_type.manager'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, Assets $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
|
||||
$entity_type_question = new Question('Entity type that can be referenced by this plugin', 'node');
|
||||
$entity_type_question->setValidator(new RequiredMachineName());
|
||||
$entity_types = \array_keys($this->entityTypeManager->getDefinitions());
|
||||
$entity_type_question->setAutocompleterValues($entity_types);
|
||||
$vars['entity_type'] = $this->io()->askQuestion($entity_type_question);
|
||||
|
||||
$vars['plugin_label'] = $ir->askPluginLabel('Plugin label', 'Advanced {entity_type} selection');
|
||||
$vars['plugin_id'] = $ir->askPluginId(default: '{machine_name}_{entity_type}_selection');
|
||||
|
||||
$vars['class'] = $ir->askPluginClass(default: '{entity_type|camelize}Selection');
|
||||
|
||||
$vars['configurable'] = $ir->confirm('Provide additional plugin configuration?', FALSE);
|
||||
|
||||
$vars['base_class_full'] = match($vars['entity_type']) {
|
||||
'comment' => CommentSelection::class,
|
||||
'file' => FileSelection::class,
|
||||
'node' => NodeSelection::class,
|
||||
'taxonomy_term' => TermSelection::class,
|
||||
'user' => UserSelection::class,
|
||||
default => DefaultSelection::class,
|
||||
};
|
||||
|
||||
$vars['base_class'] = \explode('EntityReferenceSelection\\', $vars['base_class_full'])[1];
|
||||
|
||||
$assets->addFile('src/Plugin/EntityReferenceSelection/{class}.php')
|
||||
->template('entity-reference-selection.twig');
|
||||
$assets->addSchemaFile()->template('schema.twig');
|
||||
}
|
||||
|
||||
}
|
||||
40
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Field/Formatter.php
vendored
Normal file
40
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Field/Formatter.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Plugin\Field;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
|
||||
#[Generator(
|
||||
name: 'plugin:field:formatter',
|
||||
description: 'Generates field formatter plugin',
|
||||
aliases: ['field-formatter'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Plugin/Field/_formatter',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Formatter extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['plugin_label'] = $ir->askPluginLabel();
|
||||
$vars['plugin_id'] = $ir->askPluginId();
|
||||
$vars['class'] = $ir->askPluginClass(suffix: 'Formatter');
|
||||
|
||||
$vars['configurable'] = $ir->confirm('Make the formatter configurable?', FALSE);
|
||||
$assets->addFile('src/Plugin/Field/FieldFormatter/{class}.php', 'formatter.twig');
|
||||
if ($vars['configurable']) {
|
||||
$assets->addSchemaFile()->template('schema.twig');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
39
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Field/Type.php
vendored
Normal file
39
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Field/Type.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Plugin\Field;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
|
||||
#[Generator(
|
||||
name: 'plugin:field:type',
|
||||
description: 'Generates field type plugin',
|
||||
aliases: ['field-type'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Plugin/Field/_type',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Type extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['plugin_label'] = $ir->askPluginLabel();
|
||||
$vars['plugin_id'] = $ir->askPluginId();
|
||||
$vars['class'] = $ir->askPluginClass(suffix: 'Item');
|
||||
|
||||
$vars['configurable_storage'] = $ir->confirm('Make the field storage configurable?', FALSE);
|
||||
$vars['configurable_instance'] = $ir->confirm('Make the field instance configurable?', FALSE);
|
||||
$assets->addFile('src/Plugin/Field/FieldType/{class}.php', 'type.twig');
|
||||
$assets->addSchemaFile()->template('schema.twig');
|
||||
}
|
||||
|
||||
}
|
||||
41
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Field/Widget.php
vendored
Normal file
41
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Field/Widget.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Plugin\Field;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
|
||||
#[Generator(
|
||||
name: 'plugin:field:widget',
|
||||
description: 'Generates field widget plugin',
|
||||
aliases: ['field-widget'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Plugin/Field/_widget',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Widget extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['plugin_label'] = $ir->askPluginLabel();
|
||||
$vars['plugin_id'] = $ir->askPluginId();
|
||||
$vars['class'] = $ir->askPluginClass(suffix: 'Widget');
|
||||
$vars['configurable'] = $ir->confirm('Make the widget configurable?', FALSE);
|
||||
$vars['services'] = $ir->askServices(FALSE);
|
||||
|
||||
$assets->addFile('src/Plugin/Field/FieldWidget/{class}.php', 'widget.twig');
|
||||
if ($vars['configurable']) {
|
||||
$assets->addSchemaFile()->template('schema.twig');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
51
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Filter.php
vendored
Normal file
51
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Filter.php
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Plugin;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\Assets;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
|
||||
#[Generator(
|
||||
name: 'plugin:filter',
|
||||
description: 'Generates filter plugin',
|
||||
aliases: ['filter'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Plugin/_filter',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Filter extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, Assets $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['name'] = $ir->askName();
|
||||
|
||||
$vars['plugin_label'] = $ir->askPluginLabel();
|
||||
$vars['plugin_id'] = $ir->askPluginId();
|
||||
$vars['class'] = $ir->askPluginClass();
|
||||
|
||||
$filter_types = [
|
||||
'TYPE_HTML_RESTRICTOR' => 'HTML restrictor',
|
||||
'TYPE_MARKUP_LANGUAGE' => 'Markup language',
|
||||
'TYPE_TRANSFORM_IRREVERSIBLE' => 'Irreversible transformation',
|
||||
'TYPE_TRANSFORM_REVERSIBLE' => 'Reversible transformation',
|
||||
];
|
||||
$vars['filter_type'] = $ir->choice('Filter type', $filter_types);
|
||||
$vars['configurable'] = $ir->confirm('Make the filter configurable?', FALSE);
|
||||
$vars['services'] = $ir->askServices(FALSE);
|
||||
|
||||
$assets->addFile('src/Plugin/Filter/{class}.php', 'filter.twig');
|
||||
if ($vars['configurable']) {
|
||||
$assets->addSchemaFile()->template('schema.twig');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
33
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/MenuLink.php
vendored
Normal file
33
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/MenuLink.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Plugin;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\Assets;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
|
||||
#[Generator(
|
||||
name: 'plugin:menu-link',
|
||||
description: 'Generates menu-link plugin',
|
||||
aliases: ['menu-link'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Plugin/_menu-link',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class MenuLink extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, Assets $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['class'] = $ir->askPluginClass('Class', '{machine_name|camelize}MenuLink');
|
||||
$vars['services'] = $ir->askServices(FALSE);
|
||||
$assets->addFile('src/Plugin/Menu/{class}.php', 'menu-link.twig');
|
||||
}
|
||||
|
||||
}
|
||||
34
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Migrate/Destination.php
vendored
Normal file
34
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Migrate/Destination.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Plugin\Migrate;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
|
||||
#[Generator(
|
||||
name: 'plugin:migrate:destination',
|
||||
description: 'Generates migrate destination plugin',
|
||||
aliases: ['migrate-destination'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Plugin/Migrate/_destination',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Destination extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['plugin_id'] = $ir->askPluginId(default: NULL);
|
||||
$vars['class'] = $ir->askPluginClass();
|
||||
$vars['services'] = $ir->askServices(FALSE);
|
||||
$assets->addFile('src/Plugin/migrate/destination/{class}.php', 'destination.twig');
|
||||
}
|
||||
|
||||
}
|
||||
34
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Migrate/Process.php
vendored
Normal file
34
vendor/chi-teck/drupal-code-generator/src/Command/Plugin/Migrate/Process.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DrupalCodeGenerator\Command\Plugin\Migrate;
|
||||
|
||||
use DrupalCodeGenerator\Application;
|
||||
use DrupalCodeGenerator\Asset\AssetCollection;
|
||||
use DrupalCodeGenerator\Attribute\Generator;
|
||||
use DrupalCodeGenerator\Command\BaseGenerator;
|
||||
use DrupalCodeGenerator\GeneratorType;
|
||||
|
||||
#[Generator(
|
||||
name: 'plugin:migrate:process',
|
||||
description: 'Generates migrate process plugin',
|
||||
aliases: ['migrate-process'],
|
||||
templatePath: Application::TEMPLATE_PATH . '/Plugin/Migrate/_process',
|
||||
type: GeneratorType::MODULE_COMPONENT,
|
||||
)]
|
||||
final class Process extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function generate(array &$vars, AssetCollection $assets): void {
|
||||
$ir = $this->createInterviewer($vars);
|
||||
$vars['machine_name'] = $ir->askMachineName();
|
||||
$vars['plugin_id'] = $ir->askPluginId(default: NULL);
|
||||
$vars['class'] = $ir->askPluginClass();
|
||||
$vars['services'] = $ir->askServices(FALSE);
|
||||
$assets->addFile('src/Plugin/migrate/process/{class}.php', 'process.twig');
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user