diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000000000000000000000000000000000..eda15791879e21ad76ee3d4230c9f31c762828cb --- /dev/null +++ b/.editorconfig @@ -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] +indent_size = 2 \ No newline at end of file diff --git a/README.md b/README.md index 554a14ce697908cd623c7b2b71bb3af1ca4d27b6..8c685e63729f7ce72e35e3705f02ca3e473b538e 100644 --- a/README.md +++ b/README.md @@ -1,93 +1,40 @@ -# drupal-purger -This module allows Section’s global, distributed caching layer to quickly -respond to invalidation events from a Drupal instance in exactly the same way -that Drupal’s internal cache or a local varnish cache running on the host -machine does, ensuring that the content in Section’s global caching layer is -always up to date. - -## Installation - -For installation instructions please [go here](https://www.section.io/docs/how-to/drupal-setup/drupal8/) - -## Development - -Notes on Architecture: - -- Assuming you have the purge module installed, navigate to the Purger's UI at -`/admin/config/development/performance/purge` -- This module depends on the key module to store your password for aperture. -Make sure your password is correct because the purger will send hundreds of -requests to the API which could potentially lock out your account if the -authentication attempts fail. -- Drupal will queue bans with the Core tags queuer, but make sure you have a -processor installed (cron, or LateRuntimeProcessor) -- The bundled purger will combine tag purges into one request per every 250 tag -invalidations in the queue. Bundled URL purging is not supported but we are open -to feedback – after consulting with the back-end team, the opinion is that this -would be too resource intensive. -- Tags are hashed to preserve privacy. If varnish caches a page while logged in, -you will need to clear the cache. Consider updating your VCL to not cache -requests that have either tags specific to authentication, or a session cookie. -More info on this in the installation instructions linked above. -- There are many other invalidation types that you can use with other processors -and queuers. See the table below. -- The actual purger functions are performed by code inside -`src/Plugin/Purge/Purger/SectionPurgerBase` as well as the two child classes of -it: `SectionPurger` and `SectionBundledPurger`. -- The configuration form is controlled by code in `src/Form`. Data input via -this form is stored in `/src/Entity/SectionPurgerSettings.php`. If you want to -create a hardcoded variable value that is not customer facing, simply include -this variable in this file and make no reference to it in the form. -If you'd like a default value that is subsequently adjustable by the user, add -that variable with the default value to `SectionPurgerSettings.php` and add its -field to the user input form. There are examples of both of these in the -existing codebase. Note that in order for a variable to be overwritten by the -form input, it needs to be enumerated in the `section_purger.schema.yml` -- This module was developed as a fork of the generic http purger. Any questions -on the development history can be answered by comparing the current state to -that project — the git history is rather mangled due to moving between repos. -- The generic HTTP purger also contained code for a Bundled Purger (which lived -in the Purger directory alongside the Section Purgers). The functionality of -this has not been comprehensively understood, but in the abstract it coalesces -multiple ban requests into a single API call. Because the choke point for this -operation was believed to be Varnish Cache's ability to process bans rather than -the API's ability to accept requests, this mode was determined to be unnecessary -at the time. If this functionality is desired, the relevant code (it was not -adapted for Section in any way before deletion) can be recovered from version -control or from the source HTTP Purger. -- The plugin currently supports an optional sitename feature designed to -support Drupal multisites. If no sitename is specified, then the plugin clears -cache for any pages with the relevant cache tags. If the sitename is filled in, -the plugin appends a check for the specified hostname. Each Drupal site within -a multisite has its own admin dashboard and its own UI in which to enable the -purger. -- The plugin is able to handle alternate varnish proxy names (as written in your -section config). Usually the name for the proxy is 'varnish' but some -configurations have multiple instances of varnish running for different tasks. -Note that if using multiple varnish instances, you will have to enable another -purger in order to handle multiple instances of varnish. If using multi-site -as well as multiple varnish proxies, you will need a purger instance per-varnish -instance per-site. -- If you wish to uninstall the Plugin from a live site for the purposes of -testing, the most efficient way to do so is to uninstall the plugin from the -admin console. Once it has been uninstalled there, you can delete it from the -filesystem of the live box (Drupal may overwrite old files of the same name if -you try and upload the same module again — this has not been proven). Deleting -the module from the filesystem while it is still installed will cause a total -failure of the site. The only known fix for this is a reinstall of Drupal as a -whole, although there are likely easier ways to fix it. - - -| Invalidation Type | Description | -|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------| -| domain | Invalidates an entire domain name. e.g.: example.com | -| everything | Invalidates Everything. No argument required. | -| tag | Invalidates by Drupal cache tag, e.g.: menu:footer | -| url | Invalidates by URL, e.g. http://site.com/node/1 (***NOTE:** this, by nature, does not use the sitename configured in the purger, but rather whatever url fed to this type will be purged from varnish. Also, the protocol is specific; for example if invalidating an http request, the https equivalent will not be invalidated*) | -| wildcardurl | Invalidates by URL, e.g. http://site.com/node/* (see note above) | -| path | Invalidates by path, e.g. news/article-1. This should not start with a slash, and should not contain the hostname. | -| wildcardpath | Invalidates by path, e.g. news/* | -| regex | this will insert any string into a varnish ban expression of `req.url ~ "input"`. Will also insert a domain check if multi-site is in use. | -| raw | this allows for any varnish ban expression to be input. Useful with drush, and perhaps cronjobs e.g. obj.status == 404 && req.url ~ node\/(?).*. | - -Read more about the default invalidation types in [the purge module docs](https://www.drupal.org/project/purge/releases/8.x-3.0-beta1#invalidation-types) +# drupal-purger + +This module allows Section’s global, distributed caching layer to quickly respond to invalidation events from a Drupal instance in exactly the same way that Drupal’s internal cache or a local varnish cache running on the host machine does, ensuring that the content in Section’s global caching layer is always up to date. + +## Installation + +For installation instructions please [go here](https://www.section.io/docs/how-to/drupal-setup/drupal8/) + +## Development + +Notes on Architecture: + +- Assuming you have the purge module installed, navigate to the Purger's UI at `/admin/config/development/performance/purge` +- This module depends on the key module to store your password for aperture. Make sure your password is correct because the purger will send hundreds of requests to the API which could potentially lock out your account if the authentication attempts fail. +- Drupal will queue bans with the Core tags queuer, but make sure you have a processor installed (cron, or LateRuntimeProcessor) +- The bundled purger will combine tag purges into one request per every 250 tag invalidations in the queue. Bundled URL purging is not supported but we are open to feedback – after consulting with the back-end team, the opinion is that this would be too resource intensive. +- Tags are hashed to preserve privacy. If varnish caches a page while logged in, you will need to clear the cache. Consider updating your VCL to not cache requests that have either tags specific to authentication, or a session cookie. More info on this in the installation instructions linked above. +- There are many other invalidation types that you can use with other processors and queuers. See the table below +- The actual purger functions are performed by code inside `src/Plugin/Purge/Purger/SectionPurgerBase` as well as the two child classes of it: `SectionPurger` and `SectionBundledPurger`. +- The configuration form is controlled by code in `src/Form`. Data input via this form is stored in `/src/Entity/SectionPurgerSettings.php`. If you want to create a hardcoded variable value that is not customer facing, simply include this variable in this file and make no reference to it in the form. If you'd like a default value that is subsequently adjustable by the user, add that variable with the default value to `SectionPurgerSettings.php` and add its field to the user input form. There are examples of both of these in the existing codebase. Note that in order for a variable to be overwritten by the form input, it needs to be enumerated in the `section_purger.schema.yml` +- This module was developed as a fork of the generic http purger. Any questions on the development history can be answered by comparing the current state to that project — the git history is rather mangled due to moving between repos. +- The generic HTTP purger also contained code for a Bundled Purger (which lived in the Purger directory alongside the Section Purgers). The functionality of this has not been comprehensively understood, but in the abstract it coalesces multiple ban requests into a single API call. Because the choke point for this operation was believed to be Varnish Cache's ability to process bans rather than the API's ability to accept requests, this mode was determined to be unnecessary at the time. If this functionality is desired, the relevant code (it was not adapted for Section in any way before deletion) can be recovered from version control or from the source HTTP Purger. +- The plugin currently supports an optional sitename feature designed to support Drupal multisites. If no sitename is specified, then the plugin clears cache for any pages with the relevant cache tags. If the sitename is filled in, the plugin appends a check for the specified hostname. Each Drupal site within a multisite has its own admin dashboard and its own UI in which to enable the purger. +- The plugin is able to handle alternate varnish proxy names (as written in your section config). Usually the name for the proxy is 'varnish' but some configurations have multiple instances of varnish running for different tasks. Note that if using multiple varnish instances, you will have to enable another purger in order to handle multiple instances of varnish. If using multi-site as well as multiple varnish proxies, you will need a purger instance per-varnish instance per-site. +- If you wish to uninstall the Plugin from a live site for the purposes of testing, the most efficient way to do so is to uninstall the plugin from the admin console. Once it has been uninstalled there, you can delete it from the filesystem of the live box (Drupal may overwrite old files of the same name if you try and upload the same module again — this has not been proven). Deleting the module from the filesystem while it is still installed will cause a total failure of the site. The only known fix for this is a reinstall of Drupal as a whole, although there are likely easier ways to fix it. + + +| Invalidation Type | Description | +|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------| +| domain | Invalidates an entire domain name. e.g.: example.com | +| everything | Invalidates Everything. No argument required. | +| tag | Invalidates by Drupal cache tag, e.g.: menu:footer | +| url | Invalidates by URL, e.g. http://site.com/node/1 (***NOTE:** this, by nature, does not use the sitename configured in the purger, but rather whatever url fed to this type will be purged from varnish. Also, the protocol is specific; for example if invalidating an http request, the https equivalent will not be invalidated*) | +| wildcardurl | Invalidates by URL, e.g. http://site.com/node/* (see note above) | +| path | Invalidates by path, e.g. news/article-1. This should not start with a slash, and should not contain the hostname. | +| wildcardpath | Invalidates by path, e.g. news/* | +| regex | this will insert any string into a varnish ban expression of `req.url ~ "input"`. Will also insert a domain check if multi-site is in use. | +| raw | this allows for any varnish ban expression to be input. Useful with drush, and perhaps cronjobs e.g. obj.status == 404 && req.url ~ node\/(?).*. | + +Read more about the default invalidation types in [the purge module docs](https://www.drupal.org/project/purge/releases/8.x-3.0-beta1#invalidation-types) \ No newline at end of file diff --git a/composer.json b/composer.json index e549b914a4f2be2bc17a6765d3d988f52b8746fb..dd36a692defe3251fd3d1c51ec2894b351f2f66d 100644 --- a/composer.json +++ b/composer.json @@ -1,13 +1,11 @@ -{ - "name": "drupal/section_purger", - "type": "drupal-module", - "description": "Drupal purge module integration for Section Edge compute platform.", - "license": "GPL-2.0-or-later", - "minimum-stability": "dev", - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/section/drupal-purger.git" - } - ] -} \ No newline at end of file +{ + "name": "drupal/section_purger", + "type": "drupal-module", + "description": "Drupal purge module integration for Section Edge compute platform.", + "license": "GPL-2.0-or-later", + "require": { + "drupal/core": "^9 || ^10", + "drupal/purge": "^3.4", + "drupal/key": "^1.17" + } +} diff --git a/config/schema/section_purger.data_types.schema.yml b/config/schema/section_purger.data_types.schema.yml index 877b707df2beb59d325e0cb309695fc5f391a8f3..e61ed77d8b615f9d5aa46c96e8a73dc5cf578c6c 100644 --- a/config/schema/section_purger.data_types.schema.yml +++ b/config/schema/section_purger.data_types.schema.yml @@ -1,10 +1,10 @@ -section_purger_header: - type: mapping - label: 'Section Header' - mapping: - field: - type: string - translatable: false - value: - type: string - translatable: false +section_purger_header: + type: mapping + label: 'Section Header' + mapping: + field: + type: string + translatable: false + value: + type: string + translatable: false diff --git a/config/schema/section_purger.schema.yml b/config/schema/section_purger.schema.yml index 02d35c4b910bd523cb3b76e8bf5336302837abaf..4bc1c704ed21365e557ade6db4cceb4af31405bb 100644 --- a/config/schema/section_purger.schema.yml +++ b/config/schema/section_purger.schema.yml @@ -1,105 +1,105 @@ -section_purger.settings.*: - type: config_entity - label: 'Section Purger' - mapping: - - # - # Instance metadata: - # - id: - type: string - translatable: false - name: - type: string - translatable: false - invalidationtype: - type: string - translatable: false - - # - # Primary request information: - # - hostname: - type: string - translatable: false - sitename: - type: string - translatable: false - port: - type: integer - translatable: false - path: - type: string - translatable: false - account: - type: integer - translatable: false - application: - type: integer - translatable: false - environmentname: - type: string - translatable: false - username: - type: string - translatable: false - password: - type: key_select - translatable: false - requestMethod: - type: string - translatable: false - scheme: - type: string - translatable: false - verify: - type: string - translatable: false - varnishname: - type: string - translatable: false - - # - # Request headers (outbound): - # - headers: - type: sequence - translatable: false - sequence: - type: section_purger_header - - # - # Body (request payload): - # - body: - type: text - translatable: false - bodyContentType: - type: string - translatable: false - - # - # Performance settings: - # - runtimeMeasurement: - type: boolean - translatable: false - timeout: - type: float - translatable: false - connectTimeout: - type: float - translatable: false - cooldownTime: - type: float - translatable: false - maxRequests: - type: integer - translatable: false - - # - # Success resolution: - # - httpErrors: - type: boolean - translatable: false +section_purger.settings.*: + type: config_entity + label: 'Section Purger' + mapping: + + # + # Instance metadata: + # + id: + type: string + translatable: false + name: + type: string + translatable: false + invalidationtype: + type: string + translatable: false + + # + # Primary request information: + # + hostname: + type: string + translatable: false + sitename: + type: string + translatable: false + port: + type: integer + translatable: false + path: + type: string + translatable: false + account: + type: integer + translatable: false + application: + type: integer + translatable: false + environmentname: + type: string + translatable: false + username: + type: string + translatable: false + password: + type: key_select + translatable: false + request_method: + type: string + translatable: false + scheme: + type: string + translatable: false + verify: + type: string + translatable: false + varnishname: + type: string + translatable: false + + # + # Request headers (outbound): + # + headers: + type: sequence + translatable: false + sequence: + type: section_purger_header + + # + # Body (request payload): + # + body: + type: text + translatable: false + body_content_type: + type: string + translatable: false + + # + # Performance settings: + # + runtime_measurement: + type: boolean + translatable: false + timeout: + type: float + translatable: false + connect_timeout: + type: float + translatable: false + cooldown_time: + type: float + translatable: false + max_requests: + type: integer + translatable: false + + # + # Success resolution: + # + http_errors: + type: boolean + translatable: false diff --git a/drupalci.yml b/drupalci.yml new file mode 100644 index 0000000000000000000000000000000000000000..d6c7eec917343aecf13ee106634a67db79abbcc4 --- /dev/null +++ b/drupalci.yml @@ -0,0 +1,25 @@ +# https://www.drupal.org/drupalorg/docs/drupal-ci/customizing-drupalci-testing +build: + assessment: + validate_codebase: + # phplint: + container_composer: + phpcs: + # phpcs will use core's specified version of Coder. + sniff-all-files: true + halt-on-fail: false + testing: + container_command: + commands: + - 'mkdir /var/www/html/vfs:' + - 'chmod 0777 /var/www/html/vfs:' + run_tests.standard: + types: 'PHPUnit-Unit,PHPUnit-Kernel,PHPUnit-Functional' + testgroups: '--all' + suppress-deprecations: true + run_tests.javascript: + concurrency: 15 + types: 'PHPUnit-FunctionalJavascript' + testgroups: '--all' + suppress-deprecations: true + halt-on-fail: false diff --git a/section_purger.info.yml b/section_purger.info.yml index c564cbe1447e025d04e9723732e220b22bd6a187..2108372e808f8595e483bf0a90090311fc7098cb 100644 --- a/section_purger.info.yml +++ b/section_purger.info.yml @@ -1,10 +1,9 @@ -name: Section Purger -type: module -description: 'Purger for clearing cache on the Section Platform' -package: "Purge - reverse proxies & CDNs" -dependencies: - - purge:purge - - purge:purge_tokens - - key:key - -core_version_requirement: ^8.9 || ^9 +name: Section Purger +type: module +description: 'Purger for clearing cache on the Section Platform' +package: "Purge - reverse proxies & CDNs" +dependencies: + - purge:purge + - purge:purge_tokens + - key:key +core_version_requirement: ^9 || ^10 diff --git a/src/Entity/SectionPurgerSettings.php b/src/Entity/SectionPurgerSettings.php index 5c45fb385bc87da1142b23e7f18d0008511ad49b..376136bf2f9e37b63140b12d4a50e2f3b4c04efb 100644 --- a/src/Entity/SectionPurgerSettings.php +++ b/src/Entity/SectionPurgerSettings.php @@ -15,33 +15,33 @@ use Drupal\purge\Plugin\Purge\Purger\PurgerSettingsInterface; * static_cache = TRUE, * entity_keys = {"id" = "id"}, * config_export = { - * "account", - * "application", - * "body", - * "bodyContentType", - * "connectTimeout", - * "cooldownTime", - * "description", - * "environmentname", - * "headers", - * "hostname", - * "httpErrors", * "id", - * "invalidationtype", * "label", - * "maxRequests", + * "description", * "name", - * "password", - * "path", - * "port", - * "requestMethod", - * "runtimeMeasurement", - * "scheme", + * "invalidationtype", + * "hostname", * "sitename", - * "timeout", + * "port", + * "path", + * "account", + * "application", + * "environmentname", * "username", + * "password", + * "request_method", + * "scheme", + * "verify", * "varnishname", - * "verify" + * "headers", + * "body", + * "body_content_type", + * "runtime_measurement", + * "timeout", + * "connect_timeout", + * "cooldown_time", + * "max_requests", + * "http_errors" * }, * ) */ @@ -111,6 +111,7 @@ class SectionPurgerSettings extends PurgerSettingsBase implements PurgerSettings */ public $application = 100; + /** * Section environment name i.e. Production, Staging, etc. * @@ -144,7 +145,8 @@ class SectionPurgerSettings extends PurgerSettingsBase implements PurgerSettings * * @var string */ - public $requestMethod = 'POST'; + // @phpcs:ignore + public $request_method = 'POST'; /** * The HTTP scheme. @@ -189,7 +191,8 @@ class SectionPurgerSettings extends PurgerSettingsBase implements PurgerSettings * * @var string */ - public $bodyContentType = 'application/json'; + // @phpcs:ignore + public $body_content_type = 'application/json'; /** * Performance settings. @@ -199,11 +202,12 @@ class SectionPurgerSettings extends PurgerSettingsBase implements PurgerSettings * Runtime measurement. * * When FALSE, dynamic capacity calculation will be disabled and based upon - * the connectTimeout and timeout settings. + * the connect_timeout and timeout settings. * * @var bool */ - public $runtimeMeasurement = TRUE; + // @phpcs:ignore + public $runtime_measurement = TRUE; /** * The timeout of the request in seconds. @@ -217,7 +221,8 @@ class SectionPurgerSettings extends PurgerSettingsBase implements PurgerSettings * * @var float */ - public $connectTimeout = 1.0; + // @phpcs:ignore + public $connect_timeout = 1.0; /** * Cooldown time. @@ -227,7 +232,8 @@ class SectionPurgerSettings extends PurgerSettingsBase implements PurgerSettings * * @var float */ - public $cooldownTime = 0.0; + // @phpcs:ignore + public $cooldown_time = 0.0; /** * Maximum requests. @@ -238,7 +244,8 @@ class SectionPurgerSettings extends PurgerSettingsBase implements PurgerSettings * * @var int */ - public $maxRequests = 250; + // @phpcs:ignore + public $max_requests = 250; /** * Success resolution. @@ -251,6 +258,7 @@ class SectionPurgerSettings extends PurgerSettingsBase implements PurgerSettings * * @see http://docs.guzzlephp.org/en/latest/request-options.html#http-errors */ - public $httpErrors = TRUE; + // @phpcs:ignore + public $http_errors = TRUE; } diff --git a/src/Form/SectionPurgerFormBase.php b/src/Form/SectionPurgerFormBase.php index 439e1b9281ba1447baaa77e3384f2d919fd4155c..4f05ed4c67d340190fd6f5f2e3133ba9e76eb60d 100644 --- a/src/Form/SectionPurgerFormBase.php +++ b/src/Form/SectionPurgerFormBase.php @@ -2,13 +2,13 @@ namespace Drupal\section_purger\Form; +use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\purge\Plugin\Purge\Invalidation\InvalidationsServiceInterface; use Drupal\purge_ui\Form\PurgerConfigFormBase; use Drupal\section_purger\Entity\SectionPurgerSettings; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; /** * Abstract form base for HTTP based configurable purgers. @@ -28,6 +28,7 @@ abstract class SectionPurgerFormBase extends PurgerConfigFormBase { * @var array * * @todo Confirm if all relevant HTTP methods are covered. + * * http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html */ protected $requestMethods = [ @@ -71,10 +72,10 @@ abstract class SectionPurgerFormBase extends PurgerConfigFormBase { */ public static function create(ContainerInterface $container) { return new static( - $container->get('config.factory'), - $container->get('purge.invalidation.factory'), - $container->get('entity_type.manager') - ); + $container->get('config.factory'), + $container->get('purge.invalidation.factory'), + $container->get('entity_type.manager') + ); } /** @@ -212,7 +213,7 @@ abstract class SectionPurgerFormBase extends PurgerConfigFormBase { ]; for ($i = 0; $i < $form_state->get('headers_items_count'); $i++) { if (!isset($form['headers']['headers'][$i])) { - $header = isset($settings->headers[$i]) ?? + $header = $settings->headers[$i] ?? [ 'field' => 'Section-Cache-Tags', 'value' => '[invalidation:expression]', @@ -274,36 +275,36 @@ abstract class SectionPurgerFormBase extends PurgerConfigFormBase { '#group' => 'tabs', '#title' => $this->t('Performance'), ]; - $form['performance']['cooldownTime'] = [ + $form['performance']['cooldown_time'] = [ '#type' => 'number', '#step' => 0.1, '#min' => 0.0, '#max' => 3.0, '#title' => $this->t('Cooldown time'), - '#default_value' => $settings->cooldownTime, + '#default_value' => $settings->cooldown_time, '#required' => TRUE, '#description' => $this->t('Number of seconds to wait after a group of HTTP requests (so that other purgers get fresh content)'), ]; - $form['performance']['maxRequests'] = [ + $form['performance']['max_requests'] = [ '#type' => 'number', '#step' => 1, '#min' => 1, '#max' => 500, '#title' => $this->t('Maximum requests'), - '#default_value' => $settings->maxRequests, + '#default_value' => $settings->max_requests, '#required' => TRUE, '#description' => $this->t("Maximum number of HTTP requests that can be made during Drupal's execution lifetime. Usually PHP resource restraints lower this value dynamically, but can be met at the CLI."), ]; - $form['performance']['runtimeMeasurement'] = [ + $form['performance']['runtime_measurement'] = [ '#title' => $this->t('Runtime measurement'), '#type' => 'checkbox', - '#default_value' => $settings->runtimeMeasurement, + '#default_value' => $settings->runtime_measurement, ]; - $form['performance']['runtimeMeasurement_help'] = [ + $form['performance']['runtime_measurement_help'] = [ '#type' => 'item', '#states' => [ 'visible' => [ - ':input[name="runtimeMeasurement"]' => ['checked' => FALSE], + ':input[name="runtime_measurement"]' => ['checked' => FALSE], ], ], '#description' => $this->t('When you uncheck this setting, capacity will be based on the sum of both timeouts. By default, capacity will automatically adjust (up and down) based on measured time data.'), @@ -318,22 +319,22 @@ abstract class SectionPurgerFormBase extends PurgerConfigFormBase { '#required' => TRUE, '#states' => [ 'visible' => [ - ':input[name="runtimeMeasurement"]' => ['checked' => FALSE], + ':input[name="runtime_measurement"]' => ['checked' => FALSE], ], ], '#description' => $this->t('The timeout of the request in seconds.'), ]; - $form['performance']['connectTimeout'] = [ + $form['performance']['connect_timeout'] = [ '#type' => 'number', '#step' => 0.1, '#min' => 0.1, '#max' => 4.0, '#title' => $this->t('Connection timeout'), - '#default_value' => $settings->connectTimeout, + '#default_value' => $settings->connect_timeout, '#required' => TRUE, '#states' => [ 'visible' => [ - ':input[name="runtimeMeasurement"]' => ['checked' => FALSE], + ':input[name="runtime_measurement"]' => ['checked' => FALSE], ], ], '#description' => $this->t('The number of seconds to wait while trying to connect to a server.'), @@ -346,13 +347,13 @@ abstract class SectionPurgerFormBase extends PurgerConfigFormBase { public function validateForm(array &$form, FormStateInterface $form_state) { // Validate that our timeouts stay between the boundaries purge demands. - $timeout = $form_state->getValue('connectTimeout') + $form_state->getValue('timeout'); + $timeout = $form_state->getValue('connect_timeout') + $form_state->getValue('timeout'); if ($timeout > 10) { - $form_state->setErrorByName('connectTimeout'); + $form_state->setErrorByName('connect_timeout'); $form_state->setErrorByName('timeout', $this->t('The sum of both timeouts cannot be higher than 10.00 as this would affect performance too negatively.')); } elseif ($timeout < 0.4) { - $form_state->setErrorByName('connectTimeout'); + $form_state->setErrorByName('connect_timeout'); $form_state->setErrorByName('timeout', $this->t('The sum of both timeouts cannot be lower as 0.4 as this can lead to too many failures under real usage conditions.')); } } @@ -379,12 +380,12 @@ abstract class SectionPurgerFormBase extends PurgerConfigFormBase { $form_state->setValue('headers', $headers); } - // Rewrite 'scheme' and 'requestMethod' to have the right CMI values. + // Rewrite 'scheme' and 'request_method' to have the right CMI values. if (!is_null($scheme = $form_state->getValue('scheme'))) { $form_state->setValue('scheme', $this->schemes[$scheme]); } - if (!is_null($method = $form_state->getValue('requestMethod'))) { - $form_state->setValue('requestMethod', $this->requestMethods[$method]); + if (!is_null($method = $form_state->getValue('request_method'))) { + $form_state->setValue('request_method', $this->requestMethods[$method]); } // Iterate the config object and overwrite values found in the form state. diff --git a/src/Plugin/Purge/DiagnosticCheck/ConfigurationCheck.php b/src/Plugin/Purge/DiagnosticCheck/ConfigurationCheck.php index 64eb4f9b2500e240d630758bbf577efd2ae192cf..f2998f861e772572e4020120f5d11a02f695314e 100644 --- a/src/Plugin/Purge/DiagnosticCheck/ConfigurationCheck.php +++ b/src/Plugin/Purge/DiagnosticCheck/ConfigurationCheck.php @@ -14,9 +14,9 @@ use Drupal\section_purger\Entity\SectionPurgerSettings; * @PurgeDiagnosticCheck( * id = "sectionconfiguration", * title = @Translation("Section"), - * description = @Translation("Verifies that only fully configured Section purgers load."), - * dependent_queue_plugins = {}, - * dependent_purger_plugins = {"section"} + * description = @Translation("Verifies that only fully configured Section + * purgers load."), dependent_queue_plugins = {}, dependent_purger_plugins = + * {"section"} * ) */ class ConfigurationCheck extends DiagnosticCheckBase implements DiagnosticCheckInterface { @@ -50,10 +50,10 @@ class ConfigurationCheck extends DiagnosticCheckBase implements DiagnosticCheckI */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( - $configuration, - $plugin_id, - $plugin_definition, - $container->get('purge.purgers') + $configuration, + $plugin_id, + $plugin_definition, + $container->get('purge.purgers') ); } @@ -83,7 +83,7 @@ class ConfigurationCheck extends DiagnosticCheckBase implements DiagnosticCheckI 'password', 'environmentname', 'port', - 'requestMethod', + 'request_method', 'scheme', ] as $f) { if (empty($settings->$f)) { diff --git a/src/Plugin/Purge/Invalidation/RawInvalidation.php b/src/Plugin/Purge/Invalidation/RawInvalidation.php index f03ea45602e82e105a03ccaa4cd38bb83ebc392a..b8d78752042b26f68e376b003a31e1d7abe5057c 100644 --- a/src/Plugin/Purge/Invalidation/RawInvalidation.php +++ b/src/Plugin/Purge/Invalidation/RawInvalidation.php @@ -20,4 +20,6 @@ use Drupal\purge\Plugin\Purge\Invalidation\InvalidationBase; * expression_must_be_string = TRUE * ) */ -class RawInvalidation extends InvalidationBase implements InvalidationInterface {} +class RawInvalidation extends InvalidationBase implements InvalidationInterface { + +} diff --git a/src/Plugin/Purge/Purger/SectionBundledPurger.php b/src/Plugin/Purge/Purger/SectionBundledPurger.php index 70aee7acb1be790c6381894c5e52e5133c7a8e32..414139f51958f6991d7bf438b6df3383b89f1156 100644 --- a/src/Plugin/Purge/Purger/SectionBundledPurger.php +++ b/src/Plugin/Purge/Purger/SectionBundledPurger.php @@ -14,11 +14,11 @@ use Drupal\section_purger\Plugin\Purge\TagsHeader\CacheTagsHeaderValue; * id = "sectionbundled", * label = @Translation("Section Bundled Purger"), * configform = "\Drupal\section_purger\Form\SectionBundledPurgerForm", - * cooldownTime = 0.0, - * description = @Translation("Configurable purger that sends a single HTTP request for a set of invalidation instructions."), - * multi_instance = TRUE, - * types = {"url", "raw", "wildcardurl", "tag", "everything", - * "wildcardpath", "regex", "path", "domain"}, + * cooldown_time = 0.0, + * description = @Translation("Configurable purger that sends a single HTTP + * request for a set of invalidation instructions."), multi_instance = TRUE, + * types = {"url", "raw", "wildcardurl", "tag", "everything", "wildcardpath", + * "regex", "path", "domain"}, * ) */ class SectionBundledPurger extends SectionPurgerBase implements PurgerInterface { @@ -28,23 +28,24 @@ class SectionBundledPurger extends SectionPurgerBase implements PurgerInterface */ public function invalidate(array $invalidations) { /* Since we implemented ::routeTypeToMethod(), this exception should not - ever occur because every invalidation type is routed to - a respective function. And when it does inevitably get called, - it will throw an exception easily visible within the drupal logs. + ever occur because every invalidation type is routed to a + respective function. + And when it does inevitably get called, it will throw an exception easily + visible within the drupal logs. */ throw new \Exception("invalidate() called on a multi-type purger which routes each invalidatiaton type to its own method. This error should never be seen."); } /** - * Gets an invalidations array and returns groups of 250 invalidations. + * Group(array $invalidations). * - * Group(array $invalidations) + * This takes an invalidations array and returns groups of 250 invalidations. * * @param array $invalidations - * The array of invalidations. + * An array of invalidations. * - * @return groups - * Returns a group of invalitations. + * @return array + * An array of grouped invalidations. */ public function group(array $invalidations) { $group = 0; @@ -97,23 +98,21 @@ class SectionBundledPurger extends SectionPurgerBase implements PurgerInterface } /** - * Invalidates everything within the siteName. + * InvalidateEverything($invalidations). * - * InvalidateEverything($invalidations) - * This will use obj.status != 0 to ban every page that - * does not have an empty response. + * This will use obj.status != 0 to ban every page that does not have an + * empty response. * * @param array $invalidations - * This takes in an array of Invalidation, and only make one purge because - * it only needs to ban everything once. + * This takes in an array of Invalidation, and only make one purge + * because it only needs to ban everything once. */ public function invalidateEverything(array $invalidations) { // Invalidates everything within the siteName;. - // $globalExpression = "obj.status != 0";. + $globalExpression = "obj.status != 0"; $invalidation = $invalidations[0]; - // Only make one request, but if there are multiple everything - // invalidations queued then it will make sure all of them get - // marked appropriately. + // Only make one request, but if there are multiple everything invalidations + // queued then it will make sure all of them get marked appropriately. foreach ($invalidations as $inv) { $inv->setState(InvalidationInterface::PROCESSING); } @@ -122,8 +121,8 @@ class SectionBundledPurger extends SectionPurgerBase implements PurgerInterface $uri = $this->getUri($token_data); $opt = $this->getOptions($token_data); $exp = "obj.status != 0"; - // Adds this at the end if this instance has a site name in - // the configuration, for multi-site pages. + // Adds this at the end if this instance has a site name in the + // configuration, for multi-site pages. // the ampersands are url encoded to be %26%26 in sendReq. if ($this->getSiteName()) { $exp .= ' && req.http.host == "' . $this->getSiteName() . '"'; @@ -143,9 +142,10 @@ class SectionBundledPurger extends SectionPurgerBase implements PurgerInterface /** * {@inheritdoc} */ - public function invalidateUrls(array $invalidations) { + // @phpcs:ignore + public function invalidateURLs(array $invalidations) { $this->logger->debug("[Domain] section does not support bundling URL purges but will pass this queue item on to the non-bundled purger."); - parent::invalidateUrls($invalidations); + parent::invalidateURLs($invalidations); } /** @@ -206,42 +206,36 @@ class SectionBundledPurger extends SectionPurgerBase implements PurgerInterface * The PHP method name called on the purger with a $invalidations parameter. */ public function routeTypeToMethod($type) { + // @phpcs:disable /* - Purge has to be crystal clear about what needs invalidation towards - its purgers, and therefore has the concept of invalidation types. - Individual purgers declare which types they support and can even - declare their own types when that makes sense. - Since Drupal invalidates its own caches using cache tags, the tag - type is the most important one to support in your architecture. - (and is supported, and required) + Purge has to be crystal clear about what needs invalidation towards its purgers, + and therefore has the concept of invalidation types. Individual purgers declare + which types they support and can even declare their own types when that makes sense. + Since Drupal invalidates its own caches using cache tags, the tag type is the most + important one to support in your architecture. (and is supported, and required) domain Invalidates an entire domain name. everything Invalidates everything. - path Invalidates by path, e.g. news/article-1. - This should not start with a slash, and should not contain the hostname. - regex This doesn't actually invalidate by regular expression. - It allows for varnish ban expressions. e.g. obj.status == 404 && - req.url ~ node\/(?).* !!!!!!!!!!!!!!! Invalidates by regular expression, - e.g.: \.(jpg|jpeg|css|js)$. + path Invalidates by path, e.g. news/article-1. This should not start with a slash, and should not contain the hostname. + regex This doesn't actually invalidate by regular expression. it allows for varnish ban expressions. e.g. obj.status == 404 && req.url ~ node\/(?).* !!!!!!!!!!!!!!! Invalidates by regular expression, e.g.: \.(jpg|jpeg|css|js)$. tag Invalidates by Drupal cache tag, e.g.: menu:footer. - url Invalidates by URL, e.g. http://site.com/node/1. - The protocol is specific; for example if invalidating an http request, - the https equivalent will not be invalidated + url Invalidates by URL, e.g. http://site.com/node/1. The protocol is specific; for example if invalidating an http request, the https equivalent will not be invalidated wildcardpath Invalidates by path, e.g. news/*. wildcardurl Invalidates by URL, e.g. http://site.com/node/*. */ + // @phpcs:enable $methods = [ - 'tag' => 'invalidateTags', - 'domain' => 'invalidateDomain', - 'url' => 'invalidateUrls', - 'wildcardurl' => 'invalidateWildcardUrls', - 'everything' => 'invalidateEverything', + 'tag' => 'invalidateTags', + 'domain' => 'invalidateDomain', + 'url' => 'invalidateUrls', + 'wildcardurl' => 'invalidateWildcardUrls', + 'everything' => 'invalidateEverything', 'wildcardpath' => 'invalidateWildcardPaths', - 'path' => 'invalidatePaths', - 'regex' => 'invalidateRegex', - 'raw' => 'invalidateRawExpression', + 'path' => 'invalidatePaths', + 'regex' => 'invalidateRegex', + 'raw' => 'invalidateRawExpression', ]; - return isset($methods[$type]) ?? 'invalidate'; + return $methods[$type] ?? 'invalidate'; } } diff --git a/src/Plugin/Purge/Purger/SectionPurger.php b/src/Plugin/Purge/Purger/SectionPurger.php index 79db6565b8389756eaabfe07474fc05896a8da06..a9f60d3d95a7385fb157d4b2d2dc02fabe32bb50 100644 --- a/src/Plugin/Purge/Purger/SectionPurger.php +++ b/src/Plugin/Purge/Purger/SectionPurger.php @@ -13,11 +13,11 @@ use Drupal\section_purger\Entity\Hash; * id = "section", * label = @Translation("Section Purger"), * configform = "\Drupal\section_purger\Form\SectionPurgerForm", - * cooldownTime = 0.2, - * description = @Translation("Purger that sends invalidation expressions from your Drupal instance to the Section platform."), - * multi_instance = TRUE, - * types = {"url", "wildcardurl", "tag", "everything", - * "wildcardpath", "regex", "path", "domain", "raw"}, + * cooldown_time = 0.2, + * description = @Translation("Purger that sends invalidation expressions + * from your Drupal instance to the Section platform."), multi_instance = + * TRUE, types = {"url", "wildcardurl", "tag", "everything", "wildcardpath", + * "regex", "path", "domain", "raw"}, * ) */ class SectionPurger extends SectionPurgerBase implements PurgerInterface { @@ -26,11 +26,12 @@ class SectionPurger extends SectionPurgerBase implements PurgerInterface { * {@inheritdoc} */ public function invalidate(array $invalidations) { + // @phpcs:disable /* Since we implemented ::routeTypeToMethod(), this exception should not - ever occur because every invalidation type is - routed to a respective function. And when it does inevitably get called, - it will throw an exception easily visible within the drupal logs. + ever occur because every invalidation type is routed to a respective function. + And when it does inevitably get called, it will throw an exception easily visible within the drupal logs. */ + // @phpcs:enable throw new \Exception("invalidate() called on a multi-type purger which routes each invalidatiaton type to its own method. This error should never be seen."); } @@ -57,11 +58,10 @@ class SectionPurger extends SectionPurgerBase implements PurgerInterface { } /** - * Invalidates everything within the siteName. + * InvalidateEverything($invalidations). * - * InvalidateEverything($invalidations) - * This will use obj.status != 0 to ban every page that does not have - * an empty response. + * This will use obj.status != 0 to ban every page that does not have an + * empty response. * * @param array $invalidations * This takes in an array of Invalidation, processing them all in a loop, @@ -69,15 +69,15 @@ class SectionPurger extends SectionPurgerBase implements PurgerInterface { */ public function invalidateEverything(array $invalidations) { // Invalidates everything within the siteName;. - // $globalExpression = "obj.status != 0";. + $globalExpression = "obj.status != 0"; foreach ($invalidations as $invalidation) { $invalidation->setState(InvalidationInterface::PROCESSING); $token_data = ['invalidation' => $invalidation]; $uri = $this->getUri($token_data); $opt = $this->getOptions($token_data); $exp = "obj.status != 0"; - // Adds this at the end if this instance has a site name in - // the configuration, for multi-site pages. + // Adds this at the end if this instance has a site name in the + // configuration, for multi-site pages. // the ampersands are url encoded to be %26%26 in sendReq. if ($this->getSiteName()) { $exp .= ' && req.http.host == "' . $this->getSiteName() . '"'; @@ -97,41 +97,36 @@ class SectionPurger extends SectionPurgerBase implements PurgerInterface { * The PHP method name called on the purger with a $invalidations parameter. */ public function routeTypeToMethod($type) { + // @phpcs:disable /* - Purge has to be crystal clear about what needs invalidation towards - its purgers, and therefore has the concept of invalidation types. - Individual purgers declare which types they support and can even - declare their own types when that makes sense. Since Drupal invalidates - its own caches using cache tags, the tag type is the most important one - to support in your architecture. (and is supported, and required) + Purge has to be crystal clear about what needs invalidation towards its purgers, + and therefore has the concept of invalidation types. Individual purgers declare + which types they support and can even declare their own types when that makes sense. + Since Drupal invalidates its own caches using cache tags, the tag type is the most + important one to support in your architecture. (and is supported, and required) domain Invalidates an entire domain name. everything Invalidates everything. - path Invalidates by path, e.g. news/article-1. - This should not start with a slash, and should not contain the hostname. - regex This doesn't actually invalidate by regular expression. - it allows for varnish ban expressions. e.g. obj.status == 404 && - req.url ~ node\/(?).* !!!!!!!!!!!!!!! Invalidates by regular expression, - e.g.: \.(jpg|jpeg|css|js)$. + path Invalidates by path, e.g. news/article-1. This should not start with a slash, and should not contain the hostname. + regex This doesn't actually invalidate by regular expression. it allows for varnish ban expressions. e.g. obj.status == 404 && req.url ~ node\/(?).* !!!!!!!!!!!!!!! Invalidates by regular expression, e.g.: \.(jpg|jpeg|css|js)$. tag Invalidates by Drupal cache tag, e.g.: menu:footer. - url Invalidates by URL, e.g. http://site.com/node/1. The protocol - is specific; for example if invalidating an http request, the https - equivalent will not be invalidated + url Invalidates by URL, e.g. http://site.com/node/1. The protocol is specific; for example if invalidating an http request, the https equivalent will not be invalidated wildcardpath Invalidates by path, e.g. news/*. wildcardurl Invalidates by URL, e.g. http://site.com/node/*. */ + // @phpcs:enable $methods = [ - 'tag' => 'invalidateTags', - 'domain' => 'invalidateDomain', - 'url' => 'invalidateUrls', - 'wildcardurl' => 'invalidateWildcardUrls', - 'everything' => 'invalidateEverything', + 'tag' => 'invalidateTags', + 'domain' => 'invalidateDomain', + 'url' => 'invalidateUrls', + 'wildcardurl' => 'invalidateWildcardUrls', + 'everything' => 'invalidateEverything', 'wildcardpath' => 'invalidateWildcardPaths', - 'path' => 'invalidatePaths', - 'regex' => 'invalidateRegex', - 'raw' => 'invalidateRawExpression', + 'path' => 'invalidatePaths', + 'regex' => 'invalidateRegex', + 'raw' => 'invalidateRawExpression', ]; - return isset($methods[$type]) ?? 'invalidate'; + return $methods[$type] ?? 'invalidate'; } } diff --git a/src/Plugin/Purge/Purger/SectionPurgerBase.php b/src/Plugin/Purge/Purger/SectionPurgerBase.php index 18bf83b0bd5361b7dd58666ead3c5504e0783d92..ad50c46fcd9a61f209992f02e50e43d2be6492aa 100644 --- a/src/Plugin/Purge/Purger/SectionPurgerBase.php +++ b/src/Plugin/Purge/Purger/SectionPurgerBase.php @@ -2,15 +2,15 @@ namespace Drupal\section_purger\Plugin\Purge\Purger; +use GuzzleHttp\Exception\ConnectException; use Drupal\Core\Utility\Token; -use Drupal\purge\Plugin\Purge\Invalidation\Exception\InvalidExpressionException; -use Drupal\purge\Plugin\Purge\Invalidation\InvalidationInterface; +use GuzzleHttp\ClientInterface; use Drupal\purge\Plugin\Purge\Purger\PurgerBase; use Drupal\purge\Plugin\Purge\Purger\PurgerInterface; use Drupal\section_purger\Entity\SectionPurgerSettings; -use GuzzleHttp\ClientInterface; -use GuzzleHttp\Exception\ConnectException; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\purge\Plugin\Purge\Invalidation\InvalidationInterface; +use Drupal\purge\Plugin\Purge\Invalidation\Exception\InvalidExpressionException; /** * Abstract base class for HTTP based configurable purgers. @@ -64,35 +64,36 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( - $configuration, - $plugin_id, - $plugin_definition, - $container->get('http_client'), - $container->get('token') + $configuration, + $plugin_id, + $plugin_definition, + $container->get('http_client'), + $container->get('token') ); } /** - * SendReq($invalidation,$uri,$opt) - Utilizes HTTP to avoid code repetition. + * SendReq($invalidation,$uri,$opt) + * + * This does all the HTTP dirty work to avoid code repetition. * * @param Invalidation $invalidation * The invalidation object. * @param string $uri * The URL of the API endpoint. * @param array $opt - * Request options (ie headers) + * Request options (ie headers). * @param string $exp * The ban expression. */ public function sendReq(Invalidation $invalidation, $uri, array $opt, $exp) { - // The banExpression is sent as a parameter in the URL, - // so things like ampersands, asterisks, - // question marks, etc will break the parse. + // The banExpression is sent as a parameter in the URL, so things like + // ampersands, asterisks, question marks, etc will break the parse. $exp = urlencode($exp); // Append the banExpression to the URL. $uri .= $exp; try { - /* $response = $this->client->request($this->settings->requestMethod, $uri, $opt); */ + $response = $this->client->request($this->settings->request_method, $uri, $opt); $invalidation->setState(InvalidationInterface::SUCCEEDED); } catch (ConnectException $e) { @@ -106,15 +107,15 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { $headers = $opt['headers']; unset($opt['headers']); $debug = json_encode( - str_replace( - "\n", - ' ', - [ - 'uri' => $uri, - 'method' => $this->settings->requestMethod, - 'guzzle_opt' => $opt, - 'headers' => $headers, - ] + str_replace( + "\n", + ' ', + [ + 'uri' => $uri, + 'method' => $this->settings->request_method, + 'guzzle_opt' => $opt, + 'headers' => $headers, + ] ) ); $this->logger->critical($e->getMessage() . " \ndata: " . $debug); @@ -132,14 +133,14 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { * {@inheritdoc} */ public function getCooldownTime() { - return $this->settings->cooldownTime; + return $this->settings->cooldown_time; } /** * {@inheritdoc} */ public function getIdealConditionsLimit() { - return $this->settings->maxRequests; + return $this->settings->max_requests; } /** @@ -157,15 +158,15 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { $headers['Accept'] = "application/json"; $headers['user-agent'] = 'Section Purge module for Drupal 8.'; if (strlen($this->settings->body)) { - $headers['content-type'] = $this->settings->bodyContentType; + $headers['content-type'] = $this->settings->body_content_type; } foreach ($this->settings->headers as $header) { // According to https://tools.ietf.org/html/rfc2616#section-4.2, header // names are case-insensitive. Therefore, to aid easy overrides by end // users, we lower all header names so that no doubles are sent. $headers[strtolower($header['field'])] = $this->token->replace( - $header['value'], - $token_data + $header['value'], + $token_data ); } return $headers; @@ -196,10 +197,12 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { $opt = [ 'auth' => [ $this->settings->username, - \Drupal::service('key.repository')->getKey($this->settings->password)->getKeyValue(), + \Drupal::service('key.repository') + ->getKey($this->settings->password) + ->getKeyValue(), ], - 'httpErrors' => $this->settings->httpErrors, - 'connectTimeout' => $this->settings->connectTimeout, + 'http_errors' => $this->settings->http_errors, + 'connect_timeout' => $this->settings->connect_timeout, 'timeout' => $this->settings->timeout, 'headers' => $this->getHeaders($token_data), ]; @@ -220,12 +223,12 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { */ public function getTimeHint() { // When runtime measurement is enabled, we just use the base implementation. - if ($this->settings->runtimeMeasurement) { + if ($this->settings->runtime_measurement) { return parent::getTimeHint(); } // Theoretically connection timeouts and general timeouts can add up, so // we add up our assumption of the worst possible time it takes as well. - return $this->settings->connectTimeout + $this->settings->timeout; + return $this->settings->connect_timeout + $this->settings->timeout; } /** @@ -269,7 +272,10 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { } /** - * {@inheritdoc} + * Return sitename. + * + * @return string + * The sitename string. */ protected function getSiteName() { return $this->settings->sitename; @@ -279,22 +285,20 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { * {@inheritdoc} */ public function hasRuntimeMeasurement() { - return (bool) $this->settings->runtimeMeasurement; + return (bool) $this->settings->runtime_measurement; } /** * This will invalidate urls. * - * InvalidateUrls(array $invalidations) - * The protocol is required and this must contain the hostname, - * the protocol, and path (if any) - * The protocol is specific; for example if invalidating an http request, - * the https equivalent will not be invalidated. - * e.x.: https://example.com/favicon.ico . + * The protocol is required and this must contain the hostname, the protocol, + * and path (if any). + * The protocol is specific; for example if invalidating an http request, the + * https equivalent will not be invalidated. + * https://example.com/favicon.ico for example. * * @param array $invalidations - * This takes in an array of Invalidation, - * processing them all in a loop, generally from the purge queue. + * This takes in an array of Invalidation, processing them all in a loop. */ public function invalidateUrls(array $invalidations) { foreach ($invalidations as $invalidation) { @@ -311,13 +315,15 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { // Sanitize the path. $patterns = [ // Escape regex characters except *. + '/([[\]{}()+?".,\\^$|#])/', // Replace * with .* (for actual Varnish regex) - '/([[\]{}()+?".,\\^$|#])/', '/\*/', + '/\*/', ]; $replace = [ // Escape regex characters except *. + '\\\$1', // Replace * with .* (for actual Varnish regex) - '\\\$1', '.*', + '.*', ]; $exp = 'req.http.X-Forwarded-Proto == "' . $parse['scheme'] . '" && ' . '" && req.http.host == "' . $parse['host'] . '" && req.url ~ "^'; $exp .= preg_replace($patterns, $replace, substr($parse['path'], 1) . $parse['query'] . $parse['fragment']); @@ -328,16 +334,15 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { } /** - * This will invalidate paths. + * InvalidatePaths(array $invalidations). * - * InvalidatePaths(array $invalidations) - * As per the purger module guidelines, + * This will invalidate paths. As per the purger module guidelines, * this should not start with a slash, and should not contain the hostname. - * e.x.: favicon.ico . + * e.x.: favicon.ico for example. * * @param array $invalidations - * This takes in an array of Invalidation, - * processing them all in a loop, generally from the purge queue. + * This takes in an array of Invalidation, processing them all in a loop, + * generally from the purge queue. */ public function invalidatePaths(array $invalidations) { foreach ($invalidations as $invalidation) { @@ -350,21 +355,24 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { $patterns = [ '/^\//', // Escape regex characters except *. + '/([[\]{}()+?.,\\^$|#])/', // Replace * with .* (for actual Varnish regex) - '/([[\]{}()+?.,\\^$|#])/', '/\*/', + '/\*/', ]; $replace = [ + '', // Escape regex characters except *. + '\\\$1', // Replace * with .* (for actual Varnish regex) - '', '\\\$1', '.*', + '.*', ]; // Base varnish ban expression for paths. $exp = 'req.url ~ "^/'; $exp .= preg_replace($patterns, $replace, $invalidation->getExpression()) . '$"'; - // Adds this at the end if this instance has a site name - // in the configuration, for multi-site pages. - // the ampersands are url encoded to be %26%26 in sendReq. + // Adds this at the end if this instance has a site name in the + // configuration, for multi-site pages. the ampersands are url encoded + // to be %26%26 in sendReq. if ($this->getSiteName()) { $exp .= ' && req.http.host == "' . $this->getSiteName() . '"'; } @@ -374,15 +382,15 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { } /** - * This will invalidate a hostname. + * InvalidateDomain(array $invalidations). * - * InvalidateDomain(array $invalidations) - * This should not contain the protocol, simply the hostname. - * e.x.: example.com. + * This will invalidate a hostname. + * This should not contain the protocol, simply the hostname + * example.com for example. * * @param array $invalidations - * This takes in an array of Invalidation, - * processing them all in a loop, generally from the purge queue. + * This takes in an array of Invalidation, processing them all in a loop, + * generally from the purge queue. */ public function invalidateDomain(array $invalidations) { foreach ($invalidations as $invalidation) { @@ -398,9 +406,9 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { } /** - * This will invalidate urls. + * Invalidate wildcard Urls. * - * Since by default invalidateUrls() has the ability to handle wildcard urls, + * Since by default invalidateURLs() has the ability to handle wildcard urls, * this is just an alias. * This method is still necessary to exist because purge itself has certain * validations for each type. @@ -410,23 +418,23 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { } /** - * This will invalidate paths. + * Invalidate paths. * - * Since by default invalidatePaths() has the ability to - * handle wildcard urls, this is just an alias. - * This method is still necessary to exist because purge - * itself has certain validations for each type. + * Since by default invalidatePaths() has the ability to handle wildcard urls, + * this is just an alias. + * This method is still necessary to exist because purge itself has certain + * validations for each type. */ public function invalidateWildcardPaths(array $invalidations) { $this->invalidatePaths($invalidations); } /** - * This allows for raw varnish ban expressions. + * Invalidate Raw Expression. * - * InvalidateRawExpression(array $invalidations) - * E.x.: obj.status == "404" && req.url ~ node\/(?).* - would clear the - * cache of 404'd nodes. + * This allows for raw varnish ban expressions. + * e.x.: obj.status == "404" && req.url ~ node\/(?).* - would clear the cache + * of 404'd nodes. * * @param array $invalidations * This takes in an array of Invalidation, processing them all in a loop, @@ -445,15 +453,15 @@ abstract class SectionPurgerBase extends PurgerBase implements PurgerInterface { } /** - * This allows for a regular expression match of a path. + * InvalidateRegex(array $invalidations). * - * InvalidateRegex(array $invalidations) - * e.x.: obj.status == "404" && req.url ~ "node\/(?).*" - * - would clear the cache of 404'd nodes. + * This allows for a regular expression match of a path. + * e.x.: obj.status == "404" && req.url ~ "node\/(?).*" - would clear the + * cache of 404'd nodes. * * @param array $invalidations - * This takes in an array of Invalidation, - * processing them all in a loop, generally from the purge queue. + * This takes in an array of Invalidation, processing them all in a loop, + * generally from the purge queue. */ public function invalidateRegex(array $invalidations) { foreach ($invalidations as $invalidation) { diff --git a/src/Plugin/Purge/TagsHeader/CacheTagsHeaderValue.php b/src/Plugin/Purge/TagsHeader/CacheTagsHeaderValue.php index c99505d09e017c3825a1828d9174a38cfe0571e9..6e32ea8cf7f486b60f157d947b4883aa36cead46 100644 --- a/src/Plugin/Purge/TagsHeader/CacheTagsHeaderValue.php +++ b/src/Plugin/Purge/TagsHeader/CacheTagsHeaderValue.php @@ -6,16 +6,19 @@ namespace Drupal\section_purger\Plugin\Purge\TagsHeader; * Provides simple value object for cache tag headers. */ class CacheTagsHeaderValue { + /** * String: separation character used. */ const SEPARATOR = ' '; + /** * List of original cache tags. * * @var string[] */ protected $tags = []; + /** * List of hashed cache tags. * diff --git a/Tests/SectionPurgerFormTest.php b/tests/src/FunctionalJavascript/SectionPurgerFormTest.php similarity index 91% rename from Tests/SectionPurgerFormTest.php rename to tests/src/FunctionalJavascript/SectionPurgerFormTest.php index 521f80bb6b667da80a1a68f339cac68668ea7808..d648dd822b1260a21a7f9303cd6e5816f09a9460 100644 --- a/Tests/SectionPurgerFormTest.php +++ b/tests/src/FunctionalJavascript/SectionPurgerFormTest.php @@ -1,6 +1,6 @@ drupalLogin($this->admin_user); + $this->drupalLogin($this->adminUser); $this->drupalGet($this->route); $fields = [ 'edit-name' => '', @@ -48,19 +48,7 @@ abstract class SectionPurgerFormTestBase extends PurgerConfigFormTestBase { 'edit-max-requests' => 100, ]; foreach ($fields as $field => $default_value) { - $this->assertFieldById($field, $default_value); - } - } - - /** - * Tests SectionPurgerFormBase::buildFormTokensHelp(). - */ - public function testTokensHelp() { - $this->drupalLogin($this->admin_user); - $this->drupalGet($this->route); - $this->assertText('Tokens'); - foreach ($this->tokenGroups as $token_group) { - $this->assertRaw('[' . $token_group . ':'); + $this->assertSession()->fieldValueEquals($field, $default_value); } } @@ -73,32 +61,32 @@ abstract class SectionPurgerFormTestBase extends PurgerConfigFormTestBase { $form_state->addBuildInfo('args', [$this->formArgs]); $form_state->setValues( [ - 'connectTimeout' => 0.3, + 'connect_timeout' => 0.3, 'timeout' => 0.1, 'name' => 'foobar', ] ); $form = $this->getFormInstance(); $this->formBuilder->submitForm($form, $form_state); - $this->assertEqual(0, count($form_state->getErrors())); + $this->assertEquals(0, count($form_state->getErrors())); $form_state = $this->getFormStateInstance(); $form_state->addBuildInfo('args', [$this->formArgs]); $form_state->setValues( [ - 'connectTimeout' => 2.3, + 'connect_timeout' => 2.3, 'timeout' => 7.7, 'name' => 'foobar', ] ); $form = $this->getFormInstance(); $this->formBuilder->submitForm($form, $form_state); - $this->assertEqual(0, count($form_state->getErrors())); + $this->assertEquals(0, count($form_state->getErrors())); // Submit timeout values that are too low and confirm the validation error. $form_state = $this->getFormStateInstance(); $form_state->addBuildInfo('args', [$this->formArgs]); $form_state->setValues( [ - 'connectTimeout' => 0.0, + 'connect_timeout' => 0.0, 'timeout' => 0.0, 'name' => 'foobar', ] @@ -106,15 +94,15 @@ abstract class SectionPurgerFormTestBase extends PurgerConfigFormTestBase { $form = $this->getFormInstance(); $this->formBuilder->submitForm($form, $form_state); $errors = $form_state->getErrors(); - $this->assertEqual(2, count($errors)); + $this->assertEquals(2, count($errors)); $this->assertTrue(isset($errors['timeout'])); - $this->assertTrue(isset($errors['connectTimeout'])); + $this->assertTrue(isset($errors['connect_timeout'])); // Submit timeout values that are too high and confirm the validation error. $form_state = $this->getFormStateInstance(); $form_state->addBuildInfo('args', [$this->formArgs]); $form_state->setValues( [ - 'connectTimeout' => 2.4, + 'connect_timeout' => 2.4, 'timeout' => 7.7, 'name' => 'foobar', ] @@ -122,9 +110,9 @@ abstract class SectionPurgerFormTestBase extends PurgerConfigFormTestBase { $form = $this->getFormInstance(); $this->formBuilder->submitForm($form, $form_state); $errors = $form_state->getErrors(); - $this->assertEqual(2, count($errors)); + $this->assertEquals(2, count($errors)); $this->assertTrue(isset($errors['timeout'])); - $this->assertTrue(isset($errors['connectTimeout'])); + $this->assertTrue(isset($errors['connect_timeout'])); } /** @@ -132,7 +120,7 @@ abstract class SectionPurgerFormTestBase extends PurgerConfigFormTestBase { */ public function testFormSubmit() { // Assert that all (simple) fields submit as intended. - $this->drupalLogin($this->admin_user); + $this->drupalLogin($this->adminUser); $edit = [ 'name' => 'foobar', 'invalidationtype' => 'wildcardurl', @@ -143,23 +131,24 @@ abstract class SectionPurgerFormTestBase extends PurgerConfigFormTestBase { 'password' => 'password', 'port' => 8080, 'path' => 'node/1', - 'requestMethod' => 1, + 'request_method' => 1, 'scheme' => 0, 'verify' => TRUE, 'show_body_form' => 1, - 'bodyContentType' => 'foo/bar', + 'body_content_type' => 'foo/bar', 'body' => 'baz', 'timeout' => 6, - 'runtimeMeasurement' => 1, - 'connectTimeout' => 0.5, - 'cooldownTime' => 0.8, - 'maxRequests' => 25, - 'httpErrors' => 1, + 'runtime_measurement' => 1, + 'connect_timeout' => 0.5, + 'cooldown_time' => 0.8, + 'max_requests' => 25, + 'http_errors' => 1, ]; - $this->drupalPostForm($this->route, $edit, 'Save configuration'); $this->drupalGet($this->route); + $this->submitForm($edit, t('Save configuration')); foreach ($edit as $field => $value) { - $this->assertFieldById('edit-' . str_replace('_', '-', $field), $value); + $this->assertSession() + ->fieldValueEquals('edit-' . str_replace('_', '-', $field), $value); } // Assert headers behavior. $form = $this->getFormInstance(); @@ -167,10 +156,10 @@ abstract class SectionPurgerFormTestBase extends PurgerConfigFormTestBase { $form_state->addBuildInfo('args', [$this->formArgs]); $form_state->setValue('headers', [['field' => 'foo', 'value' => 'bar']]); $this->formBuilder->submitForm($form, $form_state); - $this->assertEqual(0, count($form_state->getErrors())); + $this->assertEquals(0, count($form_state->getErrors())); $this->drupalGet($this->route); - $this->assertFieldById('edit-headers-0-field', 'foo'); - $this->assertFieldById('edit-headers-0-value', 'bar'); + $this->assertSession()->fieldValueEquals('edit-headers-0-field', 'foo'); + $this->assertSession()->fieldValueEquals('edit-headers-0-value', 'bar'); } }