From e27696abe05d497598d65f828ffd3f4fd69be565 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Fri, 19 Sep 2025 17:41:36 +0100 Subject: [PATCH 01/10] Updated admin templates for settings. Added data management settings. --- .../settings/wp-graphql-logging-settings.css | 1 + .../Fields/Field/Text_Integer_Field.php | 39 ++++++ .../Fields/Settings_Field_Collection.php | 2 + .../Fields/Tab/Data_Management_Tab.php | 111 ++++++++++++++++++ .../src/Admin/Settings/Templates/admin.php | 25 ++-- 5 files changed, 165 insertions(+), 13 deletions(-) create mode 100644 plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Text_Integer_Field.php create mode 100644 plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Data_Management_Tab.php diff --git a/plugins/wpgraphql-logging/assets/css/settings/wp-graphql-logging-settings.css b/plugins/wpgraphql-logging/assets/css/settings/wp-graphql-logging-settings.css index 556fc2e6..124bdc2b 100644 --- a/plugins/wpgraphql-logging/assets/css/settings/wp-graphql-logging-settings.css +++ b/plugins/wpgraphql-logging/assets/css/settings/wp-graphql-logging-settings.css @@ -5,6 +5,7 @@ settings_page_wpgraphql-logging #poststuff .postbox .inside h2 { } +.form-table td input[type="number"], .form-table td input[type="text"] { width: calc(99% - 24px); display: inline-block; diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Text_Integer_Field.php b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Text_Integer_Field.php new file mode 100644 index 00000000..6e211b90 --- /dev/null +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Text_Integer_Field.php @@ -0,0 +1,39 @@ +add_tab( new Basic_Configuration_Tab() ); + $this->add_tab( new Data_Management_Tab() ); do_action( 'wpgraphql_logging_settings_field_collection_init', $this ); } diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Data_Management_Tab.php b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Data_Management_Tab.php new file mode 100644 index 00000000..4cb96dfe --- /dev/null +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Data_Management_Tab.php @@ -0,0 +1,111 @@ + Array of fields keyed by field ID. + */ + public function get_fields(): array { + $fields = []; + + $fields[ self::DATA_DELETION_ENABLED ] = new Checkbox_Field( + self::DATA_DELETION_ENABLED, + $this->get_name(), + __( 'Data Deletion Enabled', 'wpgraphql-logging' ), + '', + __( 'Enable or disable data deletion for WPGraphQL logging.', 'wpgraphql-logging' ), + ); + + $fields[ self::DATA_RETENTION_DAYS ] = new Text_Integer_Field( + self::DATA_RETENTION_DAYS, + $this->get_name(), + __( 'Number of Days to Retain Logs', 'wpgraphql-logging' ), + '', + __( 'Number of days to retain log data before deletion.', 'wpgraphql-logging' ), + __( 'e.g., 30', 'wpgraphql-logging' ), + '30' + ); + + $fields[ self::DATA_SANITIZATION_ENABLED ] = new Checkbox_Field( + self::DATA_SANITIZATION_ENABLED, + $this->get_name(), + __( 'Data Sanitization Enabled', 'wpgraphql-logging' ), + '', + __( 'Enable or disable data sanitization for WPGraphQL logging.', 'wpgraphql-logging' ), + ); + + + $fields[ self::DATA_SANITIZATION_FIELDS ] = new Text_Input_Field( + self::DATA_SANITIZATION_FIELDS, + $this->get_name(), + __( 'Data Sanitization Fields', 'wpgraphql-logging' ), + '', + __( 'A comma-separated list of fields to sanitize for WPGraphQL logging.', 'wpgraphql-logging' ), + __( 'e.g., user.email, user.name, user.firstName, user.lastName', 'wpgraphql-logging' ), + 'user_email, user_pass, user_login, user_status, display_name, nickname, first_name, last_name' + ); + + + return apply_filters( 'wpgraphql_logging_data_management_fields', $fields ); + } +} diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Templates/admin.php b/plugins/wpgraphql-logging/src/Admin/Settings/Templates/admin.php index ef74a8dd..8dd0a00a 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Templates/admin.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Templates/admin.php @@ -67,24 +67,23 @@
  • -
  • -
  • -
  • +
  • +
  • +
  • +
  • -

    -

    - -

    -

    +

    +

    From 02815bcb73cc7c714c1edeede1a5d2a9e18ebcea Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Fri, 19 Sep 2025 19:06:47 +0100 Subject: [PATCH 02/10] Integrated data deletion with WP CRON scheduler. --- plugins/wpgraphql-logging/README.md | 10 +- plugins/wpgraphql-logging/composer.lock | 174 +++++++++--------- .../src/Logger/Database/LogsRepository.php | 19 ++ .../Scheduler/DataDeletionScheduler.php | 135 ++++++++++++++ plugins/wpgraphql-logging/src/Plugin.php | 5 + 5 files changed, 255 insertions(+), 88 deletions(-) create mode 100644 plugins/wpgraphql-logging/src/Logger/Scheduler/DataDeletionScheduler.php diff --git a/plugins/wpgraphql-logging/README.md b/plugins/wpgraphql-logging/README.md index bc21377f..2009d886 100644 --- a/plugins/wpgraphql-logging/README.md +++ b/plugins/wpgraphql-logging/README.md @@ -91,7 +91,9 @@ wpgraphql-logging/ │ ├── Admin/ # Admin settings, menu, and settings page logic │ ├── Settings/ # Admin settings functionality for displaying and saving data. │ ├── Events/ # Event logging, pub/sub event manager for extending the logging. -│ ├── Logging/ # Logging logic, logger service, Monolog handlers & processors +│ ├── Logger/ # Logging logic, logger service, Monolog handlers & processors +│ ├── Rules/ # Rule Management on whether we log a query +│ ├── Scheduler/ # Automated data cleanup and maintenance tasks │ ├── Plugin.php # Main plugin class (entry point) │ └── Autoload.php # PSR-4 autoloader ├── tests/ # All test suites @@ -119,6 +121,12 @@ wpgraphql-logging/ - **Monolog-powered logging pipeline** - Default handler: stores logs in a WordPress table (`{$wpdb->prefix}wpgraphql_logging`). +- **Automated data management** + - **Daily cleanup scheduler**: Automatically removes old logs based on retention settings. + - **Configurable retention period**: Set how many days to keep log data (default: 30 days). + - **Manual cleanup**: Admin interface to trigger immediate cleanup of old logs. + - **Data sanitization**: Remove sensitive fields from logged data for privacy compliance. + - **Simple developer API** - `Plugin::on()` to subscribe, `Plugin::emit()` to publish, `Plugin::transform()` to modify payloads. diff --git a/plugins/wpgraphql-logging/composer.lock b/plugins/wpgraphql-logging/composer.lock index 4dcc5a52..316030fb 100644 --- a/plugins/wpgraphql-logging/composer.lock +++ b/plugins/wpgraphql-logging/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "league/csv", - "version": "9.24.1", + "version": "9.25.0", "source": { "type": "git", "url": "https://github.com/thephpleague/csv.git", - "reference": "e0221a3f16aa2a823047d59fab5809d552e29bc8" + "reference": "f856f532866369fb1debe4e7c5a1db185f40ef86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/csv/zipball/e0221a3f16aa2a823047d59fab5809d552e29bc8", - "reference": "e0221a3f16aa2a823047d59fab5809d552e29bc8", + "url": "https://api.github.com/repos/thephpleague/csv/zipball/f856f532866369fb1debe4e7c5a1db185f40ef86", + "reference": "f856f532866369fb1debe4e7c5a1db185f40ef86", "shasum": "" }, "require": { @@ -33,7 +33,7 @@ "phpstan/phpstan-deprecation-rules": "^1.2.1", "phpstan/phpstan-phpunit": "^1.4.2", "phpstan/phpstan-strict-rules": "^1.6.2", - "phpunit/phpunit": "^10.5.16 || ^11.5.22", + "phpunit/phpunit": "^10.5.16 || ^11.5.22 || ^12.3.6", "symfony/var-dumper": "^6.4.8 || ^7.3.0" }, "suggest": { @@ -95,7 +95,7 @@ "type": "github" } ], - "time": "2025-06-25T14:53:51+00:00" + "time": "2025-09-11T08:29:08+00:00" }, { "name": "monolog/monolog", @@ -1491,16 +1491,16 @@ }, { "name": "composer/composer", - "version": "2.8.11", + "version": "2.8.12", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "00e1a3396eea67033775c4a49c772376f45acd73" + "reference": "3e38919bc9a2c3c026f2151b5e56d04084ce8f0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/00e1a3396eea67033775c4a49c772376f45acd73", - "reference": "00e1a3396eea67033775c4a49c772376f45acd73", + "url": "https://api.github.com/repos/composer/composer/zipball/3e38919bc9a2c3c026f2151b5e56d04084ce8f0b", + "reference": "3e38919bc9a2c3c026f2151b5e56d04084ce8f0b", "shasum": "" }, "require": { @@ -1511,20 +1511,20 @@ "composer/semver": "^3.3", "composer/spdx-licenses": "^1.5.7", "composer/xdebug-handler": "^2.0.2 || ^3.0.3", - "justinrainbow/json-schema": "^6.3.1", + "justinrainbow/json-schema": "^6.5.1", "php": "^7.2.5 || ^8.0", "psr/log": "^1.0 || ^2.0 || ^3.0", - "react/promise": "^2.11 || ^3.3", + "react/promise": "^3.3", "seld/jsonlint": "^1.4", "seld/phar-utils": "^1.2", "seld/signal-handler": "^2.0", - "symfony/console": "^5.4.35 || ^6.3.12 || ^7.0.3", - "symfony/filesystem": "^5.4.35 || ^6.3.12 || ^7.0.3", - "symfony/finder": "^5.4.35 || ^6.3.12 || ^7.0.3", + "symfony/console": "^5.4.47 || ^6.4.25 || ^7.1.10", + "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.1.10", + "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.1.10", "symfony/polyfill-php73": "^1.24", "symfony/polyfill-php80": "^1.24", "symfony/polyfill-php81": "^1.24", - "symfony/process": "^5.4.35 || ^6.3.12 || ^7.0.3" + "symfony/process": "^5.4.47 || ^6.4.25 || ^7.1.10" }, "require-dev": { "phpstan/phpstan": "^1.11.8", @@ -1532,7 +1532,7 @@ "phpstan/phpstan-phpunit": "^1.4.0", "phpstan/phpstan-strict-rules": "^1.6.0", "phpstan/phpstan-symfony": "^1.4.0", - "symfony/phpunit-bridge": "^6.4.3 || ^7.0.1" + "symfony/phpunit-bridge": "^6.4.25 || ^7.3.3" }, "suggest": { "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", @@ -1585,7 +1585,7 @@ "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/composer/issues", "security": "https://github.com/composer/composer/security/policy", - "source": "https://github.com/composer/composer/tree/2.8.11" + "source": "https://github.com/composer/composer/tree/2.8.12" }, "funding": [ { @@ -1597,7 +1597,7 @@ "type": "github" } ], - "time": "2025-08-21T09:29:39+00:00" + "time": "2025-09-19T11:41:59+00:00" }, { "name": "composer/metadata-minifier", @@ -3140,16 +3140,16 @@ }, { "name": "justinrainbow/json-schema", - "version": "6.5.1", + "version": "6.5.2", "source": { "type": "git", "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "b5ab21e431594897e5bb86343c01f140ba862c26" + "reference": "ac0d369c09653cf7af561f6d91a705bc617a87b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/b5ab21e431594897e5bb86343c01f140ba862c26", - "reference": "b5ab21e431594897e5bb86343c01f140ba862c26", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/ac0d369c09653cf7af561f6d91a705bc617a87b8", + "reference": "ac0d369c09653cf7af561f6d91a705bc617a87b8", "shasum": "" }, "require": { @@ -3209,22 +3209,22 @@ ], "support": { "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/6.5.1" + "source": "https://github.com/jsonrainbow/json-schema/tree/6.5.2" }, - "time": "2025-08-29T10:58:11+00:00" + "time": "2025-09-09T09:42:27+00:00" }, { "name": "lucatume/wp-browser", - "version": "4.5.5", + "version": "4.5.7", "source": { "type": "git", "url": "https://github.com/lucatume/wp-browser.git", - "reference": "5cf7588f6c23166e3ee53e2d21257bf25338323f" + "reference": "9c8bb63c26fe76ee5cfd06fac26d9b400a8216ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lucatume/wp-browser/zipball/5cf7588f6c23166e3ee53e2d21257bf25338323f", - "reference": "5cf7588f6c23166e3ee53e2d21257bf25338323f", + "url": "https://api.github.com/repos/lucatume/wp-browser/zipball/9c8bb63c26fe76ee5cfd06fac26d9b400a8216ef", + "reference": "9c8bb63c26fe76ee5cfd06fac26d9b400a8216ef", "shasum": "" }, "require": { @@ -3303,7 +3303,7 @@ ], "support": { "issues": "https://github.com/lucatume/wp-browser/issues", - "source": "https://github.com/lucatume/wp-browser/tree/4.5.5" + "source": "https://github.com/lucatume/wp-browser/tree/4.5.7" }, "funding": [ { @@ -3311,20 +3311,20 @@ "type": "github" } ], - "time": "2025-08-15T15:15:45+00:00" + "time": "2025-09-09T12:20:53+00:00" }, { "name": "marc-mabe/php-enum", - "version": "v4.7.1", + "version": "v4.7.2", "source": { "type": "git", "url": "https://github.com/marc-mabe/php-enum.git", - "reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed" + "reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/7159809e5cfa041dca28e61f7f7ae58063aae8ed", - "reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed", + "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/bb426fcdd65c60fb3638ef741e8782508fda7eef", + "reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef", "shasum": "" }, "require": { @@ -3382,9 +3382,9 @@ ], "support": { "issues": "https://github.com/marc-mabe/php-enum/issues", - "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.1" + "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.2" }, - "time": "2024-11-28T04:54:44+00:00" + "time": "2025-09-14T11:18:39+00:00" }, { "name": "masterminds/html5", @@ -4176,18 +4176,18 @@ "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", - "reference": "ec975efc6752a2a41c2d0823e9c5e464c3c2dbb6" + "reference": "771535284869cd4f3ff178c292c032b804738771" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/ec975efc6752a2a41c2d0823e9c5e464c3c2dbb6", - "reference": "ec975efc6752a2a41c2d0823e9c5e464c3c2dbb6", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/771535284869cd4f3ff178c292c032b804738771", + "reference": "771535284869cd4f3ff178c292c032b804738771", "shasum": "" }, "require": { "php": ">=5.4", "phpcsstandards/phpcsutils": "^1.1.2", - "squizlabs/php_codesniffer": "^3.13.3" + "squizlabs/php_codesniffer": "^3.13.3 || ^4.0" }, "replace": { "wimg/php-compatibility": "*" @@ -4262,7 +4262,7 @@ "type": "thanks_dev" } ], - "time": "2025-09-05T15:02:16+00:00" + "time": "2025-09-09T21:00:45+00:00" }, { "name": "phpcompatibility/phpcompatibility-paragonie", @@ -4885,16 +4885,16 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.22", + "version": "2.1.28", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "41600c8379eb5aee63e9413fe9e97273e25d57e4" + "reference": "578fa296a166605d97b94091f724f1257185d278" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/41600c8379eb5aee63e9413fe9e97273e25d57e4", - "reference": "41600c8379eb5aee63e9413fe9e97273e25d57e4", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/578fa296a166605d97b94091f724f1257185d278", + "reference": "578fa296a166605d97b94091f724f1257185d278", "shasum": "" }, "require": { @@ -4939,7 +4939,7 @@ "type": "github" } ], - "time": "2025-08-04T19:17:37+00:00" + "time": "2025-09-19T08:58:49+00:00" }, { "name": "phpstan/phpstan-strict-rules", @@ -5312,16 +5312,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.53", + "version": "10.5.55", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "32768472ebfb6969e6c7399f1c7b09009723f653" + "reference": "4b2d546b336876bd9562f24641b08a25335b06b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/32768472ebfb6969e6c7399f1c7b09009723f653", - "reference": "32768472ebfb6969e6c7399f1c7b09009723f653", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4b2d546b336876bd9562f24641b08a25335b06b6", + "reference": "4b2d546b336876bd9562f24641b08a25335b06b6", "shasum": "" }, "require": { @@ -5342,7 +5342,7 @@ "phpunit/php-timer": "^6.0.0", "sebastian/cli-parser": "^2.0.1", "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.3", + "sebastian/comparator": "^5.0.4", "sebastian/diff": "^5.1.1", "sebastian/environment": "^6.1.0", "sebastian/exporter": "^5.1.2", @@ -5393,7 +5393,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.53" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.55" }, "funding": [ { @@ -5417,7 +5417,7 @@ "type": "tidelift" } ], - "time": "2025-08-20T14:40:06+00:00" + "time": "2025-09-14T06:19:20+00:00" }, { "name": "psr/container", @@ -7050,16 +7050,16 @@ }, { "name": "slevomat/coding-standard", - "version": "8.22.0", + "version": "8.22.1", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", - "reference": "a4cef983bad2e70125612d22b2f6e2bd1333d5c2" + "reference": "1dd80bf3b93692bedb21a6623c496887fad05fec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/a4cef983bad2e70125612d22b2f6e2bd1333d5c2", - "reference": "a4cef983bad2e70125612d22b2f6e2bd1333d5c2", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/1dd80bf3b93692bedb21a6623c496887fad05fec", + "reference": "1dd80bf3b93692bedb21a6623c496887fad05fec", "shasum": "" }, "require": { @@ -7071,11 +7071,11 @@ "require-dev": { "phing/phing": "3.0.1|3.1.0", "php-parallel-lint/php-parallel-lint": "1.4.0", - "phpstan/phpstan": "2.1.22", + "phpstan/phpstan": "2.1.24", "phpstan/phpstan-deprecation-rules": "2.0.3", "phpstan/phpstan-phpunit": "2.0.7", "phpstan/phpstan-strict-rules": "2.0.6", - "phpunit/phpunit": "9.6.8|10.5.48|11.4.4|11.5.36|12.3.8" + "phpunit/phpunit": "9.6.8|10.5.48|11.4.4|11.5.36|12.3.10" }, "type": "phpcodesniffer-standard", "extra": { @@ -7099,7 +7099,7 @@ ], "support": { "issues": "https://github.com/slevomat/coding-standard/issues", - "source": "https://github.com/slevomat/coding-standard/tree/8.22.0" + "source": "https://github.com/slevomat/coding-standard/tree/8.22.1" }, "funding": [ { @@ -7111,7 +7111,7 @@ "type": "tidelift" } ], - "time": "2025-09-06T09:14:48+00:00" + "time": "2025-09-13T08:53:30+00:00" }, { "name": "softcreatr/jsonpath", @@ -9643,24 +9643,24 @@ }, { "name": "wp-cli/db-command", - "version": "v2.1.3", + "version": "v2.1.4", "source": { "type": "git", "url": "https://github.com/wp-cli/db-command.git", - "reference": "f857c91454d7092fa672bc388512a51752d9264a" + "reference": "c5277fe0335ea00c77b2790f2a892a692dfdf73c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/db-command/zipball/f857c91454d7092fa672bc388512a51752d9264a", - "reference": "f857c91454d7092fa672bc388512a51752d9264a", + "url": "https://api.github.com/repos/wp-cli/db-command/zipball/c5277fe0335ea00c77b2790f2a892a692dfdf73c", + "reference": "c5277fe0335ea00c77b2790f2a892a692dfdf73c", "shasum": "" }, "require": { - "wp-cli/wp-cli": "^2.12" + "wp-cli/wp-cli": "^2.13" }, "require-dev": { "wp-cli/entity-command": "^1.3 || ^2", - "wp-cli/wp-cli-tests": "^4" + "wp-cli/wp-cli-tests": "^5" }, "type": "wp-cli-package", "extra": { @@ -9711,9 +9711,9 @@ "homepage": "https://github.com/wp-cli/db-command", "support": { "issues": "https://github.com/wp-cli/db-command/issues", - "source": "https://github.com/wp-cli/db-command/tree/v2.1.3" + "source": "https://github.com/wp-cli/db-command/tree/v2.1.4" }, - "time": "2025-04-10T11:02:04+00:00" + "time": "2025-09-08T19:28:47+00:00" }, { "name": "wp-cli/embed-command", @@ -9784,20 +9784,20 @@ }, { "name": "wp-cli/entity-command", - "version": "v2.8.4", + "version": "v2.8.5", "source": { "type": "git", "url": "https://github.com/wp-cli/entity-command.git", - "reference": "213611f8ab619ca137d983e9b987f7fbf1ac21d4" + "reference": "896b7fb5ed51fe556017b2c71126947db5cd2b68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/entity-command/zipball/213611f8ab619ca137d983e9b987f7fbf1ac21d4", - "reference": "213611f8ab619ca137d983e9b987f7fbf1ac21d4", + "url": "https://api.github.com/repos/wp-cli/entity-command/zipball/896b7fb5ed51fe556017b2c71126947db5cd2b68", + "reference": "896b7fb5ed51fe556017b2c71126947db5cd2b68", "shasum": "" }, "require": { - "wp-cli/wp-cli": "^2.12" + "wp-cli/wp-cli": "^2.13" }, "require-dev": { "wp-cli/cache-command": "^1 || ^2", @@ -9805,7 +9805,7 @@ "wp-cli/extension-command": "^1.2 || ^2", "wp-cli/media-command": "^1.1 || ^2", "wp-cli/super-admin-command": "^1 || ^2", - "wp-cli/wp-cli-tests": "^4" + "wp-cli/wp-cli-tests": "^5" }, "type": "wp-cli-package", "extra": { @@ -10015,9 +10015,9 @@ "homepage": "https://github.com/wp-cli/entity-command", "support": { "issues": "https://github.com/wp-cli/entity-command/issues", - "source": "https://github.com/wp-cli/entity-command/tree/v2.8.4" + "source": "https://github.com/wp-cli/entity-command/tree/v2.8.5" }, - "time": "2025-05-06T16:12:49+00:00" + "time": "2025-09-12T10:52:53+00:00" }, { "name": "wp-cli/eval-command", @@ -10688,29 +10688,29 @@ }, { "name": "wp-cli/php-cli-tools", - "version": "v0.12.5", + "version": "v0.12.6", "source": { "type": "git", "url": "https://github.com/wp-cli/php-cli-tools.git", - "reference": "34b83b4f700df8a4ec3fd17bf7e7e7d8ca5f28da" + "reference": "f12b650d3738e471baed6dd47982d53c5c0ab1c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/php-cli-tools/zipball/34b83b4f700df8a4ec3fd17bf7e7e7d8ca5f28da", - "reference": "34b83b4f700df8a4ec3fd17bf7e7e7d8ca5f28da", + "url": "https://api.github.com/repos/wp-cli/php-cli-tools/zipball/f12b650d3738e471baed6dd47982d53c5c0ab1c3", + "reference": "f12b650d3738e471baed6dd47982d53c5c0ab1c3", "shasum": "" }, "require": { - "php": ">= 5.6.0" + "php": ">= 7.2.24" }, "require-dev": { "roave/security-advisories": "dev-latest", - "wp-cli/wp-cli-tests": "^4" + "wp-cli/wp-cli-tests": "^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "0.11.x-dev" + "dev-master": "0.12.x-dev" } }, "autoload": { @@ -10745,9 +10745,9 @@ ], "support": { "issues": "https://github.com/wp-cli/php-cli-tools/issues", - "source": "https://github.com/wp-cli/php-cli-tools/tree/v0.12.5" + "source": "https://github.com/wp-cli/php-cli-tools/tree/v0.12.6" }, - "time": "2025-03-26T16:13:46+00:00" + "time": "2025-09-11T12:43:04+00:00" }, { "name": "wp-cli/process", diff --git a/plugins/wpgraphql-logging/src/Logger/Database/LogsRepository.php b/plugins/wpgraphql-logging/src/Logger/Database/LogsRepository.php index d7f14398..0aa3897c 100644 --- a/plugins/wpgraphql-logging/src/Logger/Database/LogsRepository.php +++ b/plugins/wpgraphql-logging/src/Logger/Database/LogsRepository.php @@ -4,6 +4,8 @@ namespace WPGraphQL\Logging\Logger\Database; +use DateTime; + /** * LogsRepository class for WPGraphQL Logging. * @@ -109,6 +111,23 @@ public function delete(int $id): bool { return false !== $result; } + /** + * Delete a logs entry older than a specific date. + * + * @param \DateTime $date The date to delete logs older than. + */ + public function delete_log_older_than(DateTime $date): bool { + global $wpdb; + $table_name = DatabaseEntity::get_table_name(); + + $result = $wpdb->query( $wpdb->prepare( + "DELETE FROM %i WHERE datetime < %s", + $table_name, + $date->format( 'Y-m-d H:i:s' ) + ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching + return false !== $result; + } + /** * Delete all log entries. */ diff --git a/plugins/wpgraphql-logging/src/Logger/Scheduler/DataDeletionScheduler.php b/plugins/wpgraphql-logging/src/Logger/Scheduler/DataDeletionScheduler.php new file mode 100644 index 00000000..ce5a12d0 --- /dev/null +++ b/plugins/wpgraphql-logging/src/Logger/Scheduler/DataDeletionScheduler.php @@ -0,0 +1,135 @@ +> + */ + protected array $config; + + /** + * The single instance of the class. + * + * @var \WPGraphQL\Logging\Logger\Scheduler\DataDeletionScheduler|null + */ + protected static ?DataDeletionScheduler $instance = null; + + /** + * Private constructor to prevent direct instantiation. + */ + protected function __construct(readonly LogsRepository $repository) { + $full_config = get_option( WPGRAPHQL_LOGGING_SETTINGS_KEY, [] ); + $this->config = $full_config['data_management'] ?? []; + } + + /** + * Initialize the scheduler. + */ + public static function init(): self { + + if ( null === self::$instance ) { + self::$instance = new self( new LogsRepository() ); + self::$instance->setup(); + } + + return self::$instance; + } + + /** + * Schedule the daily deletion task if it's not already scheduled. + */ + public function schedule_deletion(): void { + if ( false === wp_next_scheduled( self::DELETION_HOOK ) ) { + wp_schedule_event( time(), 'daily', self::DELETION_HOOK ); + } + } + + /** + * Perform the actual deletion of old log data. + * + * This method is called by the WordPress cron system. + */ + public function perform_deletion(): void { + + if ( false === (bool) $this->config[ Data_Management_Tab::DATA_DELETION_ENABLED ] ) { + return; + } + + $retention_days = $this->config[ Data_Management_Tab::DATA_RETENTION_DAYS ]; + if ( ! is_numeric( $retention_days ) ) { + return; + } + $retention_days = (int) $retention_days; + if ( $retention_days < 1 ) { + return; + } + + try { + self::delete_old_logs( $retention_days ); + } catch ( \Throwable $e ) { + do_action('wpgraphql_logging_cleanup_error', [ + 'error_message' => $e->getMessage(), + 'retention_days' => $retention_days, + 'timestamp' => current_time( 'mysql' ), + ]); + } + } + + /** + * Clear the scheduled cleanup task. + * + * This is typically called on plugin deactivation. + */ + public static function clear_scheduled_deletion(): void { + $timestamp = wp_next_scheduled( self::DELETION_HOOK ); + if ( false !== $timestamp ) { + wp_unschedule_event( $timestamp, self::DELETION_HOOK ); + } + } + + /** + * Initialize the scheduler by registering hooks. + */ + protected function setup(): void { + add_action( 'init', [ $this, 'schedule_deletion' ], 10, 0 ); + add_action( self::DELETION_HOOK, [ $this, 'perform_deletion' ], 10, 0 ); + + // Clear scheduled event on deactivation. + register_deactivation_hook( __FILE__, [ $this, 'clear_scheduled_deletion' ] ); + } + + /** + * Delete log entries older than the specified number of days. + * + * @param int $retention_days Number of days to retain logs. + */ + protected function delete_old_logs(int $retention_days): void { + $date_time = new \DateTime(); + $date_time->modify( "-{$retention_days} days" ); + $this->repository->delete_log_older_than( $date_time ); + } +} diff --git a/plugins/wpgraphql-logging/src/Plugin.php b/plugins/wpgraphql-logging/src/Plugin.php index 0c590a96..6d3e042f 100644 --- a/plugins/wpgraphql-logging/src/Plugin.php +++ b/plugins/wpgraphql-logging/src/Plugin.php @@ -9,6 +9,7 @@ use WPGraphQL\Logging\Events\EventManager; use WPGraphQL\Logging\Events\QueryEventLifecycle; use WPGraphQL\Logging\Logger\Database\DatabaseEntity; +use WPGraphQL\Logging\Logger\Scheduler\DataDeletionScheduler; /** * Plugin class for WPGraphQL Logging. @@ -57,6 +58,7 @@ public function setup(): void { Settings_Page::init(); View_Logs_Page::init(); QueryEventLifecycle::init(); + DataDeletionScheduler::init(); } /** @@ -105,6 +107,9 @@ public static function activate(): void { * @since 0.0.1 */ public static function deactivate(): void { + + DataDeletionScheduler::clear_scheduled_deletion(); + if ( ! defined( 'WP_GRAPHQL_LOGGING_UNINSTALL_PLUGIN' ) ) { return; } From ab68db643d2d4299c0543967b16657e200f00110 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Mon, 22 Sep 2025 18:00:03 +0100 Subject: [PATCH 03/10] Add custom data sanitization options to settings Introduces a new data sanitization method selection in the settings, allowing users to choose between recommended and custom methods. Adds fields for specifying custom fields to anonymize, remove, or truncate. Includes supporting JavaScript and CSS for dynamic UI behavior, and minor code cleanup in LogsRepository. --- .../settings/wp-graphql-logging-settings.css | 5 ++ .../settings/wp-graphql-logging-settings.js | 28 ++++++++ .../Fields/Tab/Data_Management_Tab.php | 66 ++++++++++++++++--- .../src/Logger/Database/LogsRepository.php | 6 +- 4 files changed, 94 insertions(+), 11 deletions(-) create mode 100644 plugins/wpgraphql-logging/assets/js/settings/wp-graphql-logging-settings.js diff --git a/plugins/wpgraphql-logging/assets/css/settings/wp-graphql-logging-settings.css b/plugins/wpgraphql-logging/assets/css/settings/wp-graphql-logging-settings.css index 124bdc2b..94556f61 100644 --- a/plugins/wpgraphql-logging/assets/css/settings/wp-graphql-logging-settings.css +++ b/plugins/wpgraphql-logging/assets/css/settings/wp-graphql-logging-settings.css @@ -85,3 +85,8 @@ settings_page_wpgraphql-logging #poststuff .postbox .inside h2 { margin-left: 30px; padding-bottom: 16px; } + + +.wpgraphql-logging-custom:not(.block) { + display: none; +} diff --git a/plugins/wpgraphql-logging/assets/js/settings/wp-graphql-logging-settings.js b/plugins/wpgraphql-logging/assets/js/settings/wp-graphql-logging-settings.js new file mode 100644 index 00000000..65990824 --- /dev/null +++ b/plugins/wpgraphql-logging/assets/js/settings/wp-graphql-logging-settings.js @@ -0,0 +1,28 @@ +// Add this to your admin JavaScript file +document.addEventListener('DOMContentLoaded', function() { + + const sanitizationMethodSelect = document.querySelector("#data_sanitization_method"); + if (! sanitizationMethodSelect || sanitizationMethodSelect.length === 0) { + return; + } + + function toggleCustomFields() { + const isCustom = sanitizationMethodSelect.value === 'custom'; + + if (isCustom) { + document.querySelectorAll('.wpgraphql-logging-custom').forEach((el) => { + el.classList.add('block'); + }); + } else { + document.querySelectorAll('.wpgraphql-logging-custom').forEach((el) => { + el.classList.remove('block'); + }); + } + } + + // Initial check on page load + toggleCustomFields(); + + // Listen for changes + sanitizationMethodSelect.addEventListener('change', toggleCustomFields); +}); diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Data_Management_Tab.php b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Data_Management_Tab.php index 4cb96dfe..1073b562 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Data_Management_Tab.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Data_Management_Tab.php @@ -5,6 +5,7 @@ namespace WPGraphQL\Logging\Admin\Settings\Fields\Tab; use WPGraphQL\Logging\Admin\Settings\Fields\Field\Checkbox_Field; +use WPGraphQL\Logging\Admin\Settings\Fields\Field\Select_Field; use WPGraphQL\Logging\Admin\Settings\Fields\Field\Text_Input_Field; use WPGraphQL\Logging\Admin\Settings\Fields\Field\Text_Integer_Field; @@ -38,11 +39,32 @@ class Data_Management_Tab implements Settings_Tab_Interface { public const DATA_SANITIZATION_ENABLED = 'data_sanitization_enabled'; /** - * The field ID for the data sanitization fields. + * The field ID for the data sanitization method. * * @var string */ - public const DATA_SANITIZATION_FIELDS = 'data_sanitization_fields'; + public const DATA_SANITIZATION_METHOD = 'data_sanitization_method'; + + /** + * The field ID for the custom fields to sanitize. + * + * @var string + */ + public const DATA_SANITIZATION_CUSTOM_FIELD_ANONYMIZE = 'data_sanitization_custom_field_anonymize'; + + /** + * The field ID for the custom fields to remove. + * + * @var string + */ + public const DATA_SANITIZATION_CUSTOM_FIELD_REMOVE = 'data_sanitization_custom_field_remove'; + + /** + * The field ID for the custom fields to truncate. + * + * @var string + */ + public const DATA_SANITIZATION_CUSTOM_FIELD_TRUNCATE = 'data_sanitization_custom_field_truncate'; /** * Get the name/identifier of the tab. @@ -95,16 +117,44 @@ public function get_fields(): array { ); - $fields[ self::DATA_SANITIZATION_FIELDS ] = new Text_Input_Field( - self::DATA_SANITIZATION_FIELDS, + $fields[ self::DATA_SANITIZATION_METHOD ] = new Select_Field( + self::DATA_SANITIZATION_METHOD, $this->get_name(), - __( 'Data Sanitization Fields', 'wpgraphql-logging' ), + __( 'Data Sanitization Method', 'wpgraphql-logging' ), + [ + 'recommended' => __( 'Recommended', 'wpgraphql-logging' ), + 'custom' => __( 'Custom', 'wpgraphql-logging' ), + ], '', - __( 'A comma-separated list of fields to sanitize for WPGraphQL logging.', 'wpgraphql-logging' ), - __( 'e.g., user.email, user.name, user.firstName, user.lastName', 'wpgraphql-logging' ), - 'user_email, user_pass, user_login, user_status, display_name, nickname, first_name, last_name' + __( 'Select the method to use for data sanitization.', 'wpgraphql-logging' ), + false + ); + + + $fields[ self::DATA_SANITIZATION_CUSTOM_FIELD_ANONYMIZE ] = new Text_Input_Field( + self::DATA_SANITIZATION_CUSTOM_FIELD_ANONYMIZE, + $this->get_name(), + __( 'Custom Fields to Anonymize', 'wpgraphql-logging' ), + 'wpgraphql-logging-custom', + __( 'Comma-separated list of custom fields to anonymize.', 'wpgraphql-logging' ), + 'e.g., user_email, user_ip' + ); + + $fields[ self::DATA_SANITIZATION_CUSTOM_FIELD_REMOVE ] = new Text_Input_Field( + self::DATA_SANITIZATION_CUSTOM_FIELD_REMOVE, + $this->get_name(), + __( 'Custom Fields to Remove', 'wpgraphql-logging' ), + 'wpgraphql-logging-custom', + __( 'Comma-separated list of custom fields to remove.', 'wpgraphql-logging' ), ); + $fields[ self::DATA_SANITIZATION_CUSTOM_FIELD_TRUNCATE ] = new Text_Input_Field( + self::DATA_SANITIZATION_CUSTOM_FIELD_TRUNCATE, + $this->get_name(), + __( 'Custom Fields to Truncate', 'wpgraphql-logging' ), + 'wpgraphql-logging-custom', + __( 'Comma-separated list of custom fields to truncate.', 'wpgraphql-logging' ), + ); return apply_filters( 'wpgraphql_logging_data_management_fields', $fields ); } diff --git a/plugins/wpgraphql-logging/src/Logger/Database/LogsRepository.php b/plugins/wpgraphql-logging/src/Logger/Database/LogsRepository.php index 0aa3897c..bca698bf 100644 --- a/plugins/wpgraphql-logging/src/Logger/Database/LogsRepository.php +++ b/plugins/wpgraphql-logging/src/Logger/Database/LogsRepository.php @@ -120,11 +120,11 @@ public function delete_log_older_than(DateTime $date): bool { global $wpdb; $table_name = DatabaseEntity::get_table_name(); - $result = $wpdb->query( $wpdb->prepare( - "DELETE FROM %i WHERE datetime < %s", + $result = $wpdb->query( $wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery + 'DELETE FROM %i WHERE datetime < %s', $table_name, $date->format( 'Y-m-d H:i:s' ) - ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching + ) ); return false !== $result; } From 307d83ca5e7f9454633d642c7796f9f6ca8d5601 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Tue, 23 Sep 2025 14:27:24 +0100 Subject: [PATCH 04/10] Add data sanitization processor to logging Introduces DataSanitizationProcessor to sanitize sensitive data in log records based on configurable rules. Updates QueryActionLogger and QueryFilterLogger to encode requests as arrays for improved processing. Registers the new processor in LoggerService to enhance privacy and compliance. --- .../src/Events/QueryActionLogger.php | 5 +- .../src/Events/QueryFilterLogger.php | 7 +- .../src/Logger/LoggerService.php | 2 + .../Processors/DataSanitizationProcessor.php | 205 ++++++++++++++++++ 4 files changed, 214 insertions(+), 5 deletions(-) create mode 100644 plugins/wpgraphql-logging/src/Logger/Processors/DataSanitizationProcessor.php diff --git a/plugins/wpgraphql-logging/src/Events/QueryActionLogger.php b/plugins/wpgraphql-logging/src/Events/QueryActionLogger.php index 015358d4..d5868137 100644 --- a/plugins/wpgraphql-logging/src/Events/QueryActionLogger.php +++ b/plugins/wpgraphql-logging/src/Events/QueryActionLogger.php @@ -164,13 +164,14 @@ public function log_before_response_returned( if ( ! in_array( Events::BEFORE_RESPONSE_RETURNED, $selected_events, true ) ) { return; } - $context = [ + $encoded_request = wp_json_encode( $request ); + $context = [ 'response' => $response, 'schema' => $schema, 'operation_name' => $operation, 'query' => $query, 'variables' => $variables, - 'request' => $request, + 'request' => false !== $encoded_request ? json_decode( $encoded_request, true ) : null, 'query_id' => $query_id, ]; if ( ! $this->should_log_response( $this->config ) ) { diff --git a/plugins/wpgraphql-logging/src/Events/QueryFilterLogger.php b/plugins/wpgraphql-logging/src/Events/QueryFilterLogger.php index c6a5ca06..77569001 100644 --- a/plugins/wpgraphql-logging/src/Events/QueryFilterLogger.php +++ b/plugins/wpgraphql-logging/src/Events/QueryFilterLogger.php @@ -130,13 +130,14 @@ public function log_graphql_request_results( } /** @var \GraphQL\Server\OperationParams $params */ - $params = $request->params; - $context = [ + $params = $request->params; + $encoded_request = wp_json_encode( $request ); + $context = [ 'response' => $response, 'operation_name' => $params->operation, 'query' => $params->query, 'variables' => $params->variables, - 'request' => $request, + 'request' => false !== $encoded_request ? json_decode( $encoded_request, true ) : null, 'query_id' => $query_id, ]; if ( ! $this->should_log_response( $this->config ) ) { diff --git a/plugins/wpgraphql-logging/src/Logger/LoggerService.php b/plugins/wpgraphql-logging/src/Logger/LoggerService.php index 30851de3..0c5111ed 100644 --- a/plugins/wpgraphql-logging/src/Logger/LoggerService.php +++ b/plugins/wpgraphql-logging/src/Logger/LoggerService.php @@ -12,6 +12,7 @@ use Monolog\Processor\ProcessorInterface; use Monolog\Processor\WebProcessor; use WPGraphQL\Logging\Logger\Handlers\WordPressDatabaseHandler; +use WPGraphQL\Logging\Logger\Processors\DataSanitizationProcessor; use WPGraphQL\Logging\Logger\Processors\RequestHeadersProcessor; /** @@ -225,6 +226,7 @@ public static function get_default_processors(): array { new WebProcessor(), // Logs web request data. e.g. IP address, request method, URI, etc. new ProcessIdProcessor(), // Logs the process ID. new RequestHeadersProcessor(), // Custom processor to capture request headers. + new DataSanitizationProcessor(), // Custom processor to sanitize data in log records. ]; // Filter for users to add their own processors. diff --git a/plugins/wpgraphql-logging/src/Logger/Processors/DataSanitizationProcessor.php b/plugins/wpgraphql-logging/src/Logger/Processors/DataSanitizationProcessor.php new file mode 100644 index 00000000..cc10be97 --- /dev/null +++ b/plugins/wpgraphql-logging/src/Logger/Processors/DataSanitizationProcessor.php @@ -0,0 +1,205 @@ +> + */ + protected array $config; + + /** + * DataSanitizationProcessor constructor. + */ + public function __construct() { + $full_config = get_option( WPGRAPHQL_LOGGING_SETTINGS_KEY, [] ); + $this->config = $full_config['data_management'] ?? []; + } + + /** + * Check if data sanitization is enabled. + */ + protected function is_enabled(): bool { + $is_enabled = (bool) ( $this->config[ Data_Management_Tab::DATA_SANITIZATION_ENABLED ] ?? false ); + return apply_filters( 'wpgraphql_logging_data_sanitization_enabled', $is_enabled ); + } + + /** + * Get the sanitization rules based on the settings. + * + * @return array The sanitization rules. + */ + protected function get_rules(): array { + $method = $this->config[ Data_Management_Tab::DATA_SANITIZATION_METHOD ] ?? 'none'; + + + if ( 'recommended' === $method ) { + return apply_filters( 'wpgraphql_logging_data_sanitization_rules', $this->get_recommended_rules() ); + } + return apply_filters( 'wpgraphql_logging_data_sanitization_rules', $this->get_custom_rules() ); + } + + /** + * Get the recommended sanitization rules. + * + * @return array The recommended sanitization rules. + */ + protected function get_recommended_rules(): array { + $rules = [ + 'request.app_context.viewer.data' => 'remove', + 'request.app_context.viewer.allcaps' => 'remove', + 'request.app_context.viewer.cap_key' => 'remove', + 'request.app_context.viewer.caps' => 'remove', + ]; + + return apply_filters( 'wpgraphql_logging_data_sanitization_recommended_rules', $rules ); + } + + /** + * Get the custom sanitization rules based on the settings. + * + * @return array The custom sanitization rules. + */ + protected function get_custom_rules(): array { + + $rules = []; + $fields = [ + 'anonymize' => $this->config[ Data_Management_Tab::DATA_SANITIZATION_CUSTOM_FIELD_ANONYMIZE ] ?? [], + 'remove' => $this->config[ Data_Management_Tab::DATA_SANITIZATION_CUSTOM_FIELD_REMOVE ] ?? [], + 'truncate' => $this->config[ Data_Management_Tab::DATA_SANITIZATION_CUSTOM_FIELD_TRUNCATE ] ?? [], + ]; + + foreach ( $fields as $action => $field_string ) { + if ( empty( $field_string ) || ! is_string( $field_string ) ) { + continue; + } + + $field_string = trim( $field_string ); + $field_list = array_filter( + explode( ',', $field_string ), + static function ($value) { + return '' !== $value; + } + ); + + foreach ( $field_list as $field ) { + $rules[ $field ] = $action; + } + } + return $rules; + } + + /** + * Apply a sanitization rule to a specific key in the data array. + * + * @param array $data The data array to sanitize. + * @param string $key The key to apply the rule to (dot notation for nested keys). + * @param string $rule The sanitization rule ('anonymize', 'remove', 'truncate'). + */ + protected function apply_rule(array &$data, string $key, string $rule): void { + if ( empty( $data ) ) { + return; + } + + $keys = explode( '.', $key ); + $last_key = array_pop( $keys ); + $current = &$this->navigate_to_parent( $data, $keys ); + + if ( null === $current || ! array_key_exists( $last_key, $current ) ) { + return; + } + + $this->apply_sanitization_rule( $current, $last_key, $rule ); + } + + /** + * Navigate to the parent array of the target key. + * + * @param array $data The data array to navigate. + * @param array $keys The keys to navigate through. + * + * @return array|null The parent array or null if not found. + */ + protected function &navigate_to_parent(array &$data, array $keys): ?array { + $current = &$data; + foreach ( $keys as $segment ) { + if ( ! is_array( $current ) || ! isset( $current[ $segment ] ) ) { + $null = null; + return $null; + } + $current = &$current[ $segment ]; + } + return $current; + } + + /** + * Apply the sanitization rule to the target value. + * + * @param array $current The current array containing the target key. + * @param string $key The key to sanitize. + * @param string $rule The sanitization rule to apply. + * + * @phpcs:disable Generic.Metrics.NestingLevel.TooHigh + */ + protected function apply_sanitization_rule(array &$current, string $key, string $rule): void { + switch ( $rule ) { + case 'anonymize': + $current[ $key ] = '***'; + break; + case 'remove': + unset( $current[ $key ] ); + break; + case 'truncate': + if ( is_string( $current[ $key ] ) ) { + $current[ $key ] = substr( $current[ $key ], 0, 47 ) . '...'; + } + break; + } + } + + /** + * This method is called for each log record. It adds the captured + * request headers to the record's 'extra' array. + * + * @param \Monolog\LogRecord $record The log record to process. + * + * @return \Monolog\LogRecord The processed log record. + */ + public function __invoke( LogRecord $record ): LogRecord { + + if ( ! $this->is_enabled() ) { + return $record; + } + + $rules = $this->get_rules(); + + if ( empty( $rules ) ) { + return $record; + } + + $context = $record['context'] ?? []; + $extra = $record['extra'] ?? []; + foreach ( $rules as $key => $rule ) { + $this->apply_rule( $context, $key, $rule ); + $this->apply_rule( $extra, $key, $rule ); + } + + $record = $record->with( context: $context, extra: $extra ); + return apply_filters( 'wpgraphql_logging_data_sanitization_record', $record ); + } +} From 5d7851f3481ddbeb68dcb46292b3ffdd707511e4 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Tue, 23 Sep 2025 14:37:20 +0100 Subject: [PATCH 05/10] Added docs for data sanitisation. --- plugins/wpgraphql-logging/README.md | 120 ++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/plugins/wpgraphql-logging/README.md b/plugins/wpgraphql-logging/README.md index 2009d886..4060c0c5 100644 --- a/plugins/wpgraphql-logging/README.md +++ b/plugins/wpgraphql-logging/README.md @@ -135,6 +135,126 @@ wpgraphql-logging/ --- +## Data Sanitization + +WPGraphQL Logging includes robust data sanitization capabilities to help you protect sensitive information while maintaining useful logs for debugging and monitoring. The sanitization system allows you to automatically clean, anonymize, or remove sensitive fields from log records before they are stored. + +### Why Data Sanitization Matters + +When logging GraphQL requests, context data often contains sensitive information such as: +- User authentication tokens +- Personal identification information (PII) +- Password fields +- Session data +- Internal system information + +Data sanitization ensures compliance with privacy regulations (GDPR, CCPA) and security best practices while preserving the debugging value of your logs. + +### Sanitization Methods + +The plugin offers two sanitization approaches: + +#### 1. Recommended Rules (Default) +Pre-configured rules that automatically sanitize common WordPress and WPGraphQL sensitive fields: +- `request.app_context.viewer.data` - User data object +- `request.app_context.viewer.allcaps` - User capabilities +- `request.app_context.viewer.cap_key` - Capability keys +- `request.app_context.viewer.caps` - User capability array + +#### 2. Custom Rules +Define your own sanitization rules using dot notation to target specific fields: + +**Field Path Examples:** +``` +variables.password +request.headers.authorization +user.email +variables.input.creditCard +``` + +### Sanitization Actions + +For each field, you can choose from three sanitization actions: + +| Action | Description | Example | +|--------|-------------|---------| +| **Remove** | Completely removes the field from logs | `password: "secret123"` → *field removed* | +| **Anonymize** | Replaces value with `***` | `email: "user@example.com"` → `email: "***"` | +| **Truncate** | Limits string length to 47 characters + `...` | `longText: "Very long text..."` → `longText: "Very long text that gets cut off here and mo..."` | + +### Configuration + +Enable and configure data sanitization through the WordPress admin: + +1. Navigate to **GraphQL Logging → Settings** +2. Click the **Data Management** tab +3. Enable **Data Sanitization** +4. Choose your sanitization method: + - **Recommended**: Uses pre-configured rules for common sensitive fields + - **Custom**: Define your own field-specific rules + +#### Custom Configuration Fields + +When using custom rules, configure the following fields: + +- **Fields to Remove**: Comma-separated list of field paths to completely remove +- **Fields to Anonymize**: Comma-separated list of field paths to replace with `***` +- **Fields to Truncate**: Comma-separated list of field paths to limit length + +**Example Configuration:** +``` +Remove: variables.password, request.headers.authorization +Anonymize: user.email, variables.input.personalInfo +Truncate: query, variables.input.description +``` + +### Developer Hooks + +Customize sanitization behavior using WordPress filters: + +```php +// Enable/disable sanitization programmatically +add_filter( 'wpgraphql_logging_data_sanitization_enabled', function( $enabled ) { + return current_user_can( 'manage_options' ) ? false : $enabled; +}); + +// Modify recommended rules +add_filter( 'wpgraphql_logging_data_sanitization_recommended_rules', function( $rules ) { + $rules['custom.sensitive.field'] = 'remove'; + return $rules; +}); + +// Modify all sanitization rules +add_filter( 'wpgraphql_logging_data_sanitization_rules', function( $rules ) { + // Add additional rules or modify existing ones + $rules['request.custom_header'] = 'anonymize'; + return $rules; +}); + +// Modify the final log record after sanitization +add_filter( 'wpgraphql_logging_data_sanitization_record', function( $record ) { + // Additional processing after sanitization + return $record; +}); +``` + +### Performance Considerations + +- Sanitization runs on every log record when enabled +- Complex nested field paths may impact performance on high-traffic sites +- Consider using recommended rules for optimal performance +- Test custom rules thoroughly to ensure they target the intended fields + +### Security Best Practices + +1. **Review logs regularly** to ensure sanitization is working as expected +2. **Test field paths** in a development environment before applying to production +3. **Use remove over anonymize** for highly sensitive data +4. **Monitor performance impact** when implementing extensive custom rules +5. **Keep rules updated** as your GraphQL schema evolves + +--- + ## Usage WPGraphQL Logging Plugin is highly configurable and extendable and built with developers in mind to allow them to modify, change or add data, loggers etc to this plugin. Please read the docs below: From 7bf9cb625e1bee86af9436f8747ee1a24d1b273d Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Tue, 23 Sep 2025 14:51:47 +0100 Subject: [PATCH 06/10] Added Changeset --- .changeset/afraid-lobsters-hang.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/afraid-lobsters-hang.md diff --git a/.changeset/afraid-lobsters-hang.md b/.changeset/afraid-lobsters-hang.md new file mode 100644 index 00000000..6c314c87 --- /dev/null +++ b/.changeset/afraid-lobsters-hang.md @@ -0,0 +1,5 @@ +--- +"@wpengine/wpgraphql-logging-wordpress-plugin": patch +--- + +chore: Added data management for the logging plugin. From de0b02ce5fa6df892770ca036550cb03531280a9 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Tue, 23 Sep 2025 15:40:27 +0100 Subject: [PATCH 07/10] Re-formatted JS file. --- .../settings/wp-graphql-logging-settings.js | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/plugins/wpgraphql-logging/assets/js/settings/wp-graphql-logging-settings.js b/plugins/wpgraphql-logging/assets/js/settings/wp-graphql-logging-settings.js index 65990824..72c11d9f 100644 --- a/plugins/wpgraphql-logging/assets/js/settings/wp-graphql-logging-settings.js +++ b/plugins/wpgraphql-logging/assets/js/settings/wp-graphql-logging-settings.js @@ -1,28 +1,22 @@ -// Add this to your admin JavaScript file document.addEventListener('DOMContentLoaded', function() { - - const sanitizationMethodSelect = document.querySelector("#data_sanitization_method"); - if (! sanitizationMethodSelect || sanitizationMethodSelect.length === 0) { + const sanitizationMethodSelect = document.querySelector("#data_sanitization_method"); + if (!sanitizationMethodSelect) { return; } function toggleCustomFields() { - const isCustom = sanitizationMethodSelect.value === 'custom'; + const isCustom = sanitizationMethodSelect.value === 'custom'; + const customElements = document.querySelectorAll('.wpgraphql-logging-custom'); - if (isCustom) { - document.querySelectorAll('.wpgraphql-logging-custom').forEach((el) => { + customElements.forEach((el) => { + if (isCustom) { el.classList.add('block'); - }); - } else { - document.querySelectorAll('.wpgraphql-logging-custom').forEach((el) => { + } else { el.classList.remove('block'); - }); - } - } + } + }); + } - // Initial check on page load toggleCustomFields(); - - // Listen for changes sanitizationMethodSelect.addEventListener('change', toggleCustomFields); }); From e3ab90ef498c3c78b131763762885294e112df75 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Tue, 23 Sep 2025 17:02:22 +0100 Subject: [PATCH 08/10] Renamed admin classes to PSR-4 standard to follow project conventions. --- .../settings/wp-graphql-logging-settings.css | 11 ++-- plugins/wpgraphql-logging/composer.json | 1 + plugins/wpgraphql-logging/composer.lock | 2 +- plugins/wpgraphql-logging/docs/admin.md | 66 +++++++++---------- ...gs_Field.php => AbstractSettingsField.php} | 4 +- .../{Checkbox_Field.php => CheckboxField.php} | 2 +- .../{Select_Field.php => SelectField.php} | 2 +- ...ext_Input_Field.php => TextInputField.php} | 2 +- ...Integer_Field.php => TextIntegerField.php} | 4 +- ...ection.php => SettingsFieldCollection.php} | 40 +++++------ ...terface.php => SettingsFieldInterface.php} | 2 +- ...tion_Tab.php => BasicConfigurationTab.php} | 24 +++---- ...nagement_Tab.php => DataManagementTab.php} | 27 ++++---- ...Interface.php => SettingsTabInterface.php} | 4 +- ...Service.php => LoggingSettingsService.php} | 2 +- .../Menu/{Menu_Page.php => MenuPage.php} | 2 +- ...rm_Manager.php => SettingsFormManager.php} | 16 ++--- .../src/Admin/Settings/Templates/admin.php | 6 +- .../{Settings_Page.php => SettingsPage.php} | 38 +++++------ ...Log_Service.php => DownloadLogService.php} | 2 +- .../List/{List_Table.php => ListTable.php} | 6 +- .../View/Templates/wpgraphql-logger-list.php | 2 +- .../View/Templates/wpgraphql-logger-view.php | 4 +- .../{View_Logs_Page.php => ViewLogsPage.php} | 12 ++-- .../src/Events/QueryActionLogger.php | 8 +-- .../src/Events/QueryFilterLogger.php | 6 +- .../Processors/DataSanitizationProcessor.php | 12 ++-- .../src/Logger/Rules/AdminUserRule.php | 4 +- .../src/Logger/Rules/EnabledRule.php | 4 +- .../src/Logger/Rules/ExcludeQueryRule.php | 4 +- .../src/Logger/Rules/IpRestrictionsRule.php | 4 +- .../src/Logger/Rules/LogResponseRule.php | 4 +- .../src/Logger/Rules/SamplingRateRule.php | 4 +- .../Scheduler/DataDeletionScheduler.php | 6 +- plugins/wpgraphql-logging/src/Plugin.php | 8 +-- .../Fields/Field/CheckboxFieldTest.php | 8 +-- .../Settings/Fields/Field/SelectFieldTest.php | 12 ++-- .../Fields/Field/TextInputFieldTest.php | 16 ++--- .../tests/wpunit/Admin/Settings_Page_Test.php | 24 +++---- .../wpgraphql-logging/wpgraphql-logging.php | 2 +- 40 files changed, 203 insertions(+), 204 deletions(-) rename plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/{Abstract_Settings_Field.php => AbstractSettingsField.php} (96%) rename plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/{Checkbox_Field.php => CheckboxField.php} (96%) rename plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/{Select_Field.php => SelectField.php} (98%) rename plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/{Text_Input_Field.php => TextInputField.php} (97%) rename plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/{Text_Integer_Field.php => TextIntegerField.php} (86%) rename plugins/wpgraphql-logging/src/Admin/Settings/Fields/{Settings_Field_Collection.php => SettingsFieldCollection.php} (62%) rename plugins/wpgraphql-logging/src/Admin/Settings/Fields/{Settings_Field_Interface.php => SettingsFieldInterface.php} (96%) rename plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/{Basic_Configuration_Tab.php => BasicConfigurationTab.php} (85%) rename plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/{Data_Management_Tab.php => DataManagementTab.php} (83%) rename plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/{Settings_Tab_Interface.php => SettingsTabInterface.php} (88%) rename plugins/wpgraphql-logging/src/Admin/Settings/{Logging_Settings_Service.php => LoggingSettingsService.php} (98%) rename plugins/wpgraphql-logging/src/Admin/Settings/Menu/{Menu_Page.php => MenuPage.php} (99%) rename plugins/wpgraphql-logging/src/Admin/Settings/{Settings_Form_Manager.php => SettingsFormManager.php} (84%) rename plugins/wpgraphql-logging/src/Admin/{Settings_Page.php => SettingsPage.php} (80%) rename plugins/wpgraphql-logging/src/Admin/View/Download/{Download_Log_Service.php => DownloadLogService.php} (98%) rename plugins/wpgraphql-logging/src/Admin/View/List/{List_Table.php => ListTable.php} (98%) rename plugins/wpgraphql-logging/src/Admin/{View_Logs_Page.php => ViewLogsPage.php} (95%) diff --git a/plugins/wpgraphql-logging/assets/css/settings/wp-graphql-logging-settings.css b/plugins/wpgraphql-logging/assets/css/settings/wp-graphql-logging-settings.css index 94556f61..432d6e61 100644 --- a/plugins/wpgraphql-logging/assets/css/settings/wp-graphql-logging-settings.css +++ b/plugins/wpgraphql-logging/assets/css/settings/wp-graphql-logging-settings.css @@ -1,15 +1,15 @@ -settings_page_wpgraphql-logging #poststuff .postbox .inside h2 { +.settings_page_wpgraphql-logging #poststuff .postbox .inside h2 { font-size: 1.3em; font-weight: 600; padding-left: 0; } - .form-table td input[type="number"], .form-table td input[type="text"] { width: calc(99% - 24px); display: inline-block; } + .form-table td select { width: calc(99% - 24px); display: inline-block; @@ -48,12 +48,11 @@ settings_page_wpgraphql-logging #poststuff .postbox .inside h2 { .wpgraphql-logging-tooltip .tooltip-text::after { content: ""; position: absolute; - top: 0; + top: 50%; left: -10px; border-width: 6px; border-style: solid; border-color: transparent #1d2327 transparent transparent; - top: 50%; transform: translateY(-50%); } @@ -72,13 +71,12 @@ settings_page_wpgraphql-logging #poststuff .postbox .inside h2 { .wpgraphql-logging-docs ul li:before { content: url(../../icons/doc.svg); height: 1em; + width: 0.5em; margin-left: -29px; margin-top: -2px; position: absolute; - width: 0.5em; } - .wpgraphql-logging-feature-list { list-style-type: disc; font-size: 1.1em; @@ -86,7 +84,6 @@ settings_page_wpgraphql-logging #poststuff .postbox .inside h2 { padding-bottom: 16px; } - .wpgraphql-logging-custom:not(.block) { display: none; } diff --git a/plugins/wpgraphql-logging/composer.json b/plugins/wpgraphql-logging/composer.json index b06909b4..44d746f7 100644 --- a/plugins/wpgraphql-logging/composer.json +++ b/plugins/wpgraphql-logging/composer.json @@ -48,6 +48,7 @@ "johnpbloch/wordpress-core": "^6.8", "lucatume/wp-browser": "^4.0", "mockery/mockery": "^1.5", + "php-stubs/wordpress-stubs": "^6.8", "phpcompatibility/php-compatibility": "dev-develop as 9.99.99", "phpcompatibility/phpcompatibility-wp": "^2.0", "phpstan/phpstan-strict-rules": "^2.0", diff --git a/plugins/wpgraphql-logging/composer.lock b/plugins/wpgraphql-logging/composer.lock index 316030fb..188e898c 100644 --- a/plugins/wpgraphql-logging/composer.lock +++ b/plugins/wpgraphql-logging/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "80763354fb1a58eacf78bd70d5e8cfbc", + "content-hash": "be7c7a0aff5b08c432f2b70dc142b6f5", "packages": [ { "name": "league/csv", diff --git a/plugins/wpgraphql-logging/docs/admin.md b/plugins/wpgraphql-logging/docs/admin.md index 09e35b47..cbaab46b 100644 --- a/plugins/wpgraphql-logging/docs/admin.md +++ b/plugins/wpgraphql-logging/docs/admin.md @@ -6,34 +6,34 @@ This document explains how the WPGraphQL Logging admin settings UI is built and ## Architecture Overview -- **Settings page entry**: `WPGraphQL\Logging\Admin\Settings_Page` +- **Settings page entry**: `WPGraphQL\Logging\Admin\SettingsPage` - Registers the submenu page and orchestrates fields and tabs - Hooks added: `init` (init fields), `admin_menu` (page), `admin_init` (fields), `admin_enqueue_scripts` (assets) -- **Menu page**: `WPGraphQL\Logging\Admin\Settings\Menu\Menu_Page` +- **Menu page**: `WPGraphQL\Logging\Admin\Settings\Menu\MenuPage` - Adds a submenu under Settings → WPGraphQL Logging (`wpgraphql-logging`) - Renders template `src/Admin/Settings/Templates/admin.php` -- **Form manager**: `WPGraphQL\Logging\Admin\Settings\Settings_Form_Manager` +- **Form manager**: `WPGraphQL\Logging\Admin\Settings\SettingsFormManager` - Registers the settings (`register_setting`) and sections/fields per tab - Sanitizes and saves values per tab; unknown fields are pruned -- **Field collection**: `WPGraphQL\Logging\Admin\Settings\Fields\Settings_Field_Collection` - - Holds all tabs and fields. A default `Basic_Configuration_Tab` is registered -- **Tabs**: Implement `Settings_Tab_Interface` with `get_name()`, `get_label()`, `get_fields()` -- **Fields**: Implement `Settings_Field_Interface` or use built-ins: - - `Field\Checkbox_Field` - - `Field\Text_Input_Field` - - `Field\Select_Field` +- **Field collection**: `WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldCollection` + - Holds all tabs and fields. A default `BasicConfigurationTab` is registered +- **Tabs**: Implement `SettingsTabInterface` with `get_name()`, `get_label()`, `get_fields()` +- **Fields**: Implement `SettingsFieldInterface` or use built-ins: + - `Field\CheckboxField` + - `Field\TextInputField` + - `Field\SelectField` Settings are stored in an array option. Keys are filterable: - Option key: `wpgraphql_logging_settings` (filter `wpgraphql_logging_settings_group_option_key`) - Settings group: `wpgraphql_logging_settings_group` (filter `wpgraphql_logging_settings_group_settings_group`) -To read values at runtime, use `WPGraphQL\Logging\Admin\Settings\Logging_Settings_Service`: +To read values at runtime, use `WPGraphQL\Logging\Admin\Settings\LoggingSettingsService`: ```php -use WPGraphQL\Logging\Admin\Settings\Logging_Settings_Service; +use WPGraphQL\Logging\Admin\Settings\LoggingSettingsService; -$settings = new Logging_Settings_Service(); +$settings = new LoggingSettingsService(); $enabled = $settings->get_setting('basic_configuration', 'enabled', false); ``` @@ -41,11 +41,11 @@ $enabled = $settings->get_setting('basic_configuration', 'enabled', false); ## Hooks Reference (Admin) -- Action: `wpgraphql_logging_settings_init( Settings_Page $instance )` +- Action: `wpgraphql_logging_settings_init( SettingsPage $instance )` - Fired after the settings page is initialized -- Action: `wpgraphql_logging_settings_field_collection_init( Settings_Field_Collection $collection )` +- Action: `wpgraphql_logging_settings_field_collection_init( SettingsFieldCollection $collection )` - Fired after default tabs/fields are registered; primary extension point to add tabs/fields -- Action: `wpgraphql_logging_settings_form_manager_init( Settings_Form_Manager $manager )` +- Action: `wpgraphql_logging_settings_form_manager_init( SettingsFormManager $manager )` - Fired when the form manager is constructed - Filter: `wpgraphql_logging_settings_group_option_key( string $option_key )` - Change the option key used to store settings @@ -53,14 +53,14 @@ $enabled = $settings->get_setting('basic_configuration', 'enabled', false); - Change the settings group name used in `register_setting` - Filter: `wpgraphql_logging_basic_configuration_fields( array $fields )` - - Modify the default fields rendered in the `basic_configuration` tab. You can add, remove, or replace fields by returning a modified associative array of `field_id => Settings_Field_Interface`. + - Modify the default fields rendered in the `basic_configuration` tab. You can add, remove, or replace fields by returning a modified associative array of `field_id => SettingsFieldInterface`. - Example: ```php - use WPGraphQL\Logging\Admin\Settings\Fields\Field\Checkbox_Field; + use WPGraphQL\Logging\Admin\Settings\Fields\Field\CheckboxField; add_filter('wpgraphql_logging_basic_configuration_fields', function(array $fields): array { // Add a custom toggle into the Basic Configuration tab - $fields['enable_feature_x'] = new Checkbox_Field( + $fields['enable_feature_x'] = new CheckboxField( 'enable_feature_x', 'basic_configuration', 'Enable Feature X', @@ -69,7 +69,7 @@ $enabled = $settings->get_setting('basic_configuration', 'enabled', false); ); // Optionally remove an existing field - // unset($fields[ WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab::DATA_SAMPLING ]); + // unset($fields[ WPGraphQL\Logging\Admin\Settings\Fields\Tab\BasicConfigurationTab::DATA_SAMPLING ]); return $fields; }); @@ -84,17 +84,17 @@ Related (non-admin) hooks for context: ## Add a New Tab -Create a tab class implementing `Settings_Tab_Interface` and register it during `wpgraphql_logging_settings_field_collection_init`. +Create a tab class implementing `SettingsTabInterface` and register it during `wpgraphql_logging_settings_field_collection_init`. ```php new Text_Input_Field( + 'my_setting' => new TextInputField( 'my_setting', $this->get_name(), 'My Setting', @@ -117,7 +117,7 @@ class My_Custom_Tab implements Settings_Tab_Interface { } } -add_action('wpgraphql_logging_settings_field_collection_init', function (Settings_Field_Collection $collection): void { +add_action('wpgraphql_logging_settings_field_collection_init', function (SettingsFieldCollection $collection): void { $collection->add_tab(new My_Custom_Tab()); }); ``` @@ -137,13 +137,13 @@ You can add fields directly to the shared field collection. Ensure the field’s add_field( 'enable_feature_x', - new Checkbox_Field( + new CheckboxField( 'enable_feature_x', 'basic_configuration', // target the built-in Basic Configuration tab 'Enable Feature X', @@ -170,9 +170,9 @@ Tips: Example of reading a value elsewhere: ```php -use WPGraphQL\Logging\Admin\Settings\Logging_Settings_Service; +use WPGraphQL\Logging\Admin\Settings\LoggingSettingsService; -$settings = new Logging_Settings_Service(); +$settings = new LoggingSettingsService(); $thresholdSeconds = (float) $settings->get_setting('basic_configuration', 'performance_metrics', '0'); ``` diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Abstract_Settings_Field.php b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/AbstractSettingsField.php similarity index 96% rename from plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Abstract_Settings_Field.php rename to plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/AbstractSettingsField.php index f42c0276..58751bf7 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Abstract_Settings_Field.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/AbstractSettingsField.php @@ -4,7 +4,7 @@ namespace WPGraphQL\Logging\Admin\Settings\Fields\Field; -use WPGraphQL\Logging\Admin\Settings\Fields\Settings_Field_Interface; +use WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldInterface; /** * Abstract Settings Field class for WPGraphQL Logging. @@ -15,7 +15,7 @@ * * @since 0.0.1 */ -abstract class Abstract_Settings_Field implements Settings_Field_Interface { +abstract class AbstractSettingsField implements SettingsFieldInterface { /** * Constructor. * diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Checkbox_Field.php b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/CheckboxField.php similarity index 96% rename from plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Checkbox_Field.php rename to plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/CheckboxField.php index ba3a5f13..711d55b7 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Checkbox_Field.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/CheckboxField.php @@ -13,7 +13,7 @@ * * @since 0.0.1 */ -class Checkbox_Field extends Abstract_Settings_Field { +class CheckboxField extends AbstractSettingsField { /** * Render the checkbox field. * diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Select_Field.php b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/SelectField.php similarity index 98% rename from plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Select_Field.php rename to plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/SelectField.php index 1f25b812..68a061e8 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Select_Field.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/SelectField.php @@ -13,7 +13,7 @@ * * @since 0.0.1 */ -class Select_Field extends Abstract_Settings_Field { +class SelectField extends AbstractSettingsField { /** * Constructor. * diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Text_Input_Field.php b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/TextInputField.php similarity index 97% rename from plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Text_Input_Field.php rename to plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/TextInputField.php index 2c4d79ad..4d897327 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Text_Input_Field.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/TextInputField.php @@ -13,7 +13,7 @@ * * @since 0.0.1 */ -class Text_Input_Field extends Abstract_Settings_Field { +class TextInputField extends AbstractSettingsField { /** * Constructor. * diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Text_Integer_Field.php b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/TextIntegerField.php similarity index 86% rename from plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Text_Integer_Field.php rename to plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/TextIntegerField.php index 6e211b90..44abdba2 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/Text_Integer_Field.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/TextIntegerField.php @@ -4,7 +4,7 @@ namespace WPGraphQL\Logging\Admin\Settings\Fields\Field; -use WPGraphQL\Logging\Admin\Settings\Fields\Field\Text_Input_Field; +use WPGraphQL\Logging\Admin\Settings\Fields\Field\TextInputField; /** * Text Integer Field class for WPGraphQL Logging settings. @@ -15,7 +15,7 @@ * * @since 0.0.1 */ -class Text_Integer_Field extends Text_Input_Field { +class TextIntegerField extends TextInputField { /** * Sanitize the text input field value. * diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Settings_Field_Collection.php b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/SettingsFieldCollection.php similarity index 62% rename from plugins/wpgraphql-logging/src/Admin/Settings/Fields/Settings_Field_Collection.php rename to plugins/wpgraphql-logging/src/Admin/Settings/Fields/SettingsFieldCollection.php index 9ed61f7c..eab07113 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Settings_Field_Collection.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/SettingsFieldCollection.php @@ -4,29 +4,29 @@ namespace WPGraphQL\Logging\Admin\Settings\Fields; -use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab; -use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Data_Management_Tab; -use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Settings_Tab_Interface; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\BasicConfigurationTab; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\DataManagementTab; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\SettingsTabInterface; /** - * Class Settings_Field_Collection + * Class SettingsFieldCollection * * @package WPGraphQL\Logging * * @since 0.0.1 */ -class Settings_Field_Collection { +class SettingsFieldCollection { /** * Array of fields * - * @var array<\WPGraphQL\Logging\Admin\Settings\Fields\Settings_Field_Interface> + * @var array<\WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldInterface> */ protected array $fields = []; /** * Array of tabs * - * @var array<\WPGraphQL\Logging\Admin\Settings\Fields\Tab\Settings_Tab_Interface> + * @var array<\WPGraphQL\Logging\Admin\Settings\Fields\Tab\SettingsTabInterface> */ protected array $tabs = []; @@ -34,13 +34,13 @@ class Settings_Field_Collection { * Constructor to initialize the fields. */ public function __construct() { - $this->add_tab( new Basic_Configuration_Tab() ); - $this->add_tab( new Data_Management_Tab() ); + $this->add_tab( new BasicConfigurationTab() ); + $this->add_tab( new DataManagementTab() ); do_action( 'wpgraphql_logging_settings_field_collection_init', $this ); } /** - * @return array<\WPGraphQL\Logging\Admin\Settings\Fields\Settings_Field_Interface> + * @return array<\WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldInterface> */ public function get_fields(): array { return $this->fields; @@ -51,19 +51,19 @@ public function get_fields(): array { * * @param string $key The key of the field to retrieve. * - * @return \WPGraphQL\Logging\Admin\Settings\Fields\Settings_Field_Interface|null The field if found, null otherwise. + * @return \WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldInterface|null The field if found, null otherwise. */ - public function get_field( string $key ): ?Settings_Field_Interface { + public function get_field( string $key ): ?SettingsFieldInterface { return $this->fields[ $key ] ?? null; } /** * Add a field to the collection. * - * @param string $key The key for the field. - * @param \WPGraphQL\Logging\Admin\Settings\Fields\Settings_Field_Interface $field The field to add. + * @param string $key The key for the field. + * @param \WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldInterface $field The field to add. */ - public function add_field( string $key, Settings_Field_Interface $field ): void { + public function add_field( string $key, SettingsFieldInterface $field ): void { $this->fields[ $key ] = $field; } @@ -79,9 +79,9 @@ public function remove_field( string $key ): void { /** * Add a tab to the collection. * - * @param \WPGraphQL\Logging\Admin\Settings\Fields\Tab\Settings_Tab_Interface $tab The tab to add. + * @param \WPGraphQL\Logging\Admin\Settings\Fields\Tab\SettingsTabInterface $tab The tab to add. */ - public function add_tab( Settings_Tab_Interface $tab ): void { + public function add_tab( SettingsTabInterface $tab ): void { $this->tabs[ $tab->get_name() ] = $tab; foreach ( $tab->get_fields() as $field_key => $field ) { @@ -92,7 +92,7 @@ public function add_tab( Settings_Tab_Interface $tab ): void { /** * Get all tabs. * - * @return array<\WPGraphQL\Logging\Admin\Settings\Fields\Tab\Settings_Tab_Interface> + * @return array<\WPGraphQL\Logging\Admin\Settings\Fields\Tab\SettingsTabInterface> */ public function get_tabs(): array { return $this->tabs; @@ -103,9 +103,9 @@ public function get_tabs(): array { * * @param string $tab_name The name of the tab to retrieve. * - * @return \WPGraphQL\Logging\Admin\Settings\Fields\Tab\Settings_Tab_Interface|null The tab if found, null otherwise. + * @return \WPGraphQL\Logging\Admin\Settings\Fields\Tab\SettingsTabInterface|null The tab if found, null otherwise. */ - public function get_tab( string $tab_name ): ?Settings_Tab_Interface { + public function get_tab( string $tab_name ): ?SettingsTabInterface { return $this->tabs[ $tab_name ] ?? null; } } diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Settings_Field_Interface.php b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/SettingsFieldInterface.php similarity index 96% rename from plugins/wpgraphql-logging/src/Admin/Settings/Fields/Settings_Field_Interface.php rename to plugins/wpgraphql-logging/src/Admin/Settings/Fields/SettingsFieldInterface.php index 0332e3b0..a2a1cd95 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Settings_Field_Interface.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/SettingsFieldInterface.php @@ -11,7 +11,7 @@ * * @since 0.0.1 */ -interface Settings_Field_Interface { +interface SettingsFieldInterface { /** * Render the settings field * diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Basic_Configuration_Tab.php b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/BasicConfigurationTab.php similarity index 85% rename from plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Basic_Configuration_Tab.php rename to plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/BasicConfigurationTab.php index 92d49ed0..7d9c66b5 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Basic_Configuration_Tab.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/BasicConfigurationTab.php @@ -4,9 +4,9 @@ namespace WPGraphQL\Logging\Admin\Settings\Fields\Tab; -use WPGraphQL\Logging\Admin\Settings\Fields\Field\Checkbox_Field; -use WPGraphQL\Logging\Admin\Settings\Fields\Field\Select_Field; -use WPGraphQL\Logging\Admin\Settings\Fields\Field\Text_Input_Field; +use WPGraphQL\Logging\Admin\Settings\Fields\Field\CheckboxField; +use WPGraphQL\Logging\Admin\Settings\Fields\Field\SelectField; +use WPGraphQL\Logging\Admin\Settings\Fields\Field\TextInputField; use WPGraphQL\Logging\Events\Events; /** @@ -16,7 +16,7 @@ * * @since 0.0.1 */ -class Basic_Configuration_Tab implements Settings_Tab_Interface { +class BasicConfigurationTab implements SettingsTabInterface { /** * The field ID for the enabled checkbox. * @@ -85,12 +85,12 @@ public function get_label(): string { /** * Get the fields for this tab. * - * @return array Array of fields keyed by field ID. + * @return array Array of fields keyed by field ID. */ public function get_fields(): array { $fields = []; - $fields[ self::ENABLED ] = new Checkbox_Field( + $fields[ self::ENABLED ] = new CheckboxField( self::ENABLED, $this->get_name(), __( 'Enabled', 'wpgraphql-logging' ), @@ -98,7 +98,7 @@ public function get_fields(): array { __( 'Enable or disable WPGraphQL logging.', 'wpgraphql-logging' ), ); - $fields[ self::IP_RESTRICTIONS ] = new Text_Input_Field( + $fields[ self::IP_RESTRICTIONS ] = new TextInputField( self::IP_RESTRICTIONS, $this->get_name(), __( 'IP Restrictions', 'wpgraphql-logging' ), @@ -107,7 +107,7 @@ public function get_fields(): array { __( 'e.g., 192.168.1.1, 10.0.0.1', 'wpgraphql-logging' ) ); - $fields[ self::EXCLUDE_QUERY ] = new Text_Input_Field( + $fields[ self::EXCLUDE_QUERY ] = new TextInputField( self::EXCLUDE_QUERY, $this->get_name(), __( 'Exclude Queries', 'wpgraphql-logging' ), @@ -116,7 +116,7 @@ public function get_fields(): array { __( 'e.g., __schema,SeedNode,__typename', 'wpgraphql-logging' ) ); - $fields[ self::ADMIN_USER_LOGGING ] = new Checkbox_Field( + $fields[ self::ADMIN_USER_LOGGING ] = new CheckboxField( self::ADMIN_USER_LOGGING, $this->get_name(), __( 'Admin User Logging', 'wpgraphql-logging' ), @@ -124,7 +124,7 @@ public function get_fields(): array { __( 'Log only for admin users.', 'wpgraphql-logging' ) ); - $fields[ self::DATA_SAMPLING ] = new Select_Field( + $fields[ self::DATA_SAMPLING ] = new SelectField( self::DATA_SAMPLING, $this->get_name(), __( 'Data Sampling Rate', 'wpgraphql-logging' ), @@ -140,7 +140,7 @@ public function get_fields(): array { false ); - $fields[ self::EVENT_LOG_SELECTION ] = new Select_Field( + $fields[ self::EVENT_LOG_SELECTION ] = new SelectField( self::EVENT_LOG_SELECTION, $this->get_name(), __( 'Log Points', 'wpgraphql-logging' ), @@ -157,7 +157,7 @@ public function get_fields(): array { true ); - $fields[ self::LOG_RESPONSE ] = new Checkbox_Field( + $fields[ self::LOG_RESPONSE ] = new CheckboxField( self::LOG_RESPONSE, $this->get_name(), __( 'Log Response', 'wpgraphql-logging' ), diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Data_Management_Tab.php b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/DataManagementTab.php similarity index 83% rename from plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Data_Management_Tab.php rename to plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/DataManagementTab.php index 1073b562..94cd5625 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Data_Management_Tab.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/DataManagementTab.php @@ -4,10 +4,11 @@ namespace WPGraphQL\Logging\Admin\Settings\Fields\Tab; -use WPGraphQL\Logging\Admin\Settings\Fields\Field\Checkbox_Field; -use WPGraphQL\Logging\Admin\Settings\Fields\Field\Select_Field; -use WPGraphQL\Logging\Admin\Settings\Fields\Field\Text_Input_Field; -use WPGraphQL\Logging\Admin\Settings\Fields\Field\Text_Integer_Field; +use WPGraphQL\Logging\Admin\Settings\Fields\Field\CheckboxField; +use WPGraphQL\Logging\Admin\Settings\Fields\Field\SelectField; +use WPGraphQL\Logging\Admin\Settings\Fields\Field\TextInputField; +use WPGraphQL\Logging\Admin\Settings\Fields\Field\TextIntegerField; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\SettingsTabInterface; /** * Data Management Tab class. @@ -16,7 +17,7 @@ * * @since 0.0.1 */ -class Data_Management_Tab implements Settings_Tab_Interface { +class DataManagementTab implements SettingsTabInterface { /** * The field ID for the enabled checkbox. * @@ -85,12 +86,12 @@ public function get_label(): string { /** * Get the fields for this tab. * - * @return array Array of fields keyed by field ID. + * @return array Array of fields keyed by field ID. */ public function get_fields(): array { $fields = []; - $fields[ self::DATA_DELETION_ENABLED ] = new Checkbox_Field( + $fields[ self::DATA_DELETION_ENABLED ] = new CheckboxField( self::DATA_DELETION_ENABLED, $this->get_name(), __( 'Data Deletion Enabled', 'wpgraphql-logging' ), @@ -98,7 +99,7 @@ public function get_fields(): array { __( 'Enable or disable data deletion for WPGraphQL logging.', 'wpgraphql-logging' ), ); - $fields[ self::DATA_RETENTION_DAYS ] = new Text_Integer_Field( + $fields[ self::DATA_RETENTION_DAYS ] = new TextIntegerField( self::DATA_RETENTION_DAYS, $this->get_name(), __( 'Number of Days to Retain Logs', 'wpgraphql-logging' ), @@ -108,7 +109,7 @@ public function get_fields(): array { '30' ); - $fields[ self::DATA_SANITIZATION_ENABLED ] = new Checkbox_Field( + $fields[ self::DATA_SANITIZATION_ENABLED ] = new CheckboxField( self::DATA_SANITIZATION_ENABLED, $this->get_name(), __( 'Data Sanitization Enabled', 'wpgraphql-logging' ), @@ -117,7 +118,7 @@ public function get_fields(): array { ); - $fields[ self::DATA_SANITIZATION_METHOD ] = new Select_Field( + $fields[ self::DATA_SANITIZATION_METHOD ] = new SelectField( self::DATA_SANITIZATION_METHOD, $this->get_name(), __( 'Data Sanitization Method', 'wpgraphql-logging' ), @@ -131,7 +132,7 @@ public function get_fields(): array { ); - $fields[ self::DATA_SANITIZATION_CUSTOM_FIELD_ANONYMIZE ] = new Text_Input_Field( + $fields[ self::DATA_SANITIZATION_CUSTOM_FIELD_ANONYMIZE ] = new TextInputField( self::DATA_SANITIZATION_CUSTOM_FIELD_ANONYMIZE, $this->get_name(), __( 'Custom Fields to Anonymize', 'wpgraphql-logging' ), @@ -140,7 +141,7 @@ public function get_fields(): array { 'e.g., user_email, user_ip' ); - $fields[ self::DATA_SANITIZATION_CUSTOM_FIELD_REMOVE ] = new Text_Input_Field( + $fields[ self::DATA_SANITIZATION_CUSTOM_FIELD_REMOVE ] = new TextInputField( self::DATA_SANITIZATION_CUSTOM_FIELD_REMOVE, $this->get_name(), __( 'Custom Fields to Remove', 'wpgraphql-logging' ), @@ -148,7 +149,7 @@ public function get_fields(): array { __( 'Comma-separated list of custom fields to remove.', 'wpgraphql-logging' ), ); - $fields[ self::DATA_SANITIZATION_CUSTOM_FIELD_TRUNCATE ] = new Text_Input_Field( + $fields[ self::DATA_SANITIZATION_CUSTOM_FIELD_TRUNCATE ] = new TextInputField( self::DATA_SANITIZATION_CUSTOM_FIELD_TRUNCATE, $this->get_name(), __( 'Custom Fields to Truncate', 'wpgraphql-logging' ), diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Settings_Tab_Interface.php b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/SettingsTabInterface.php similarity index 88% rename from plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Settings_Tab_Interface.php rename to plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/SettingsTabInterface.php index 7c102479..08d417d5 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/Settings_Tab_Interface.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Tab/SettingsTabInterface.php @@ -14,7 +14,7 @@ * * @since 0.0.1 */ -interface Settings_Tab_Interface { +interface SettingsTabInterface { /** * Get the name of the tab. * @@ -32,7 +32,7 @@ public function get_label(): string; /** * Get the fields for this tab. * - * @return array Array of fields keyed by field ID. + * @return array Array of fields keyed by field ID. */ public function get_fields(): array; } diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Logging_Settings_Service.php b/plugins/wpgraphql-logging/src/Admin/Settings/LoggingSettingsService.php similarity index 98% rename from plugins/wpgraphql-logging/src/Admin/Settings/Logging_Settings_Service.php rename to plugins/wpgraphql-logging/src/Admin/Settings/LoggingSettingsService.php index 833d447d..90ebe75f 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Logging_Settings_Service.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/LoggingSettingsService.php @@ -13,7 +13,7 @@ * * @since 0.0.1 */ -class Logging_Settings_Service { +class LoggingSettingsService { /** * The settings value * diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Menu/Menu_Page.php b/plugins/wpgraphql-logging/src/Admin/Settings/Menu/MenuPage.php similarity index 99% rename from plugins/wpgraphql-logging/src/Admin/Settings/Menu/Menu_Page.php rename to plugins/wpgraphql-logging/src/Admin/Settings/Menu/MenuPage.php index 99e5052e..db66bb0d 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Menu/Menu_Page.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Menu/MenuPage.php @@ -13,7 +13,7 @@ * * @since 0.0.1 */ -class Menu_Page { +class MenuPage { /** * The title of the page. * diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Settings_Form_Manager.php b/plugins/wpgraphql-logging/src/Admin/Settings/SettingsFormManager.php similarity index 84% rename from plugins/wpgraphql-logging/src/Admin/Settings/Settings_Form_Manager.php rename to plugins/wpgraphql-logging/src/Admin/Settings/SettingsFormManager.php index 2fc32bd2..07c736e9 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Settings_Form_Manager.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/SettingsFormManager.php @@ -4,7 +4,7 @@ namespace WPGraphQL\Logging\Admin\Settings; -use WPGraphQL\Logging\Admin\Settings\Fields\Settings_Field_Collection; +use WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldCollection; /** * Settings Form Manager class for WPGraphQL Logging. @@ -15,15 +15,15 @@ * * @since 0.0.1 */ -class Settings_Form_Manager { +class SettingsFormManager { /** - * @param \WPGraphQL\Logging\Admin\Settings\Fields\Settings_Field_Collection $field_collection Collection of fields to be registered in the settings sections. + * @param \WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldCollection $field_collection Collection of fields to be registered in the settings sections. */ - public function __construct(readonly Settings_Field_Collection $field_collection ) { + public function __construct(readonly SettingsFieldCollection $field_collection ) { /** * Fire off init action. * - * @param \WPGraphQL\Logging\Admin\Settings\Settings_Form_Manager $instance the instance of the settings class. + * @param \WPGraphQL\Logging\Admin\Settings\SettingsFormManager $instance the instance of the settings class. */ do_action( 'wpgraphql_logging_settings_form_manager_init', $this ); } @@ -110,14 +110,14 @@ public function sanitize_settings( ?array $new_input ): array { * Get the option key for the settings group. */ public function get_option_key(): string { - return Logging_Settings_Service::get_option_key(); + return LoggingSettingsService::get_option_key(); } /** * Get the settings group for the options. */ public function get_settings_group(): string { - return Logging_Settings_Service::get_settings_group(); + return LoggingSettingsService::get_settings_group(); } /** @@ -135,7 +135,7 @@ protected function render_tab_section( string $tab_key, string $label ): void { add_settings_section( $page_id, $label, static fn() => null, $page_uri ); - /** @var \WPGraphQL\Logging\Admin\Settings\Fields\Settings_Field_Interface $field */ + /** @var \WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldInterface $field */ foreach ( $fields as $field ) { if ( ! $field->should_render_for_tab( $tab_key ) ) { continue; diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Templates/admin.php b/plugins/wpgraphql-logging/src/Admin/Settings/Templates/admin.php index 8dd0a00a..1a743da0 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Templates/admin.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Templates/admin.php @@ -9,7 +9,7 @@ declare(strict_types=1); -use WPGraphQL\Logging\Admin\Settings\Logging_Settings_Service; +use WPGraphQL\Logging\Admin\Settings\LoggingSettingsService; $wpgraphql_logging_tabs_config = (array) get_query_var( 'wpgraphql_logging_main_page_config' ); $wpgraphql_logging_current_tab = (string) ( $wpgraphql_logging_tabs_config['current_tab'] ?? '' ); @@ -37,7 +37,7 @@
    @@ -94,7 +94,7 @@ break; } ?> - +
    diff --git a/plugins/wpgraphql-logging/src/Admin/Settings_Page.php b/plugins/wpgraphql-logging/src/Admin/SettingsPage.php similarity index 80% rename from plugins/wpgraphql-logging/src/Admin/Settings_Page.php rename to plugins/wpgraphql-logging/src/Admin/SettingsPage.php index f49650a8..6a1244dd 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings_Page.php +++ b/plugins/wpgraphql-logging/src/Admin/SettingsPage.php @@ -4,13 +4,13 @@ namespace WPGraphQL\Logging\Admin; -use WPGraphQL\Logging\Admin\Settings\Fields\Settings_Field_Collection; -use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Settings_Tab_Interface; -use WPGraphQL\Logging\Admin\Settings\Menu\Menu_Page; -use WPGraphQL\Logging\Admin\Settings\Settings_Form_Manager; +use WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldCollection; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\SettingsTabInterface; +use WPGraphQL\Logging\Admin\Settings\Menu\MenuPage; +use WPGraphQL\Logging\Admin\Settings\SettingsFormManager; /** - * Settings_Page class for WPGraphQL Logging. + * SettingsPage class for WPGraphQL Logging. * * This class handles the registration of the settings page, settings fields, and loading of scripts and styles for the plugin. * @@ -18,7 +18,7 @@ * * @since 0.0.1 */ -class Settings_Page { +class SettingsPage { /** * @var string The slug for the plugin menu. */ @@ -27,21 +27,21 @@ class Settings_Page { /** * The field collection. * - * @var \WPGraphQL\Logging\Admin\Settings\Fields\Settings_Field_Collection|null + * @var \WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldCollection|null */ - protected ?Settings_Field_Collection $field_collection = null; + protected ?SettingsFieldCollection $field_collection = null; /** * The instance of the plugin. * - * @var \WPGraphQL\Logging\Admin\Settings_Page|null + * @var \WPGraphQL\Logging\Admin\SettingsPage|null */ - protected static ?Settings_Page $instance = null; + protected static ?SettingsPage $instance = null; /** * Initializes the settings page. */ - public static function init(): ?Settings_Page { + public static function init(): ?SettingsPage { if ( ! current_user_can( 'manage_options' ) ) { return null; } @@ -54,7 +54,7 @@ public static function init(): ?Settings_Page { /** * Fire off init action. * - * @param \WPGraphQL\Logging\Admin\Settings_Page $instance the instance of the plugin class. + * @param \WPGraphQL\Logging\Admin\SettingsPage $instance the instance of the plugin class. */ do_action( 'wpgraphql_logging_settings_init', self::$instance ); @@ -75,7 +75,7 @@ public function setup(): void { * Initialize the field collection. */ public function init_field_collection(): void { - $this->field_collection = new Settings_Field_Collection(); + $this->field_collection = new SettingsFieldCollection(); } /** @@ -90,14 +90,14 @@ public function register_settings_page(): void { $tab_labels = []; foreach ( $tabs as $tab_key => $tab ) { - if ( ! is_a( $tab, Settings_Tab_Interface::class ) ) { + if ( ! is_a( $tab, SettingsTabInterface::class ) ) { continue; } $tab_labels[ $tab_key ] = $tab->get_label(); } - $page = new Menu_Page( + $page = new MenuPage( __( 'WPGraphQL Logging Settings', 'wpgraphql-logging' ), 'WPGraphQL Logging', self::PLUGIN_MENU_SLUG, @@ -120,14 +120,14 @@ public function register_settings_fields(): void { if ( ! isset( $this->field_collection ) ) { return; } - $settings_manager = new Settings_Form_Manager( $this->field_collection ); + $settings_manager = new SettingsFormManager( $this->field_collection ); $settings_manager->render_form(); } /** * Get the current tab for the settings page. * - * @param array $tabs Optional. The available tabs. If not provided, uses the instance tabs. + * @param array $tabs Optional. The available tabs. If not provided, uses the instance tabs. * * @return string The current tab slug. */ @@ -195,9 +195,9 @@ public function load_scripts_styles( string $hook_suffix ): void { /** * Get the tabs for the settings page. * - * @param array $tabs Optional. The available tabs. If not provided, uses the instance tabs. + * @param array $tabs Optional. The available tabs. If not provided, uses the instance tabs. * - * @return array The tabs. + * @return array The tabs. */ protected function get_tabs(array $tabs = []): array { if ( ! empty( $tabs ) ) { diff --git a/plugins/wpgraphql-logging/src/Admin/View/Download/Download_Log_Service.php b/plugins/wpgraphql-logging/src/Admin/View/Download/DownloadLogService.php similarity index 98% rename from plugins/wpgraphql-logging/src/Admin/View/Download/Download_Log_Service.php rename to plugins/wpgraphql-logging/src/Admin/View/Download/DownloadLogService.php index b16f8ba5..4032be55 100644 --- a/plugins/wpgraphql-logging/src/Admin/View/Download/Download_Log_Service.php +++ b/plugins/wpgraphql-logging/src/Admin/View/Download/DownloadLogService.php @@ -14,7 +14,7 @@ * * @since 0.0.1 */ -class Download_Log_Service { +class DownloadLogService { /** * Generates and serves a CSV file for a single log entry. * diff --git a/plugins/wpgraphql-logging/src/Admin/View/List/List_Table.php b/plugins/wpgraphql-logging/src/Admin/View/List/ListTable.php similarity index 98% rename from plugins/wpgraphql-logging/src/Admin/View/List/List_Table.php rename to plugins/wpgraphql-logging/src/Admin/View/List/ListTable.php index 670d8e12..f6e16d76 100644 --- a/plugins/wpgraphql-logging/src/Admin/View/List/List_Table.php +++ b/plugins/wpgraphql-logging/src/Admin/View/List/ListTable.php @@ -14,7 +14,7 @@ } /** - * List_Table class for WPGraphQL Logging. + * ListTable class for WPGraphQL Logging. * * This class handles the display of the logs in a table format. * @@ -22,7 +22,7 @@ * * @since 0.0.1 */ -class List_Table extends WP_List_Table { +class ListTable extends WP_List_Table { /** * Default number of items per page. * @@ -299,7 +299,7 @@ public function column_cb( $item ): string { * @return string The rendered ID column or null. */ public function column_id( DatabaseEntity $item ): string { - $url = \WPGraphQL\Logging\Admin\View_Logs_Page::ADMIN_PAGE_SLUG; + $url = \WPGraphQL\Logging\Admin\ViewLogsPage::ADMIN_PAGE_SLUG; $actions = [ 'view' => sprintf( '%s', diff --git a/plugins/wpgraphql-logging/src/Admin/View/Templates/wpgraphql-logger-list.php b/plugins/wpgraphql-logging/src/Admin/View/Templates/wpgraphql-logger-list.php index 398ed9dc..fa26bef5 100644 --- a/plugins/wpgraphql-logging/src/Admin/View/Templates/wpgraphql-logger-list.php +++ b/plugins/wpgraphql-logging/src/Admin/View/Templates/wpgraphql-logger-list.php @@ -7,7 +7,7 @@ * * @package WPGraphQL\Logger\Admin\View\List\Templates * - * @var \WPGraphQL\Logging\Admin\View\List\List_Table $list_table List table instance. + * @var \WPGraphQL\Logging\Admin\View\List\ListTable $list_table List table instance. * * @since 0.0.1 */ diff --git a/plugins/wpgraphql-logging/src/Admin/View/Templates/wpgraphql-logger-view.php b/plugins/wpgraphql-logging/src/Admin/View/Templates/wpgraphql-logger-view.php index 7a782aac..cd105433 100644 --- a/plugins/wpgraphql-logging/src/Admin/View/Templates/wpgraphql-logger-view.php +++ b/plugins/wpgraphql-logging/src/Admin/View/Templates/wpgraphql-logger-view.php @@ -17,7 +17,7 @@ admin_url( sprintf( 'admin.php?page=%s&action=%s&log=%d', - \WPGraphQL\Logging\Admin\View_Logs_Page::ADMIN_PAGE_SLUG, + \WPGraphQL\Logging\Admin\ViewLogsPage::ADMIN_PAGE_SLUG, 'download', $log->get_id() ) @@ -71,7 +71,7 @@

    - +

    diff --git a/plugins/wpgraphql-logging/src/Admin/View_Logs_Page.php b/plugins/wpgraphql-logging/src/Admin/ViewLogsPage.php similarity index 95% rename from plugins/wpgraphql-logging/src/Admin/View_Logs_Page.php rename to plugins/wpgraphql-logging/src/Admin/ViewLogsPage.php index 5116eb59..6942b05d 100644 --- a/plugins/wpgraphql-logging/src/Admin/View_Logs_Page.php +++ b/plugins/wpgraphql-logging/src/Admin/ViewLogsPage.php @@ -4,8 +4,8 @@ namespace WPGraphQL\Logging\Admin; -use WPGraphQL\Logging\Admin\View\Download\Download_Log_Service; -use WPGraphQL\Logging\Admin\View\List\List_Table; +use WPGraphQL\Logging\Admin\View\Download\DownloadLogService; +use WPGraphQL\Logging\Admin\View\List\ListTable; use WPGraphQL\Logging\Logger\Database\LogsRepository; /** @@ -15,7 +15,7 @@ * * @since 0.0.1 */ -class View_Logs_Page { +class ViewLogsPage { /** * The admin page slug. * @@ -40,7 +40,7 @@ class View_Logs_Page { /** * Initializes the view logs page. */ - public static function init(): ?View_Logs_Page { + public static function init(): ?ViewLogsPage { if ( ! current_user_can( 'manage_options' ) ) { return null; } @@ -231,7 +231,7 @@ protected function get_post_value(string $key): ?string { */ protected function render_list_page(): void { // Variable required for list template. - $list_table = new List_Table( new LogsRepository() ); // @phpcs:ignore SlevomatCodingStandard.Variables.UnusedVariable.UnusedVariable + $list_table = new ListTable( new LogsRepository() ); // @phpcs:ignore SlevomatCodingStandard.Variables.UnusedVariable.UnusedVariable $list_template = apply_filters( 'wpgraphql_logging_list_template', __DIR__ . '/View/Templates/wpgraphql-logger-list.php' @@ -248,7 +248,7 @@ protected function process_log_download(): void { } $log_id = isset( $_GET['log'] ) ? absint( $_GET['log'] ) : 0; // @phpcs:ignore WordPress.Security.NonceVerification.Recommended - $downloader = new Download_Log_Service(); + $downloader = new DownloadLogService(); $downloader->generate_csv( $log_id ); } diff --git a/plugins/wpgraphql-logging/src/Events/QueryActionLogger.php b/plugins/wpgraphql-logging/src/Events/QueryActionLogger.php index d5868137..ab18d09f 100644 --- a/plugins/wpgraphql-logging/src/Events/QueryActionLogger.php +++ b/plugins/wpgraphql-logging/src/Events/QueryActionLogger.php @@ -6,7 +6,7 @@ use GraphQL\Executor\ExecutionResult; use Monolog\Level; -use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\BasicConfigurationTab; use WPGraphQL\Logging\Logger\LoggerService; use WPGraphQL\Logging\Logger\LoggingHelper; use WPGraphQL\Request; @@ -64,7 +64,7 @@ public function log_pre_request( ?string $query, ?string $operation_name, ?array if ( ! $this->is_logging_enabled( $this->config, $query ) ) { return; } - $selected_events = $this->config[ Basic_Configuration_Tab::EVENT_LOG_SELECTION ] ?? []; + $selected_events = $this->config[ BasicConfigurationTab::EVENT_LOG_SELECTION ] ?? []; if ( ! is_array( $selected_events ) || empty( $selected_events ) ) { return; } @@ -107,7 +107,7 @@ public function log_graphql_before_execute( Request $request ): void { if ( ! $this->is_logging_enabled( $this->config, $params->query ) ) { return; } - $selected_events = $this->config[ Basic_Configuration_Tab::EVENT_LOG_SELECTION ] ?? []; + $selected_events = $this->config[ BasicConfigurationTab::EVENT_LOG_SELECTION ] ?? []; if ( ! is_array( $selected_events ) || empty( $selected_events ) ) { return; } @@ -157,7 +157,7 @@ public function log_before_response_returned( if ( ! $this->is_logging_enabled( $this->config, $query ) ) { return; } - $selected_events = $this->config[ Basic_Configuration_Tab::EVENT_LOG_SELECTION ] ?? []; + $selected_events = $this->config[ BasicConfigurationTab::EVENT_LOG_SELECTION ] ?? []; if ( ! is_array( $selected_events ) || empty( $selected_events ) ) { return; } diff --git a/plugins/wpgraphql-logging/src/Events/QueryFilterLogger.php b/plugins/wpgraphql-logging/src/Events/QueryFilterLogger.php index 77569001..4a7d1891 100644 --- a/plugins/wpgraphql-logging/src/Events/QueryFilterLogger.php +++ b/plugins/wpgraphql-logging/src/Events/QueryFilterLogger.php @@ -6,7 +6,7 @@ use GraphQL\Executor\ExecutionResult; use Monolog\Level; -use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\BasicConfigurationTab; use WPGraphQL\Logging\Logger\LoggerService; use WPGraphQL\Logging\Logger\LoggingHelper; use WPGraphQL\Logging\Logger\Rules\EnabledRule; @@ -63,7 +63,7 @@ public function __construct( LoggerService $logger, array $config ) { */ public function log_graphql_request_data( array $query_data ): array { try { - $selected_events = $this->config[ Basic_Configuration_Tab::EVENT_LOG_SELECTION ] ?? []; + $selected_events = $this->config[ BasicConfigurationTab::EVENT_LOG_SELECTION ] ?? []; if ( ! is_array( $selected_events ) || empty( $selected_events ) ) { return $query_data; } @@ -121,7 +121,7 @@ public function log_graphql_request_results( return $response; } - $selected_events = $this->config[ Basic_Configuration_Tab::EVENT_LOG_SELECTION ] ?? []; + $selected_events = $this->config[ BasicConfigurationTab::EVENT_LOG_SELECTION ] ?? []; if ( ! is_array( $selected_events ) || empty( $selected_events ) ) { return $response; } diff --git a/plugins/wpgraphql-logging/src/Logger/Processors/DataSanitizationProcessor.php b/plugins/wpgraphql-logging/src/Logger/Processors/DataSanitizationProcessor.php index cc10be97..52d24d1f 100644 --- a/plugins/wpgraphql-logging/src/Logger/Processors/DataSanitizationProcessor.php +++ b/plugins/wpgraphql-logging/src/Logger/Processors/DataSanitizationProcessor.php @@ -6,7 +6,7 @@ use Monolog\LogRecord; use Monolog\Processor\ProcessorInterface; -use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Data_Management_Tab; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\DataManagementTab; /** * This class is responsible for sanitizing data in log records @@ -35,7 +35,7 @@ public function __construct() { * Check if data sanitization is enabled. */ protected function is_enabled(): bool { - $is_enabled = (bool) ( $this->config[ Data_Management_Tab::DATA_SANITIZATION_ENABLED ] ?? false ); + $is_enabled = (bool) ( $this->config[ DataManagementTab::DATA_SANITIZATION_ENABLED ] ?? false ); return apply_filters( 'wpgraphql_logging_data_sanitization_enabled', $is_enabled ); } @@ -45,7 +45,7 @@ protected function is_enabled(): bool { * @return array The sanitization rules. */ protected function get_rules(): array { - $method = $this->config[ Data_Management_Tab::DATA_SANITIZATION_METHOD ] ?? 'none'; + $method = $this->config[ DataManagementTab::DATA_SANITIZATION_METHOD ] ?? 'none'; if ( 'recommended' === $method ) { @@ -79,9 +79,9 @@ protected function get_custom_rules(): array { $rules = []; $fields = [ - 'anonymize' => $this->config[ Data_Management_Tab::DATA_SANITIZATION_CUSTOM_FIELD_ANONYMIZE ] ?? [], - 'remove' => $this->config[ Data_Management_Tab::DATA_SANITIZATION_CUSTOM_FIELD_REMOVE ] ?? [], - 'truncate' => $this->config[ Data_Management_Tab::DATA_SANITIZATION_CUSTOM_FIELD_TRUNCATE ] ?? [], + 'anonymize' => $this->config[ DataManagementTab::DATA_SANITIZATION_CUSTOM_FIELD_ANONYMIZE ] ?? [], + 'remove' => $this->config[ DataManagementTab::DATA_SANITIZATION_CUSTOM_FIELD_REMOVE ] ?? [], + 'truncate' => $this->config[ DataManagementTab::DATA_SANITIZATION_CUSTOM_FIELD_TRUNCATE ] ?? [], ]; foreach ( $fields as $action => $field_string ) { diff --git a/plugins/wpgraphql-logging/src/Logger/Rules/AdminUserRule.php b/plugins/wpgraphql-logging/src/Logger/Rules/AdminUserRule.php index e4d1e0e2..dd346efa 100644 --- a/plugins/wpgraphql-logging/src/Logger/Rules/AdminUserRule.php +++ b/plugins/wpgraphql-logging/src/Logger/Rules/AdminUserRule.php @@ -4,7 +4,7 @@ namespace WPGraphQL\Logging\Logger\Rules; -use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\BasicConfigurationTab; /** * Rule to check if logging should occur based on admin user setting. @@ -24,7 +24,7 @@ class AdminUserRule implements LoggingRuleInterface { */ public function passes(array $config, ?string $query_string = null): bool { - $is_admin_user = (bool) ( $config[ Basic_Configuration_Tab::ADMIN_USER_LOGGING ] ?? false ); + $is_admin_user = (bool) ( $config[ BasicConfigurationTab::ADMIN_USER_LOGGING ] ?? false ); if ( ! $is_admin_user ) { return true; } diff --git a/plugins/wpgraphql-logging/src/Logger/Rules/EnabledRule.php b/plugins/wpgraphql-logging/src/Logger/Rules/EnabledRule.php index d8f98415..2b95ffba 100644 --- a/plugins/wpgraphql-logging/src/Logger/Rules/EnabledRule.php +++ b/plugins/wpgraphql-logging/src/Logger/Rules/EnabledRule.php @@ -4,7 +4,7 @@ namespace WPGraphQL\Logging\Logger\Rules; -use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\BasicConfigurationTab; /** * Rule to check if logging is enabled. @@ -23,7 +23,7 @@ class EnabledRule implements LoggingRuleInterface { * @return bool True if the rule passes (logging should continue). */ public function passes(array $config, ?string $query_string = null): bool { - return (bool) ( $config[ Basic_Configuration_Tab::ENABLED ] ?? false ); + return (bool) ( $config[ BasicConfigurationTab::ENABLED ] ?? false ); } /** diff --git a/plugins/wpgraphql-logging/src/Logger/Rules/ExcludeQueryRule.php b/plugins/wpgraphql-logging/src/Logger/Rules/ExcludeQueryRule.php index 2b57fc96..ce06cde9 100644 --- a/plugins/wpgraphql-logging/src/Logger/Rules/ExcludeQueryRule.php +++ b/plugins/wpgraphql-logging/src/Logger/Rules/ExcludeQueryRule.php @@ -4,7 +4,7 @@ namespace WPGraphQL\Logging\Logger\Rules; -use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\BasicConfigurationTab; /** * Rule to check if the query is excluded from logging. @@ -23,7 +23,7 @@ class ExcludeQueryRule implements LoggingRuleInterface { * @return bool True if the rule passes (logging should continue). */ public function passes(array $config, ?string $query_string = null): bool { - $queries = $config[ Basic_Configuration_Tab::EXCLUDE_QUERY ] ?? ''; + $queries = $config[ BasicConfigurationTab::EXCLUDE_QUERY ] ?? ''; if ( null === $query_string ) { return true; } diff --git a/plugins/wpgraphql-logging/src/Logger/Rules/IpRestrictionsRule.php b/plugins/wpgraphql-logging/src/Logger/Rules/IpRestrictionsRule.php index da291574..2b1ff8ef 100644 --- a/plugins/wpgraphql-logging/src/Logger/Rules/IpRestrictionsRule.php +++ b/plugins/wpgraphql-logging/src/Logger/Rules/IpRestrictionsRule.php @@ -4,7 +4,7 @@ namespace WPGraphQL\Logging\Logger\Rules; -use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\BasicConfigurationTab; /** * Rule to check if logging should occur based on IP restrictions. @@ -24,7 +24,7 @@ class IpRestrictionsRule implements LoggingRuleInterface { */ public function passes(array $config, ?string $query_string = null): bool { - $ip_restrictions = $config[ Basic_Configuration_Tab::IP_RESTRICTIONS ] ?? ''; + $ip_restrictions = $config[ BasicConfigurationTab::IP_RESTRICTIONS ] ?? ''; if ( empty( $ip_restrictions ) ) { return true; } diff --git a/plugins/wpgraphql-logging/src/Logger/Rules/LogResponseRule.php b/plugins/wpgraphql-logging/src/Logger/Rules/LogResponseRule.php index 6c734b30..4c2b1c09 100644 --- a/plugins/wpgraphql-logging/src/Logger/Rules/LogResponseRule.php +++ b/plugins/wpgraphql-logging/src/Logger/Rules/LogResponseRule.php @@ -4,7 +4,7 @@ namespace WPGraphQL\Logging\Logger\Rules; -use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\BasicConfigurationTab; /** * Rule to check if we should log the response. @@ -23,7 +23,7 @@ class LogResponseRule implements LoggingRuleInterface { * @return bool True if the rule passes (logging should continue). */ public function passes(array $config, ?string $query_string = null): bool { - return (bool) ( $config[ Basic_Configuration_Tab::LOG_RESPONSE ] ?? false ); + return (bool) ( $config[ BasicConfigurationTab::LOG_RESPONSE ] ?? false ); } /** diff --git a/plugins/wpgraphql-logging/src/Logger/Rules/SamplingRateRule.php b/plugins/wpgraphql-logging/src/Logger/Rules/SamplingRateRule.php index 450a8f65..0358469e 100644 --- a/plugins/wpgraphql-logging/src/Logger/Rules/SamplingRateRule.php +++ b/plugins/wpgraphql-logging/src/Logger/Rules/SamplingRateRule.php @@ -4,7 +4,7 @@ namespace WPGraphQL\Logging\Logger\Rules; -use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\BasicConfigurationTab; /** * Rule to check if logging is enabled. @@ -23,7 +23,7 @@ class SamplingRateRule implements LoggingRuleInterface { * @return bool True if the rule passes (logging should continue). */ public function passes(array $config, ?string $query_string = null): bool { - $sampling_rate = (int) ( $config[ Basic_Configuration_Tab::DATA_SAMPLING ] ?? 100 ); + $sampling_rate = (int) ( $config[ BasicConfigurationTab::DATA_SAMPLING ] ?? 100 ); $rand = wp_rand( 0, 100 ); return $rand <= $sampling_rate; } diff --git a/plugins/wpgraphql-logging/src/Logger/Scheduler/DataDeletionScheduler.php b/plugins/wpgraphql-logging/src/Logger/Scheduler/DataDeletionScheduler.php index ce5a12d0..11db9b6f 100644 --- a/plugins/wpgraphql-logging/src/Logger/Scheduler/DataDeletionScheduler.php +++ b/plugins/wpgraphql-logging/src/Logger/Scheduler/DataDeletionScheduler.php @@ -4,7 +4,7 @@ namespace WPGraphQL\Logging\Logger\Scheduler; -use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Data_Management_Tab; +use WPGraphQL\Logging\Admin\Settings\Fields\Tab\DataManagementTab; use WPGraphQL\Logging\Logger\Database\LogsRepository; /** @@ -75,11 +75,11 @@ public function schedule_deletion(): void { */ public function perform_deletion(): void { - if ( false === (bool) $this->config[ Data_Management_Tab::DATA_DELETION_ENABLED ] ) { + if ( false === (bool) $this->config[ DataManagementTab::DATA_DELETION_ENABLED ] ) { return; } - $retention_days = $this->config[ Data_Management_Tab::DATA_RETENTION_DAYS ]; + $retention_days = $this->config[ DataManagementTab::DATA_RETENTION_DAYS ]; if ( ! is_numeric( $retention_days ) ) { return; } diff --git a/plugins/wpgraphql-logging/src/Plugin.php b/plugins/wpgraphql-logging/src/Plugin.php index 6d3e042f..5b9c7f53 100644 --- a/plugins/wpgraphql-logging/src/Plugin.php +++ b/plugins/wpgraphql-logging/src/Plugin.php @@ -4,8 +4,8 @@ namespace WPGraphQL\Logging; -use WPGraphQL\Logging\Admin\Settings_Page; -use WPGraphQL\Logging\Admin\View_Logs_Page; +use WPGraphQL\Logging\Admin\SettingsPage; +use WPGraphQL\Logging\Admin\ViewLogsPage; use WPGraphQL\Logging\Events\EventManager; use WPGraphQL\Logging\Events\QueryEventLifecycle; use WPGraphQL\Logging\Logger\Database\DatabaseEntity; @@ -55,8 +55,8 @@ public static function init(): self { * Initialize the plugin admin, frontend & api functionality. */ public function setup(): void { - Settings_Page::init(); - View_Logs_Page::init(); + SettingsPage::init(); + ViewLogsPage::init(); QueryEventLifecycle::init(); DataDeletionScheduler::init(); } diff --git a/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings/Fields/Field/CheckboxFieldTest.php b/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings/Fields/Field/CheckboxFieldTest.php index 1ff8290f..e456f5db 100644 --- a/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings/Fields/Field/CheckboxFieldTest.php +++ b/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings/Fields/Field/CheckboxFieldTest.php @@ -4,17 +4,17 @@ namespace WPGraphQL\Logging\wpunit\Admin\Settings\Fields\Field; -use WPGraphQL\Logging\Admin\Settings\Fields\Field\Checkbox_Field; -use WPGraphQL\Logging\Admin\Settings\Fields\Settings_Field_Interface; +use WPGraphQL\Logging\Admin\Settings\Fields\Field\CheckboxField; +use WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldInterface; use lucatume\WPBrowser\TestCase\WPTestCase; class CheckboxFieldTest extends WPTestCase { - protected ?Checkbox_Field $field = null; + protected ?CheckboxField $field = null; protected function setUp(): void { parent::setUp(); - $this->field = new Checkbox_Field( + $this->field = new CheckboxField( 'enable_logging', 'basic_configuration', 'Enable Logging', diff --git a/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings/Fields/Field/SelectFieldTest.php b/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings/Fields/Field/SelectFieldTest.php index eef473b8..aa07150e 100644 --- a/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings/Fields/Field/SelectFieldTest.php +++ b/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings/Fields/Field/SelectFieldTest.php @@ -4,18 +4,18 @@ namespace WPGraphQL\Logging\wpunit\Admin\Settings\Fields\Field; -use WPGraphQL\Logging\Admin\Settings\Fields\Field\Select_Field; -use WPGraphQL\Logging\Admin\Settings\Fields\Settings_Field_Interface; +use WPGraphQL\Logging\Admin\Settings\Fields\Field\SelectField; +use WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldInterface; use lucatume\WPBrowser\TestCase\WPTestCase; class SelectFieldTest extends WPTestCase { - protected ?Select_Field $field = null; - protected ?Select_Field $multipleField = null; + protected ?SelectField $field = null; + protected ?SelectField $multipleField = null; protected function setUp(): void { parent::setUp(); - $this->field = new Select_Field( + $this->field = new SelectField( 'log_level', 'basic_configuration', 'Log Level', @@ -30,7 +30,7 @@ protected function setUp(): void { false ); - $this->multipleField = new Select_Field( + $this->multipleField = new SelectField( 'query_types', 'basic_configuration', 'Query Types', diff --git a/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings/Fields/Field/TextInputFieldTest.php b/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings/Fields/Field/TextInputFieldTest.php index d2c877dc..0b436cc1 100644 --- a/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings/Fields/Field/TextInputFieldTest.php +++ b/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings/Fields/Field/TextInputFieldTest.php @@ -4,17 +4,17 @@ namespace WPGraphQL\Logging\wpunit\Admin\Settings\Fields\Field; -use WPGraphQL\Logging\Admin\Settings\Fields\Field\Text_Input_Field; -use WPGraphQL\Logging\Admin\Settings\Fields\Settings_Field_Interface; +use WPGraphQL\Logging\Admin\Settings\Fields\Field\TextInputField; +use WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldInterface; use lucatume\WPBrowser\TestCase\WPTestCase; class TextInputFieldTest extends WPTestCase { - protected ?Text_Input_Field $field = null; + protected ?TextInputField $field = null; protected function setUp(): void { parent::setUp(); - $this->field = new Text_Input_Field( + $this->field = new TextInputField( 'ip_restrictions', 'basic_configuration', 'IP Restrictions', @@ -79,7 +79,7 @@ public function test_render_field() { public function test_sanitize_field_email() { - $field = new Text_Input_Field( + $field = new TextInputField( 'email_address', 'basic_configuration', 'Email Address', @@ -95,7 +95,7 @@ public function test_sanitize_field_email() { public function test_sanitize_field_url() { - $field = new Text_Input_Field( + $field = new TextInputField( 'url', 'basic_configuration', 'URL', @@ -143,7 +143,7 @@ public function test_render_field_callback() { public function test_get_field_value() { // Use a field with a non-empty default value to verify fallbacks - $field = new Text_Input_Field( + $field = new TextInputField( 'test_field', 'basic_configuration', 'Test Field', @@ -180,7 +180,7 @@ public function test_get_field_value() { // 5) Empty field ID -> default // Create a subclass overriding get_id to simulate empty ID - $emptyIdField = new class('ignored', $tab_key, 'Title', 'css', 'desc', 'ph', 'DEF') extends Text_Input_Field { + $emptyIdField = new class('ignored', $tab_key, 'Title', 'css', 'desc', 'ph', 'DEF') extends TextInputField { public function get_id(): string { return ''; } }; $html = $emptyIdField->render_field( [ $tab_key => [ 'ignored' => 'value' ] ], $settings_key, $tab_key ); diff --git a/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings_Page_Test.php b/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings_Page_Test.php index eb6b8fe8..2682123b 100644 --- a/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings_Page_Test.php +++ b/plugins/wpgraphql-logging/tests/wpunit/Admin/Settings_Page_Test.php @@ -5,7 +5,7 @@ namespace WPGraphQL\Logging\wpunit\Admin; use lucatume\WPBrowser\TestCase\WPTestCase; -use WPGraphQL\Logging\Admin\Settings_Page; +use WPGraphQL\Logging\Admin\SettingsPage; use ReflectionClass; class Settings_Page_Test extends WPTestCase { @@ -26,20 +26,20 @@ protected function tearDown(): void { } public function test_settings_page_instance() { - $reflection = new ReflectionClass( Settings_Page::class ); + $reflection = new ReflectionClass( SettingsPage::class ); $instanceProperty = $reflection->getProperty( 'instance' ); $instanceProperty->setAccessible( true ); $instanceProperty->setValue( null ); $this->assertNull( $instanceProperty->getValue() ); - $instance = Settings_Page::init(); + $instance = SettingsPage::init(); - $this->assertInstanceOf( Settings_Page::class, $instanceProperty->getValue() ); - $this->assertSame( $instance, $instanceProperty->getValue(), 'Settings_Page::init() should set the static instance property' ); + $this->assertInstanceOf( SettingsPage::class, $instanceProperty->getValue() ); + $this->assertSame( $instance, $instanceProperty->getValue(), 'SettingsPage::init() should set the static instance property' ); } public function test_setup_registers_hooks(): void { - $page = new Settings_Page(); + $page = new SettingsPage(); $page->setup(); $this->assertEquals(10, has_action('init', [$page, 'init_field_collection'])); @@ -52,7 +52,7 @@ public function test_register_settings_page_no_field_collection_does_nothing(): global $submenu; $submenu = []; // reset - $page = new Settings_Page(); + $page = new SettingsPage(); // Do not call init_field_collection() to trigger early return $page->register_settings_page(); @@ -60,19 +60,19 @@ public function test_register_settings_page_no_field_collection_does_nothing(): } public function test_get_current_tab_behaviour(): void { - $page = new Settings_Page(); + $page = new SettingsPage(); // With no tabs provided -> default $this->assertSame('basic_configuration', $page->get_current_tab([])); // Provide custom tabs and no $_GET -> default $tabs = [ - 'basic_configuration' => new class implements \WPGraphQL\Logging\Admin\Settings\Fields\Tab\Settings_Tab_Interface { + 'basic_configuration' => new class implements \WPGraphQL\Logging\Admin\Settings\Fields\Tab\SettingsTabInterface { public function get_name(): string { return 'basic_configuration'; } public function get_label(): string { return 'Basic Configuration'; } public function get_fields(): array { return []; } }, - 'advanced' => new class implements \WPGraphQL\Logging\Admin\Settings\Fields\Tab\Settings_Tab_Interface { + 'advanced' => new class implements \WPGraphQL\Logging\Admin\Settings\Fields\Tab\SettingsTabInterface { public function get_name(): string { return 'advanced'; } public function get_label(): string { return 'Advanced'; } public function get_fields(): array { return []; } @@ -91,7 +91,7 @@ public function get_fields(): array { return []; } } public function test_load_scripts_styles_enqueues_assets_conditionally(): void { - $page = new Settings_Page(); + $page = new SettingsPage(); // Wrong page hook -> nothing enqueued $page->load_scripts_styles('some_other_page'); @@ -99,7 +99,7 @@ public function test_load_scripts_styles_enqueues_assets_conditionally(): void { $this->assertFalse(wp_script_is('wpgraphql-logging-settings-js', 'enqueued')); // Correct page hook -> stylesheet should enqueue if file exists; script only if file exists - $page->load_scripts_styles('settings_page_' . Settings_Page::PLUGIN_MENU_SLUG); + $page->load_scripts_styles('settings_page_' . SettingsPage::PLUGIN_MENU_SLUG); // CSS is present in this repository, so this should be enqueued $this->assertTrue(wp_style_is('wpgraphql-logging-settings-css', 'enqueued')); diff --git a/plugins/wpgraphql-logging/wpgraphql-logging.php b/plugins/wpgraphql-logging/wpgraphql-logging.php index 32e78125..d9667991 100644 --- a/plugins/wpgraphql-logging/wpgraphql-logging.php +++ b/plugins/wpgraphql-logging/wpgraphql-logging.php @@ -12,7 +12,7 @@ * Domain Path: /languages * Requires at least: 6.5 * Tested up to: 6.8.2 - * Requires PHP: 8.1+ + * Requires PHP: 8.1.2+ * License: GPLv2 or later * License URI: https://www.gnu.org/licenses/gpl-2.0.html * Requires Plugins: wp-graphql From a113fce96288e11cfabaab9305d81e85da264693 Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Tue, 23 Sep 2025 17:33:10 +0100 Subject: [PATCH 09/10] Add ConfigurationHelper for centralized config access Introduces a ConfigurationHelper class to provide cached, singleton-based access to WPGraphQL Logging configuration. Refactors settings and config retrieval throughout the plugin to use this helper, improving performance, consistency, and cache management. Updates related classes and documentation to use the new approach and initializes automatic cache invalidation in the main plugin setup. --- .../docs/ConfigurationHelper.md | 105 +++++++++ .../Admin/Settings/ConfigurationHelper.php | 222 ++++++++++++++++++ .../Fields/Field/AbstractSettingsField.php | 4 +- .../Admin/Settings/LoggingSettingsService.php | 39 +-- .../src/Events/QueryEventLifecycle.php | 7 +- .../Processors/DataSanitizationProcessor.php | 5 +- .../Scheduler/DataDeletionScheduler.php | 5 +- plugins/wpgraphql-logging/src/Plugin.php | 4 + 8 files changed, 354 insertions(+), 37 deletions(-) create mode 100644 plugins/wpgraphql-logging/docs/ConfigurationHelper.md create mode 100644 plugins/wpgraphql-logging/src/Admin/Settings/ConfigurationHelper.php diff --git a/plugins/wpgraphql-logging/docs/ConfigurationHelper.md b/plugins/wpgraphql-logging/docs/ConfigurationHelper.md new file mode 100644 index 00000000..706f68f9 --- /dev/null +++ b/plugins/wpgraphql-logging/docs/ConfigurationHelper.md @@ -0,0 +1,105 @@ +# Configuration Helper Usage Examples + +The `ConfigurationHelper` class provides a centralized and cached way to access WPGraphQL Logging configuration. This class implements a singleton pattern to ensure configuration is only loaded once per request and provides convenient methods for accessing different configuration sections. + +## Basic Usage + +### Getting the Configuration Helper Instance + +```php +use WPGraphQL\Logging\Admin\Settings\ConfigurationHelper; + +$config_helper = ConfigurationHelper::get_instance(); +``` + +### Getting Full Configuration + +```php +$config_helper = ConfigurationHelper::get_instance(); +$full_config = $config_helper->get_config(); +``` + +### Getting Configuration Sections + +```php +$config_helper = ConfigurationHelper::get_instance(); + +// Get basic configuration +$basic_config = $config_helper->get_basic_config(); + +// Get data management configuration +$data_management_config = $config_helper->get_data_management_config(); + +// Get any custom section +$custom_section = $config_helper->get_section_config('custom_section', []); +``` + +### Getting Specific Settings + +```php +$config_helper = ConfigurationHelper::get_instance(); + +// Get a specific setting from a section +$log_level = $config_helper->get_setting('basic_configuration', 'log_level', 'info'); + +// Check if a feature is enabled +$is_sanitization_enabled = $config_helper->is_enabled('data_management', 'data_sanitization_enabled'); +``` + +## Migration from Direct get_option() Usage + +### Before (old approach): +```php +$full_config = get_option( WPGRAPHQL_LOGGING_SETTINGS_KEY, [] ); +$basic_config = $full_config['basic_configuration'] ?? []; +$log_level = $basic_config['log_level'] ?? 'info'; +``` + +### After (using ConfigurationHelper): +```php +$config_helper = ConfigurationHelper::get_instance(); +$log_level = $config_helper->get_setting('basic_configuration', 'log_level', 'info'); +``` + +## Cache Management + +### Clearing Cache +```php +$config_helper = ConfigurationHelper::get_instance(); +$config_helper->clear_cache(); // Clears cache, next access will reload from DB +``` + +### Force Reload +```php +$config_helper = ConfigurationHelper::get_instance(); +$config_helper->reload_config(); // Clears cache and immediately reloads +``` + +## Benefits + +1. **Performance**: Configuration is cached in memory and only loaded once per request +2. **Consistency**: Centralized access point prevents inconsistent configuration retrieval +3. **Convenience**: Convenient methods for common access patterns +4. **Cache Management**: Automatic cache invalidation when settings are updated +5. **Type Safety**: Better type hints and documentation + +## Automatic Cache Invalidation + +The ConfigurationHelper automatically clears its cache when WordPress settings are updated. This is initialized in the main Plugin class: + +```php +// This is already set up in src/Plugin.php +ConfigurationHelper::init_cache_hooks(); +``` + +The cache hooks listen for: +- `update_option_{$option_key}` +- `add_option_{$option_key}` +- `delete_option_{$option_key}` + +## Performance Notes + +- Configuration is cached using WordPress's `wp_cache_*` functions +- Multiple cache groups are used for optimal performance +- Cache duration is set to 1 hour by default +- In-memory caching ensures subsequent accesses within the same request are instant diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/ConfigurationHelper.php b/plugins/wpgraphql-logging/src/Admin/Settings/ConfigurationHelper.php new file mode 100644 index 00000000..7cea4f49 --- /dev/null +++ b/plugins/wpgraphql-logging/src/Admin/Settings/ConfigurationHelper.php @@ -0,0 +1,222 @@ +get_setting('basic_configuration', 'log_level', 'info'); + * + * // Check if a feature is enabled + * $is_enabled = $config->is_enabled('data_management', 'data_sanitization_enabled'); + * + * // Get an entire configuration section + * $basic_config = $config->get_basic_config(); + * ``` + * + * @package WPGraphQL\Logging + * + * @since 0.0.1 + */ +class ConfigurationHelper { + /** + * Cache group for configuration. + * + * @var string + */ + public const CACHE_GROUP = 'wpgraphql_logging_config'; + + /** + * Cache duration in seconds (1 hour). + * + * @var int + */ + public const CACHE_DURATION = 3600; + + /** + * The cached configuration values. + * + * @var array|null + */ + protected ?array $config = null; + + /** + * The single instance of this class. + * + * @var \WPGraphQL\Logging\Admin\Settings\ConfigurationHelper|null + */ + protected static ?ConfigurationHelper $instance = null; + + /** + * Get the singleton instance. + */ + public static function get_instance(): ConfigurationHelper { + if ( null === self::$instance ) { + self::$instance = new self(); + } + + return self::$instance; + } + + /** + * Get the full configuration array. + * + * @return array + */ + public function get_config(): array { + if ( null === $this->config ) { + $this->load_config(); + } + + return $this->config ?? []; + } + + /** + * Get configuration for a specific section (tab). + * + * @param string $section The configuration section key. + * @param array $default_value Default value if section not found. + * + * @return array + */ + public function get_section_config( string $section, array $default_value = [] ): array { + $config = $this->get_config(); + return $config[ $section ] ?? $default_value; + } + + /** + * Get a specific setting value from a configuration section. + * + * @param string $section The configuration section key. + * @param string $setting_key The setting key within the section. + * @param mixed $default_value Default value if setting not found. + */ + public function get_setting( string $section, string $setting_key, $default_value = null ): mixed { + $section_config = $this->get_section_config( $section ); + return $section_config[ $setting_key ] ?? $default_value; + } + + /** + * Get the basic configuration section. + * + * @return array + */ + public function get_basic_config(): array { + return $this->get_section_config( 'basic_configuration' ); + } + + /** + * Get the data management configuration section. + * + * @return array + */ + public function get_data_management_config(): array { + return $this->get_section_config( 'data_management' ); + } + + /** + * Check if a specific feature is enabled. + * + * @param string $section The configuration section. + * @param string $setting_key The setting key for the feature. + */ + public function is_enabled( string $section, string $setting_key ): bool { + return (bool) $this->get_setting( $section, $setting_key, false ); + } + + /** + * Clear the configuration cache. + * This forces a reload of the configuration on the next access. + */ + public function clear_cache(): void { + $this->config = null; + $option_key = $this->get_option_key(); + wp_cache_delete( $option_key, self::CACHE_GROUP ); + wp_cache_delete( $option_key, $this->get_settings_group() ); + } + + /** + * Reload the configuration from the database. + * This bypasses any cache and forces a fresh load. + */ + public function reload_config(): void { + $this->clear_cache(); + $this->load_config(); + } + + /** + * Get the option key for the settings. + */ + public function get_option_key(): string { + return (string) apply_filters( 'wpgraphql_logging_settings_group_option_key', WPGRAPHQL_LOGGING_SETTINGS_KEY ); + } + + /** + * Get the settings group for caching. + */ + public function get_settings_group(): string { + return (string) apply_filters( 'wpgraphql_logging_settings_group_settings_group', WPGRAPHQL_LOGGING_SETTINGS_GROUP ); + } + + /** + * Hook into WordPress to clear cache when settings are updated. + * This should be called during plugin initialization. + * + * @psalm-suppress PossiblyInvalidArgument + */ + public static function init_cache_hooks(): void { + $instance = self::get_instance(); + $option_key = $instance->get_option_key(); + + // Clear cache when the option is updated. + add_action( "update_option_{$option_key}", [ $instance, 'clear_cache' ] ); + add_action( "add_option_{$option_key}", [ $instance, 'clear_cache' ] ); + add_action( "delete_option_{$option_key}", [ $instance, 'clear_cache' ] ); + } + + /** + * Load the configuration from cache or database. + * + * @phpcs:disable WordPressVIPMinimum.Performance.LowExpiryCacheTime.CacheTimeUndetermined + */ + protected function load_config(): void { + $option_key = $this->get_option_key(); + + $cache_duration = self::CACHE_DURATION; + + // Try to get from wp_cache first (in-memory cache). + $cached_config = wp_cache_get( $option_key, self::CACHE_GROUP ); + if ( is_array( $cached_config ) ) { + $this->config = $cached_config; + return; + } + + // Try to get from the WordPress object cache (could be Redis, Memcached, etc.). + $cached_config = wp_cache_get( $option_key, $this->get_settings_group() ); + if ( is_array( $cached_config ) ) { + $this->config = $cached_config; + // Store in our custom cache group for faster access next time. + wp_cache_set( $option_key, $cached_config, self::CACHE_GROUP, $cache_duration ); + return; + } + + // Load from database. + $this->config = (array) get_option( $option_key, [] ); + + // Cache the result in both cache groups. + wp_cache_set( $option_key, $this->config, self::CACHE_GROUP, $cache_duration ); + wp_cache_set( $option_key, $this->config, $this->get_settings_group(), $cache_duration ); + } +} diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/AbstractSettingsField.php b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/AbstractSettingsField.php index 58751bf7..ab8270be 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/AbstractSettingsField.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/Fields/Field/AbstractSettingsField.php @@ -4,6 +4,7 @@ namespace WPGraphQL\Logging\Admin\Settings\Fields\Field; +use WPGraphQL\Logging\Admin\Settings\ConfigurationHelper; use WPGraphQL\Logging\Admin\Settings\Fields\SettingsFieldInterface; /** @@ -84,7 +85,8 @@ public function render_field_callback( array $args ): void { $tab_key = (string) ( $args['tab_key'] ?? '' ); $settings_key = (string) ( $args['settings_key'] ?? '' ); - $option_value = (array) get_option( $settings_key, [] ); + $config_helper = ConfigurationHelper::get_instance(); + $option_value = $config_helper->get_config(); $id = $this->get_field_name( $settings_key, $tab_key, $this->get_id() ); diff --git a/plugins/wpgraphql-logging/src/Admin/Settings/LoggingSettingsService.php b/plugins/wpgraphql-logging/src/Admin/Settings/LoggingSettingsService.php index 90ebe75f..e84caa79 100644 --- a/plugins/wpgraphql-logging/src/Admin/Settings/LoggingSettingsService.php +++ b/plugins/wpgraphql-logging/src/Admin/Settings/LoggingSettingsService.php @@ -15,17 +15,17 @@ */ class LoggingSettingsService { /** - * The settings value + * The configuration helper instance. * - * @var array + * @var \WPGraphQL\Logging\Admin\Settings\ConfigurationHelper */ - protected array $settings_values = []; + protected ConfigurationHelper $config_helper; /** * Initialize the settings service. */ public function __construct() { - $this->setup(); + $this->config_helper = ConfigurationHelper::get_instance(); } /** @@ -34,7 +34,7 @@ public function __construct() { * @return array */ public function get_settings_values(): array { - return $this->settings_values; + return $this->config_helper->get_config(); } /** @@ -45,7 +45,8 @@ public function get_settings_values(): array { * @return array|null */ public function get_tab_config( string $tab_key ): ?array { - return $this->settings_values[ $tab_key ] ?? null; + $config = $this->config_helper->get_section_config( $tab_key ); + return empty( $config ) ? null : $config; } /** @@ -56,40 +57,20 @@ public function get_tab_config( string $tab_key ): ?array { * @param mixed $default_value The default value if not found. */ public function get_setting( string $tab_key, string $setting_key, $default_value = null ): mixed { - $tab_config = $this->get_tab_config( $tab_key ); - return $tab_config[ $setting_key ] ?? $default_value; + return $this->config_helper->get_setting( $tab_key, $setting_key, $default_value ); } /** * The option key for the settings group. */ public static function get_option_key(): string { - return (string) apply_filters( 'wpgraphql_logging_settings_group_option_key', WPGRAPHQL_LOGGING_SETTINGS_KEY ); + return ConfigurationHelper::get_instance()->get_option_key(); } /** * The settings group for the options. */ public static function get_settings_group(): string { - return (string) apply_filters( 'wpgraphql_logging_settings_group_settings_group', WPGRAPHQL_LOGGING_SETTINGS_GROUP ); - } - - /** - * Set up the settings values by retrieving them from the database or cache. - * This method is called in the constructor to ensure settings are available. - */ - protected function setup(): void { - $option_key = self::get_option_key(); - $settings_group = self::get_settings_group(); - - $value = wp_cache_get( $option_key, $settings_group ); - if ( is_array( $value ) ) { - $this->settings_values = $value; - - return; - } - - $this->settings_values = (array) get_option( $option_key, [] ); - wp_cache_set( $option_key, $this->settings_values, $settings_group ); + return ConfigurationHelper::get_instance()->get_settings_group(); } } diff --git a/plugins/wpgraphql-logging/src/Events/QueryEventLifecycle.php b/plugins/wpgraphql-logging/src/Events/QueryEventLifecycle.php index 2e309431..86d82607 100644 --- a/plugins/wpgraphql-logging/src/Events/QueryEventLifecycle.php +++ b/plugins/wpgraphql-logging/src/Events/QueryEventLifecycle.php @@ -4,6 +4,7 @@ namespace WPGraphQL\Logging\Events; +use WPGraphQL\Logging\Admin\Settings\ConfigurationHelper; use WPGraphQL\Logging\Logger\LoggerService; /** @@ -58,9 +59,9 @@ class QueryEventLifecycle { * @param \WPGraphQL\Logging\Logger\LoggerService $logger The logger instance. */ protected function __construct( LoggerService $logger ) { - $this->logger = $logger; - $full_config = get_option( WPGRAPHQL_LOGGING_SETTINGS_KEY, [] ); - $this->config = $full_config['basic_configuration'] ?? []; + $this->logger = $logger; + $config_helper = ConfigurationHelper::get_instance(); + $this->config = $config_helper->get_basic_config(); // Initialize the specialized logger components. $this->action_logger = new QueryActionLogger( $this->logger, $this->config ); diff --git a/plugins/wpgraphql-logging/src/Logger/Processors/DataSanitizationProcessor.php b/plugins/wpgraphql-logging/src/Logger/Processors/DataSanitizationProcessor.php index 52d24d1f..4fdd3ce4 100644 --- a/plugins/wpgraphql-logging/src/Logger/Processors/DataSanitizationProcessor.php +++ b/plugins/wpgraphql-logging/src/Logger/Processors/DataSanitizationProcessor.php @@ -6,6 +6,7 @@ use Monolog\LogRecord; use Monolog\Processor\ProcessorInterface; +use WPGraphQL\Logging\Admin\Settings\ConfigurationHelper; use WPGraphQL\Logging\Admin\Settings\Fields\Tab\DataManagementTab; /** @@ -27,8 +28,8 @@ class DataSanitizationProcessor implements ProcessorInterface { * DataSanitizationProcessor constructor. */ public function __construct() { - $full_config = get_option( WPGRAPHQL_LOGGING_SETTINGS_KEY, [] ); - $this->config = $full_config['data_management'] ?? []; + $config_helper = ConfigurationHelper::get_instance(); + $this->config = $config_helper->get_data_management_config(); } /** diff --git a/plugins/wpgraphql-logging/src/Logger/Scheduler/DataDeletionScheduler.php b/plugins/wpgraphql-logging/src/Logger/Scheduler/DataDeletionScheduler.php index 11db9b6f..9acf5d7c 100644 --- a/plugins/wpgraphql-logging/src/Logger/Scheduler/DataDeletionScheduler.php +++ b/plugins/wpgraphql-logging/src/Logger/Scheduler/DataDeletionScheduler.php @@ -4,6 +4,7 @@ namespace WPGraphQL\Logging\Logger\Scheduler; +use WPGraphQL\Logging\Admin\Settings\ConfigurationHelper; use WPGraphQL\Logging\Admin\Settings\Fields\Tab\DataManagementTab; use WPGraphQL\Logging\Logger\Database\LogsRepository; @@ -42,8 +43,8 @@ class DataDeletionScheduler { * Private constructor to prevent direct instantiation. */ protected function __construct(readonly LogsRepository $repository) { - $full_config = get_option( WPGRAPHQL_LOGGING_SETTINGS_KEY, [] ); - $this->config = $full_config['data_management'] ?? []; + $config_helper = ConfigurationHelper::get_instance(); + $this->config = $config_helper->get_data_management_config(); } /** diff --git a/plugins/wpgraphql-logging/src/Plugin.php b/plugins/wpgraphql-logging/src/Plugin.php index 5b9c7f53..ab86a0b0 100644 --- a/plugins/wpgraphql-logging/src/Plugin.php +++ b/plugins/wpgraphql-logging/src/Plugin.php @@ -4,6 +4,7 @@ namespace WPGraphQL\Logging; +use WPGraphQL\Logging\Admin\Settings\ConfigurationHelper; use WPGraphQL\Logging\Admin\SettingsPage; use WPGraphQL\Logging\Admin\ViewLogsPage; use WPGraphQL\Logging\Events\EventManager; @@ -55,6 +56,9 @@ public static function init(): self { * Initialize the plugin admin, frontend & api functionality. */ public function setup(): void { + // Initialize configuration caching hooks. + ConfigurationHelper::init_cache_hooks(); + SettingsPage::init(); ViewLogsPage::init(); QueryEventLifecycle::init(); From 228692e32180d127562aff8b2977fd3fa3b6394b Mon Sep 17 00:00:00 2001 From: Colin Murphy Date: Wed, 24 Sep 2025 11:47:34 +0100 Subject: [PATCH 10/10] Pushed a fix for Excluded queries. --- plugins/wpgraphql-logging/src/Logger/Rules/ExcludeQueryRule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wpgraphql-logging/src/Logger/Rules/ExcludeQueryRule.php b/plugins/wpgraphql-logging/src/Logger/Rules/ExcludeQueryRule.php index ce06cde9..9a2bf6e0 100644 --- a/plugins/wpgraphql-logging/src/Logger/Rules/ExcludeQueryRule.php +++ b/plugins/wpgraphql-logging/src/Logger/Rules/ExcludeQueryRule.php @@ -24,7 +24,7 @@ class ExcludeQueryRule implements LoggingRuleInterface { */ public function passes(array $config, ?string $query_string = null): bool { $queries = $config[ BasicConfigurationTab::EXCLUDE_QUERY ] ?? ''; - if ( null === $query_string ) { + if ( null === $query_string || '' === trim( $queries ) ) { return true; }