├── LICENSE
├── README.md
├── composer.json
├── config
├── app.yaml
├── routing.yaml
└── services.yaml
├── install
├── Makefile
├── bin
│ └── console
├── docker-compose.prod.yml
├── docker-compose.yml
├── docker
│ ├── dev
│ │ └── php
│ │ │ └── config.ini
│ ├── dk.nginx.Dockerfile
│ ├── dk.nginx.Dockerfile.dockerignore
│ ├── dk.php.Dockerfile
│ ├── dk.php.Dockerfile.dockerignore
│ └── nginx
│ │ ├── conf.d
│ │ └── default.conf
│ │ └── nginx.conf
└── wp
│ └── wp-config.php
└── src
├── Attribute
└── AsWordpressCommand.php
├── Command
├── WordpressCommand.php
└── WpCommand.php
├── Controller
├── ReauthenticateController.php
├── Routes.php
└── WordpressController.php
├── DependencyInjection
├── Compiler
│ └── WordpressPass.php
├── Configuration.php
└── SwordExtension.php
├── Entity
└── WordpressEntityInterface.php
├── EnvVarProcessor
└── AutoFileEnvVarProcessor.php
├── Event
└── WooCommerceRegistrationEvent.php
├── EventListener
├── WordpressLoggedInStatusCheckEventSubscriber.php
├── WordpressTablePrefixEventListener.php
└── WordpressTerminateEventListener.php
├── Exception
├── WordpressLoginSuccessfulException.php
└── WordpressLougoutSuccessfulException.php
├── Helper
└── ContainerHelper.php
├── Loader
├── LazyServiceInstantiator.php
├── WordpressGlobals.php
├── WordpressLoader.php
└── wp-load.php
├── Security
├── User.php
├── UserAuthenticator.php
├── UserProvider.php
├── UserReauthenticator.php
└── Voter
│ ├── CapabilityVoter.php
│ └── RoleVoter.php
├── Service
├── AbstractWordpressService.php
└── WordpressService.php
├── Store
└── WordpressWidgetStore.php
├── SwordBundle.php
├── Translation
├── ChildThemeTranslationInitializer.php
└── LocaleSwitcher.php
└── Widget
└── DefineWidgetTrait.php
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2022-2023, William Arin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 |
5 | [](https://github.com/phpsword/sworld-bundle/actions)
6 |
7 | # Introduction
8 |
9 | Modern WordPress development with Symfony.
10 |
11 | # Documentation
12 | Visit [https://getsword.com/](https://getsword.com/) for official documentation.
13 |
14 | # Contributions
15 | Feel free to submit issues and pull requests.
16 |
17 | # License
18 | [MIT](LICENSE)
19 |
20 | Copyright (c) 2022, William Arin
21 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "phpsword/sword-bundle",
3 | "description": "Modern WordPress development with Symfony",
4 | "license": "MIT",
5 | "type": "symfony-bundle",
6 | "keywords": [
7 | "wordpress",
8 | "modern-wordpress",
9 | "symfony",
10 | "symfony-bundle"
11 | ],
12 | "authors": [
13 | {
14 | "name": "William Arin",
15 | "email": "williamarin.dev@gmail.com"
16 | }
17 | ],
18 | "require": {
19 | "php": ">=8.1",
20 | "ext-ctype": "*",
21 | "ext-iconv": "*",
22 | "composer/composer": "^2.4.1",
23 | "doctrine/doctrine-bundle": "^2.7.2",
24 | "doctrine/orm": "^2.13 || ^3.0",
25 | "roots/wp-password-bcrypt": "^1.1.0",
26 | "symfony/dependency-injection": "^6.1 || ^7.0",
27 | "symfony/framework-bundle": "^6.1 || ^7.0",
28 | "symfony/http-kernel": "^6.1 || ^7.0",
29 | "symfony/security-bundle": "^6.1 || ^7.0",
30 | "symfony/translation": "^6.1 || ^7.0",
31 | "symfony/yaml": "^6.1 || ^7.0",
32 | "williarin/wordpress-interop": "^1.11",
33 | "williarin/wordpress-interop-bundle": "^1.1.1",
34 | "wp-cli/wp-cli-bundle": "^2.10"
35 | },
36 | "require-dev": {
37 | "brain/monkey": "^2.6",
38 | "ergebnis/composer-normalize": "^2.28.3",
39 | "kubawerlos/php-cs-fixer-custom-fixers": "^3.11",
40 | "matthiasnoback/symfony-dependency-injection-test": "^4.3",
41 | "mockery/mockery": "^1.5",
42 | "nikic/php-parser": "^4.15",
43 | "php-parallel-lint/php-parallel-lint": "^1.3",
44 | "phpro/grumphp": "^1.13",
45 | "phpunit/phpunit": "^9.5.22",
46 | "roave/security-advisories": "dev-latest",
47 | "symplify/coding-standard": "^11.1",
48 | "symplify/easy-coding-standard": "^11.1"
49 | },
50 | "minimum-stability": "dev",
51 | "prefer-stable": true,
52 | "autoload": {
53 | "psr-4": {
54 | "Sword\\SwordBundle\\": "src/"
55 | },
56 | "files": [
57 | "src/Helper/ContainerHelper.php"
58 | ]
59 | },
60 | "autoload-dev": {
61 | "psr-4": {
62 | "Sword\\SwordBundle\\Test\\": "tests/"
63 | }
64 | },
65 | "config": {
66 | "allow-plugins": {
67 | "ergebnis/composer-normalize": true,
68 | "phpro/grumphp": false
69 | },
70 | "sort-packages": true
71 | },
72 | "extra": {
73 | "branch-alias": {
74 | "dev-master": "1.x-dev"
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/config/app.yaml:
--------------------------------------------------------------------------------
1 | security:
2 | password_hashers:
3 | Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
4 | providers:
5 | app_user_provider:
6 | id: Sword\SwordBundle\Security\UserProvider
7 | role_hierarchy:
8 | customer: ROLE_USER
9 | subscriber: customer
10 | contributor: subscriber
11 | author: contributor
12 | editor: author
13 | shop_manager: editor
14 | administrator: shop_manager
15 | ROLE_SUPER_ADMIN: [ administrator, ROLE_ALLOWED_TO_SWITCH ]
16 | firewalls:
17 | dev:
18 | pattern: ^/(_(profiler|wdt)|css|images|js)/
19 | security: false
20 | main:
21 | lazy: true
22 | logout: true
23 | provider: app_user_provider
24 | entry_point: Sword\SwordBundle\Security\UserAuthenticator
25 | custom_authenticator: Sword\SwordBundle\Security\UserAuthenticator
26 | access_control:
27 | - { path: ^/, role: PUBLIC_ACCESS }
28 |
29 | doctrine:
30 | dbal:
31 | dbname: '%env(auto_file:WORDPRESS_DB_NAME)%'
32 | host: '%env(auto_file:WORDPRESS_DB_HOST)%'
33 | user: '%env(auto_file:WORDPRESS_DB_USER)%'
34 | password: '%env(auto_file:WORDPRESS_DB_PASSWORD)%'
35 | charset: '%env(auto_file:WORDPRESS_DB_CHARSET)%'
36 | driver: 'mysqli'
37 | server_version: '8.0'
38 | url: ~
39 |
40 | orm:
41 | auto_generate_proxy_classes: true
42 | naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
43 | auto_mapping: true
44 | mappings:
45 | SwordSecurity:
46 | is_bundle: false
47 | dir: '%kernel.project_dir%/vendor/phpsword/sword-bundle/src/Security'
48 | prefix: 'Sword\SwordBundle\Security'
49 | alias: SwordSecurity
50 |
51 | framework:
52 | serializer:
53 | name_converter: 'serializer.name_converter.camel_case_to_snake_case'
54 |
55 | williarin_wordpress_interop:
56 | entity_managers:
57 | default:
58 | connection: default
59 |
--------------------------------------------------------------------------------
/config/routing.yaml:
--------------------------------------------------------------------------------
1 | controllers:
2 | resource: ../src/Controller/
3 | type: attribute
4 |
--------------------------------------------------------------------------------
/config/services.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | _defaults:
3 | autowire: true # Automatically injects dependencies in your services.
4 | autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
5 |
6 | Sword\SwordBundle\:
7 | resource: '../src/'
8 | exclude:
9 | - '../src/Attribute/'
10 | - '../src/DependencyInjection/'
11 | - '../src/Helper/'
12 |
--------------------------------------------------------------------------------
/install/Makefile:
--------------------------------------------------------------------------------
1 | .DEFAULT_GOAL = help
2 |
3 | .PHONY: cc
4 | cc: ## Clear Symfony cache
5 | @docker compose exec php bin/console cache:clear
6 |
7 | .PHONY: opcache
8 | opcache: ## Clear opcache
9 | docker-compose exec php cachetool opcache:reset
10 |
11 | .PHONY: build
12 | build: ## Build containers
13 | @docker compose build
14 |
15 | .PHONY: stop
16 | stop: ## Stop containers
17 | @docker compose stop
18 |
19 | .PHONY: down
20 | down: ## Remove containers but keep volumes
21 | @docker compose down
22 |
23 | .PHONY: remove
24 | remove: ## Remove containers and volumes
25 | @docker compose down --remove-orphans -v
26 |
27 | .PHONY: up
28 | up: ## Run containers
29 | @docker compose up -d --remove-orphans
30 |
31 | .PHONY: up-build
32 | up-build: ## Build containers and run them
33 | @docker compose up -d --build --remove-orphans
34 |
35 | .PHONY: upgrade
36 | upgrade: ## Upgrade database after a WordPress upgrade
37 | @docker-compose exec -u 82:82 php bin/console wp core update-db
38 | @docker-compose exec -u 82:82 php bin/console wp wc update
39 | @docker-compose exec -u 82:82 php bin/console wp cron event run --due-now
40 | @docker-compose exec -u 82:82 php bin/console wp action-scheduler run
41 |
42 | .PHONY: acl
43 | acl: ## Reset project files and directories ACL
44 | @sudo chown -R $(whoami):$(whoami) .
45 | @sudo setfacl -dR -m u:$(whoami):rwX -m u:www-data:rwX -m u:82:rwX .
46 | @sudo setfacl -R -m u:$(whoami):rwX -m u:www-data:rwX -m u:82:rwX .
47 |
48 | .PHONY: help
49 | help: ## List all commands
50 | @grep -E '(^[a-zA-Z_-]+:.*?##.*$$)|(^##)' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[32m%-30s\033[0m %s\n", $$1, $$2}' | sed -e 's/\[32m##/[33m/'
51 |
--------------------------------------------------------------------------------
/install/bin/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | = 2 && $argv[1] === 'wp') {
18 | $bootstrapSteps = [
19 | DeclareFallbackFunctions::class,
20 | LoadUtilityFunctions::class,
21 | LoadDispatcher::class,
22 | ];
23 |
24 | if (!defined('WP_CLI')) {
25 | define('WP_CLI', true);
26 | }
27 | if (!defined('WP_CLI_ROOT')) {
28 | define('WP_CLI_ROOT', dirname(__DIR__) . '/vendor/wp-cli/wp-cli');
29 | }
30 | if (!defined('WP_CLI_VERSION')) {
31 | define('WP_CLI_VERSION', trim(file_get_contents(WP_CLI_ROOT . '/VERSION')));
32 | }
33 | if (!defined('WP_CLI_START_MICROTIME')) {
34 | define('WP_CLI_START_MICROTIME', microtime(true));
35 | }
36 |
37 | if (!defined('WP_CLI_VENDOR_DIR')) {
38 | if (file_exists(WP_CLI_ROOT . '/vendor/autoload.php')) {
39 | define('WP_CLI_VENDOR_DIR', WP_CLI_ROOT . '/vendor');
40 | } elseif (file_exists(dirname(WP_CLI_ROOT, 2) . '/autoload.php')) {
41 | define('WP_CLI_VENDOR_DIR', dirname(WP_CLI_ROOT, 2));
42 | } elseif (file_exists(dirname(WP_CLI_ROOT) . '/vendor/autoload.php')) {
43 | define('WP_CLI_VENDOR_DIR', dirname(WP_CLI_ROOT) . '/vendor');
44 | } else {
45 | define('WP_CLI_VENDOR_DIR', WP_CLI_ROOT . '/vendor');
46 | }
47 | }
48 |
49 | require_once WP_CLI_ROOT . '/php/compat.php';
50 |
51 | $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.0';
52 | $_SERVER['HTTP_USER_AGENT'] = '';
53 | $_SERVER['REQUEST_METHOD'] = 'GET';
54 | $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
55 |
56 | require_once WP_CLI_ROOT . '/php/WP_CLI/Autoloader.php';
57 |
58 | $autoloader = new Autoloader();
59 |
60 | $autoloader->add_namespace(
61 | 'WP_CLI\Bootstrap',
62 | WP_CLI_ROOT . '/php/WP_CLI/Bootstrap'
63 | )->register();
64 |
65 | global $wpCliBootstrapState;
66 | $wpCliBootstrapState = new BootstrapState();
67 |
68 | foreach ($bootstrapSteps as $step) {
69 | /** @var BootstrapStep $stepInstance */
70 | $stepInstance = new $step();
71 | $wpCliBootstrapState = $stepInstance->process($wpCliBootstrapState);
72 | }
73 | }
74 |
75 | require_once dirname(__DIR__) . '/vendor/autoload_runtime.php';
76 |
77 | return function (array $context) {
78 | $kernel = new Kernel($context['APP_ENV'], (bool)$context['APP_DEBUG']);
79 |
80 | return new Application($kernel);
81 | };
82 |
--------------------------------------------------------------------------------
/install/docker-compose.prod.yml:
--------------------------------------------------------------------------------
1 | version: "3.8"
2 |
3 | services:
4 | php:
5 | build:
6 | context: .
7 | dockerfile: docker/dk.php.Dockerfile
8 | args:
9 | PHP_VERSION: 8.1
10 | image: 'changeme/changeme-php:staging'
11 | restart: 'no'
12 | environment:
13 | WORDPRESS_SITE_URL: https://staging.example.com
14 | WORDPRESS_DB_NAME: sword_app
15 | WORDPRESS_DB_USER: ChangeMe
16 | WORDPRESS_DB_PASSWORD: ChangeMe
17 | WORDPRESS_DB_HOST: mysql
18 | WORDPRESS_AUTH_KEY: ChangeMe
19 | WORDPRESS_SECURE_AUTH_KEY: ChangeMe
20 | WORDPRESS_LOGGED_IN_KEY: ChangeMe
21 | WORDPRESS_NONCE_KEY: ChangeMe
22 | WORDPRESS_AUTH_SALT: ChangeMe
23 | WORDPRESS_SECURE_AUTH_SALT: ChangeMe
24 | WORDPRESS_LOGGED_IN_SALT: ChangeMe
25 | WORDPRESS_NONCE_SALT: ChangeMe
26 |
27 | nginx:
28 | build:
29 | context: .
30 | dockerfile: docker/dk.nginx.Dockerfile
31 | image: 'changeme/changeme-nginx:staging'
32 | restart: 'no'
33 | depends_on:
34 | - php
35 | - traefik
36 | networks:
37 | - default
38 | - traefik
39 | labels:
40 | - traefik.enable=true
41 | - traefik.http.routers.${APP_NAME:-sword}.rule=Host(`staging.example.com`)
42 | - traefik.http.routers.${APP_NAME:-sword}.tls=true
43 | - traefik.http.routers.${APP_NAME:-sword}.entrypoints=websecure
44 | - traefik.http.services.${APP_NAME:-sword}.loadbalancer.server.port=80
45 |
46 | mysql:
47 | image: mysql:8.0.37
48 | restart: 'no'
49 | environment:
50 | - MYSQL_USER=ChangeMe
51 | - MYSQL_PASSWORD=ChangeMe
52 | - MYSQL_ROOT_PASSWORD=root
53 | - MYSQL_DATABASE=sword_app
54 | volumes:
55 | - mysql_data:/var/lib/mysql
56 |
57 | traefik:
58 | image: traefik:2.11
59 | ports:
60 | - '443:443'
61 | volumes:
62 | - /var/run/docker.sock:/var/run/docker.sock:ro
63 | networks:
64 | - traefik
65 | command:
66 | - --providers.docker
67 | - --providers.docker.exposedbydefault=false
68 | - --providers.docker.network=${PROJECT_DIR:-sword}_traefik
69 | - --entrypoints.web.address=:80
70 | - --entrypoints.web.http.redirections.entryPoint.to=websecure
71 | - --entrypoints.web.http.redirections.entryPoint.scheme=https
72 | - --entrypoints.websecure.address=:443
73 |
74 | volumes:
75 | mysql_data:
76 |
77 | networks:
78 | traefik:
79 |
--------------------------------------------------------------------------------
/install/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.8"
2 |
3 | services:
4 | php:
5 | build:
6 | context: .
7 | dockerfile: docker/dk.php.Dockerfile
8 | args:
9 | PHP_VERSION: 8.1-dev
10 | restart: 'no'
11 | environment:
12 | WORDPRESS_SITE_URL: https://${APP_NAME:-sword}.localhost
13 | WORDPRESS_DB_NAME: sword_app
14 | WORDPRESS_DB_USER: user
15 | WORDPRESS_DB_PASSWORD: user
16 | WORDPRESS_DB_HOST: mysql
17 | WORDPRESS_AUTH_KEY: ChangeMe
18 | WORDPRESS_SECURE_AUTH_KEY: ChangeMe
19 | WORDPRESS_LOGGED_IN_KEY: ChangeMe
20 | WORDPRESS_NONCE_KEY: ChangeMe
21 | WORDPRESS_AUTH_SALT: ChangeMe
22 | WORDPRESS_SECURE_AUTH_SALT: ChangeMe
23 | WORDPRESS_LOGGED_IN_SALT: ChangeMe
24 | WORDPRESS_NONCE_SALT: ChangeMe
25 | WORDPRESS_DEBUG: 'true'
26 | WORDPRESS_DEBUG_DISPLAY: 'false'
27 | WORDPRESS_CONFIG_EXTRA: define('WP_ENVIRONMENT_TYPE', 'development');
28 | volumes:
29 | - ./:/var/www/html
30 | - ./docker/dev/php/config.ini:/etc/php81/conf.d/99_dev.ini:ro
31 | extra_hosts:
32 | - host.docker.internal:host-gateway
33 |
34 | nginx:
35 | build:
36 | context: .
37 | dockerfile: docker/dk.nginx.Dockerfile
38 | restart: 'no'
39 | volumes:
40 | - ./public/:/var/www/html/public:ro
41 | - ./wp/:/var/www/html/wp:ro
42 | depends_on:
43 | - php
44 | - traefik
45 | networks:
46 | - default
47 | - traefik
48 | labels:
49 | - traefik.enable=true
50 | - traefik.http.routers.${APP_NAME:-sword}.rule=Host(`${APP_NAME:-sword}.localhost`)
51 | - traefik.http.routers.${APP_NAME:-sword}.tls=true
52 | - traefik.http.routers.${APP_NAME:-sword}.entrypoints=websecure
53 | - traefik.http.services.${APP_NAME:-sword}.loadbalancer.server.port=80
54 |
55 | mysql:
56 | image: mysql:8.0.37
57 | restart: 'no'
58 | environment:
59 | - MYSQL_USER=user
60 | - MYSQL_PASSWORD=user
61 | - MYSQL_ROOT_PASSWORD=root
62 | - MYSQL_DATABASE=sword_app
63 | volumes:
64 | - mysql_data:/var/lib/mysql
65 |
66 | mailer:
67 | image: maildev/maildev
68 | restart: 'no'
69 | networks:
70 | - default
71 | - traefik
72 | labels:
73 | - traefik.enable=true
74 | - traefik.http.routers.${APP_NAME:-sword}-mail.rule=Host(`${APP_NAME:-sword}-mail.localhost`)
75 | - traefik.http.routers.${APP_NAME:-sword}-mail.tls=true
76 | - traefik.http.routers.${APP_NAME:-sword}-mail.entrypoints=websecure
77 | - traefik.http.services.${APP_NAME:-sword}-mail.loadbalancer.server.port=1080
78 | - traefik.tcp.routers.${APP_NAME:-sword}-smtp.rule=HostSNI(`${APP_NAME:-sword}-smtp.localhost`)
79 | - traefik.tcp.routers.${APP_NAME:-sword}-smtp.entrypoints=smtpsecure
80 | - traefik.tcp.routers.${APP_NAME:-sword}-smtp.tls=true
81 | - traefik.tcp.routers.${APP_NAME:-sword}-smtp.service=${APP_NAME:-sword}-smtp
82 | - traefik.tcp.services.${APP_NAME:-sword}-smtp.loadbalancer.server.port=1025
83 |
84 | traefik:
85 | image: traefik:2.11
86 | ports:
87 | - '443:443'
88 | volumes:
89 | - /var/run/docker.sock:/var/run/docker.sock:ro
90 | networks:
91 | - traefik
92 | command:
93 | - --providers.docker
94 | - --providers.docker.exposedbydefault=false
95 | - --providers.docker.network=${PROJECT_DIR:-sword}_traefik
96 | - --entrypoints.web.address=:80
97 | - --entrypoints.web.http.redirections.entryPoint.to=websecure
98 | - --entrypoints.web.http.redirections.entryPoint.scheme=https
99 | - --entrypoints.websecure.address=:443
100 | - --entrypoints.smtp.address=:25
101 | - --entrypoints.smtpsecure.address=:465
102 |
103 | volumes:
104 | mysql_data:
105 |
106 | networks:
107 | traefik:
108 |
--------------------------------------------------------------------------------
/install/docker/dev/php/config.ini:
--------------------------------------------------------------------------------
1 | apc.enable_cli = 1
2 | date.timezone = UTC
3 | session.auto_start = Off
4 | short_open_tag = Off
5 | memory_limit = 1G
6 |
7 | # Upload
8 | file_uploads = On
9 | upload_max_filesize = 64M
10 | post_max_size = 64M
11 | max_execution_time = 600
12 |
13 | realpath_cache_size = 4096K
14 | realpath_cache_ttl = 600
15 |
16 | [opcache]
17 | opcache.revalidate_freq = 1
18 | opcache.validate_timestamps = 1
19 | opcache.interned_strings_buffer = 16
20 | opcache.max_accelerated_files = 20000
21 | opcache.memory_consumption = 256
22 |
23 | [xdebug]
24 | xdebug.mode=debug
25 | xdebug.start_with_request=trigger
26 | xdebug.discover_client_host=no
27 | xdebug.client_host=host.docker.internal
28 | xdebug.client_port=9003
29 | xdebug.idekey=PHPSTORM
30 |
--------------------------------------------------------------------------------
/install/docker/dk.nginx.Dockerfile:
--------------------------------------------------------------------------------
1 | FROM nginx:alpine
2 |
3 | COPY --chown=www-data:www-data . /var/www/html/
4 |
5 | RUN cp -R /var/www/html/docker/nginx/* /etc/nginx/ \
6 | && rm -rf /var/www/html/docker
7 |
8 | WORKDIR /var/www/html/public
9 |
--------------------------------------------------------------------------------
/install/docker/dk.nginx.Dockerfile.dockerignore:
--------------------------------------------------------------------------------
1 | *
2 | !public
3 | !docker
4 |
5 | !wp
6 | wp/*
7 |
8 | !wp/core
9 | wp/core/*
10 | !wp/core/wp-admin
11 | wp/core/wp-admin/*
12 | !wp/core/wp-admin/**/*.js
13 | !wp/core/wp-admin/**/*.css
14 | !wp/core/wp-admin/**/*.png
15 | !wp/core/wp-admin/**/*.jpg
16 | !wp/core/wp-admin/**/*.jpeg
17 | !wp/core/wp-admin/**/*.gif
18 | !wp/core/wp-admin/**/*.ico
19 | !wp/core/wp-admin/**/*.svg
20 | !wp/core/wp-admin/**/*.woff
21 | !wp/core/wp-admin/**/*.woff2
22 | !wp/core/wp-admin/**/*.otf
23 | !wp/core/wp-admin/**/*.ttf
24 | !wp/core/wp-admin/**/*.xsl
25 |
26 | !wp/core/wp-includes
27 | wp/core/wp-includes/*
28 | !wp/core/wp-includes/**/*.js
29 | !wp/core/wp-includes/**/*.css
30 | !wp/core/wp-includes/**/*.png
31 | !wp/core/wp-includes/**/*.jpg
32 | !wp/core/wp-includes/**/*.jpeg
33 | !wp/core/wp-includes/**/*.gif
34 | !wp/core/wp-includes/**/*.ico
35 | !wp/core/wp-includes/**/*.svg
36 | !wp/core/wp-includes/**/*.woff
37 | !wp/core/wp-includes/**/*.woff2
38 | !wp/core/wp-includes/**/*.otf
39 | !wp/core/wp-includes/**/*.ttf
40 | !wp/core/wp-includes/**/*.xsl
41 |
42 | !wp/content
43 | wp/content/*
44 |
45 | !wp/content/plugins
46 | wp/content/plugins/*
47 | !wp/content/plugins/**/*.js
48 | !wp/content/plugins/**/*.css
49 | !wp/content/plugins/**/*.png
50 | !wp/content/plugins/**/*.jpg
51 | !wp/content/plugins/**/*.jpeg
52 | !wp/content/plugins/**/*.gif
53 | !wp/content/plugins/**/*.ico
54 | !wp/content/plugins/**/*.svg
55 | !wp/content/plugins/**/*.woff
56 | !wp/content/plugins/**/*.woff2
57 | !wp/content/plugins/**/*.otf
58 | !wp/content/plugins/**/*.ttf
59 | !wp/content/plugins/**/*.xsl
60 |
61 | !wp/content/themes
62 | wp/content/themes/*
63 | !wp/content/themes/**/*.js
64 | !wp/content/themes/**/*.css
65 | !wp/content/themes/**/*.png
66 | !wp/content/themes/**/*.jpg
67 | !wp/content/themes/**/*.jpeg
68 | !wp/content/themes/**/*.gif
69 | !wp/content/themes/**/*.ico
70 | !wp/content/themes/**/*.svg
71 | !wp/content/themes/**/*.woff
72 | !wp/content/themes/**/*.woff2
73 | !wp/content/themes/**/*.otf
74 | !wp/content/themes/**/*.ttf
75 | !wp/content/themes/**/*.xsl
76 |
--------------------------------------------------------------------------------
/install/docker/dk.php.Dockerfile:
--------------------------------------------------------------------------------
1 | ARG PHP_VERSION=8.1
2 |
3 | FROM ghcr.io/phpsword/php:$PHP_VERSION
4 |
5 | COPY --chown=www-data:www-data . /var/www/html/
6 |
7 | RUN rm -rf /var/www/html/docker
8 |
--------------------------------------------------------------------------------
/install/docker/dk.php.Dockerfile.dockerignore:
--------------------------------------------------------------------------------
1 | .git*
2 | .github
3 | .idea
4 | node_modules
5 | tests
6 | var/cache
7 | var/logs
8 | var/sessions
9 | assets
10 | public/uploads
11 | bin/phpunit
12 |
13 | */*/.htaccess
14 | *.lock
15 | package*.json
16 | *.dist
17 | *.md
18 | *.txt
19 | *.local
20 | *.ci
21 | docker-compose.*
22 | Dockerfile
23 | *.Dockerfile
24 | .dockerignore
25 | *.dockerignore
26 | Makefile
27 | .nvmrc
28 | .phpunit.*
29 | *.test
30 | *.neon
31 | *.dev
32 | webpack.config.js
33 |
34 | wp/content/uploads
35 |
--------------------------------------------------------------------------------
/install/docker/nginx/conf.d/default.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | server_name localhost;
4 |
5 | # access_log /var/log/nginx/wp-access.log;
6 | error_log /var/log/nginx/wp-error.log;
7 |
8 | # Remove X-Powered-By, which is an information leak
9 | fastcgi_hide_header X-Powered-By;
10 |
11 | root /var/www/html/public/;
12 |
13 | index index.php;
14 |
15 | location / {
16 | try_files $uri /index.php$is_args$args;
17 | }
18 |
19 | location ~ ^/index\.php(/|$) {
20 | fastcgi_pass php:9000;
21 | fastcgi_split_path_info ^(.+\.php)(/.*)$;
22 | include fastcgi_params;
23 |
24 | fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
25 | fastcgi_param DOCUMENT_ROOT $realpath_root;
26 | fastcgi_param HTTPS on;
27 | }
28 |
29 | location ~ \.php$ {
30 | try_files $uri /index.php$is_args$args;
31 | }
32 |
33 | location = /robots.txt {
34 | allow all;
35 | log_not_found off;
36 | access_log off;
37 | }
38 |
39 | location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|eot|woff2?|otf|ttf|xsl)$ {
40 | root /;
41 | rewrite ^/wp-content/(.*)$ /content/$1 last;
42 | rewrite ^/wp-includes/(.*)$ /core/wp-includes/$1 last;
43 | rewrite ^/wp-admin/(.*)$ /core/wp-admin/$1 last;
44 | try_files /var/www/html/public$uri /var/www/html/wp$uri =404;
45 | expires max;
46 | log_not_found off;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/install/docker/nginx/nginx.conf:
--------------------------------------------------------------------------------
1 | worker_processes 1;
2 | user root;
3 |
4 | error_log /dev/stdout info;
5 |
6 | events {
7 | worker_connections 1024;
8 | }
9 |
10 | http {
11 | include /etc/nginx/mime.types;
12 | include /etc/nginx/fastcgi.conf;
13 |
14 | error_log /dev/stdout info;
15 |
16 | sendfile on;
17 | tcp_nopush on;
18 | server_names_hash_bucket_size 128;
19 |
20 | real_ip_header X-Forwarded-For;
21 | set_real_ip_from traefik;
22 |
23 | client_body_buffer_size 16K;
24 | client_body_timeout 12;
25 | client_header_buffer_size 4k;
26 | client_header_timeout 12;
27 | client_max_body_size 8M;
28 | fastcgi_buffers 16 64k;
29 | fastcgi_buffer_size 128k;
30 | keepalive_timeout 15;
31 | large_client_header_buffers 4 32k;
32 | proxy_hide_header X-Powered-By;
33 | send_timeout 10;
34 | server_tokens off;
35 |
36 | proxy_read_timeout 300;
37 | proxy_connect_timeout 300;
38 | proxy_send_timeout 300;
39 | uwsgi_read_timeout 300;
40 | fastcgi_send_timeout 300;
41 | fastcgi_read_timeout 300;
42 |
43 | gzip on;
44 | gzip_disable "msie6";
45 | gzip_vary on;
46 | gzip_proxied any;
47 | gzip_comp_level 6;
48 | gzip_buffers 16 8k;
49 | gzip_http_version 1.1;
50 | gzip_min_length 256;
51 | gzip_types
52 | application/atom+xml
53 | application/geo+json
54 | application/javascript
55 | application/x-javascript
56 | application/json
57 | application/ld+json
58 | application/manifest+json
59 | application/rdf+xml
60 | application/rss+xml
61 | application/xhtml+xml
62 | application/xml
63 | font/eot
64 | font/otf
65 | font/ttf
66 | image/svg+xml
67 | text/css
68 | text/javascript
69 | text/plain
70 | text/xml;
71 |
72 | include /etc/nginx/conf.d/*.conf;
73 | }
74 |
--------------------------------------------------------------------------------
/install/wp/wp-config.php:
--------------------------------------------------------------------------------
1 | qEz?<;dqgKIodM@Tp(aO.%?Y;[X(Si{e{6??lhHI') );
69 | define( 'SECURE_AUTH_KEY', getenv_docker('WORDPRESS_SECURE_AUTH_KEY', 'CgT Q9P13xC+96TQ?}kt|X&?+i6lg8hxyceDQd=+<[*?_>`jE[mfOD ?eEhYB(2v') );
70 | define( 'LOGGED_IN_KEY', getenv_docker('WORDPRESS_LOGGED_IN_KEY', '-;7}G6-h-HcyvR.Gq-X91pVW{u|_gAUE]yTR0g Ayf.[.Kj+&pFtb=DOy$;#gk-%') );
71 | define( 'NONCE_KEY', getenv_docker('WORDPRESS_NONCE_KEY', 'd+tg52@Q#@HyUodDL8U}+%HU|lIy|O>%-i!wBmTEVFve9y#)t2k}k#D-~i+cd4:g') );
72 | define( 'AUTH_SALT', getenv_docker('WORDPRESS_AUTH_SALT', '(zG&d7g0.qgC3ttU/*=~k|8{]%w1O68LW=j+tkJ81YtikE#GW))G[|Z9/ d!F~)kc&dp>+WoLQrV9s?D|?CgMcz') );
74 | define( 'LOGGED_IN_SALT', getenv_docker('WORDPRESS_LOGGED_IN_SALT', 'yq7w~y03EL|ctX-|kR}v$=[E?P+[zNf8IhP@}?3-FtNY^-t|;8-8R0@K6HR!sm7o') );
75 | define( 'NONCE_SALT', getenv_docker('WORDPRESS_NONCE_SALT', '1{1G%>#~Va8TRt-TU;pi.v{@;P-+M%g}Ud!- 4eWl](=pw?|-Rym:jGtU9|/#@4t') );
76 |
77 | /**#@-*/
78 |
79 | /**
80 | * WordPress Database Table prefix.
81 | *
82 | * You can have multiple installations in one database if you give each
83 | * a unique prefix. Only numbers, letters, and underscores please!
84 | */
85 | $table_prefix = getenv_docker('WORDPRESS_TABLE_PREFIX', 'wp_');
86 |
87 | /**
88 | * For developers: WordPress debugging mode.
89 | *
90 | * Change this to true to enable the display of notices during development.
91 | * It is strongly recommended that plugin and theme developers use WP_DEBUG
92 | * in their development environments.
93 | *
94 | * For information on other constants that can be used for debugging,
95 | * visit the Codex.
96 | *
97 | * @link https://codex.wordpress.org/Debugging_in_WordPress
98 | */
99 | define('WP_DEBUG', filter_var(getenv_docker('WORDPRESS_DEBUG', 'false'), FILTER_VALIDATE_BOOLEAN));
100 |
101 | /* Add any custom values between this line and the "stop editing" line. */
102 |
103 | define('WP_DEBUG_LOG', filter_var(getenv_docker('WORDPRESS_DEBUG_LOG', 'false'), FILTER_VALIDATE_BOOLEAN));
104 | define('WP_DEBUG_DISPLAY', filter_var(getenv_docker('WORDPRESS_DEBUG_DISPLAY', 'false'), FILTER_VALIDATE_BOOLEAN));
105 | define('WP_DISABLE_FATAL_ERROR_HANDLER', filter_var(getenv_docker('WORDPRESS_DISABLE_FATAL_ERROR_HANDLER', 'true'), FILTER_VALIDATE_BOOLEAN));
106 |
107 | define('WP_REDIS_HOST', getenv_docker('WORDPRESS_REDIS_HOST', 'redis'));
108 | define('WP_REDIS_PASSWORD', getenv_docker('WORDPRESS_REDIS_PASSWORD', 'password'));
109 | define('WP_CACHE_KEY_SALT', getenv_docker('WORDPRESS_CACHE_KEY_SALT', 'R!0uA_0:DmiDAX|18owsU[{9f-]+}p`,;lGaU:}}f#T}f-K%#I>:?DvpPuv|_8Bl'));
110 |
111 | define('DISABLE_WP_CRON', filter_var(getenv_docker('WORDPRESS_DISABLE_WP_CRON', 'true'), FILTER_VALIDATE_BOOLEAN));
112 |
113 | /** WP-Optimize Cache */
114 | define('WP_CACHE', filter_var(getenv_docker('WORDPRESS_CACHE', 'true'), FILTER_VALIDATE_BOOLEAN));
115 |
116 | /** Automatic updates */
117 | define('WP_HTTP_BLOCK_EXTERNAL', filter_var(getenv_docker('WORDPRESS_HTTP_BLOCK_EXTERNAL', 'false'), FILTER_VALIDATE_BOOLEAN));
118 | define('WP_AUTO_UPDATE_CORE', filter_var(getenv_docker('WORDPRESS_AUTO_UPDATE_CORE', 'false'), FILTER_VALIDATE_BOOLEAN));
119 | define('AUTOMATIC_UPDATER_DISABLED', filter_var(getenv_docker('WORDPRESS_AUTOMATIC_UPDATER_DISABLED', 'true'), FILTER_VALIDATE_BOOLEAN));
120 |
121 | /** Move directories */
122 | define('WP_CONTENT_DIR', __DIR__ . '/content');
123 | define('WP_CONTENT_URL', getenv_docker('WORDPRESS_SITE_URL', 'https://localhost') . '/wp-content');
124 |
125 | define('WP_PLUGIN_DIR', __DIR__ . '/content/plugins');
126 | define('WP_PLUGIN_URL', getenv_docker('WORDPRESS_SITE_URL', 'https://localhost') . '/wp-content/plugins');
127 | define('PLUGINDIR', __DIR__ . '/content/plugins');
128 |
129 |
130 | /**
131 | * Handle SSL reverse proxy
132 | */
133 | if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && str_contains($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https')) {
134 | $_SERVER['HTTPS'] = 'on';
135 | }
136 |
137 | if ($configExtra = getenv_docker('WORDPRESS_CONFIG_EXTRA', '')) {
138 | eval($configExtra);
139 | }
140 |
141 | /* That's all, stop editing! Happy blogging. */
142 |
143 | /** Absolute path to the WordPress directory. */
144 | if (!defined('ABSPATH')) {
145 | define('ABSPATH', __DIR__ . '/core/');
146 | }
147 |
148 | /** Sets up WordPress vars and included files. */
149 | require_once ABSPATH . 'wp-settings.php';
150 |
151 | /** Handles additional stuff in global scope. */
152 | require_once __DIR__ . '/../vendor/phpsword/sword-bundle/src/Loader/wp-load.php';
153 |
--------------------------------------------------------------------------------
/src/Attribute/AsWordpressCommand.php:
--------------------------------------------------------------------------------
1 | getAttributes(AsWordpressCommand::class)) {
35 | return $attribute[0]->newInstance()->name;
36 | }
37 |
38 | return null;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Command/WpCommand.php:
--------------------------------------------------------------------------------
1 | ignoreValidationErrors();
42 | }
43 |
44 | protected function execute(InputInterface $input, OutputInterface $output): int
45 | {
46 | global $wordpressLoader, $argv, $argc, $wpCliBootstrapState;
47 |
48 | $wordpressLoader = $this->wordpressLoader;
49 |
50 | foreach (WordpressGlobals::GLOBALS as $global) {
51 | global $$global;
52 | }
53 |
54 | $argv = \array_slice($argv, 1, $argc - 1);
55 | $argv[] = sprintf('--path=%s', $this->wordpressDirectory);
56 | $argv = array_unique($argv);
57 | $argc = \count($argv);
58 |
59 | foreach ($this->getBootstrapStates() as $step) {
60 | /** @var BootstrapStep $stepInstance */
61 | $stepInstance = new $step();
62 | $wpCliBootstrapState = $stepInstance->process($wpCliBootstrapState);
63 | }
64 |
65 | return Command::SUCCESS;
66 | }
67 |
68 | private function getBootstrapStates(): array
69 | {
70 | return [
71 | DeclareMainClass::class,
72 | DeclareAbstractBaseCommand::class,
73 | IncludeFrameworkAutoloader::class,
74 | ConfigureRunner::class,
75 | InitializeColorization::class,
76 | InitializeLogger::class,
77 | DefineProtectedCommands::class,
78 | LoadExecCommand::class,
79 | LoadRequiredCommand::class,
80 | IncludePackageAutoloader::class,
81 | IncludeFallbackAutoloader::class,
82 | RegisterFrameworkCommands::class,
83 | RegisterDeferredCommands::class,
84 | InitializeContexts::class,
85 | LaunchRunner::class,
86 | ];
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/Controller/ReauthenticateController.php:
--------------------------------------------------------------------------------
1 | headers->get('referer') === $request->getRequestUri()
25 | ? $this->redirectToRoute(Routes::WORDPRESS, [
26 | 'path' => ''
27 | ])
28 | : $this->redirect($request->headers->get('referer') ?: $this->generateUrl(Routes::WORDPRESS, [
29 | 'path' => ''
30 | ]));
31 |
32 | $wordpressLoader->loadWordpress();
33 | $userReauthenticator->reauthenticate();
34 |
35 | return $response;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Controller/Routes.php:
--------------------------------------------------------------------------------
1 | }', name: Routes::WORDPRESS, priority: -100)]
15 | public function index(WordpressLoader $wordpressLoader, string $path): Response
16 | {
17 | return $wordpressLoader->createWordpressResponse($path);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/DependencyInjection/Compiler/WordpressPass.php:
--------------------------------------------------------------------------------
1 | processWidgets($container);
16 | $this->processPublicServices($container);
17 | }
18 |
19 | private function processWidgets(ContainerBuilder $container): void
20 | {
21 | $widgetStore = $container->findDefinition(WordpressWidgetStore::class);
22 | $taggedServices = $container->findTaggedServiceIds('sword.wordpress_widget');
23 |
24 | foreach (array_keys($taggedServices) as $widget) {
25 | $widgetStore->addMethodCall('addWidget', [$widget]);
26 | }
27 | }
28 |
29 | /**
30 | * @param ContainerBuilder $container
31 | * @return void
32 | */
33 | private function processPublicServices(ContainerBuilder $container): void
34 | {
35 | $publicServices = $container->getParameter('sword.public_services');
36 |
37 | foreach ($publicServices as $service) {
38 | $definition = $container->findDefinition($service);
39 |
40 | if ($container->hasAlias($service)) {
41 | $alias = $container->getAlias($service);
42 | $alias->setPublic(true);
43 | } else {
44 | $definition->setPublic(true);
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/DependencyInjection/Configuration.php:
--------------------------------------------------------------------------------
1 | getRootNode()
15 | ->children()
16 | ->scalarNode('wordpress_core_dir')->defaultValue('%kernel.project_dir%/wp/core')->end()
17 | ->scalarNode('wordpress_content_dir')->defaultValue('%kernel.project_dir%/wp/content')->end()
18 | ->scalarNode('child_theme_translation_domain')->isRequired()->end()
19 | ->scalarNode('child_theme_language_path')->defaultValue('%kernel.project_dir%/translations/%sword.child_theme_translation_domain%')->end()
20 | ->scalarNode('table_prefix')->defaultValue('wp_')->end()
21 | ->scalarNode('app_namespace')->defaultValue('App\\')->end()
22 | ->scalarNode('widgets_namespace')->defaultValue('App\\Widget\\')->end()
23 | ->scalarNode('widgets_path')->defaultValue('%kernel.project_dir%/src/Widget/')->end()
24 | ->scalarNode('wordpress_host')->defaultValue('')->end()
25 | ->arrayNode('overridden_configurations')
26 | ->scalarPrototype()->end()
27 | ->end()
28 | ->arrayNode('public_services')
29 | ->scalarPrototype()->end()
30 | ->end()
31 | ->end()
32 | ;
33 |
34 | return $treeBuilder;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/DependencyInjection/SwordExtension.php:
--------------------------------------------------------------------------------
1 | getExtensionConfig('sword');
26 | $prioritizedConfigNames = array_diff(
27 | ['security', 'doctrine'],
28 | $swordConfig[0]['overridden_configurations'] ?? []
29 | );
30 | $prioritizedConfigs = [];
31 | $extensions = $container->getExtensions();
32 |
33 | foreach (Yaml::parseFile(__DIR__ . '/../../config/app.yaml') as $name => $config) {
34 | if (empty($extensions[$name])) {
35 | continue;
36 | }
37 |
38 | if (\in_array($name, $prioritizedConfigNames, true)) {
39 | if (!\array_key_exists($name, $prioritizedConfigs)) {
40 | $prioritizedConfigs[$name] = [];
41 | }
42 |
43 | $prioritizedConfigs[$name][] = $config;
44 | } else {
45 | if ($name === 'doctrine') {
46 | $config = $this->mergeDoctrineConfig($container, $config);
47 | }
48 |
49 | $this->mergeConfigIntoOne($container, $name, $config);
50 | }
51 | }
52 |
53 | foreach ($prioritizedConfigNames as $name) {
54 | if (empty($prioritizedConfigs[$name])) {
55 | continue;
56 | }
57 |
58 | foreach ($prioritizedConfigs[$name] as $config) {
59 | if ($name === 'doctrine') {
60 | $config = $this->mergeDoctrineConfig($container, $config);
61 | }
62 |
63 | $this->mergeConfigIntoOne($container, $name, $config, true);
64 | }
65 | }
66 | }
67 |
68 | protected function loadInternal(array $mergedConfig, ContainerBuilder $container): void
69 | {
70 | $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../../config'));
71 | $loader->load('services.yaml');
72 |
73 | $container->registerForAutoconfiguration(WordpressService::class)
74 | ->addTag('sword.wordpress_service')
75 | ;
76 |
77 | $container->setParameter('sword.wordpress_core_dir', $mergedConfig['wordpress_core_dir']);
78 | $container->setParameter('sword.wordpress_content_dir', $mergedConfig['wordpress_content_dir']);
79 | $container->setParameter(
80 | 'sword.child_theme_translation_domain',
81 | $mergedConfig['child_theme_translation_domain'],
82 | );
83 | $container->setParameter('sword.table_prefix', $mergedConfig['table_prefix']);
84 | $container->setParameter('sword.public_services', $mergedConfig['public_services']);
85 | $container->setParameter('sword.widgets_path', $mergedConfig['widgets_path']);
86 | $container->setParameter('sword.app_namespace', $mergedConfig['app_namespace']);
87 | $container->setParameter('sword.wordpress_host', $mergedConfig['wordpress_host']);
88 |
89 | if ($mergedConfig['widgets_path'] && file_exists($mergedConfig['widgets_path'])) {
90 | $definition = (new Definition())
91 | ->setLazy(true)
92 | ->addTag('sword.wordpress_widget')
93 | ;
94 | $loader->registerClasses($definition, $mergedConfig['widgets_namespace'], $mergedConfig['widgets_path']);
95 | }
96 |
97 | $definition = new Definition(RegexSchemaAssetFilter::class, ['~^(?!(%sword.table_prefix%))~']);
98 | $definition->addTag('doctrine.dbal.schema_filter', [
99 | 'connection' => 'default',
100 | ]);
101 | $container->setDefinition('doctrine.dbal.default_regex_schema_filter', $definition);
102 | }
103 |
104 | private function mergeDoctrineConfig(ContainerBuilder $container, array $config): array
105 | {
106 | $doctrineConfig = $container->getExtensionConfig('doctrine');
107 |
108 | if (isset($doctrineConfig[0]['dbal']['connections'])) {
109 | if (empty($doctrineConfig[0]['dbal']['connections']['default'])) {
110 | $doctrineConfig[0]['dbal']['connections']['default'] = $config['dbal'];
111 | }
112 |
113 | $config['dbal'] = $doctrineConfig[0]['dbal'];
114 | }
115 |
116 | return $config;
117 | }
118 |
119 | private function mergeConfigIntoOne(
120 | ContainerBuilder $container,
121 | string $name,
122 | array $config = [],
123 | bool $reverse = false,
124 | ): void {
125 | $originalConfig = $container->getExtensionConfig($name);
126 | if (!\count($originalConfig)) {
127 | $originalConfig[] = [];
128 | }
129 |
130 | $originalConfig[0] = $reverse
131 | ? $this->mergeDistinct($originalConfig[0], $config)
132 | : $this->mergeDistinct($config, $originalConfig[0]);
133 |
134 | $this->setExtensionConfig($container, $name, $originalConfig);
135 | }
136 |
137 | private function setExtensionConfig(ContainerBuilder $container, string $name, array $config = []): void
138 | {
139 | $classRef = new ReflectionClass(ContainerBuilder::class);
140 | $extensionConfigsRef = $classRef->getProperty('extensionConfigs');
141 |
142 | $newConfig = $extensionConfigsRef->getValue($container);
143 | $newConfig[$name] = $config;
144 | $extensionConfigsRef->setValue($container, $newConfig);
145 | }
146 |
147 | private function mergeDistinct(array $first, array $second): array
148 | {
149 | foreach ($second as $index => $value) {
150 | if (\is_int($index) && !\in_array($value, $first, true)) {
151 | $first[] = $value;
152 | } elseif (!\array_key_exists($index, $first)) {
153 | $first[$index] = $value;
154 | } elseif (\is_array($value)) {
155 | if (\is_array($first[$index])) {
156 | $first[$index] = $this->mergeDistinct($first[$index], $value);
157 | } else {
158 | $first[$index] = $value;
159 | }
160 | } else {
161 | $first[$index] = $value;
162 | }
163 | }
164 |
165 | return $first;
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/src/Entity/WordpressEntityInterface.php:
--------------------------------------------------------------------------------
1 | 'string',
28 | ];
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Event/WooCommerceRegistrationEvent.php:
--------------------------------------------------------------------------------
1 | 'checkWordpressLoggedInStatus',
33 | ];
34 | }
35 |
36 | public function checkWordpressLoggedInStatus(RequestEvent $event): void
37 | {
38 | $controller = $event->getRequest()
39 | ->attributes->get('_controller');
40 |
41 | if (
42 | !(str_starts_with($controller, 'Sword\\SwordBundle\\') || str_starts_with($controller, $this->appNamespace))
43 | || $event->getRequest()
44 | ->attributes->get('_route') === Routes::REAUTHENTICATE
45 | || $this->tokenStorage->getToken()?->getUser()
46 | ) {
47 | return;
48 | }
49 |
50 | $host = $this->wordpressHost ?: $event->getRequest()
51 | ->getSchemeAndHttpHost();
52 | $cookieName = 'wordpress_logged_in_' . md5($host);
53 |
54 | if (\array_key_exists($cookieName, $event->getRequest()->cookies->all())) {
55 | $this->wordpressLoader->loadWordpress();
56 |
57 | if (!is_user_logged_in()) {
58 | $response = new RedirectResponse($event->getRequest()->getRequestUri());
59 | $response->headers->clearCookie($cookieName);
60 | $event->setResponse($response);
61 |
62 | return;
63 | }
64 |
65 | $this->userReauthenticator->reauthenticate();
66 |
67 | if (str_starts_with($controller, 'Sword\\SwordBundle\\')) {
68 | $event->setResponse(new RedirectResponse($host . $event->getRequest()->getRequestUri()));
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/EventListener/WordpressTablePrefixEventListener.php:
--------------------------------------------------------------------------------
1 | getClassMetadata();
25 |
26 | if ($classMetadata->isInheritanceTypeSingleTable() && !$classMetadata->isRootEntity()) {
27 | return;
28 | }
29 |
30 | if (
31 | $classMetadata->getReflectionClass()
32 | && $classMetadata->getReflectionClass()
33 | ->implementsInterface(WordpressEntityInterface::class)
34 | ) {
35 | $classMetadata->setPrimaryTable([
36 | 'name' => $this->prefix . $classMetadata->getTableName()
37 | ]);
38 |
39 | foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
40 | if ($mapping['type'] === ClassMetadataInfo::MANY_TO_MANY) {
41 | $mappedTableName = $classMetadata->associationMappings[$fieldName]['joinTable']['name'];
42 | $classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName;
43 | }
44 | }
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/EventListener/WordpressTerminateEventListener.php:
--------------------------------------------------------------------------------
1 | ['onResponse', -2048],
26 | ];
27 | }
28 |
29 | public function onResponse(ResponseEvent $event): void
30 | {
31 | if ($event->getRequest()->attributes->get('_route') === Routes::WORDPRESS) {
32 | $response = $event->getResponse();
33 |
34 | $response->sendHeaders();
35 | $response->sendContent();
36 |
37 | $this->dispatcher->dispatch(
38 | new TerminateEvent($event->getKernel(), $event->getRequest(), $response),
39 | KernelEvents::TERMINATE,
40 | );
41 |
42 | Response::closeOutputBuffers(0, true);
43 |
44 | // Trigger WordPress register_shutdown_function() callbacks
45 | exit;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Exception/WordpressLoginSuccessfulException.php:
--------------------------------------------------------------------------------
1 | $serviceId
13 | * @return T
14 | */
15 | function get_symfony_service(string $serviceId): mixed
16 | {
17 | /** @var WordpressLoader $wordpressLoader */
18 | global $wordpressLoader;
19 |
20 | return $wordpressLoader->container->get($serviceId);
21 | }
22 |
23 | function get_symfony_parameter(string $parameter): mixed
24 | {
25 | /** @var WordpressLoader $wordpressLoader */
26 | global $wordpressLoader;
27 |
28 | return $wordpressLoader->container->getParameter($parameter);
29 | }
30 |
31 | function initialize_services(): void
32 | {
33 | /** @var WordpressLoader $wordpressLoader */
34 | global $wordpressLoader;
35 |
36 | $services = iterator_to_array($wordpressLoader->wordpressServices->getIterator());
37 | $wordpressLoader->lazyServiceInstantiator->requireAll();
38 |
39 | usort(
40 | $services,
41 | static fn (WordpressService $a, WordpressService $b) => $b->getPriority() <=> $a->getPriority(),
42 | );
43 |
44 | foreach ($services as $service) {
45 | $service->initialize();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Loader/LazyServiceInstantiator.php:
--------------------------------------------------------------------------------
1 | widgetsStore->getWidgets() as $widget) {
21 | $this->load($widget);
22 | add_action('widgets_init', static fn () => register_widget($widget));
23 | }
24 | }
25 |
26 | private function load(string $class): void
27 | {
28 | $prefix = 'App\\';
29 | $baseDir = $this->projectDirectory . '/src/';
30 |
31 | $length = \strlen($prefix);
32 |
33 | if (strncmp($prefix, $class, $length) !== 0) {
34 | return;
35 | }
36 |
37 | $relativeClass = substr($class, $length);
38 | $file = $baseDir . str_replace('\\', '/', $relativeClass) . '.php';
39 |
40 | if (file_exists($file)) {
41 | require $file;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Loader/WordpressGlobals.php:
--------------------------------------------------------------------------------
1 | 'onWooCommerceRegistration',
44 | ];
45 | }
46 |
47 | public function onWooCommerceRegistration(WooCommerceRegistrationEvent $event): void
48 | {
49 | $this->auth = [
50 | 'id' => $event->customerId,
51 | 'data' => $event->customerData,
52 | ];
53 | }
54 |
55 | public function createWordpressResponse(string $urlPathName): Response
56 | {
57 | $request = $this->requestStack->getCurrentRequest();
58 |
59 | ob_start();
60 | $obLevel = ob_get_level();
61 |
62 | global $wordpressLoader;
63 | $wordpressLoader = $this;
64 |
65 | foreach (WordpressGlobals::GLOBALS as $global) {
66 | global $$global;
67 | }
68 |
69 | $entryPoint = $this->wordpressDirectory . '/index.php';
70 |
71 | if (\in_array(basename($urlPathName), ['wp-login.php', 'wp-signup.php', 'wp-comments-post.php'], true)) {
72 | $_SERVER['PHP_SELF'] = '/' . basename($urlPathName);
73 | $entryPoint = $this->wordpressDirectory . '/' . basename($urlPathName);
74 | } elseif (str_starts_with($urlPathName, 'wp-admin/')) {
75 | if ($urlPathName === 'wp-admin/') {
76 | $urlPathName = 'wp-admin/index.php';
77 | }
78 |
79 | $_SERVER['PHP_SELF'] = '/' . $urlPathName;
80 | $entryPoint = $this->wordpressDirectory . '/' . $urlPathName;
81 | } else {
82 | $_SERVER['PHP_SELF'] = '/' . $urlPathName;
83 | }
84 |
85 | $_SERVER['SCRIPT_FILENAME'] = $entryPoint;
86 |
87 | try {
88 | require_once $entryPoint;
89 | } catch (WordpressLoginSuccessfulException $exception) {
90 | return $this->getAuthResponse($exception->username, $exception->password, $exception->rememberMe);
91 | } catch (WordpressLougoutSuccessfulException) {
92 | return new RedirectResponse($this->userAuthenticator->getLoginUrl($request));
93 | }
94 |
95 | if ($this->auth) {
96 | wc_set_customer_auth_cookie($this->auth['id']);
97 |
98 | return $this->getAuthResponse(
99 | $this->auth['data']['user_login'] ?? '',
100 | $this->auth['data']['user_pass'] ?? '',
101 | false,
102 | );
103 | }
104 |
105 | while (ob_get_level() > $obLevel) {
106 | ob_end_flush();
107 | }
108 |
109 | return new Response(ob_get_clean(), is_404() ? 404 : 200);
110 | }
111 |
112 | public function loadWordpress(): void
113 | {
114 | global $wordpressLoader;
115 | $wordpressLoader = $this;
116 |
117 | foreach (WordpressGlobals::GLOBALS as $global) {
118 | global $$global;
119 | }
120 |
121 | require_once $this->wordpressDirectory . '/wp-load.php';
122 | }
123 |
124 | private function getAuthResponse(string $username, string $password, bool $rememberMe): RedirectResponse
125 | {
126 | $session = $this->requestStack->getSession();
127 | $session->getFlashBag()
128 | ->set(
129 | 'wp_login',
130 | [$username, $password, $rememberMe, $this->csrfTokenManager->getToken('authenticate') ->getValue()],
131 | );
132 |
133 | return new RedirectResponse($this->requestStack->getCurrentRequest()?->getRequestUri(), 302);
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/Loader/wp-load.php:
--------------------------------------------------------------------------------
1 | true
21 | ])]
22 | protected ?int $id = null;
23 |
24 | #[ORM\Column(name: 'user_login', type: 'string', length: 60)]
25 | protected ?string $login = null;
26 |
27 | #[ORM\Column(name: 'user_pass', type: 'string', length: 255)]
28 | protected ?string $pass = null;
29 |
30 | #[ORM\Column(name: 'user_nicename', type: 'string', length: 50)]
31 | protected ?string $nicename = null;
32 |
33 | #[ORM\Column(name: 'user_email', type: 'string', length: 100)]
34 | protected ?string $email = null;
35 |
36 | #[ORM\Column(name: 'user_url', type: 'string', length: 100)]
37 | protected ?string $url = null;
38 |
39 | #[ORM\Column(name: 'user_registered', type: 'datetime')]
40 | protected ?DateTime $registered;
41 |
42 | #[ORM\Column(name: 'user_activation_key', type: 'string', length: 255)]
43 | protected ?string $activationKey = null;
44 |
45 | #[ORM\Column(name: 'user_status', type: 'integer')]
46 | protected ?int $status = null;
47 |
48 | #[ORM\Column(name: 'display_name', type: 'string', length: 250)]
49 | protected ?string $displayName = null;
50 |
51 | protected ArrayCollection $metas;
52 |
53 | private array $roles = [];
54 |
55 | private array $capabilities = [];
56 |
57 | public function __construct()
58 | {
59 | $this->registered = new DateTime('1970-01-01 00:00:00');
60 | $this->metas = new ArrayCollection();
61 | }
62 |
63 | public function getId(): ?int
64 | {
65 | return $this->id;
66 | }
67 |
68 | public function getLogin(): ?string
69 | {
70 | return $this->login;
71 | }
72 |
73 | public function setLogin(string $login): self
74 | {
75 | $this->login = $login;
76 |
77 | return $this;
78 | }
79 |
80 | public function getPass(): ?string
81 | {
82 | return $this->pass;
83 | }
84 |
85 | public function setPass(?string $pass): self
86 | {
87 | $this->pass = $pass;
88 |
89 | return $this;
90 | }
91 |
92 | public function getNicename(): ?string
93 | {
94 | return $this->nicename;
95 | }
96 |
97 | public function setNicename(?string $nicename): self
98 | {
99 | $this->nicename = $nicename;
100 |
101 | return $this;
102 | }
103 |
104 | public function getEmail(): ?string
105 | {
106 | return $this->email;
107 | }
108 |
109 | public function setEmail(?string $email): self
110 | {
111 | $this->email = $email;
112 |
113 | return $this;
114 | }
115 |
116 | public function getUrl(): ?string
117 | {
118 | return $this->url;
119 | }
120 |
121 | public function setUrl(?string $url): self
122 | {
123 | $this->url = $url;
124 |
125 | return $this;
126 | }
127 |
128 | public function getRegistered(): ?DateTime
129 | {
130 | return $this->registered;
131 | }
132 |
133 | public function setRegistered(?DateTime $registered): self
134 | {
135 | $this->registered = $registered;
136 |
137 | return $this;
138 | }
139 |
140 | public function getActivationKey(): ?string
141 | {
142 | return $this->activationKey;
143 | }
144 |
145 | public function setActivationKey(?string $activationKey): self
146 | {
147 | $this->activationKey = $activationKey;
148 |
149 | return $this;
150 | }
151 |
152 | public function getStatus(): ?int
153 | {
154 | return $this->status;
155 | }
156 |
157 | public function setStatus(?int $status): self
158 | {
159 | $this->status = $status;
160 |
161 | return $this;
162 | }
163 |
164 | public function getDisplayName(): ?string
165 | {
166 | return $this->displayName;
167 | }
168 |
169 | public function setDisplayName(?string $displayName): self
170 | {
171 | $this->displayName = $displayName;
172 |
173 | return $this;
174 | }
175 |
176 | public function getMetas(): ArrayCollection
177 | {
178 | return $this->metas;
179 | }
180 |
181 | public function setMetas(ArrayCollection $metas): self
182 | {
183 | $this->metas = $metas;
184 |
185 | return $this;
186 | }
187 |
188 | public function getUserIdentifier(): string
189 | {
190 | return (string) $this->login;
191 | }
192 |
193 | public function getRoles(): array
194 | {
195 | $roles = $this->roles;
196 | $roles[] = 'ROLE_USER';
197 |
198 | return array_unique($roles);
199 | }
200 |
201 | public function setRoles(array $roles): self
202 | {
203 | $this->roles = $roles;
204 |
205 | return $this;
206 | }
207 |
208 | public function getCapabilities(): array
209 | {
210 | $capabilities = $this->capabilities;
211 |
212 | return array_unique($capabilities);
213 | }
214 |
215 | public function setCapabilities(array $capabilities): self
216 | {
217 | $this->capabilities = $capabilities;
218 |
219 | return $this;
220 | }
221 |
222 | public function eraseCredentials(): void
223 | {
224 | }
225 |
226 | public function getPassword(): ?string
227 | {
228 | return $this->getPass();
229 | }
230 |
231 | public function isEqualTo(UserInterface $user): bool
232 | {
233 | if ($user instanceof self) {
234 | $isEqual =
235 | \count($this->getRoles()) === \count($user->getRoles())
236 | && \count($this->getCapabilities()) === \count($user->getCapabilities())
237 | ;
238 |
239 | if ($isEqual) {
240 | foreach ($this->getRoles() as $role) {
241 | $isEqual = $isEqual && \in_array($role, $user->getRoles(), true);
242 | }
243 |
244 | foreach ($this->getCapabilities() as $capability) {
245 | $isEqual = $isEqual && \in_array($capability, $user->getCapabilities(), true);
246 | }
247 | }
248 |
249 | return $isEqual;
250 | }
251 |
252 | return false;
253 | }
254 | }
255 |
--------------------------------------------------------------------------------
/src/Security/UserAuthenticator.php:
--------------------------------------------------------------------------------
1 | requestStack->getCurrentRequest();
69 | $this->wordpressUsername = $username;
70 | $this->wordpressPassword = $request?->get('password', $request?->get('pwd', ''));
71 | $this->wordpressRememberMe = (bool) $request?->get('rememberme');
72 |
73 | $this->onWordpressLoginSuccess();
74 | }
75 |
76 | public function onWooCommerceLoginTerminate(): void
77 | {
78 | if (!$this->wordpressUsername || !$this->wordpressPassword) {
79 | return;
80 | }
81 |
82 | $this->onWordpressLoginSuccess();
83 | }
84 |
85 | public function onWordpressLogout(): void
86 | {
87 | if (!$this->authorizationChecker->isGranted('ROLE_USER')) {
88 | return;
89 | }
90 |
91 | if (class_exists('WC_Session_Handler')) {
92 | $woocommerceSession = apply_filters('woocommerce_session_handler', 'WC_Session_Handler');
93 |
94 | if ($woocommerceSession instanceof WC_Session_Handler) {
95 | $woocommerceSession->destroy_session();
96 | }
97 | }
98 |
99 | $logoutEvent = new LogoutEvent($this->requestStack->getCurrentRequest(), $this->tokenStorage->getToken());
100 | $this->eventDispatcher->dispatch($logoutEvent);
101 |
102 | $response = $logoutEvent->getResponse();
103 | if (!$response instanceof Response) {
104 | $response = new RedirectResponse($this->urlGenerator->generate(Routes::WORDPRESS, [
105 | 'path' => ''
106 | ]));
107 | }
108 |
109 | $this->tokenStorage->setToken();
110 | $this->requestStack->getSession()
111 | ->invalidate();
112 |
113 | throw new WordpressLougoutSuccessfulException($response);
114 | }
115 |
116 | public function onWooCommerceRegister(int $customerId, array $newCustomerData, bool $passwordGenerated): void
117 | {
118 | $this->eventDispatcher->dispatch(new WooCommerceRegistrationEvent($customerId, $newCustomerData));
119 | }
120 |
121 | public function supports(Request $request): bool
122 | {
123 | $data = $this->requestStack->getSession()
124 | ->getFlashBag()
125 | ->get('wp_login');
126 |
127 | if (!empty($data)) {
128 | [$this->wordpressUsername, $this->wordpressPassword, $this->wordpressRememberMe, $this->csrfToken] = $data;
129 | }
130 |
131 | return $this->wordpressUsername && $this->wordpressPassword && \in_array(
132 | $request->getPathInfo(),
133 | [$this->getLoginUrl($request), '/wp-login.php'],
134 | true,
135 | );
136 | }
137 |
138 | public function start(Request $request, AuthenticationException $authException = null): RedirectResponse
139 | {
140 | $url = '/wp-login.php?' . http_build_query([
141 | 'redirect_to' => $request->getUri(),
142 | 'reauth' => 0,
143 | ]);
144 |
145 | return new RedirectResponse($url, 302);
146 | }
147 |
148 | public function getLoginUrl(Request $request): string
149 | {
150 | try {
151 | $myAccountId = (int) $this->entityManager->getRepository(Option::class)
152 | ->find('woocommerce_myaccount_page_id');
153 |
154 | return sprintf(
155 | '/%s/',
156 | $this->entityManager->getRepository(Page::class)
157 | ->find($myAccountId)
158 | ->postName,
159 | );
160 | } catch (OptionNotFoundException) {
161 | return '/wp-login.php';
162 | }
163 | }
164 |
165 | public function authenticate(Request $request): Passport
166 | {
167 | $badges = [new CsrfTokenBadge('authenticate', $this->csrfToken)];
168 |
169 | if ($this->wordpressRememberMe) {
170 | $badges[] = new RememberMeBadge();
171 | }
172 |
173 | return new Passport(
174 | new UserBadge($this->wordpressUsername),
175 | new PasswordCredentials($this->wordpressPassword),
176 | $badges,
177 | );
178 | }
179 |
180 | public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
181 | {
182 | $redirectPath = $this->getRedirectPath($request);
183 |
184 | if ($request->getPathInfo() === '/wp-login.php') {
185 | if ($redirectPath) {
186 | return new RedirectResponse($redirectPath);
187 | }
188 |
189 | return new RedirectResponse($this->urlGenerator->generate(Routes::WORDPRESS, [
190 | 'path' => ''
191 | ]));
192 | }
193 |
194 | return $redirectPath
195 | ? new RedirectResponse($redirectPath)
196 | : null;
197 | }
198 |
199 | private function getRedirectPath(Request $request): ?string
200 | {
201 | $referer = $request->headers->get('referer');
202 |
203 | if ($referer && ($queryString = parse_url($referer, PHP_URL_QUERY))) {
204 | parse_str($queryString, $result);
205 |
206 | if (!empty($result['redirect_to'])) {
207 | return $result['redirect_to'];
208 | }
209 | }
210 |
211 | return null;
212 | }
213 |
214 | private function onWordpressLoginSuccess(): never
215 | {
216 | throw new WordpressLoginSuccessfulException(
217 | $this->wordpressUsername,
218 | $this->wordpressPassword,
219 | $this->wordpressRememberMe,
220 | );
221 | }
222 | }
223 |
--------------------------------------------------------------------------------
/src/Security/UserProvider.php:
--------------------------------------------------------------------------------
1 | doctrine->getRepository(User::class)
27 | ->findOneBy([
28 | 'login' => $identifier
29 | ]);
30 |
31 | $userInterop = $this->interop->getRepository(InteropUser::class)
32 | ->findOneBy([
33 | new SelectColumns(['id', 'capabilities']),
34 | 'user_login' => $identifier,
35 | ]);
36 |
37 | $wordpressRoles = $this->interop->getRepository(Option::class)
38 | ->find($this->tablePrefix . 'user_roles');
39 |
40 | $userRoles = [];
41 | $userCapabilities = [];
42 |
43 | foreach (array_keys($userInterop->capabilities->data, true) as $capability) {
44 | if (\array_key_exists($capability, $wordpressRoles)) {
45 | $userRoles[] = $capability;
46 | $userCapabilities = [...$userCapabilities, ...array_keys(
47 | $wordpressRoles[$capability]['capabilities'],
48 | true,
49 | )];
50 | } else {
51 | $userCapabilities[] = $capability;
52 | }
53 | }
54 |
55 | $user->setRoles($userRoles);
56 | $user->setCapabilities($userCapabilities);
57 |
58 | return $user;
59 | }
60 |
61 | public function refreshUser(UserInterface $user): UserInterface
62 | {
63 | if (!$user instanceof User) {
64 | throw new UnsupportedUserException(sprintf('Invalid user class "%s".', \get_class($user)));
65 | }
66 |
67 | return $this->loadUserByIdentifier($user->getUserIdentifier());
68 | }
69 |
70 | public function supportsClass(string $class): bool
71 | {
72 | return $class === User::class || is_subclass_of($class, User::class);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/Security/UserReauthenticator.php:
--------------------------------------------------------------------------------
1 | userProvider->loadUserByIdentifier(wp_get_current_user()->user_login);
31 | $this->userChecker->checkPreAuth($user);
32 | $this->managersLocator->get('main')
33 | ->authenticateUser($user, $this->authenticator, $this->requestStack->getMainRequest());
34 |
35 | return true;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Security/Voter/CapabilityVoter.php:
--------------------------------------------------------------------------------
1 | getUser() instanceof User ? $token->getUser() : null;
17 |
18 | if (!$user instanceof User) {
19 | return $result;
20 | }
21 |
22 | foreach ($attributes as $attribute) {
23 | $result = self::ACCESS_DENIED;
24 |
25 | if (\in_array($attribute, $user->getCapabilities(), true)) {
26 | return self::ACCESS_GRANTED;
27 | }
28 | }
29 |
30 | return $result;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Security/Voter/RoleVoter.php:
--------------------------------------------------------------------------------
1 | getUser() instanceof User ? $token->getUser() : null;
23 |
24 | if (!$user instanceof User) {
25 | return $result;
26 | }
27 |
28 | foreach ($attributes as $attribute) {
29 | $result = VoterInterface::ACCESS_DENIED;
30 |
31 | if (\in_array($attribute, $this->roleHierarchy->getReachableRoleNames($user->getRoles()), true)) {
32 | return VoterInterface::ACCESS_GRANTED;
33 | }
34 | }
35 |
36 | return $result;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Service/AbstractWordpressService.php:
--------------------------------------------------------------------------------
1 | widgets;
14 | }
15 |
16 | public function addWidget(string $widget): void
17 | {
18 | $this->widgets[$widget] = $widget;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/SwordBundle.php:
--------------------------------------------------------------------------------
1 | addCompilerPass(new WordpressPass());
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Translation/ChildThemeTranslationInitializer.php:
--------------------------------------------------------------------------------
1 | textDomain, $this->getLanguagesPath());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Translation/LocaleSwitcher.php:
--------------------------------------------------------------------------------
1 | localeSwitcher->setLocale(get_locale());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Widget/DefineWidgetTrait.php:
--------------------------------------------------------------------------------
1 | widget_id = $id;
17 | $this->widget_name = $name;
18 | $this->widget_description = $description;
19 | $this->widget_cssclass = $cssClass;
20 | $this->settings = $fields;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------