diff --git a/.github/workflows/build-dev-artifacts.yml b/.github/workflows/build-dev-artifacts.yml index b13dae1b0..61b2c634a 100755 --- a/.github/workflows/build-dev-artifacts.yml +++ b/.github/workflows/build-dev-artifacts.yml @@ -28,7 +28,13 @@ jobs: run: | composer install --no-dev --prefer-dist --no-progress - name: Create zip - run: npm run dist + run: | + npm ci + CURRENT_VERSION=$(node -p -e "require('./package.json').version") + COMMIT_HASH=$(git rev-parse --short HEAD) + DEV_VERSION="${CURRENT_VERSION}-dev.${COMMIT_HASH}" + npm run grunt version::${DEV_VERSION} + npm run dist - name: Retrieve branch name id: retrieve-branch-name run: echo "::set-output name=branch_name::$(REF=${GITHUB_HEAD_REF:-$GITHUB_REF} && echo ${REF#refs/heads/} | sed 's/\//-/g')" diff --git a/.github/workflows/translations.yml b/.github/workflows/translations.yml new file mode 100644 index 000000000..b8c2c5f8e --- /dev/null +++ b/.github/workflows/translations.yml @@ -0,0 +1,45 @@ +name: Translations Diff + +on: + pull_request_review: + pull_request: + types: [opened, edited, synchronize, ready_for_review] + branches: + - development + - master + +jobs: + translation: + runs-on: ubuntu-latest + steps: + - name: Checkout Base Branch + uses: actions/checkout@master + with: + ref: ${{ github.base_ref }} + path: visualizer-base + - name: Setup node 22 + uses: actions/setup-node@v6 + with: + node-version: 22.x + - name: Checkout PR Branch (Head) + uses: actions/checkout@master + with: + path: visualizer-head + - name: Build POT for PR Branch + run: | + chmod +x ./visualizer-head/bin/make-pot.sh + ./visualizer-head/bin/make-pot.sh ./visualizer-head ./visualizer-head/languages/visualizer.pot + ls ./visualizer-head/languages/ + - name: Build POT for Base Branch + run: | + ./visualizer-head/bin/make-pot.sh ./visualizer-base ./visualizer-base/languages/visualizer.pot + ls ./visualizer-base/languages/ + - name: Compare POT files + uses: Codeinwp/action-i18n-string-reviewer@main + with: + fail-on-changes: "false" + openrouter-key: ${{ secrets.OPEN_ROUTER_API_KEY }} + openrouter-model: "google/gemini-2.5-flash" + base-pot-file: "visualizer-base/languages/visualizer.pot" + target-pot-file: "visualizer-head/languages/visualizer.pot" + github-token: ${{ secrets.BOT_TOKEN }} diff --git a/.wp-env.json b/.wp-env.json index d4d36aa0b..86dd6cef1 100644 --- a/.wp-env.json +++ b/.wp-env.json @@ -1,5 +1,5 @@ { - "core": "WordPress/WordPress#6.5.0", + "core": null, "phpVersion": "7.4", "plugins": ["."], "themes": [], diff --git a/AGENTS.md b/AGENTS.md index 5e9877b11..9dbe23c17 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -34,14 +34,31 @@ npm run dev # Watch mode for development ``` ### E2E Tests & Environment + +Requires Docker to be running. Uses `docker-compose.ci.yml` (MariaDB + WordPress on port 8889). + ```bash -npm install # Install root-level JS dependencies -npm run test:env:start # Start wp-env WordPress environment -npm run test:env:stop # Stop wp-env -npm run test:e2e:playwright # Run Playwright E2E tests -npm run test:e2e:playwright:debug # Playwright UI debug mode +# 1. Install dependencies +npm ci +npx playwright install --with-deps chromium +composer install --no-dev + +# 2. Start the WordPress environment (boots Docker, installs WP, activates plugin) +DOCKER_FILE=docker-compose.ci.yml bash bin/wp-init.sh + +# 3. Run the full Playwright suite +npm run test:e2e:playwright + +# 4. Run a single spec file +npx wp-scripts test-playwright --config tests/e2e/playwright.config.js tests/e2e/specs/gutenberg-editor.spec.js + +# 5. Tear down +DOCKER_FILE=docker-compose.ci.yml bash bin/wp-down.sh ``` +WordPress is installed at `http://localhost:8889` with credentials `admin` / `password`. +The `TI_E2E_TESTING` constant is set to `true` in `wp-config.php` by the setup script, which enables test-only code paths in the plugin. + --- ## Architecture Overview diff --git a/bin/make-pot.sh b/bin/make-pot.sh new file mode 100644 index 000000000..af19c5d73 --- /dev/null +++ b/bin/make-pot.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Script to generate POT file via Docker +# Usage: ./bin/make-pot.sh [plugin-path] [destination-path] + +# Set defaults +PLUGIN_PATH="${1:-.}" +DESTINATION="${2:-.}" + +# Resolve absolute paths +PLUGIN_PATH="$(cd "$PLUGIN_PATH" 2>/dev/null && pwd)" || { + echo "Error: Plugin path '$1' does not exist" + exit 1 +} + +DESTINATION="$(cd "$(dirname "$DESTINATION")" 2>/dev/null && pwd)/$(basename "$DESTINATION")" || { + echo "Error: Unable to resolve destination path" + exit 1 +} + +# Extract destination filename and directory +DEST_DIR="$(dirname "$DESTINATION")" +DEST_FILE="$(basename "$DESTINATION")" + +# Ensure destination directory exists +mkdir -p "$DEST_DIR" + +echo "Generating POT file..." +echo "Plugin Path: $PLUGIN_PATH" +echo "Destination: $DESTINATION" +echo "" + +# Run Docker container with wp-cli to generate POT +docker run --user root --rm \ + --volume "$PLUGIN_PATH:/var/www/html/plugin" \ + wordpress:cli \ + bash -c 'php -d memory_limit=512M "$(which wp)" --version --allow-root && wp i18n make-pot plugin ./plugin/languages/'"$DEST_FILE"' --include=admin,includes,libs,assets,views --allow-root --domain=anti-spam' + +# Check if the file was created inside the container +if [ $? -eq 0 ]; then + echo "" + echo "✓ POT file successfully generated at: $DESTINATION" +else + echo "" + echo "✗ Error generating POT file" + exit 1 +fi diff --git a/classes/Visualizer/Gutenberg/Block.php b/classes/Visualizer/Gutenberg/Block.php index 045819b54..38b479ee9 100644 --- a/classes/Visualizer/Gutenberg/Block.php +++ b/classes/Visualizer/Gutenberg/Block.php @@ -186,8 +186,7 @@ public function gutenberg_block_callback( $atts ) { return ''; } - // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison - if ( $atts['lazy'] == -1 || $atts['lazy'] == false ) { + if ( $atts['lazy'] === '-1' || $atts['lazy'] === false ) { $atts['lazy'] = 'no'; } @@ -472,11 +471,12 @@ public function get_visualizer_data( $post ) { $permissions = get_post_meta( $post_id, Visualizer_Pro::CF_PERMISSIONS, true ); if ( empty( $permissions ) ) { - $permissions = array( 'permissions' => array( + $permissions = array( + 'permissions' => array( 'read' => 'all', 'edit' => 'roles', 'edit-specific' => array( 'administrator' ), - ), + ), ); } @@ -824,7 +824,7 @@ public function get_permission_data( $data ) { foreach ( $users as $user ) { $options[ $i ]['value'] = $user->ID; $options[ $i ]['label'] = $user->display_name; - $i++; + ++$i; } } break; @@ -838,7 +838,7 @@ public function get_permission_data( $data ) { foreach ( get_editable_roles() as $name => $info ) { $options[ $i ]['value'] = $name; $options[ $i ]['label'] = $name; - $i++; + ++$i; } } break; @@ -874,7 +874,7 @@ public function add_rest_query_vars( $args, \WP_REST_Request $request ) { * @param mixed $value The value to sanitize. * @return mixed Sanitized value. */ - private function sanitize_value( $value ) { + public function sanitize_value( $value ) { if ( is_string( $value ) ) { return sanitize_text_field( $value ); } diff --git a/classes/Visualizer/Module.php b/classes/Visualizer/Module.php index 8ef678c16..9762a56e2 100644 --- a/classes/Visualizer/Module.php +++ b/classes/Visualizer/Module.php @@ -68,8 +68,7 @@ public function __construct( Visualizer_Plugin $plugin ) { $this->_addFilter( Visualizer_Plugin::FILTER_HANDLE_REVISIONS, 'handleExistingRevisions', 10, 2 ); $this->_addFilter( Visualizer_Plugin::FILTER_GET_CHART_DATA_AS, 'getDataAs', 10, 3 ); $this->_addAction( 'pre_get_posts', 'PreGetPosts' ); - register_shutdown_function( array($this, 'onShutdown') ); - + register_shutdown_function( array( $this, 'onShutdown' ) ); } /** @@ -114,16 +113,16 @@ protected function _addAction( $tag, $method, $methodClass = null, $priority = 1 * @param string $tag The name of the AJAX action to which the $method is hooked. * @param string $method Optional. The name of the method to be called. If the name of the method is not provided, tag name will be used as method name. * @param bool $methodClass The root of the method. - * @param boolean $private Optional. Determines if we should register hook for logged in users. - * @param boolean $public Optional. Determines if we should register hook for not logged in users. + * @param boolean $logged_in Optional. Determines if we should register hook for logged in users. + * @param boolean $logged_out Optional. Determines if we should register hook for not logged in users. * @return Visualizer_Module */ - protected function _addAjaxAction( $tag, $method = '', $methodClass = null, $private = true, $public = false ) { - if ( $private ) { + protected function _addAjaxAction( $tag, $method = '', $methodClass = null, $logged_in = true, $logged_out = false ) { + if ( $logged_in ) { $this->_addAction( 'wp_ajax_' . $tag, $method, $methodClass ); } - if ( $public ) { + if ( $logged_out ) { $this->_addAction( 'wp_ajax_nopriv_' . $tag, $method, $methodClass ); } @@ -169,7 +168,7 @@ protected function _addShortcode( $tag, $method ) { * * @since 3.2.0 */ - public function getDataAs( $final, $chart_id, $type ) { + public function getDataAs( $data, $chart_id, $type ) { return $this->_getDataAs( $chart_id, $type ); } @@ -270,12 +269,15 @@ private function _getCSV( $rows, $filename, $enclose ) { $bom = chr( 0xEF ) . chr( 0xBB ) . chr( 0xBF ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged $fp = function_exists( 'tmpfile' ) ? @tmpfile() : null; - if ( null === $fp ) { + if ( ! $fp ) { if ( ! function_exists( 'wp_tempnam' ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; } $fp = fopen( wp_tempnam(), 'w+' ); } + if ( ! $fp ) { + return array( 'csv' => '', 'name' => $filename, 'string' => '' ); + } if ( ! apply_filters( 'vizualizer_export_include_series_type', true ) ) { unset( $rows[1] ); $rows = array_values( $rows ); @@ -287,8 +289,8 @@ private function _getCSV( $rows, $filename, $enclose ) { } rewind( $fp ); $csv = ''; - // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition - while ( ( $array = fgetcsv( $fp ) ) !== false ) { + $array = fgetcsv( $fp ); + while ( $array !== false ) { if ( strlen( $csv ) > 0 ) { $csv .= PHP_EOL; } @@ -304,7 +306,8 @@ private function _getCSV( $rows, $filename, $enclose ) { } $array = $temp_array; } - $csv .= implode( ',', $array ); + $csv .= implode( ',', $array ); + $array = fgetcsv( $fp ); } fclose( $fp ); @@ -330,7 +333,7 @@ private function _getExcel( $rows, $filename ) { unset( $rows[1] ); $rows = array_values( $rows ); $rows = array_map( - function( $r ) { + function ( $r ) { return array_map( 'strval', $r ); }, $rows @@ -402,7 +405,7 @@ private function _getHTML( $rows ) { foreach ( $rows as $row ) { // skip the data type row. if ( 1 === $index ) { - $index++; + ++$index; continue; } @@ -415,7 +418,7 @@ private function _getHTML( $rows ) { } } $table .= ''; - $index++; + ++$index; } $table .= ''; @@ -430,9 +433,9 @@ private function _getHTML( $rows ) { /** * Disable revisions temporarily for visualizer post type. */ - protected final function disableRevisionsTemporarily() { + final protected function disableRevisionsTemporarily() { add_filter( - 'wp_revisions_to_keep', function( $num, $post ) { + 'wp_revisions_to_keep', function ( $num, $post ) { if ( $post->post_type === Visualizer_Plugin::CPT_VISUALIZER ) { return 0; } @@ -446,7 +449,7 @@ protected final function disableRevisionsTemporarily() { * * @return bool If any revisions were found. */ - public final function undoRevisions( $chart_id, $restore = false ) { + final public function undoRevisions( $chart_id, $restore = false ) { do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'undoRevisions for %d with%s restore', $chart_id, ( $restore ? '' : 'out' ) ), 'debug', __FILE__, __LINE__ ); if ( get_post_type( $chart_id ) !== Visualizer_Plugin::CPT_VISUALIZER ) { return false; @@ -478,7 +481,7 @@ public final function undoRevisions( $chart_id, $restore = false ) { /** * If existing revisions exist for the chart, restore the earliest version and then create a new revision to initiate editing. */ - public final function handleExistingRevisions( $chart_id, $chart ) { + final public function handleExistingRevisions( $chart_id, $chart ) { do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'handleExistingRevisions for %d', $chart_id ), 'debug', __FILE__, __LINE__ ); if ( get_post_type( $chart_id ) !== Visualizer_Plugin::CPT_VISUALIZER ) { @@ -529,50 +532,53 @@ protected function get_user_customization_js() { return $default; } - require_once( ABSPATH . 'wp-admin/includes/file.php' ); - WP_Filesystem(); - global $wp_filesystem; - if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base' ) ) { - $creds = request_filesystem_credentials( site_url() ); - wp_filesystem( $creds ); - } - - $multisite_arg = '/'; - if ( is_multisite() && ! is_main_site() ) { - $multisite_arg = '/sites/' . get_current_blog_id() . '/'; - } + try { + require_once ABSPATH . 'wp-admin/includes/file.php'; + WP_Filesystem(); + global $wp_filesystem; + if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base' ) ) { + return $default; + } - $dir = $wp_filesystem->wp_content_dir() . 'uploads' . $multisite_arg . 'visualizer'; - $file = $wp_filesystem->wp_content_dir() . 'uploads' . $multisite_arg . 'visualizer/customization.js'; + $multisite_arg = '/'; + if ( is_multisite() && ! is_main_site() ) { + $multisite_arg = '/sites/' . get_current_blog_id() . '/'; + } - if ( $wp_filesystem->is_readable( $file ) ) { - return $specific; - } + $dir = $wp_filesystem->wp_content_dir() . 'uploads' . $multisite_arg . 'visualizer'; + $file = $wp_filesystem->wp_content_dir() . 'uploads' . $multisite_arg . 'visualizer/customization.js'; - if ( $wp_filesystem->exists( $file ) && ! $wp_filesystem->is_readable( $file ) ) { - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Unable to read file %s', $file ), 'error', __FILE__, __LINE__ ); - return $default; - } + if ( $wp_filesystem->is_readable( $file ) ) { + return $specific; + } - if ( ! $wp_filesystem->exists( $dir ) ) { - // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.Found - if ( ( $done = $wp_filesystem->mkdir( $dir ) ) === false ) { - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Unable to create directory %s', $dir ), 'error', __FILE__, __LINE__ ); + if ( $wp_filesystem->exists( $file ) && ! $wp_filesystem->is_readable( $file ) ) { + do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Unable to read file %s', $file ), 'error', __FILE__, __LINE__ ); return $default; } - } - // if file does not exist, copy. - if ( ! $wp_filesystem->exists( $file ) ) { - $src = str_replace( ABSPATH, $wp_filesystem->abspath(), VISUALIZER_ABSPATH . '/js/customization.js' ); - // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.Found - if ( ( $done = $wp_filesystem->copy( $src, $file ) ) === false ) { - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Unable to copy file %s to %s', $src, $file ), 'error', __FILE__, __LINE__ ); - return $default; + if ( ! $wp_filesystem->exists( $dir ) ) { + $done = $wp_filesystem->mkdir( $dir ); + if ( $done === false ) { + do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Unable to create directory %s', $dir ), 'error', __FILE__, __LINE__ ); + return $default; + } + } + + // if file does not exist, copy. + if ( ! $wp_filesystem->exists( $file ) ) { + $src = str_replace( ABSPATH, $wp_filesystem->abspath(), VISUALIZER_ABSPATH . '/js/customization.js' ); + $done = $wp_filesystem->copy( $src, $file ); + if ( $done === false ) { + do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Unable to copy file %s to %s', $src, $file ), 'error', __FILE__, __LINE__ ); + return $default; + } } - } - return $specific; + return $specific; + } catch ( \Throwable $e ) { + return $default; + } } /** @@ -582,10 +588,7 @@ protected function load_chart_type( $chart_id ) { $name = $this->load_chart_class_name( $chart_id ); $class = null; if ( class_exists( $name ) || true === apply_filters( 'visualizer_load_chart', false, $name ) ) { - if ( 'Visualizer_Render_Sidebar_Type_DataTable_DataTable' === $name ) { - $name = 'Visualizer_Render_Sidebar_Type_DataTable_Tabular'; - } - $class = new $name; + $class = new $name(); } if ( is_null( $class ) && Visualizer_Module::is_pro() ) { @@ -746,7 +749,7 @@ public static function can_show_feature( $feature ) { /** * Gets the features for the provided license type. */ - public static final function get_features_for_license( $plan ) { + final public static function get_features_for_license( $plan ) { $is_new_personal = apply_filters( 'visualizer_is_new_personal', false ); switch ( $plan ) { case 1: diff --git a/classes/Visualizer/Module/AMP.php b/classes/Visualizer/Module/AMP.php index b9b3a079a..9b5977140 100644 --- a/classes/Visualizer/Module/AMP.php +++ b/classes/Visualizer/Module/AMP.php @@ -100,5 +100,4 @@ public function get_chart( $chart, $data, $series, $settings ) { } return $output['csv']; } - } diff --git a/classes/Visualizer/Module/Admin.php b/classes/Visualizer/Module/Admin.php index 2c02da8d0..02a3f16db 100644 --- a/classes/Visualizer/Module/Admin.php +++ b/classes/Visualizer/Module/Admin.php @@ -96,7 +96,6 @@ public function __construct( Visualizer_Plugin $plugin ) { if ( defined( 'TI_E2E_TESTING' ) ) { $this->load_cypress_hooks(); } - } /** * Display review notice. @@ -104,7 +103,7 @@ public function __construct( Visualizer_Plugin $plugin ) { public function render_review_notice( $footer_text ) { $current_screen = get_current_screen(); - $visualizer_page_ids = ['toplevel_page_visualizer', 'visualizer_page_viz-support', 'visualizer_page_ti-about-visualizer' ]; + $visualizer_page_ids = array( 'toplevel_page_visualizer', 'visualizer_page_viz-support', 'visualizer_page_ti-about-visualizer' ); if ( ! empty( $current_screen ) && isset( $current_screen->id ) ) { foreach ( $visualizer_page_ids as $page_to_check ) { @@ -134,7 +133,7 @@ public function render_review_notice( $footer_text ) { private function load_cypress_hooks() { // all charts should load on the same page without pagination. add_filter( - 'visualizer_query_args', function( $args ) { + 'visualizer_query_args', function ( $args ) { $args['posts_per_page'] = 20; return $args; }, 10, 1 @@ -253,8 +252,7 @@ public function restoreRevision( $post_id, $revision_id ) { * @access public */ public function init() { - // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison - if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' == get_user_option( 'rich_editing' ) ) { + if ( current_user_can( 'edit_posts' ) && current_user_can( 'edit_pages' ) && 'true' === get_user_option( 'rich_editing' ) ) { $this->_addFilter( 'mce_external_languages', 'add_tinymce_lang', 10, 1 ); $this->_addFilter( 'mce_external_plugins', 'tinymce_plugin', 10, 1 ); $this->_addFilter( 'mce_buttons', 'register_mce_button', 10, 1 ); @@ -268,7 +266,7 @@ public function init() { * @since ? * @access friendly */ - function get_strings_for_block( $settings ) { + public function get_strings_for_block( $settings ) { $class = new Visualizer_Module_Language(); $strings = $class->get_strings(); $array = array( 'visualizer_tinymce_plugin' => json_encode( $strings ) ); @@ -797,7 +795,7 @@ public function handleGetProSubMenu() { /** * Adds the screen options for pagination. */ - function addScreenOptions() { + public function addScreenOptions() { $screen = get_current_screen(); // bail if it's some other page. @@ -816,7 +814,7 @@ function addScreenOptions() { /** * Returns the screen option for pagination. */ - function setScreenOptions( $status, $option, $value ) { + public function setScreenOptions( $status, $option, $value ) { if ( 'visualizer_library_per_page' === $option ) { return $value; } diff --git a/classes/Visualizer/Module/Chart.php b/classes/Visualizer/Module/Chart.php index e31133b1a..4c5038b6b 100644 --- a/classes/Visualizer/Module/Chart.php +++ b/classes/Visualizer/Module/Chart.php @@ -70,7 +70,6 @@ public function __construct( Visualizer_Plugin $plugin ) { $this->_addAjaxAction( Visualizer_Plugin::ACTION_SAVE_FILTER_QUERY, 'saveFilter' ); $this->_addFilter( 'visualizer_get_sidebar', 'getSidebar', 10, 2 ); - } /** @@ -539,7 +538,8 @@ public function renderChartPages() { if ( ! empty( $_POST ) ) { $_POST = map_deep( $_POST, 'wp_strip_all_tags' ); } - if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) { + $chart = $chart_id ? get_post( $chart_id ) : null; + if ( ! $chart_id || ! $chart || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) { if ( empty( $_GET['lang'] ) || empty( $_GET['parent_chart_id'] ) ) { $this->deleteOldCharts(); $default_type = isset( $_GET['type'] ) && ! empty( $_GET['type'] ) ? $_GET['type'] : 'line'; @@ -738,7 +738,7 @@ private function loadCodeEditorAssets( $chart_id ) { wp_register_script( 'visualizer-codemirror-closebrackets', '//codemirror.net/addon/edit/closebrackets.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION ); wp_register_script( 'visualizer-codemirror-sql', '//codemirror.net/mode/sql/sql.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION ); wp_register_script( 'visualizer-codemirror-sql-hint', '//codemirror.net/addon/hint/sql-hint.js', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION ); - wp_register_script( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.js', array( 'visualizer-codemirror-sql', 'visualizer-codemirror-sql-hint', 'visualizer-codemirror-placeholder', 'visualizer-codemirror-matchbrackets', 'visualizer-codemirror-closebrackets' ), Visualizer_Plugin::VERSION ); + wp_register_script( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.js', array( 'visualizer-codemirror-sql', 'visualizer-codemirror-sql-hint', 'visualizer-codemirror-placeholder', 'visualizer-codemirror-matchbrackets', 'visualizer-codemirror-closebrackets' ), Visualizer_Plugin::VERSION ); wp_register_style( 'visualizer-codemirror-core', '//codemirror.net/lib/codemirror.css', array(), Visualizer_Plugin::VERSION ); wp_register_style( 'visualizer-codemirror-hint', '//codemirror.net/addon/hint/show-hint.css', array( 'visualizer-codemirror-core' ), Visualizer_Plugin::VERSION ); @@ -862,10 +862,8 @@ private function _handleDataAndSettingsPage() { array( 'ajax' => array( 'url' => admin_url( 'admin-ajax.php' ), - 'nonces' => array( - ), - 'actions' => array( - ), + 'nonces' => array(), + 'actions' => array(), ), ) ); @@ -878,12 +876,13 @@ private function _handleDataAndSettingsPage() { 'visualizer', array( 'l10n' => array( - 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ), - 'loading' => esc_html__( 'Loading...', 'visualizer' ), - 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ), - 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ), - 'save_settings' => __( 'You have modified the chart\'s settings. To modify the source/data again, you must save this chart and reopen it for editing. If you continue without saving the chart, you may lose your changes.', 'visualizer' ), - 'copied' => __( 'The data has been copied to your clipboard. Hit Ctrl-V/Cmd-V in your spreadsheet editor to paste the data.', 'visualizer' ), + 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ), + 'loading' => esc_html__( 'Loading...', 'visualizer' ), + 'json_error' => esc_html__( 'An error occured in fetching data.', 'visualizer' ), + 'select_columns' => esc_html__( 'Please select a few columns to include in the chart.', 'visualizer' ), + 'save_settings' => __( 'You have modified the chart\'s settings. To modify the source/data again, you must save this chart and reopen it for editing. If you continue without saving the chart, you may lose your changes.', 'visualizer' ), + 'copied' => __( 'The data has been copied to your clipboard. Hit Ctrl-V/Cmd-V in your spreadsheet editor to paste the data.', 'visualizer' ), + 'invalid_format' => esc_html__( 'This format pattern is not supported in the series settings field. Use the Manual Configuration option instead.', 'visualizer' ), ), 'charts' => array( 'canvas' => $data, @@ -1028,7 +1027,7 @@ private function handleCSVasString( $data, $editor_type ) { } $row = explode( ',', $row ); $row = array_map( - function( $r ) { + function ( $r ) { return '' === $r ? ' ' : $r; }, $row @@ -1079,7 +1078,7 @@ private function handleTabularData() { if ( empty( $type ) ) { $exclude[] = $index; } - $index++; + ++$index; } // when N headers are being renamed, the number of headers increases by N @@ -1156,9 +1155,10 @@ public function uploadData() { // check chart, if chart exists // do not use filter_input as it does not work for phpunit test cases, use filter_var instead $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : ''; + $chart = $chart_id ? get_post( $chart_id ) : null; if ( ! $chart_id || - ! ( $chart = get_post( $chart_id ) ) || + ! $chart || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER || ! current_user_can( 'edit_post', $chart_id ) ) { @@ -1214,8 +1214,7 @@ public function uploadData() { if ( isset( $_POST['vz-import-time'] ) ) { apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $remote_data, $_POST['vz-import-time'] ); } - // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison - } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] == 0 ) { + } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] === 0 ) { $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] ); } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) { $source = $this->handleCSVasString( $_POST['chart_data'], $_POST['editor-type'] ); @@ -1407,7 +1406,8 @@ private function _handleDataPage() { array( 'l10n' => array( 'invalid_source' => esc_html__( 'You have entered an invalid URL. Please provide a valid URL.', 'visualizer' ), - 'loading' => esc_html__( 'Loading...', 'visualizer' ), + 'loading' => esc_html__( 'Loading...', 'visualizer' ), + 'invalid_format' => esc_html__( 'This format pattern is not supported in the series settings field. To display percentages, use the Manual Configuration option instead.', 'visualizer' ), ), 'charts' => array( 'canvas' => $data, diff --git a/classes/Visualizer/Module/Frontend.php b/classes/Visualizer/Module/Frontend.php index c8cb044bc..1905165e6 100644 --- a/classes/Visualizer/Module/Frontend.php +++ b/classes/Visualizer/Module/Frontend.php @@ -87,7 +87,7 @@ public function __construct( Visualizer_Plugin $plugin ) { /** * Adds the async attribute to certain scripts. */ - function script_loader_tag( $tag, $handle, $src ) { + public function script_loader_tag( $tag, $handle, $src ) { if ( is_admin() ) { return $tag; } @@ -98,7 +98,7 @@ function script_loader_tag( $tag, $handle, $src ) { $tag = str_replace( ' src', ' async src', $tag ); break; } - }; + } // Async scripts. $scripts = array( 'dom-to-image' ); @@ -124,7 +124,7 @@ function script_loader_tag( $tag, $handle, $src ) { /** * Returns the language/locale. */ - function getLanguage( $dummy, $only_language ) { + public function getLanguage( $dummy, $only_language ) { return $this->get_language(); } @@ -132,7 +132,7 @@ function getLanguage( $dummy, $only_language ) { /** * Registers the endpoints */ - function endpoint_register() { + public function endpoint_register() { register_rest_route( 'visualizer/v' . VISUALIZER_REST_VERSION, '/action/(?P\d+)/(?P.+)/', @@ -142,7 +142,7 @@ function endpoint_register() { 'args' => array( 'chart' => array( 'required' => true, - 'sanitize_callback' => function( $param ) { + 'sanitize_callback' => function ( $param ) { return is_numeric( $param ) ? $param : null; }, ), @@ -342,8 +342,8 @@ public function renderChart( $atts ) { } // in case revisions exist. - // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.Found - if ( true === ( $revisions = $this->undoRevisions( $chart->ID, true ) ) ) { + $revisions = $this->undoRevisions( $chart->ID, true ); + if ( true === $revisions ) { $chart = get_post( $chart->ID ); } @@ -509,7 +509,7 @@ public function renderChart( $atts ) { ) ); } - $count++; + ++$count; } $prefix = 'C' . 'h' . 'a' . 'rt'; if ( $type === 'tabular' ) { diff --git a/classes/Visualizer/Module/Language.php b/classes/Visualizer/Module/Language.php index cfaafdac2..38239a644 100644 --- a/classes/Visualizer/Module/Language.php +++ b/classes/Visualizer/Module/Language.php @@ -19,7 +19,7 @@ */ if ( ! class_exists( '_WP_Editors' ) ) { - require( ABSPATH . WPINC . '/class-wp-editor.php' ); + require ABSPATH . WPINC . '/class-wp-editor.php'; } /** @@ -79,7 +79,6 @@ public function tinymce_translation() { public function get_strings() { return $this->strings; } - } $visualizerLangClass = new Visualizer_Module_Language(); diff --git a/classes/Visualizer/Module/Sources.php b/classes/Visualizer/Module/Sources.php index 8d93e2920..b279d5f46 100644 --- a/classes/Visualizer/Module/Sources.php +++ b/classes/Visualizer/Module/Sources.php @@ -53,7 +53,7 @@ public function __construct( Visualizer_Plugin $plugin ) { parent::__construct( $plugin ); $this->_addFilter( Visualizer_Plugin::FILTER_GET_CHART_SERIES, 'filterChartSeries', 1, 2 ); $this->_addFilter( Visualizer_Plugin::FILTER_GET_CHART_DATA, 'filterChartData', 1, 2 ); - $this->_addFilter( 'visualizer_pro_upsell', 'addProUpsell', 10, 2 ); + $this->_addFilter( 'visualizer_pro_upsell', 'addProUpsell', 10, 3 ); } /** @@ -129,7 +129,7 @@ public function filterChartData( $data, $chart_id ) { * * @return string The new html code. */ - public function addProUpsell( $old, $feature = null ) { + public function addProUpsell( $old, $feature = null, string $docs_url = '' ) { $pro_features = Visualizer_Module::get_features_for_license( 1 ); $biz_features = Visualizer_Module::get_features_for_license( 2 ); $return = ''; @@ -145,7 +145,7 @@ public function addProUpsell( $old, $feature = null ) { if ( in_array( $feature, $biz_features, true ) && Visualizer_Module::is_pro() ) { $msg = $plus_msg; } - if ( in_array( $feature, [ 'db-query', 'chart-permissions' ], true ) ) { + if ( in_array( $feature, array( 'db-query', 'chart-permissions' ), true ) ) { $msg = $plus_msg; } @@ -153,7 +153,10 @@ public function addProUpsell( $old, $feature = null ) { $return .= '
'; $return .= '
'; $return .= '

' . $msg . '

'; - $return .= ' ' . __( 'Upgrade Now', 'visualizer' ) . ''; + if ( ! empty( $docs_url ) ) { + $return .= ' ' . esc_html__( 'Documentation', 'visualizer' ) . ''; + } + $return .= ' ' . __( 'Upgrade Now', 'visualizer' ) . ''; $return .= '
'; $return .= '
'; $return .= ''; @@ -165,5 +168,4 @@ public function addProUpsell( $old, $feature = null ) { return $return; } - } diff --git a/classes/Visualizer/Module/Upgrade.php b/classes/Visualizer/Module/Upgrade.php index 630dafe12..5bf975b60 100644 --- a/classes/Visualizer/Module/Upgrade.php +++ b/classes/Visualizer/Module/Upgrade.php @@ -71,6 +71,5 @@ private static function makeAllTableChartsTabular() { AND pm.meta_value IN ( 'dataTable', 'table' )" ); // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared - } } diff --git a/classes/Visualizer/Plugin.php b/classes/Visualizer/Plugin.php index 62f6724e9..85cbfd425 100644 --- a/classes/Visualizer/Plugin.php +++ b/classes/Visualizer/Plugin.php @@ -222,10 +222,10 @@ public function hasModule( $name ) { * * @access public * - * @param string $class The name of the module to use in the plugin. + * @param string $class_name The name of the module to use in the plugin. */ - public function setModule( $class ) { - $this->_modules[ $class ] = new $class( $this ); + public function setModule( $class_name ) { + $this->_modules[ $class_name ] = new $class_name( $this ); } /** @@ -241,11 +241,10 @@ private function __clone() { /** * For local testing, overrides the 'themeisle_log_event' hook and redirects to error.log. */ - final function themeisle_log_event_debug( $name, $message, $type, $file, $line ) { + final public function themeisle_log_event_debug( $name, $message, $type, $file, $line ) { if ( Visualizer_Plugin::NAME !== $name ) { return; } error_log( sprintf( '%s (%s): %s in %s:%s', $name, $type, $message, $file, $line ) ); } - } diff --git a/classes/Visualizer/Render.php b/classes/Visualizer/Render.php index bcb036fce..93b51bf30 100644 --- a/classes/Visualizer/Render.php +++ b/classes/Visualizer/Render.php @@ -112,7 +112,7 @@ public function __unset( $name ) { * @abstract * @access protected */ - protected abstract function _toHTML(); + abstract protected function _toHTML(); /** * Builds template and return it as string. @@ -215,6 +215,4 @@ protected function can_chart_have_action( $action, $chart_id = null ) { return true; } - - } diff --git a/classes/Visualizer/Render/Layout.php b/classes/Visualizer/Render/Layout.php index a89353ef5..d2cd516c6 100644 --- a/classes/Visualizer/Render/Layout.php +++ b/classes/Visualizer/Render/Layout.php @@ -390,7 +390,6 @@ public static function _renderSimpleEditorScreen( $args ) { '; Visualizer_Render_Sidebar::_renderGroupEnd(); } @@ -787,20 +786,20 @@ public static function _renderTabBasic( $args ) {

-

+ -

+ @@ -1017,8 +1016,8 @@ class="dashicons dashicons-lock"> + value="" + data-viz-link=""> - + @@ -1218,7 +1217,7 @@ class="dashicons dashicons-lock"> - + diff --git a/classes/Visualizer/Render/Library.php b/classes/Visualizer/Render/Library.php index b4aba1b8d..5a59d7fb1 100644 --- a/classes/Visualizer/Render/Library.php +++ b/classes/Visualizer/Render/Library.php @@ -152,7 +152,7 @@ private function getDisplayForm() { } $sources = array_filter( $sources ); uasort( - $sources, function( $a, $b ) { + $sources, function ( $a, $b ) { if ( $a === $b ) { return 0; } @@ -223,8 +223,8 @@ private function _renderProPopupBlocker() { $license_key = ''; $download_id = ''; if ( ! empty( $license ) && is_object( $license ) ) { - $license_key = $license->key; - $download_id = $license->download_id; + $license_key = isset( $license->key ) ? $license->key : ''; + $download_id = isset( $license->download_id ) ? $license->download_id : ''; } $admin_license_url = admin_url( 'options-general.php#visualizer_pro_license' ); $renew_license_url = tsdk_utmify( Visualizer_Plugin::STORE_URL . '?edd_license_key=' . $license_key . '&download_id=' . $download_id, 'visualizer_license_block' ); @@ -257,7 +257,6 @@ function closePopup() { popup.style.display = "none"; } '; - } /** * Renders library content. @@ -287,7 +286,7 @@ private function _renderLibrary() { $count = 0; foreach ( $this->charts as $placeholder_id => $chart ) { // show the sidebar after the first 3 charts. - $count++; + ++$count; $enable_controls = false; $settings = isset( $chart['settings'] ) ? $chart['settings'] : array(); if ( ! empty( $settings['controls']['controlType'] ) ) { @@ -400,7 +399,7 @@ private function _renderChartBox( $placeholder_id, $chart_id, $with_filter = fal ); $chart_type = get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, true ); - $types = ['area', 'geo', 'column', 'bubble', 'scatter', 'gauge', 'candlestick', 'timeline', 'combo', 'polarArea', 'radar' ]; + $types = array( 'area', 'geo', 'column', 'bubble', 'scatter', 'gauge', 'candlestick', 'timeline', 'combo', 'polarArea', 'radar' ); $pro_class = ''; @@ -477,5 +476,4 @@ private function _renderSidebar() { echo ''; } } - } diff --git a/classes/Visualizer/Render/Page.php b/classes/Visualizer/Render/Page.php index aa5eacd6c..5f70c1e0c 100644 --- a/classes/Visualizer/Render/Page.php +++ b/classes/Visualizer/Render/Page.php @@ -86,5 +86,4 @@ protected function _renderSidebarContent() {} * @access protected */ protected function _renderToolbar() {} - } diff --git a/classes/Visualizer/Render/Page/Data.php b/classes/Visualizer/Render/Page/Data.php index 9e248ec48..6730db0bd 100644 --- a/classes/Visualizer/Render/Page/Data.php +++ b/classes/Visualizer/Render/Page/Data.php @@ -93,7 +93,7 @@ protected function _renderSidebarContent() {
- +
@@ -156,5 +156,4 @@ private function add_additional_content() { Visualizer_Render_Layout::show( 'db-query', $query, $this->chart->ID ); Visualizer_Render_Layout::show( 'json-screen', $this->chart->ID ); } - } diff --git a/classes/Visualizer/Render/Page/Send.php b/classes/Visualizer/Render/Page/Send.php index 3f21f2c26..b1cb52483 100644 --- a/classes/Visualizer/Render/Page/Send.php +++ b/classes/Visualizer/Render/Page/Send.php @@ -53,5 +53,4 @@ protected function _toHTML() { echo ''; echo ''; } - } diff --git a/classes/Visualizer/Render/Page/Settings.php b/classes/Visualizer/Render/Page/Settings.php index e3b1d37b0..a8133eb74 100644 --- a/classes/Visualizer/Render/Page/Settings.php +++ b/classes/Visualizer/Render/Page/Settings.php @@ -80,5 +80,4 @@ protected function _toHTML() { protected function _renderSidebarContent() { echo $this->sidebar; } - } diff --git a/classes/Visualizer/Render/Page/Update.php b/classes/Visualizer/Render/Page/Update.php index 0eb54d3fa..c9f8f6735 100644 --- a/classes/Visualizer/Render/Page/Update.php +++ b/classes/Visualizer/Render/Page/Update.php @@ -91,5 +91,4 @@ private function updateEditorAndSettings() { return 'win.vizUpdateHTML(' . json_encode( array( 'html' => $editor ) ) . ', ' . json_encode( array( 'html' => $sidebar ) ) . ');'; } - } diff --git a/classes/Visualizer/Render/Sidebar.php b/classes/Visualizer/Render/Sidebar.php index 79e400b43..5e13bd01f 100644 --- a/classes/Visualizer/Render/Sidebar.php +++ b/classes/Visualizer/Render/Sidebar.php @@ -208,7 +208,6 @@ protected function _renderAdvancedSettings() { self::_renderSectionEnd(); self::_renderGroupEnd(); - } /** @@ -276,7 +275,7 @@ protected function _renderActionSettings() { private static function is_excel_enabled() { $vendor_file = VISUALIZER_ABSPATH . '/vendor/autoload.php'; if ( is_readable( $vendor_file ) ) { - include_once( $vendor_file ); + include_once $vendor_file; } if ( version_compare( phpversion(), '5.6.0', '<' ) ) { @@ -313,7 +312,7 @@ public static function _renderSelectItem( $title, $name, $value, array $options, echo '
'; echo '[?]'; echo '', $title, ''; - echo ''; foreach ( $options as $key => $label ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict $extra = $multiple && is_array( $value ) ? ( in_array( $key, $value ) ? 'selected' : '' ) : selected( $key, $value, false ); @@ -336,13 +335,13 @@ public static function _renderSelectItem( $title, $name, $value, array $options, * @param string $title The title of the select item. * @param string $name The name of the select item. * @param string $value The actual value of the select item. - * @param string $default The default value of the color picker. + * @param string $default_color The default value of the color picker. */ - protected static function _renderColorPickerItem( $title, $name, $value, $default ) { + protected static function _renderColorPickerItem( $title, $name, $value, $default_color ) { echo '
'; echo '', $title, ''; echo '
'; - echo ''; + echo ''; echo '
'; echo '
'; } @@ -387,10 +386,10 @@ protected static function _renderTextItem( $title, $name, $value, $desc, $placeh * @access public * @param string $title The title of this group. * @param string $html Any additional HTML. - * @param string $class Any additional classes. + * @param string $extra_class Any additional classes. */ - public static function _renderGroupStart( $title, $html = '', $class = '', $id = '' ) { - echo '
  • '; + public static function _renderGroupStart( $title, $html = '', $extra_class = '', $id = '' ) { + echo '
  • '; echo '

    ', $title, '

    '; echo $html; echo '
      '; @@ -506,12 +505,11 @@ protected function _renderFormatField( $index = 0 ) { /** * Render a checkbox item */ - protected static function _renderCheckboxItem( $title, $name, $value, $default, $desc, $disabled = false ) { + protected static function _renderCheckboxItem( $title, $name, $value, $default_value, $desc, $disabled = false ) { echo '
      '; echo '[?]'; echo '', $title, ''; - // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison - echo ''; + echo ''; echo '

      ', $desc, '

      '; echo '
      '; } @@ -552,7 +550,6 @@ protected function load_dependent_assets( $libs ) { if ( in_array( 'numeral', $libs, true ) && ! wp_script_is( 'numeral', 'registered' ) ) { wp_register_script( 'numeral', VISUALIZER_ABSURL . 'js/lib/numeral.min.js', array(), Visualizer_Plugin::VERSION ); } - } /** @@ -656,8 +653,8 @@ protected function _renderChartControlsSettings() { array( 'vz-controls-opt' ) ); - $column_index = [ 'false' => '' ]; - $column_label = [ 'false' => '' ]; + $column_index = array( 'false' => '' ); + $column_label = array( 'false' => '' ); if ( ! empty( $this->__series ) ) { foreach ( $this->__series as $key => $column ) { $column_type = isset( $column['type'] ) ? $column['type'] : ''; diff --git a/classes/Visualizer/Render/Sidebar/ChartJS.php b/classes/Visualizer/Render/Sidebar/ChartJS.php index d4da43b31..1323e6c2e 100644 --- a/classes/Visualizer/Render/Sidebar/ChartJS.php +++ b/classes/Visualizer/Render/Sidebar/ChartJS.php @@ -38,7 +38,6 @@ public function __construct( $data = array() ) { 'bottom' => esc_html__( 'Below the chart', 'visualizer' ), 'none' => esc_html__( 'Omit the legend', 'visualizer' ), ); - } /** @@ -78,7 +77,7 @@ protected function hooks() { /** * Loads the assets. */ - function load_chartjs_assets( $deps, $is_frontend ) { + public function load_chartjs_assets( $deps, $is_frontend ) { $this->load_dependent_assets( array( 'moment', 'numeral' ) ); wp_register_script( 'chartjs', VISUALIZER_ABSURL . 'js/lib/chartjs.min.js', array( 'numeral', 'moment' ), null, true ); @@ -96,7 +95,6 @@ function load_chartjs_assets( $deps, $is_frontend ) { $deps, array( 'visualizer-render-chartjs-lib' ) ); - } /** @@ -133,7 +131,6 @@ protected function _renderSeriesSettings() { protected function _renderSeries( $index ) { $this->_renderFormatField( $index ); $this->_renderChartTypeSeries( $index ); - } /** @@ -187,7 +184,6 @@ protected function _renderChartTitleSettings() { '' ) ); - } /** @@ -367,7 +363,6 @@ protected function _renderAnimationSettings() { ); self::_renderSectionEnd(); - } /** diff --git a/classes/Visualizer/Render/Sidebar/Columnar.php b/classes/Visualizer/Render/Sidebar/Columnar.php index 460043b9e..1a1af1709 100644 --- a/classes/Visualizer/Render/Sidebar/Columnar.php +++ b/classes/Visualizer/Render/Sidebar/Columnar.php @@ -110,5 +110,4 @@ protected function _renderHorizontalAxisGeneralSettings() { '#000' ); } - } diff --git a/classes/Visualizer/Render/Sidebar/Google.php b/classes/Visualizer/Render/Sidebar/Google.php index 3f7cd8198..5810cc1ed 100644 --- a/classes/Visualizer/Render/Sidebar/Google.php +++ b/classes/Visualizer/Render/Sidebar/Google.php @@ -82,7 +82,6 @@ public function __construct( $data = array() ) { 'center' => esc_html__( 'Centered in the allocated area', 'visualizer' ), 'end' => esc_html__( 'Aligned to the end of the allocated area', 'visualizer' ), ); - } /** @@ -99,7 +98,7 @@ protected function hooks() { /** * Loads the assets. */ - function load_google_assets( $deps, $is_frontend ) { + public function load_google_assets( $deps, $is_frontend ) { wp_register_script( 'google-jsapi', '//www.gstatic.com/charts/loader.js', array(), null, true ); wp_register_script( 'dom-to-image', VISUALIZER_ABSURL . 'js/lib/dom-to-image.min.js', array(), null, true ); wp_register_script( @@ -117,7 +116,6 @@ function load_google_assets( $deps, $is_frontend ) { $deps, array( 'visualizer-render-google-lib' ) ); - } /** @@ -309,7 +307,6 @@ protected function _renderAnimationSettings() { ); self::_renderSectionEnd(); - } /** diff --git a/classes/Visualizer/Render/Sidebar/Graph.php b/classes/Visualizer/Render/Sidebar/Graph.php index 7ee73de7b..80a2a51a9 100644 --- a/classes/Visualizer/Render/Sidebar/Graph.php +++ b/classes/Visualizer/Render/Sidebar/Graph.php @@ -136,7 +136,6 @@ protected function _renderChartTitleSettings() { '' ) ); - } /** @@ -461,7 +460,6 @@ protected function _renderSeries( $index ) { ); $this->_renderRoleField( $index ); - } /** @@ -525,5 +523,4 @@ protected function _renderVerticalAxisFormatField() { ) ); } - } diff --git a/classes/Visualizer/Render/Sidebar/Linear.php b/classes/Visualizer/Render/Sidebar/Linear.php index 5769f4bc4..7a7b250f8 100644 --- a/classes/Visualizer/Render/Sidebar/Linear.php +++ b/classes/Visualizer/Render/Sidebar/Linear.php @@ -291,7 +291,5 @@ protected function _renderSeries( $index ) { ); $this->_renderRoleField( $index ); - } - } diff --git a/classes/Visualizer/Render/Sidebar/Type/ChartJS/Bar.php b/classes/Visualizer/Render/Sidebar/Type/ChartJS/Bar.php index 807ae4376..7f0bdb385 100644 --- a/classes/Visualizer/Render/Sidebar/Type/ChartJS/Bar.php +++ b/classes/Visualizer/Render/Sidebar/Type/ChartJS/Bar.php @@ -131,6 +131,5 @@ protected function _renderChartTypeSettings() { self::_renderSectionEnd(); self::_renderGroupEnd(); - } } diff --git a/classes/Visualizer/Render/Sidebar/Type/ChartJS/Linear.php b/classes/Visualizer/Render/Sidebar/Type/ChartJS/Linear.php index a1646331b..f42cac084 100644 --- a/classes/Visualizer/Render/Sidebar/Type/ChartJS/Linear.php +++ b/classes/Visualizer/Render/Sidebar/Type/ChartJS/Linear.php @@ -79,7 +79,6 @@ protected function _renderHorizontalTickSettings() { ); self::_renderSectionEnd(); - } /** @@ -124,7 +123,6 @@ protected function _renderVerticalTickSettings() { ); self::_renderSectionEnd(); - } /** @@ -318,6 +316,5 @@ protected function _renderVerticalAxisGeneralSettings() { ); self::_renderSectionEnd(); - } } diff --git a/classes/Visualizer/Render/Sidebar/Type/ChartJS/Pie.php b/classes/Visualizer/Render/Sidebar/Type/ChartJS/Pie.php index 987dbf202..96fb590b7 100644 --- a/classes/Visualizer/Render/Sidebar/Type/ChartJS/Pie.php +++ b/classes/Visualizer/Render/Sidebar/Type/ChartJS/Pie.php @@ -86,7 +86,6 @@ protected function _renderSliceSettings( $index ) { isset( $this->slices[ $index ]['hoverBackgroundColor'] ) ? $this->slices[ $index ]['hoverBackgroundColor'] : null, null ); - } /** diff --git a/classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php b/classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php deleted file mode 100644 index fd48a5130..000000000 --- a/classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php +++ /dev/null @@ -1,527 +0,0 @@ - | -// +----------------------------------------------------------------------+ -/** - * Class for datatables.net table chart sidebar settings. - * - * THIS IS ONLY FOR BACKWARD COMPATIBILITY ON DEV SYSTEMS. CAN BE REMOVED IN A FUTURE RELEASE. - * - * @since 1.0.0 - */ -class Visualizer_Render_Sidebar_Type_DataTable_DataTable extends Visualizer_Render_Sidebar { - - - /** - * Constructor. - * - * @since 1.0.0 - * - * @access public - * @param array $data The data what has to be associated with this render. - */ - public function __construct( $data = array() ) { - $this->_library = 'datatables'; - $this->_includeCurveTypes = false; - - parent::__construct( $data ); - } - - /** - * Registers additional hooks. - * - * @access protected - */ - protected function hooks() { - if ( $this->_library === 'datatables' ) { - add_filter( 'visualizer_assets_render', array( $this, 'load_assets' ), 10, 2 ); - } - } - - /** - * Registers assets. - * - * @access public - */ - function load_assets( $deps, $is_frontend ) { - $this->load_dependent_assets( array( 'moment' ) ); - - wp_register_script( 'visualizer-datatables', VISUALIZER_ABSURL . 'js/lib/datatables.min.js', array( 'jquery-ui-core', 'moment' ), Visualizer_Plugin::VERSION ); - wp_enqueue_style( 'visualizer-datatables', VISUALIZER_ABSURL . 'css/lib/datatables.min.css', array(), Visualizer_Plugin::VERSION ); - - wp_register_script( - 'visualizer-render-datatables-lib', - VISUALIZER_ABSURL . 'js/render-datatables.js', - array( - 'visualizer-datatables', - ), - Visualizer_Plugin::VERSION, - true - ); - - return array_merge( - $deps, - array( 'visualizer-render-datatables-lib' ) - ); - } - - /** - * Enqueue assets. - */ - public static function enqueue_assets( $deps = array() ) { - wp_enqueue_style( 'visualizer-datatables', VISUALIZER_ABSURL . 'css/lib/datatables.min.css', array(), Visualizer_Plugin::VERSION ); - wp_enqueue_script( 'visualizer-datatables', VISUALIZER_ABSURL . 'js/lib/datatables.min.js', array( 'jquery-ui-core' ), Visualizer_Plugin::VERSION ); - wp_enqueue_script( 'visualizer-render-datatables-lib', VISUALIZER_ABSURL . 'js/render-datatables.js', array_merge( $deps, array( 'jquery-ui-core', 'visualizer-datatables' ) ), Visualizer_Plugin::VERSION, true ); - return 'visualizer-render-datatables-lib'; - } - - /** - * Renders template. - * - * @since 1.0.0 - * - * @access protected - */ - protected function _toHTML() { - $this->_supportsAnimation = false; - $this->_renderGeneralSettings(); - $this->_renderTableSettings(); - $this->_renderColumnSettings(); - $this->_renderAdvancedSettings(); - } - - /** - * Renders chart advanced settings group. - * - * @access protected - */ - protected function _renderAdvancedSettings() { - self::_renderGroupStart( esc_html__( 'Frontend Actions', 'visualizer' ) ); - self::_renderSectionStart(); - self::_renderSectionDescription( esc_html__( 'Configure frontend actions that need to be shown.', 'visualizer' ) ); - self::_renderSectionEnd(); - - $this->_renderActionSettings(); - self::_renderGroupEnd(); - } - - /** - * Renders general settings group. - * - * @since 1.0.0 - * - * @access protected - */ - protected function _renderGeneralSettings() { - self::_renderGroupStart( esc_html__( 'General Settings', 'visualizer' ) ); - self::_renderSectionStart( esc_html__( 'Title', 'visualizer' ), true ); - self::_renderTextItem( - esc_html__( 'Chart Title', 'visualizer' ), - 'title', - $this->title, - esc_html__( 'Text to display in the back-end admin area.', 'visualizer' ) - ); - - echo '
      '; - - self::_renderTextAreaItem( - esc_html__( 'Chart Description', 'visualizer' ), - 'description', - $this->description, - sprintf( - // translators: %1$s - HTML link tag, %2$s - HTML closing link tag. - esc_html__( 'Description to display in the structured data schema as explained %1$shere%2$s', 'visualizer' ), - '', - '' - ) - ); - - self::_renderSectionEnd(); - - self::_renderChartImageSettings(); - - self::_renderGroupEnd(); - } - - /** - * Renders line settings items. - * - * @since 1.0.0 - * - * @access protected - */ - protected function _renderTableSettings() { - self::_renderGroupStart( esc_html__( 'Table Settings', 'visualizer' ) ); - self::_renderSectionStart(); - - self::_renderCheckboxItem( - esc_html__( 'Enable Pagination', 'visualizer' ), - 'paging_bool', - $this->paging_bool, - 'true', - esc_html__( 'To enable paging through the data.', 'visualizer' ) - ); - - echo '
      '; - - self::_renderTextItem( - esc_html__( 'Number of rows per page', 'visualizer' ), - 'pageLength_int', - $this->pageLength_int, - esc_html__( 'The number of rows in each page, when paging is enabled.', 'visualizer' ), - 10, - 'number', - array( 'min' => 1 ) - ); - - echo '
      '; - - self::_renderSelectItem( - esc_html__( 'Pagination type', 'visualizer' ), - 'pagingType', - $this->pagingType, - array( - 'numbers' => esc_html__( 'Page number buttons only', 'visualizer' ), - 'simple' => esc_html__( '\'Previous\' and \'Next\' buttons only', 'visualizer' ), - 'simple_numbers' => esc_html__( '\'Previous\' and \'Next\' buttons, plus page numbers', 'visualizer' ), - 'full' => esc_html__( '\'First\', \'Previous\', \'Next\' and \'Last\' buttons', 'visualizer' ), - 'full_numbers' => esc_html__( '\'First\', \'Previous\', \'Next\' and \'Last\' buttons, plus page numbers', 'visualizer' ), - 'first_last_numbers' => esc_html__( '\'First\' and \'Last\' buttons, plus page numbers', 'visualizer' ), - ), - esc_html__( 'Determines what type of pagination options to show.', 'visualizer' ) - ); - - do_action( 'visualizer_chart_settings', __CLASS__, $this->_data, 'pagination' ); - - echo '
      '; - - self::_renderTextItem( - esc_html__( 'Table Height', 'visualizer' ), - 'scrollY_int', - isset( $this->scrollY_int ) ? $this->scrollY_int : '', - esc_html__( 'Height of the table in pixels (the table will show a scrollbar).', 'visualizer' ), - '', - 'number', - array( - 'min' => 0, - ) - ); - - self::_renderCheckboxItem( - esc_html__( 'Enable Horizontal Scrolling', 'visualizer' ), - 'scrollX', - $this->scrollX, - 'true', - esc_html__( 'To disable wrapping of columns and enabling horizontal scrolling.', 'visualizer' ) - ); - - echo '
      '; - - self::_renderCheckboxItem( - esc_html__( 'Disable Sort', 'visualizer' ), - 'ordering_bool', - $this->ordering_bool, - 'false', - esc_html__( 'To disable sorting on columns.', 'visualizer' ) - ); - - echo '
      '; - - self::_renderCheckboxItem( - esc_html__( 'Freeze Header/Footer', 'visualizer' ), - 'fixedHeader_bool', - $this->fixedHeader_bool, - 'true', - esc_html__( 'Freeze the header and footer.', 'visualizer' ) - ); - - echo '
      '; - - self::_renderCheckboxItem( - esc_html__( 'Responsive table?', 'visualizer' ), - 'responsive_bool', - $this->responsive_bool, - 'true', - esc_html__( 'Enable the table to be responsive.', 'visualizer' ) - ); - - do_action( 'visualizer_chart_settings', __CLASS__, $this->_data, 'table' ); - - self::_renderSectionEnd(); - self::_renderGroupEnd(); - - self::_renderGroupStart( esc_html__( 'Row/Cell Settings', 'visualizer' ) ); - - self::_renderSectionStart( esc_html__( 'Header Row', 'visualizer' ) ); - - self::_renderSectionDescription( esc_html__( 'These values may not reflect on preview and will be applied once you save and reload the chart. ', 'visualizer' ), 'viz-info-msg' ); - - self::_renderColorPickerItem( - esc_html__( 'Background Color', 'visualizer' ), - 'customcss[headerRow][background-color]', - isset( $this->customcss['headerRow']['background-color'] ) ? $this->customcss['headerRow']['background-color'] : null, - null - ); - - self::_renderColorPickerItem( - esc_html__( 'Color', 'visualizer' ), - 'customcss[headerRow][color]', - isset( $this->customcss['headerRow']['color'] ) ? $this->customcss['headerRow']['color'] : null, - null - ); - - self::_renderTextItem( - esc_html__( 'Text Orientation', 'visualizer' ), - 'customcss[headerRow][transform]', - isset( $this->customcss['headerRow']['transform'] ) ? $this->customcss['headerRow']['transform'] : null, - esc_html__( 'In degrees.', 'visualizer' ), - '', - 'number', - array( - 'min' => -180, - 'max' => 180, - ) - ); - self::_renderSectionEnd(); - - self::_renderSectionStart( esc_html__( 'Odd Table Row', 'visualizer' ) ); - - self::_renderSectionDescription( esc_html__( 'These values may not reflect on preview and will be applied once you save and reload the chart. ', 'visualizer' ), 'viz-info-msg' ); - - self::_renderColorPickerItem( - esc_html__( 'Background Color', 'visualizer' ), - 'customcss[oddTableRow][background-color]', - isset( $this->customcss['oddTableRow']['background-color'] ) ? $this->customcss['oddTableRow']['background-color'] : null, - null - ); - - self::_renderColorPickerItem( - esc_html__( 'Color', 'visualizer' ), - 'customcss[oddTableRow][color]', - isset( $this->customcss['oddTableRow']['color'] ) ? $this->customcss['oddTableRow']['color'] : null, - null - ); - - self::_renderTextItem( - esc_html__( 'Text Orientation', 'visualizer' ), - 'customcss[oddTableRow][transform]', - isset( $this->customcss['oddTableRow']['transform'] ) ? $this->customcss['oddTableRow']['transform'] : null, - esc_html__( 'In degrees.', 'visualizer' ), - '', - 'number', - array( - 'min' => -180, - 'max' => 180, - ) - ); - self::_renderSectionEnd(); - - self::_renderSectionStart( esc_html__( 'Even Table Row', 'visualizer' ) ); - - self::_renderSectionDescription( esc_html__( 'These values may not reflect on preview and will be applied once you save and reload the chart. ', 'visualizer' ), 'viz-info-msg' ); - - self::_renderColorPickerItem( - esc_html__( 'Background Color', 'visualizer' ), - 'customcss[evenTableRow][background-color]', - isset( $this->customcss['evenTableRow']['background-color'] ) ? $this->customcss['evenTableRow']['background-color'] : null, - null - ); - - self::_renderColorPickerItem( - esc_html__( 'Color', 'visualizer' ), - 'customcss[evenTableRow][color]', - isset( $this->customcss['evenTableRow']['color'] ) ? $this->customcss['evenTableRow']['color'] : null, - null - ); - - self::_renderTextItem( - esc_html__( 'Text Orientation', 'visualizer' ), - 'customcss[evenTableRow][transform]', - isset( $this->customcss['evenTableRow']['transform'] ) ? $this->customcss['evenTableRow']['transform'] : null, - esc_html__( 'In degrees.', 'visualizer' ), - '', - 'number', - array( - 'min' => -180, - 'max' => 180, - ) - ); - self::_renderSectionEnd(); - - self::_renderSectionStart( esc_html__( 'Table Cell', 'visualizer' ) ); - - self::_renderSectionDescription( esc_html__( 'These values may not reflect on preview and will be applied once you save and reload the chart. ', 'visualizer' ), 'viz-info-msg' ); - - self::_renderColorPickerItem( - esc_html__( 'Background Color', 'visualizer' ), - 'customcss[tableCell][background-color]', - isset( $this->customcss['tableCell']['background-color'] ) ? $this->customcss['tableCell']['background-color'] : null, - null - ); - - self::_renderColorPickerItem( - esc_html__( 'Color', 'visualizer' ), - 'customcss[tableCell][color]', - isset( $this->customcss['tableCell']['color'] ) ? $this->customcss['tableCell']['color'] : null, - null - ); - - self::_renderTextItem( - esc_html__( 'Text Orientation', 'visualizer' ), - 'customcss[tableCell][transform]', - isset( $this->customcss['tableCell']['transform'] ) ? $this->customcss['tableCell']['transform'] : null, - esc_html__( 'In degrees.', 'visualizer' ), - '', - 'number', - array( - 'min' => -180, - 'max' => 180, - ) - ); - self::_renderSectionEnd(); - - do_action( 'visualizer_chart_settings', __CLASS__, $this->_data, 'style' ); - - self::_renderGroupEnd(); - } - - - /** - * Renders combo series settings - * - * @since 1.0.0 - * - * @access protected - */ - protected function _renderColumnSettings() { - self::_renderGroupStart( esc_html__( 'Column Settings', 'visualizer' ) ); - for ( $i = 0, $cnt = count( $this->__series ); $i < $cnt; $i++ ) { - if ( ! empty( $this->__series[ $i ]['label'] ) ) { - self::_renderSectionStart( esc_html( $this->__series[ $i ]['label'] ), false ); - $this->_renderFormatField( $i ); - self::_renderSectionEnd(); - } - } - self::_renderGroupEnd(); - } - - /** - * Renders format field according to series type. - * - * @since 1.3.0 - * - * @access protected - * @param int $index The index of the series. - */ - protected function _renderFormatField( $index = 0 ) { - switch ( $this->__series[ $index ]['type'] ) { - case 'number': - self::_renderTextItem( - esc_html__( 'Thousands Separator', 'visualizer' ), - 'series[' . $index . '][format][thousands]', - isset( $this->series[ $index ]['format']['thousands'] ) ? $this->series[ $index ]['format']['thousands'] : ',', - null, - ',' - ); - self::_renderTextItem( - esc_html__( 'Decimal Separator', 'visualizer' ), - 'series[' . $index . '][format][decimal]', - isset( $this->series[ $index ]['format']['decimal'] ) ? $this->series[ $index ]['format']['decimal'] : '.', - null, - '.' - ); - self::_renderTextItem( - esc_html__( 'Precision', 'visualizer' ), - 'series[' . $index . '][format][precision]', - isset( $this->series[ $index ]['format']['precision'] ) ? $this->series[ $index ]['format']['precision'] : '', - esc_html__( 'Round values to how many decimal places?', 'visualizer' ), - '', - 'number', - array( 'min' => 0 ) - ); - self::_renderTextItem( - esc_html__( 'Prefix', 'visualizer' ), - 'series[' . $index . '][format][prefix]', - isset( $this->series[ $index ]['format']['prefix'] ) ? $this->series[ $index ]['format']['prefix'] : '', - null, - '' - ); - self::_renderTextItem( - esc_html__( 'Suffix', 'visualizer' ), - 'series[' . $index . '][format][suffix]', - isset( $this->series[ $index ]['format']['suffix'] ) ? $this->series[ $index ]['format']['suffix'] : '', - null, - '' - ); - break; - case 'date': - case 'datetime': - case 'timeofday': - self::_renderTextItem( - esc_html__( 'Display Date Format', 'visualizer' ), - 'series[' . $index . '][format][to]', - isset( $this->series[ $index ]['format']['to'] ) ? $this->series[ $index ]['format']['to'] : '', - sprintf( - // translators: %1$s - HTML link tag, %2$s - HTML closing link tag. - esc_html__( 'Enter custom format pattern to apply to this series value, similar to the %1$sdate and time formats here%2$s.', 'visualizer' ), - '', - '' - ), - 'Do MMM YYYY' - ); - self::_renderTextItem( - esc_html__( 'Source Date Format', 'visualizer' ), - 'series[' . $index . '][format][from]', - isset( $this->series[ $index ]['format']['from'] ) ? $this->series[ $index ]['format']['from'] : '', - sprintf( - // translators: %1$s - HTML link tag, %2$s - HTML closing link tag. - esc_html__( 'What format is the source date in? Similar to the %1$sdate and time formats here%2$s.', 'visualizer' ), '', '' - ), - 'YYYY-MM-DD' - ); - break; - case 'boolean': - self::_renderTextItem( - esc_html__( 'Truthy value', 'visualizer' ), - 'series[' . $index . '][format][truthy]', - isset( $this->series[ $index ]['format']['truthy'] ) ? $this->series[ $index ]['format']['truthy'] : '', - sprintf( - // translators: %1$s - HTML entity code, %2$s - HTML entity code. - esc_html__( 'Provide the HTML entity code for the value the table should display when the value of the column is true. e.g. %1$s (Code: %2$s) instead of true', 'visualizer' ), '✔', '&#10004;' - ), - '' - ); - self::_renderTextItem( - esc_html__( 'Falsy value', 'visualizer' ), - 'series[' . $index . '][format][falsy]', - isset( $this->series[ $index ]['format']['falsy'] ) ? $this->series[ $index ]['format']['falsy'] : '', - sprintf( - // translators: %1$s - HTML entity code, %2$s - HTML entity code. - esc_html__( 'Provide the HTML entity code for the value the table should display when the value of the column is false. e.g. %1$s (Code: %2$s) instead of false', 'visualizer' ), - '✖', - '&#10006;' - ), - '' - ); - break; - } - } - -} diff --git a/classes/Visualizer/Render/Sidebar/Type/DataTable/Tabular.php b/classes/Visualizer/Render/Sidebar/Type/DataTable/Tabular.php index 7839f34dc..32c68c879 100644 --- a/classes/Visualizer/Render/Sidebar/Type/DataTable/Tabular.php +++ b/classes/Visualizer/Render/Sidebar/Type/DataTable/Tabular.php @@ -58,7 +58,7 @@ protected function hooks() { * * @access public */ - function load_assets( $deps, $is_frontend ) { + public function load_assets( $deps, $is_frontend ) { $this->load_dependent_assets( array( 'moment' ) ); wp_register_script( 'visualizer-datatables', VISUALIZER_ABSURL . 'js/lib/datatables.min.js', array( 'jquery-ui-core', 'moment' ), Visualizer_Plugin::VERSION ); @@ -101,7 +101,7 @@ protected function _toHTML() { $this->_supportsAnimation = false; $this->_renderGeneralSettings(); $this->_renderTableSettings(); - $this->_renderColumnSettings(); + $this->_renderColumnSettings(); $this->_renderAdvancedSettings(); } @@ -177,6 +177,9 @@ protected function _renderTableSettings() { esc_html__( 'To enable paging through the data.', 'visualizer' ) ); + $paging_enabled = ( isset( $this->paging_bool ) && 'true' === $this->paging_bool ); + echo ''; + + echo '
      '; self::_renderTextItem( esc_html__( 'Table Height', 'visualizer' ), @@ -499,5 +504,4 @@ protected function _renderFormatField( $index = 0 ) { break; } } - } diff --git a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Area.php b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Area.php index d4a522362..3d5c0bce4 100644 --- a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Area.php +++ b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Area.php @@ -148,5 +148,4 @@ protected function _renderSeries( $index ) { null ); } - } diff --git a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Bar.php b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Bar.php index fb1f38a55..098f8a8e3 100644 --- a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Bar.php +++ b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Bar.php @@ -72,5 +72,4 @@ protected function _toHTML() { $this->_renderViewSettings(); $this->_renderAdvancedSettings(); } - } diff --git a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Bubble.php b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Bubble.php index 203ad8874..28d2761a0 100644 --- a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Bubble.php +++ b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Bubble.php @@ -115,8 +115,5 @@ protected function _renderBubbleSettings() { self::_renderSectionEnd(); self::_renderGroupEnd(); - } - - } diff --git a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Candlestick.php b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Candlestick.php index 04eec1042..453d469b3 100644 --- a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Candlestick.php +++ b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Candlestick.php @@ -175,5 +175,4 @@ protected function _renderSeries( $index ) { null ); } - } diff --git a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Column.php b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Column.php index a9f8024e1..24ee5e3cb 100644 --- a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Column.php +++ b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Column.php @@ -72,5 +72,4 @@ protected function _toHTML() { $this->_renderViewSettings(); $this->_renderAdvancedSettings(); } - } diff --git a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Gauge.php b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Gauge.php index a3529e8a4..56a2c4db1 100644 --- a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Gauge.php +++ b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Gauge.php @@ -309,5 +309,4 @@ protected function _renderViewSettings() { self::_renderSectionEnd(); self::_renderGroupEnd(); } - } diff --git a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Geo.php b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Geo.php index 4b72929bc..2c07589c1 100644 --- a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Geo.php +++ b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Geo.php @@ -465,5 +465,4 @@ protected function _renderViewSettings() { self::_renderSectionEnd(); self::_renderGroupEnd(); } - } diff --git a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Line.php b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Line.php index 8f2f786d5..e8c954353 100644 --- a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Line.php +++ b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Line.php @@ -66,5 +66,4 @@ protected function _renderLineSettingsItems() { esc_html__( 'Whether to guess the value of missing points. If yes, it will guess the value of any missing data based on neighboring points. If no, it will leave a break in the line at the unknown point.', 'visualizer' ) ); } - } diff --git a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Pie.php b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Pie.php index 16c2a0840..17e4624bc 100644 --- a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Pie.php +++ b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Pie.php @@ -229,5 +229,4 @@ protected function _renderTooltipSettigns() { esc_html__( 'Determines what information to display when the user hovers over a pie slice.', 'visualizer' ) ); } - } diff --git a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Scatter.php b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Scatter.php index 7706d3369..ae1b4c534 100644 --- a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Scatter.php +++ b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Scatter.php @@ -60,5 +60,4 @@ protected function _toHTML() { $this->_renderViewSettings(); $this->_renderAdvancedSettings(); } - } diff --git a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Tabular.php b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Tabular.php index 163645c11..da1e2deea 100644 --- a/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Tabular.php +++ b/classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Tabular.php @@ -124,6 +124,9 @@ protected function _renderColumnarSettings() { esc_html__( 'To enable paging through the data.', 'visualizer' ) ); + $paging_enabled = ( isset( $this->pagination ) && 1 === $this->pagination ); // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison + echo ''; + + echo '
      '; self::_renderCheckboxItem( esc_html__( 'Disable Sort', 'visualizer' ), @@ -410,5 +415,4 @@ protected function _renderSeries( $index ) { protected function _renderSeriesSettings() { parent::_renderSeriesSettings(); } - } diff --git a/classes/Visualizer/Render/Templates.php b/classes/Visualizer/Render/Templates.php index 26676e2af..d8998a66f 100644 --- a/classes/Visualizer/Render/Templates.php +++ b/classes/Visualizer/Render/Templates.php @@ -105,5 +105,4 @@ protected function _toHTML() { $this->_renderTemplate( $template, $callback ); } } - } diff --git a/classes/Visualizer/Source.php b/classes/Visualizer/Source.php index 7b3d6b597..ecd186249 100644 --- a/classes/Visualizer/Source.php +++ b/classes/Visualizer/Source.php @@ -109,7 +109,7 @@ protected static function _validateTypes( $types ) { * @access public * @return string The name of source. */ - public abstract function getSourceName(); + abstract public function getSourceName(); /** * Fetches information from source, parses it and builds series and data arrays. @@ -119,7 +119,7 @@ public abstract function getSourceName(); * @abstract * @access public */ - public abstract function fetch(); + abstract public function fetch(); /** * Returns series parsed from source. @@ -263,7 +263,7 @@ protected function _normalizeData( $data ) { * * @return string The converted data. */ - protected final function toUTF8( $datum ) { + final protected function toUTF8( $datum ) { if ( ! function_exists( 'mb_detect_encoding' ) || mb_detect_encoding( $datum ) !== 'ASCII' ) { $datum = \ForceUTF8\Encoding::toUTF8( $datum ); } @@ -280,7 +280,7 @@ protected final function toUTF8( $datum ) { * * @return array */ - public static final function get_date_formats_if_exists( $series, $data ) { + final public static function get_date_formats_if_exists( $series, $data ) { $date_formats = array(); $types = array(); $index = 0; @@ -288,7 +288,7 @@ public static final function get_date_formats_if_exists( $series, $data ) { if ( in_array( $column['type'], array( 'date', 'datetime', 'timeofday' ), true ) ) { $types[] = array( 'index' => $index, 'type' => $column['type'] ); } - $index++; + ++$index; } if ( ! $types ) { @@ -474,6 +474,4 @@ private function _fetchDataFromEditableTable() { return true; } - - } diff --git a/classes/Visualizer/Source/Csv.php b/classes/Visualizer/Source/Csv.php index 796658646..5d4e91873 100644 --- a/classes/Visualizer/Source/Csv.php +++ b/classes/Visualizer/Source/Csv.php @@ -143,9 +143,10 @@ public function fetch() { } // fetch data - // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition - while ( ( $data = fgetcsv( $handle, 0, VISUALIZER_CSV_DELIMITER, VISUALIZER_CSV_ENCLOSURE ) ) !== false ) { + $data = fgetcsv( $handle, 0, VISUALIZER_CSV_DELIMITER, VISUALIZER_CSV_ENCLOSURE ); + while ( $data !== false ) { $this->_data[] = $this->_normalizeData( $data ); + $data = fgetcsv( $handle, 0, VISUALIZER_CSV_DELIMITER, VISUALIZER_CSV_ENCLOSURE ); } // close file handle diff --git a/classes/Visualizer/Source/Csv/Remote.php b/classes/Visualizer/Source/Csv/Remote.php index 3261133a1..e034ca15e 100644 --- a/classes/Visualizer/Source/Csv/Remote.php +++ b/classes/Visualizer/Source/Csv/Remote.php @@ -161,5 +161,4 @@ protected function _get_file_handle( $filename = false ) { return ! is_wp_error( $this->_tmpfile ) ? parent::_get_file_handle( $this->_tmpfile ) : false; } - } diff --git a/classes/Visualizer/Source/Json.php b/classes/Visualizer/Source/Json.php index 2961cd3ba..027b4c0fc 100644 --- a/classes/Visualizer/Source/Json.php +++ b/classes/Visualizer/Source/Json.php @@ -321,7 +321,6 @@ private function collectCommonElements( $data ) { } return $rows; - } /** @@ -331,7 +330,7 @@ private function collectCommonElements( $data ) { * * @access private */ - private function getNextPage( $array ) { + private function getNextPage( $data ) { if ( empty( $this->_paging ) ) { return null; } @@ -339,10 +338,10 @@ private function getNextPage( $array ) { $root = explode( self::TAG_SEPARATOR, $this->_paging ); // get rid of the first element as that is the faux root element indicator array_shift( $root ); - $leaf = $array; + $leaf = $data; foreach ( $root as $tag ) { if ( array_key_exists( $tag, $leaf ) ) { - $leaf = $array[ $tag ]; + $leaf = $data[ $tag ]; } else { // if the tag does not exist, we assume it is present in the 0th element of the current array. // TODO: we may want to change this to a filter later. @@ -362,19 +361,19 @@ private function getNextPage( $array ) { * * @access private */ - private function getRootElements( $parent, $now, $root, $array ) { - if ( is_null( $array ) ) { + private function getRootElements( $parent_key, $now, $root, $data ) { + if ( is_null( $data ) ) { return null; } - $root[] = $parent; - foreach ( $array as $key => $value ) { + $root[] = $parent_key; + foreach ( $data as $key => $value ) { if ( is_array( $value ) && ! empty( $value ) ) { if ( ! is_numeric( $key ) ) { - $now = sprintf( '%s%s%s', $parent, self::TAG_SEPARATOR, $key ); + $now = sprintf( '%s%s%s', $parent_key, self::TAG_SEPARATOR, $key ); $root[] = $now; } else { - $now = $parent; + $now = $parent_key; } $root = $this->getRootElements( $now, $key, $root, $value ); } @@ -442,7 +441,7 @@ private function connect( $url ) { $this->_additional_headers = array_filter( $this->_additional_headers ); if ( ! empty( $this->_additional_headers ) ) { $this->_additional_headers = array_map( - function( $headers ) { + function ( $headers ) { $headers = explode( ':', $headers ); $headers = array_map( 'trim', $headers ); return $headers; @@ -555,5 +554,4 @@ private function is_woocommerce_request( $url ) { public function getSourceName() { return __CLASS__; } - } diff --git a/classes/Visualizer/Source/Query.php b/classes/Visualizer/Source/Query.php index 9b9f6622e..b08798c8e 100644 --- a/classes/Visualizer/Source/Query.php +++ b/classes/Visualizer/Source/Query.php @@ -152,7 +152,8 @@ function ( $value ) { $headers = array(); // short circuit results for remote dbs. - if ( false !== ( $remote_results = apply_filters( 'visualizer_db_query_execute', false, $this->_query, $as_html, $results_as_numeric_array, $raw_results, $this->_chart_id, $this->_params ) ) ) { + $remote_results = apply_filters( 'visualizer_db_query_execute', false, $this->_query, $as_html, $results_as_numeric_array, $raw_results, $this->_chart_id, $this->_params ); + if ( false !== $remote_results ) { $error = $remote_results['error']; if ( empty( $error ) ) { $results = $remote_results['results']; @@ -180,7 +181,7 @@ function ( $value ) { if ( $wpdb->last_error ) { $this->_error = $wpdb->last_error; - return []; + return array(); } if ( $rows ) { @@ -198,7 +199,7 @@ function ( $value ) { } } $results[] = $result; - $row_num++; + ++$row_num; } } diff --git a/classes/Visualizer/Source/Query/Params.php b/classes/Visualizer/Source/Query/Params.php index 0309a9916..528b23ec6 100644 --- a/classes/Visualizer/Source/Query/Params.php +++ b/classes/Visualizer/Source/Query/Params.php @@ -79,7 +79,7 @@ private function rearrange_columns_for_x_axis( $columns, $select, $tables ) { } } } - $index++; + ++$index; } if ( $first ) { diff --git a/composer.json b/composer.json index 841014c42..31a5cfe6e 100644 --- a/composer.json +++ b/composer.json @@ -33,8 +33,8 @@ "scripts": { "format": "phpcbf --standard=phpcs.xml --report-summary --report-source", "lint": "phpcs --standard=phpcs.xml", - "phpstan": "phpstan", - "phpstan:generate:baseline": "phpstan --generate-baseline" + "phpstan": "phpstan --memory-limit=2G", + "phpstan:generate:baseline": "phpstan --generate-baseline --memory-limit=2G" }, "minimum-stability": "dev", "prefer-stable": true, @@ -48,10 +48,11 @@ } }, "require-dev": { - "wp-coding-standards/wpcs": "^2.3", + "wp-coding-standards/wpcs": "^3.3", "dealerdirect/phpcodesniffer-composer-installer": "^1.0.0", "phpcompatibility/phpcompatibility-wp": "*", "phpstan/phpstan": "^2.1", - "szepeviktor/phpstan-wordpress": "^2.0" + "szepeviktor/phpstan-wordpress": "^2.0", + "yoast/phpunit-polyfills": "^4.0" } } diff --git a/composer.lock b/composer.lock index 9d638f7d8..2becf81de 100644 --- a/composer.lock +++ b/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": "6e978a0b38c64a0f62a8ddadae59cfa2", + "content-hash": "f939ee5350ac149f2ec1e5fca3a9ec30", "packages": [ { "name": "codeinwp/themeisle-sdk", @@ -181,29 +181,29 @@ "packages-dev": [ { "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v1.0.0", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "4be43904336affa5c2f70744a348312336afd0da" + "reference": "845eb62303d2ca9b289ef216356568ccc075ffd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", - "reference": "4be43904336affa5c2f70744a348312336afd0da", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/845eb62303d2ca9b289ef216356568ccc075ffd1", + "reference": "845eb62303d2ca9b289ef216356568ccc075ffd1", "shasum": "" }, "require": { - "composer-plugin-api": "^1.0 || ^2.0", + "composer-plugin-api": "^2.2", "php": ">=5.4", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + "squizlabs/php_codesniffer": "^3.1.0 || ^4.0" }, "require-dev": { - "composer/composer": "*", + "composer/composer": "^2.2", "ext-json": "*", "ext-zip": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev", "yoast/phpunit-polyfills": "^1.0" }, "type": "composer-plugin", @@ -222,9 +222,9 @@ "authors": [ { "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" + "email": "opensource@frenck.dev", + "homepage": "https://frenck.dev", + "role": "Open source developer" }, { "name": "Contributors", @@ -232,7 +232,6 @@ } ], "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", "keywords": [ "PHPCodeSniffer", "PHP_CodeSniffer", @@ -253,22 +252,347 @@ ], "support": { "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "security": "https://github.com/PHPCSStandards/composer-installer/security/policy", "source": "https://github.com/PHPCSStandards/composer-installer" }, - "time": "2023-01-05T11:28:13+00:00" + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-11-11T04:32:07+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-12-30T00:15:36+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.13.4", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-08-01T08:46:24+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.7.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" + }, + "time": "2025-12-06T11:56:16+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" }, { "name": "php-stubs/wordpress-stubs", - "version": "v6.8.2", + "version": "v6.9.1", "source": { "type": "git", "url": "https://github.com/php-stubs/wordpress-stubs.git", - "reference": "9c8e22e437463197c1ec0d5eaa9ddd4a0eb6d7f8" + "reference": "f12220f303e0d7c0844c0e5e957b0c3cee48d2f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/9c8e22e437463197c1ec0d5eaa9ddd4a0eb6d7f8", - "reference": "9c8e22e437463197c1ec0d5eaa9ddd4a0eb6d7f8", + "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/f12220f303e0d7c0844c0e5e957b0c3cee48d2f7", + "reference": "f12220f303e0d7c0844c0e5e957b0c3cee48d2f7", "shasum": "" }, "conflict": { @@ -279,9 +603,10 @@ "nikic/php-parser": "^5.5", "php": "^7.4 || ^8.0", "php-stubs/generator": "^0.8.3", - "phpdocumentor/reflection-docblock": "^5.4.1", + "phpdocumentor/reflection-docblock": "^6.0", "phpstan/phpstan": "^2.1", "phpunit/phpunit": "^9.5", + "symfony/polyfill-php80": "*", "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.1.1", "wp-coding-standards/wpcs": "3.1.0 as 2.3.0" }, @@ -304,9 +629,9 @@ ], "support": { "issues": "https://github.com/php-stubs/wordpress-stubs/issues", - "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.8.2" + "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.9.1" }, - "time": "2025-07-16T06:41:00+00:00" + "time": "2026-02-03T19:29:21+00:00" }, { "name": "phpcompatibility/php-compatibility", @@ -372,16 +697,16 @@ }, { "name": "phpcompatibility/phpcompatibility-paragonie", - "version": "1.3.3", + "version": "1.3.4", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", - "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac" + "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/293975b465e0e709b571cbf0c957c6c0a7b9a2ac", - "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/244d7b04fc4bc2117c15f5abe23eb933b5f02bbf", + "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf", "shasum": "" }, "require": { @@ -438,27 +763,32 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" } ], - "time": "2024-04-24T21:30:46+00:00" + "time": "2025-09-19T17:43:28+00:00" }, { "name": "phpcompatibility/phpcompatibility-wp", - "version": "2.1.5", + "version": "2.1.8", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", - "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082" + "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/01c1ff2704a58e46f0cb1ca9d06aee07b3589082", - "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/7c8d18b4d90dac9e86b0869a608fa09158e168fa", + "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa", "shasum": "" }, "require": { "phpcompatibility/php-compatibility": "^9.0", - "phpcompatibility/phpcompatibility-paragonie": "^1.0" + "phpcompatibility/phpcompatibility-paragonie": "^1.0", + "squizlabs/php_codesniffer": "^3.3" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0" @@ -508,80 +838,1695 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" } ], - "time": "2024-04-24T21:37:59+00:00" + "time": "2025-10-18T00:05:59+00:00" }, { - "name": "phpstan/phpstan", - "version": "2.1.22", + "name": "phpcsstandards/phpcsextra", + "version": "1.5.0", "source": { "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "41600c8379eb5aee63e9413fe9e97273e25d57e4" + "url": "https://github.com/PHPCSStandards/PHPCSExtra.git", + "reference": "b598aa890815b8df16363271b659d73280129101" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/41600c8379eb5aee63e9413fe9e97273e25d57e4", - "reference": "41600c8379eb5aee63e9413fe9e97273e25d57e4", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/b598aa890815b8df16363271b659d73280129101", + "reference": "b598aa890815b8df16363271b659d73280129101", "shasum": "" }, "require": { - "php": "^7.4|^8.0" + "php": ">=5.4", + "phpcsstandards/phpcsutils": "^1.2.0", + "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1" }, - "conflict": { - "phpstan/phpstan-shim": "*" + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.2.0", + "phpcsstandards/phpcsdevtools": "^1.2.1", + "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "LGPL-3.0-or-later" ], - "description": "PHPStan - PHP Static Analysis Tool", + "authors": [ + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSExtra/graphs/contributors" + } + ], + "description": "A collection of sniffs and standards for use with PHP_CodeSniffer.", "keywords": [ - "dev", + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "standards", "static analysis" ], "support": { - "docs": "https://phpstan.org/user-guide/getting-started", - "forum": "https://github.com/phpstan/phpstan/discussions", - "issues": "https://github.com/phpstan/phpstan/issues", - "security": "https://github.com/phpstan/phpstan/security/policy", - "source": "https://github.com/phpstan/phpstan-src" + "issues": "https://github.com/PHPCSStandards/PHPCSExtra/issues", + "security": "https://github.com/PHPCSStandards/PHPCSExtra/security/policy", + "source": "https://github.com/PHPCSStandards/PHPCSExtra" }, "funding": [ { - "url": "https://github.com/ondrejmirtes", + "url": "https://github.com/PHPCSStandards", "type": "github" }, { - "url": "https://github.com/phpstan", + "url": "https://github.com/jrfnl", "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2025-08-04T19:17:37+00:00" + "time": "2025-11-12T23:06:57+00:00" }, { - "name": "squizlabs/php_codesniffer", - "version": "3.10.3", + "name": "phpcsstandards/phpcsutils", + "version": "1.2.2", "source": { "type": "git", - "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "62d32998e820bddc40f99f8251958aed187a5c9c" + "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", + "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/62d32998e820bddc40f99f8251958aed187a5c9c", - "reference": "62d32998e820bddc40f99f8251958aed187a5c9c", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/c216317e96c8b3f5932808f9b0f1f7a14e3bbf55", + "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1" + }, + "require-dev": { + "ext-filter": "*", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.2.0", + "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0 || ^3.0.0" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" + } + }, + "autoload": { + "classmap": [ + "PHPCSUtils/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors" + } + ], + "description": "A suite of utility functions for use with PHP_CodeSniffer", + "homepage": "https://phpcsutils.com/", + "keywords": [ + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "phpcs3", + "phpcs4", + "standards", + "static analysis", + "tokens", + "utility" + ], + "support": { + "docs": "https://phpcsutils.com/", + "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues", + "security": "https://github.com/PHPCSStandards/PHPCSUtils/security/policy", + "source": "https://github.com/PHPCSStandards/PHPCSUtils" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-12-08T14:27:58+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "2.1.40", + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b", + "reference": "9b2c7aeb83a75d8680ea5e7c9b7fca88052b766b", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2026-02-23T15:04:35+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.32", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-text-template": "^2.0.4", + "sebastian/code-unit-reverse-lookup": "^2.0.3", + "sebastian/complexity": "^2.0.3", + "sebastian/environment": "^5.1.5", + "sebastian/lines-of-code": "^1.0.4", + "sebastian/version": "^3.0.2", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.6" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-22T04:23:01+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "3.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.6.34", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "b36f02317466907a230d3aa1d34467041271ef4a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b36f02317466907a230d3aa1d34467041271ef4a", + "reference": "b36f02317466907a230d3aa1d34467041271ef4a", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.5.0 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.4", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.32", + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", + "sebastian/comparator": "^4.0.10", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.8", + "sebastian/global-state": "^5.0.8", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", + "sebastian/version": "^3.0.2" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.6-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.34" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2026-01-27T05:45:00+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:27:43+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.10", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e4df00b9b3571187db2831ae9aada2c6efbd715d", + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.10" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" + } + ], + "time": "2026-01-24T09:22:56+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:19:30+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:30:58+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:03:51+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/14c6ba52f95a36c3d27c835d65efc7123c446e8c", + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" + } + ], + "time": "2025-09-24T06:03:27+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/b6781316bdcd28260904e7cc18ec983d0d2ef4f6", + "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", + "type": "tidelift" + } + ], + "time": "2025-08-10T07:10:35+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:20:34+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "539c6691e0623af6dc6f9c20384c120f963465a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/539c6691e0623af6dc6f9c20384c120f963465a0", + "reference": "539c6691e0623af6dc6f9c20384c120f963465a0", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" + } + ], + "time": "2025-08-10T06:57:39+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-14T16:00:52+00:00" + }, + { + "name": "sebastian/type", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:13:03+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.13.5", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4", + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4", "shasum": "" }, "require": { @@ -598,11 +2543,6 @@ "bin/phpcs" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -646,22 +2586,26 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2024-09-18T10:38:58+00:00" + "time": "2025-11-04T16:30:35+00:00" }, { "name": "szepeviktor/phpstan-wordpress", - "version": "v2.0.2", + "version": "v2.0.3", "source": { "type": "git", "url": "https://github.com/szepeviktor/phpstan-wordpress.git", - "reference": "963887b04c21fe7ac78e61c1351f8b00fff9f8f8" + "reference": "aa722f037b2d034828cd6c55ebe9e5c74961927e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/szepeviktor/phpstan-wordpress/zipball/963887b04c21fe7ac78e61c1351f8b00fff9f8f8", - "reference": "963887b04c21fe7ac78e61c1351f8b00fff9f8f8", + "url": "https://api.github.com/repos/szepeviktor/phpstan-wordpress/zipball/aa722f037b2d034828cd6c55ebe9e5c74961927e", + "reference": "aa722f037b2d034828cd6c55ebe9e5c74961927e", "shasum": "" }, "require": { @@ -671,6 +2615,7 @@ }, "require-dev": { "composer/composer": "^2.1.14", + "composer/semver": "^3.4", "dealerdirect/phpcodesniffer-composer-installer": "^1.0", "php-parallel-lint/php-parallel-lint": "^1.1", "phpstan/phpstan-strict-rules": "^2.0", @@ -708,36 +2653,94 @@ ], "support": { "issues": "https://github.com/szepeviktor/phpstan-wordpress/issues", - "source": "https://github.com/szepeviktor/phpstan-wordpress/tree/v2.0.2" + "source": "https://github.com/szepeviktor/phpstan-wordpress/tree/v2.0.3" + }, + "time": "2025-09-14T02:58:22+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, - "time": "2025-02-12T18:43:37+00:00" + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2025-11-17T20:03:58+00:00" }, { "name": "wp-coding-standards/wpcs", - "version": "2.3.0", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/WordPress/WordPress-Coding-Standards.git", - "reference": "7da1894633f168fe244afc6de00d141f27517b62" + "reference": "7795ec6fa05663d716a549d0b44e47ffc8b0d4a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7da1894633f168fe244afc6de00d141f27517b62", - "reference": "7da1894633f168fe244afc6de00d141f27517b62", + "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7795ec6fa05663d716a549d0b44e47ffc8b0d4a6", + "reference": "7795ec6fa05663d716a549d0b44e47ffc8b0d4a6", "shasum": "" }, "require": { - "php": ">=5.4", - "squizlabs/php_codesniffer": "^3.3.1" + "ext-filter": "*", + "ext-libxml": "*", + "ext-tokenizer": "*", + "ext-xmlreader": "*", + "php": ">=7.2", + "phpcsstandards/phpcsextra": "^1.5.0", + "phpcsstandards/phpcsutils": "^1.1.0", + "squizlabs/php_codesniffer": "^3.13.4" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || ^0.6", - "phpcompatibility/php-compatibility": "^9.0", - "phpcsstandards/phpcsdevtools": "^1.0", - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcompatibility/php-compatibility": "^10.0.0@dev", + "phpcsstandards/phpcsdevtools": "^1.2.0", + "phpunit/phpunit": "^8.0 || ^9.0" }, "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.6 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically." + "ext-iconv": "For improved results", + "ext-mbstring": "For improved results" }, "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", @@ -754,6 +2757,7 @@ "keywords": [ "phpcs", "standards", + "static analysis", "wordpress" ], "support": { @@ -761,7 +2765,76 @@ "source": "https://github.com/WordPress/WordPress-Coding-Standards", "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki" }, - "time": "2020-05-13T23:57:56+00:00" + "funding": [ + { + "url": "https://opencollective.com/php_codesniffer", + "type": "custom" + } + ], + "time": "2025-11-25T12:08:04+00:00" + }, + { + "name": "yoast/phpunit-polyfills", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/Yoast/PHPUnit-Polyfills.git", + "reference": "134921bfca9b02d8f374c48381451da1d98402f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/134921bfca9b02d8f374c48381451da1d98402f9", + "reference": "134921bfca9b02d8f374c48381451da1d98402f9", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "phpunit/phpunit": "^7.5 || ^8.0 || ^9.0 || ^11.0 || ^12.0" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "yoast/yoastcs": "^3.1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.x-dev" + } + }, + "autoload": { + "files": [ + "phpunitpolyfills-autoload.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Team Yoast", + "email": "support@yoast.com", + "homepage": "https://yoast.com" + }, + { + "name": "Contributors", + "homepage": "https://github.com/Yoast/PHPUnit-Polyfills/graphs/contributors" + } + ], + "description": "Set of polyfills for changed PHPUnit functionality to allow for creating PHPUnit cross-version compatible tests", + "homepage": "https://github.com/Yoast/PHPUnit-Polyfills", + "keywords": [ + "phpunit", + "polyfill", + "testing" + ], + "support": { + "issues": "https://github.com/Yoast/PHPUnit-Polyfills/issues", + "security": "https://github.com/Yoast/PHPUnit-Polyfills/security/policy", + "source": "https://github.com/Yoast/PHPUnit-Polyfills" + }, + "time": "2025-02-09T18:58:54+00:00" } ], "aliases": [], @@ -774,5 +2847,5 @@ "platform-overrides": { "php": "7.4" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/css/frame.css b/css/frame.css index 4dcef45df..65c73f66a 100644 --- a/css/frame.css +++ b/css/frame.css @@ -53,17 +53,17 @@ /******************************************************************************/ #sidebar { - overflow: auto; + overflow-x: hidden; + overflow-y: auto; position: absolute; - z-index: 75; + z-index: 80; top: 0; right: 0; bottom: 60px; width: 350px; border-left: 1px solid #dfdfdf; background: whitesmoke; - - -webkit-overflow-scrolling: touch; + overscroll-behavior: contain; } .viz-group { @@ -1113,12 +1113,14 @@ button#editor-chart-button { left: 0; width: 100%; opacity: 0; + pointer-events: none; background: rgba(253,253,253,0.9); transition: 0.5s ease; } .only-pro-feature:hover .only-pro-content { opacity: 1; + pointer-events: auto; } .only-pro-container { @@ -1134,10 +1136,11 @@ button#editor-chart-button { flex-direction: column; align-items: center; justify-content: center; + gap: 12px; } .only-pro-content p { - margin: 0 0 15px; + margin: 0; font-size: 14px; font-weight: 700; } @@ -1154,9 +1157,6 @@ button#editor-chart-button { border-style: solid; border-radius: 3px; } -.only-pro-content .only-pro-container a { - color: #fff !important; -} .only-pro-content a:hover { background: #2D419B; diff --git a/index.php b/index.php index 484de429f..41f50ffb1 100644 --- a/index.php +++ b/index.php @@ -36,15 +36,15 @@ * * @since 1.0.0 * - * @param string $class The class name to autoload. + * @param string $class_name The class name to autoload. * * @return boolean Returns TRUE if the class is located. Otherwise FALSE. */ -function visualizer_autoloader( $class ) { +function visualizer_autoloader( $class_name ) { $namespaces = array( 'Visualizer' ); foreach ( $namespaces as $namespace ) { - if ( substr( $class, 0, strlen( $namespace ) ) === $namespace ) { - $filename = dirname( __FILE__ ) . str_replace( '_', DIRECTORY_SEPARATOR, "_classes_{$class}.php" ); + if ( substr( $class_name, 0, strlen( $namespace ) ) === $namespace ) { + $filename = __DIR__ . str_replace( '_', DIRECTORY_SEPARATOR, "_classes_{$class_name}.php" ); if ( is_readable( $filename ) ) { require $filename; @@ -66,7 +66,7 @@ function visualizer_launch() { define( 'VISUALIZER_BASEFILE', __FILE__ ); define( 'VISUALIZER_BASENAME', plugin_basename( __FILE__ ) ); define( 'VISUALIZER_ABSURL', plugins_url( '/', __FILE__ ) ); - define( 'VISUALIZER_ABSPATH', dirname( __FILE__ ) ); + define( 'VISUALIZER_ABSPATH', __DIR__ ); define( 'VISUALIZER_DIRNAME', basename( VISUALIZER_ABSPATH ) ); define( 'VISUALIZER_REST_VERSION', 1 ); // if the below is true, then the js/customization.js in the plugin folder will be used instead of the one in the uploads folder (if it exists). @@ -133,7 +133,7 @@ function visualizer_launch() { $vendor_file = VISUALIZER_ABSPATH . '/vendor/autoload.php'; if ( is_readable( $vendor_file ) ) { - include_once( $vendor_file ); + include_once $vendor_file; } add_filter( 'themeisle_sdk_products', 'visualizer_register_sdk', 10, 1 ); add_filter( 'pirate_parrot_log', 'visualizer_register_parrot', 10, 1 ); @@ -149,7 +149,7 @@ function visualizer_launch() { ); add_filter( 'visualizer_about_us_metadata', - function() { + function () { return array( 'logo' => esc_url( VISUALIZER_ABSURL . 'images/visualizer-logo.svg' ), 'location' => 'visualizer', @@ -164,12 +164,12 @@ function() { add_filter( 'themeisle_sdk_enable_telemetry', '__return_true' ); add_filter( 'themeisle_sdk_telemetry_products', - function( $products ) { + function ( $products ) { $already_registered = false; $license = get_option( 'visualizer_pro_license_data', 'free' ); if ( ! empty( $license ) && is_object( $license ) ) { - $license = $license->key; + $license = $license->key ?? 'free'; } $track_hash = 'free' === $license ? 'free' : wp_hash( $license ); diff --git a/js/frame.js b/js/frame.js index 95abd0ed7..592244d80 100644 --- a/js/frame.js +++ b/js/frame.js @@ -100,8 +100,9 @@ // collapse other open subsections of this section $(document).on('click', '.viz-section-title', function () { var grandparent = $(this).parent().parent(); - grandparent.find('.viz-section-title.open ~ .viz-section-items').hide(); - grandparent.find('.viz-section-title.open').removeClass('open'); + grandparent.find('.viz-section-title.open').not(this).each(function () { + $(this).removeClass('open').siblings('.viz-section-items').hide(); + }); }); $('#view-remote-file').click(function () { diff --git a/js/preview.js b/js/preview.js index 90768cf51..877ecd968 100644 --- a/js/preview.js +++ b/js/preview.js @@ -187,6 +187,10 @@ }); $('textarea[name="manual"]').change(validateJSON).keyup(validateJSON); + $(document).on('change', 'input[name="paging_bool"], input[name="pagination"]', function() { + $('.viz-pagination-options').toggle($(this).is(':checked')); + }); + }); })(jQuery, visualizer); diff --git a/js/render-chartjs.js b/js/render-chartjs.js index 251f92e4d..04f782d3b 100644 --- a/js/render-chartjs.js +++ b/js/render-chartjs.js @@ -148,6 +148,8 @@ } }; + override(settings, chart); + var chartjs = new Chart(context, { type: type, data: { @@ -234,8 +236,6 @@ } handleAxes(settings, chart); - - override(settings, chart); } function handleAxes(settings, chart){ @@ -501,7 +501,7 @@ if (settings.manual) { try{ var options = JSON.parse(settings.manual); - $.extend(settings, options); + $.extend(true, settings, options); delete settings.manual; }catch(error){ console.error("Error while adding manual configuration override " + settings.manual); diff --git a/js/render-facade.js b/js/render-facade.js index 5dfc069a0..9ff2a90c9 100644 --- a/js/render-facade.js +++ b/js/render-facade.js @@ -1,7 +1,8 @@ /* global console */ /* global visualizer */ /* global jQuery */ -var vizClipboard1=null; +window['vizClipboard1'] = window['vizClipboard1'] || null; +window['vizClipboard2'] = window['vizClipboard2'] || null; (function($, visualizer){ function initActionsButtons(v) { @@ -13,12 +14,12 @@ var vizClipboard1=null; }); } - if($('a.visualizer-action[data-visualizer-type=copy]').length > 0) { + if($('a.visualizer-action[data-visualizer-type=copy]').length > 0 && vizClipboard2 === null) { $('a.visualizer-action[data-visualizer-type=copy]').on('click', function(e) { e.preventDefault(); }); - var clipboard = new ClipboardJS('a.visualizer-action[data-visualizer-type=copy]'); // jshint ignore:line - clipboard.on('success', function(e) { + vizClipboard2 = new ClipboardJS('a.visualizer-action[data-visualizer-type=copy]'); // jshint ignore:line + vizClipboard2.on('success', function(e) { window.alert(v.i10n['copied']); }); } diff --git a/js/render-google.js b/js/render-google.js index 3cdcd475f..18ac617b9 100644 --- a/js/render-google.js +++ b/js/render-google.js @@ -31,12 +31,17 @@ var isResizeRequest = false; // remember, some charts do not support annotations so they should not be included in this. var no_annotation_charts = ['tabular', 'timeline', 'gauge', 'geo', 'bubble', 'candlestick']; if ( undefined !== chart.settings && undefined !== chart.settings.series && undefined === chart.settings.series.length ) { - var chartSeries = []; - var chartSeriesValue = Object.values( chart.settings.series ); - $.each( Object.keys( chart.settings.series ), function( index, element ) { - chartSeries[element] = chartSeriesValue[index]; - } ); - chart.settings.series = chartSeries; + var seriesKeys = Object.keys( chart.settings.series ); + // Only convert when keys are numeric indices (PHP JSON-encoded array). + // String keys (e.g. named series from manual config) must be left as-is. + if ( seriesKeys.every( function( k ) { return ! isNaN( k ); } ) ) { + var chartSeries = []; + var chartSeriesValue = Object.values( chart.settings.series ); + $.each( seriesKeys, function( index, element ) { + chartSeries[ element ] = chartSeriesValue[ index ]; + } ); + chart.settings.series = chartSeries; + } } if(id !== 'canvas' && typeof chart.series !== 'undefined' && typeof chart.settings.series !== 'undefined' && ! no_annotation_charts.includes(chart.type) ) { hasAnnotation = chart.series.length - chart.settings.series.length > 1; @@ -444,19 +449,30 @@ var isResizeRequest = false; } var formatter = null; - switch (type) { - case 'number': - formatter = new gv.NumberFormat({pattern: format}); - break; - case 'date': - case 'datetime': - case 'timeofday': - formatter = new gv.DateFormat({pattern: format}); - break; - } + var $formatInput = $('input.control-text[name*="[format]"]').filter(function() { + return $(this).val() === format; + }); + try { + switch (type) { + case 'number': + formatter = new gv.NumberFormat({pattern: format}); + break; + case 'date': + case 'datetime': + case 'timeofday': + formatter = new gv.DateFormat({pattern: format}); + break; + } - if (formatter) { - formatter.format(table, index); + if (formatter) { + formatter.format(table, index); + $formatInput.nextAll('.visualizer-format-error').remove(); + } + } catch (e) { + if ($formatInput.length) { + $formatInput.nextAll('.visualizer-format-error').remove(); + $('

      ').text(visualizer.l10n.invalid_format).insertAfter($formatInput); + } } var arr = id.split('-'); diff --git a/js/simple-editor.js b/js/simple-editor.js index 109b486df..31094f283 100644 --- a/js/simple-editor.js +++ b/js/simple-editor.js @@ -30,6 +30,7 @@ button.html( button.attr( 'data-t-chart' ) ); button.attr( 'data-current', 'chart' ); $('p.viz-editor-selection').show(); + $('p.viz-info-msg').hide(); $('.viz-text-editor').hide(); $('.viz-simple-editor').hide(); $( '#canvas' ).css('z-index', '1').show(); @@ -40,6 +41,7 @@ button.html( button.attr( 'data-t-editor' ) ); button.attr( 'data-current', 'editor' ); $('p.viz-editor-selection').hide(); + $('p.viz-info-msg').show(); $('.viz-text-editor').css('z-index', '9999').show(); $('.viz-simple-editor').css('z-index', '9999').show(); $( '#canvas' ).css('z-index', '-100').hide(); @@ -53,6 +55,7 @@ button.html( button.attr( 'data-t-chart' ) ); button.attr( 'data-current', 'chart' ); $('p.viz-editor-selection').show(); + $('p.viz-info-msg').hide(); $('.viz-text-editor').hide(); $('.viz-simple-editor').hide(); $( '#canvas' ).css('z-index', '1').show(); @@ -74,6 +77,7 @@ button.html( button.attr( 'data-t-chart' ) ); button.attr( 'data-current', 'chart' ); $('p.viz-editor-selection').show(); + $('p.viz-info-msg').hide(); $('.viz-table-editor').hide(); $('.viz-simple-editor').hide(); $( '#canvas' ).css('z-index', '1').show(); @@ -84,6 +88,7 @@ button.html( button.attr( 'data-t-editor' ) ); button.attr( 'data-current', 'editor' ); $('p.viz-editor-selection').hide(); + $('p.viz-info-msg').show(); $( '.viz-table-editor' ).css("z-index", "9999").show(); $('.viz-simple-editor').css('z-index', '9999').show(); $('body').trigger('visualizer:db:editor:table:redraw', {}); @@ -98,6 +103,7 @@ button.html( button.attr( 'data-t-chart' ) ); button.attr( 'data-current', 'chart' ); $('p.viz-editor-selection').show(); + $('p.viz-info-msg').hide(); $('.viz-table-editor').hide(); $('.viz-simple-editor').hide(); $( '#canvas' ).css('z-index', '1').show(); diff --git a/package-lock.json b/package-lock.json index 05915e6f7..0be3f3826 100755 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "visualizer", - "version": "3.11.14", + "version": "3.11.15", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "visualizer", - "version": "3.11.14", + "version": "3.11.15", "license": "GPL-2.0+", "devDependencies": { "@semantic-release/changelog": "^5.0.1", @@ -16,6 +16,8 @@ "@wordpress/env": "^11.0.0", "@wordpress/scripts": "^27.4.0", "conventional-changelog-simple-preset": "^1.0.15", + "grunt": "^1.6.1", + "grunt-cli": "^1.5.0", "grunt-version": "^2.0.0", "grunt-wp-readme-to-markdown": "^2.0.1", "load-project-config": "~0.2.1", @@ -16121,15 +16123,19 @@ } }, "node_modules/findup-sync": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", - "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz", + "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", "dev": true, + "license": "MIT", "dependencies": { - "glob": "~5.0.0" + "detect-file": "^1.0.0", + "is-glob": "^4.0.3", + "micromatch": "^4.0.4", + "resolve-dir": "^1.0.1" }, "engines": { - "node": ">= 0.6.0" + "node": ">= 10.13.0" } }, "node_modules/fined": { @@ -16822,45 +16828,45 @@ "dev": true }, "node_modules/grunt": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.4.0.tgz", - "integrity": "sha512-yRFc0GVCDu9yxqOFzpuXQ2pEdgtLDnFv5Qz54jfIcNnpJ8Z7B7P7kPkT4VMuRvm+N+QOsI8C4v/Q0DSaoj3LgQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.6.1.tgz", + "integrity": "sha512-/ABUy3gYWu5iBmrUSRBP97JLpQUm0GgVveDCp6t3yRNIoltIYw7rEj3g5y1o2PGPR2vfTRGa7WC/LZHLTXnEzA==", "dev": true, + "license": "MIT", "dependencies": { - "dateformat": "~3.0.3", + "dateformat": "~4.6.2", "eventemitter2": "~0.4.13", "exit": "~0.1.2", - "findup-sync": "~0.3.0", + "findup-sync": "~5.0.0", "glob": "~7.1.6", - "grunt-cli": "~1.4.2", - "grunt-known-options": "~1.1.1", + "grunt-cli": "~1.4.3", + "grunt-known-options": "~2.0.0", "grunt-legacy-log": "~3.0.0", "grunt-legacy-util": "~2.0.1", - "iconv-lite": "~0.4.13", + "iconv-lite": "~0.6.3", "js-yaml": "~3.14.0", "minimatch": "~3.0.4", - "mkdirp": "~1.0.4", - "nopt": "~3.0.6", - "rimraf": "~3.0.2" + "nopt": "~3.0.6" }, "bin": { "grunt": "bin/grunt" }, "engines": { - "node": ">=8" + "node": ">=16" } }, "node_modules/grunt-cli": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.4.2.tgz", - "integrity": "sha512-wsu6BZh7KCnfeaSkDrKIAvOlqGKxNRTZjc8xfZlvxCByQIqUfZ31kh5uHpPnhQ4NdVgvaWaVxa1LUbVU80nACw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.5.0.tgz", + "integrity": "sha512-rILKAFoU0dzlf22SUfDtq2R1fosChXXlJM5j7wI6uoW8gwmXDXzbUvirlKZSYCdXl3LXFbR+8xyS+WFo+b6vlA==", "dev": true, + "license": "MIT", "dependencies": { - "grunt-known-options": "~1.1.1", + "grunt-known-options": "~2.0.0", "interpret": "~1.1.0", "liftup": "~3.0.1", - "nopt": "~4.0.1", - "v8flags": "~3.2.0" + "nopt": "~5.0.0", + "v8flags": "^4.0.1" }, "bin": { "grunt": "bin/grunt" @@ -16870,23 +16876,27 @@ } }, "node_modules/grunt-cli/node_modules/nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "dev": true, + "license": "ISC", "dependencies": { - "abbrev": "1", - "osenv": "^0.1.4" + "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" } }, "node_modules/grunt-known-options": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.1.tgz", - "integrity": "sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-2.0.0.tgz", + "integrity": "sha512-GD7cTz0I4SAede1/+pAbmJRG44zFLPipVtdL9o3vqx9IEyb7b4/Y3s7r6ofI3CchR5GvYJ+8buCSioDv5dQLiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -16977,6 +16987,16 @@ "grunt": ">=0.4.0" } }, + "node_modules/grunt/node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/grunt/node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -17016,6 +17036,53 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/grunt/node_modules/grunt-cli": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.4.3.tgz", + "integrity": "sha512-9Dtx/AhVeB4LYzsViCjUQkd0Kw0McN2gYpdmGYKtE2a5Yt7v1Q+HYZVWhqXc/kGnxlMtqKDxSwotiGeFmkrCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "grunt-known-options": "~2.0.0", + "interpret": "~1.1.0", + "liftup": "~3.0.1", + "nopt": "~4.0.1", + "v8flags": "~3.2.0" + }, + "bin": { + "grunt": "bin/grunt" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/grunt/node_modules/grunt-cli/node_modules/nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "1", + "osenv": "^0.1.4" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/grunt/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/grunt/node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", @@ -17029,16 +17096,17 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/grunt/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/grunt/node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" + "license": "MIT", + "dependencies": { + "homedir-polyfill": "^1.0.1" }, "engines": { - "node": ">=10" + "node": ">= 0.10" } }, "node_modules/gzip-size": { @@ -25550,8 +25618,9 @@ "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -25560,7 +25629,9 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "deprecated": "This package is no longer supported.", "dev": true, + "license": "ISC", "dependencies": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.0" @@ -31516,15 +31587,13 @@ } }, "node_modules/v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-4.0.1.tgz", + "integrity": "sha512-fcRLaS4H/hrZk9hYwbdRM35D0U8IYMfEClhXxCivOojl+yTRAZH3Zy2sSy6qVCiGbV9YAtPssP6jaChqC9vPCg==", "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, + "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">= 10.13.0" } }, "node_modules/validate-npm-package-license": { @@ -44193,12 +44262,15 @@ } }, "findup-sync": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", - "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz", + "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", "dev": true, "requires": { - "glob": "~5.0.0" + "detect-file": "^1.0.0", + "is-glob": "^4.0.3", + "micromatch": "^4.0.4", + "resolve-dir": "^1.0.1" } }, "fined": { @@ -44697,28 +44769,32 @@ "dev": true }, "grunt": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.4.0.tgz", - "integrity": "sha512-yRFc0GVCDu9yxqOFzpuXQ2pEdgtLDnFv5Qz54jfIcNnpJ8Z7B7P7kPkT4VMuRvm+N+QOsI8C4v/Q0DSaoj3LgQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.6.1.tgz", + "integrity": "sha512-/ABUy3gYWu5iBmrUSRBP97JLpQUm0GgVveDCp6t3yRNIoltIYw7rEj3g5y1o2PGPR2vfTRGa7WC/LZHLTXnEzA==", "dev": true, "requires": { - "dateformat": "~3.0.3", + "dateformat": "~4.6.2", "eventemitter2": "~0.4.13", "exit": "~0.1.2", - "findup-sync": "~0.3.0", + "findup-sync": "~5.0.0", "glob": "~7.1.6", - "grunt-cli": "~1.4.2", - "grunt-known-options": "~1.1.1", + "grunt-cli": "~1.4.3", + "grunt-known-options": "~2.0.0", "grunt-legacy-log": "~3.0.0", "grunt-legacy-util": "~2.0.1", - "iconv-lite": "~0.4.13", + "iconv-lite": "~0.6.3", "js-yaml": "~3.14.0", "minimatch": "~3.0.4", - "mkdirp": "~1.0.4", - "nopt": "~3.0.6", - "rimraf": "~3.0.2" + "nopt": "~3.0.6" }, "dependencies": { + "dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "dev": true + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -44745,6 +44821,40 @@ "path-is-absolute": "^1.0.0" } }, + "grunt-cli": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.4.3.tgz", + "integrity": "sha512-9Dtx/AhVeB4LYzsViCjUQkd0Kw0McN2gYpdmGYKtE2a5Yt7v1Q+HYZVWhqXc/kGnxlMtqKDxSwotiGeFmkrCoQ==", + "dev": true, + "requires": { + "grunt-known-options": "~2.0.0", + "interpret": "~1.1.0", + "liftup": "~3.0.1", + "nopt": "~4.0.1", + "v8flags": "~3.2.0" + }, + "dependencies": { + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + } + } + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, "js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", @@ -44755,43 +44865,45 @@ "esprima": "^4.0.0" } }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true + "v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } } } }, "grunt-cli": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.4.2.tgz", - "integrity": "sha512-wsu6BZh7KCnfeaSkDrKIAvOlqGKxNRTZjc8xfZlvxCByQIqUfZ31kh5uHpPnhQ4NdVgvaWaVxa1LUbVU80nACw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.5.0.tgz", + "integrity": "sha512-rILKAFoU0dzlf22SUfDtq2R1fosChXXlJM5j7wI6uoW8gwmXDXzbUvirlKZSYCdXl3LXFbR+8xyS+WFo+b6vlA==", "dev": true, "requires": { - "grunt-known-options": "~1.1.1", + "grunt-known-options": "~2.0.0", "interpret": "~1.1.0", "liftup": "~3.0.1", - "nopt": "~4.0.1", - "v8flags": "~3.2.0" + "nopt": "~5.0.0", + "v8flags": "^4.0.1" }, "dependencies": { "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "dev": true, "requires": { - "abbrev": "1", - "osenv": "^0.1.4" + "abbrev": "1" } } } }, "grunt-known-options": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.1.tgz", - "integrity": "sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-2.0.0.tgz", + "integrity": "sha512-GD7cTz0I4SAede1/+pAbmJRG44zFLPipVtdL9o3vqx9IEyb7b4/Y3s7r6ofI3CchR5GvYJ+8buCSioDv5dQLiA==", "dev": true }, "grunt-legacy-log": { @@ -51114,7 +51226,7 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true }, "osenv": { @@ -55495,13 +55607,10 @@ } }, "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-4.0.1.tgz", + "integrity": "sha512-fcRLaS4H/hrZk9hYwbdRM35D0U8IYMfEClhXxCivOojl+yTRAZH3Zy2sSy6qVCiGbV9YAtPssP6jaChqC9vPCg==", + "dev": true }, "validate-npm-package-license": { "version": "3.0.4", diff --git a/package.json b/package.json index 6295b182b..19943cbad 100755 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "env:up": "export DOCKER_FILE=docker-compose.ci.yml && bash bin/wp-init.sh", "env:down": "export DOCKER_FILE=docker-compose.ci.yml && bash bin/wp-down.sh", "wp-env": "wp-env", + "grunt": "grunt", "test:env:start": "wp-env start", "test:env:stop": "wp-env stop", "test:env:clean": "wp-env clean", @@ -41,6 +42,8 @@ "@wordpress/env": "^11.0.0", "@wordpress/scripts": "^27.4.0", "conventional-changelog-simple-preset": "^1.0.15", + "grunt": "^1.6.1", + "grunt-cli": "^1.5.0", "grunt-version": "^2.0.0", "grunt-wp-readme-to-markdown": "^2.0.1", "load-project-config": "~0.2.1", diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index a96b74d51..2b3373401 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -7,7 +7,7 @@ parameters: path: classes/Visualizer/Gutenberg/Block.php - - message: '#^Call to function is_wp_error\(\) with string will always evaluate to false\.$#' + message: '#^Call to function is_wp_error\(\) with non\-empty\-string will always evaluate to false\.$#' identifier: function.impossibleType count: 1 path: classes/Visualizer/Gutenberg/Block.php @@ -36,12 +36,6 @@ parameters: count: 1 path: classes/Visualizer/Gutenberg/Block.php - - - message: '#^Method Visualizer_Gutenberg_Block\:\:add_rest_query_vars\(\) has parameter \$request with generic class WP_REST_Request but does not specify its types\: T$#' - identifier: missingType.generics - count: 1 - path: classes/Visualizer/Gutenberg/Block.php - - message: '#^Method Visualizer_Gutenberg_Block\:\:enqueue_gutenberg_scripts\(\) has no return type specified\.$#' identifier: missingType.return @@ -204,6 +198,12 @@ parameters: count: 1 path: classes/Visualizer/Gutenberg/Block.php + - + message: '#^Unable to resolve the template type TUrl in call to function wp_http_validate_url$#' + identifier: argument.templateType + count: 1 + path: classes/Visualizer/Gutenberg/Block.php + - message: '#^Constant VISUALIZER_PRO_VERSION not found\.$#' identifier: constant.notFound @@ -295,7 +295,7 @@ parameters: path: classes/Visualizer/Module.php - - message: '#^Method Visualizer_Module\:\:getDataAs\(\) has parameter \$final with no type specified\.$#' + message: '#^Method Visualizer_Module\:\:getDataAs\(\) has parameter \$data with no type specified\.$#' identifier: missingType.parameter count: 1 path: classes/Visualizer/Module.php @@ -1386,6 +1386,12 @@ parameters: count: 1 path: classes/Visualizer/Module/Chart.php + - + message: '#^Unable to resolve the template type TUrl in call to function wp_http_validate_url$#' + identifier: argument.templateType + count: 1 + path: classes/Visualizer/Module/Chart.php + - message: '#^Undefined variable\: \$atts$#' identifier: variable.undefined @@ -1512,12 +1518,6 @@ parameters: count: 1 path: classes/Visualizer/Module/Frontend.php - - - message: '#^Method Visualizer_Module_Frontend\:\:perform_action\(\) has parameter \$params with generic class WP_REST_Request but does not specify its types\: T$#' - identifier: missingType.generics - count: 1 - path: classes/Visualizer/Module/Frontend.php - - message: '#^Method Visualizer_Module_Frontend\:\:printFooterScripts\(\) has no return type specified\.$#' identifier: missingType.return @@ -2034,12 +2034,6 @@ parameters: count: 1 path: classes/Visualizer/Module/Wizard.php - - - message: '#^Path in include_once\(\) "\./wp\-admin/includes/plugin\-install\.php" is not a file or it does not exist\.$#' - identifier: includeOnce.fileNotFound - count: 1 - path: classes/Visualizer/Module/Wizard.php - - message: '#^Property Visualizer_Module_Wizard\:\:\$wizard_data has no type specified\.$#' identifier: missingType.property @@ -2743,7 +2737,7 @@ parameters: path: classes/Visualizer/Render/Sidebar.php - - message: '#^Method Visualizer_Render_Sidebar\:\:_renderCheckboxItem\(\) has parameter \$default with no type specified\.$#' + message: '#^Method Visualizer_Render_Sidebar\:\:_renderCheckboxItem\(\) has parameter \$default_value with no type specified\.$#' identifier: missingType.parameter count: 1 path: classes/Visualizer/Render/Sidebar.php @@ -3421,7 +3415,7 @@ parameters: path: classes/Visualizer/Render/Sidebar/Graph.php - - message: '#^Parameter \#4 \$default of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' + message: '#^Parameter \#4 \$default_color of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' identifier: argument.type count: 3 path: classes/Visualizer/Render/Sidebar/Graph.php @@ -3517,7 +3511,7 @@ parameters: path: classes/Visualizer/Render/Sidebar/Linear.php - - message: '#^Parameter \#4 \$default of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' + message: '#^Parameter \#4 \$default_color of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' identifier: argument.type count: 1 path: classes/Visualizer/Render/Sidebar/Linear.php @@ -3547,7 +3541,7 @@ parameters: path: classes/Visualizer/Render/Sidebar/Type/ChartJS/Bar.php - - message: '#^Parameter \#4 \$default of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' + message: '#^Parameter \#4 \$default_color of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' identifier: argument.type count: 3 path: classes/Visualizer/Render/Sidebar/Type/ChartJS/Bar.php @@ -3583,7 +3577,7 @@ parameters: path: classes/Visualizer/Render/Sidebar/Type/ChartJS/Line.php - - message: '#^Parameter \#4 \$default of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' + message: '#^Parameter \#4 \$default_color of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' identifier: argument.type count: 2 path: classes/Visualizer/Render/Sidebar/Type/ChartJS/Line.php @@ -3691,7 +3685,7 @@ parameters: path: classes/Visualizer/Render/Sidebar/Type/ChartJS/Pie.php - - message: '#^Parameter \#4 \$default of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' + message: '#^Parameter \#4 \$default_color of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' identifier: argument.type count: 4 path: classes/Visualizer/Render/Sidebar/Type/ChartJS/Pie.php @@ -3702,168 +3696,6 @@ parameters: count: 1 path: classes/Visualizer/Render/Sidebar/Type/ChartJS/Pie.php - - - message: '#^Access to an undefined property Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:\$__series\.$#' - identifier: property.notFound - count: 2 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Access to an undefined property Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:\$_includeCurveTypes\.$#' - identifier: property.notFound - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Access to an undefined property Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:\$description\.$#' - identifier: property.notFound - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Access to an undefined property Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:\$fixedHeader_bool\.$#' - identifier: property.notFound - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Access to an undefined property Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:\$ordering_bool\.$#' - identifier: property.notFound - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Access to an undefined property Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:\$pageLength_int\.$#' - identifier: property.notFound - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Access to an undefined property Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:\$pagingType\.$#' - identifier: property.notFound - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Access to an undefined property Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:\$paging_bool\.$#' - identifier: property.notFound - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Access to an undefined property Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:\$responsive_bool\.$#' - identifier: property.notFound - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Access to an undefined property Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:\$scrollX\.$#' - identifier: property.notFound - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Access to an undefined property Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:\$title\.$#' - identifier: property.notFound - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Method Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:__construct\(\) has parameter \$data with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Method Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:_renderAdvancedSettings\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Method Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:_renderColumnSettings\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Method Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:_renderFormatField\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Method Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:_renderGeneralSettings\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Method Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:_renderTableSettings\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Method Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:_toHTML\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Method Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:enqueue_assets\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Method Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:enqueue_assets\(\) has parameter \$deps with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Method Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:hooks\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Method Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:load_assets\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Method Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:load_assets\(\) has parameter \$deps with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Method Visualizer_Render_Sidebar_Type_DataTable_DataTable\:\:load_assets\(\) has parameter \$is_frontend with no type specified\.$#' - identifier: missingType.parameter - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Parameter \#4 \$default of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' - identifier: argument.type - count: 8 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Parameter \#4 \$desc of static method Visualizer_Render_Sidebar\:\:_renderTextItem\(\) expects string, null given\.$#' - identifier: argument.type - count: 4 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - - - message: '#^Parameter \#5 \$placeholder of static method Visualizer_Render_Sidebar\:\:_renderTextItem\(\) expects string, int given\.$#' - identifier: argument.type - count: 1 - path: classes/Visualizer/Render/Sidebar/Type/DataTable/DataTable.php - - message: '#^Access to an undefined property Visualizer_Render_Sidebar_Type_DataTable_Tabular\:\:\$__series\.$#' identifier: property.notFound @@ -4009,7 +3841,7 @@ parameters: path: classes/Visualizer/Render/Sidebar/Type/DataTable/Tabular.php - - message: '#^Parameter \#4 \$default of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' + message: '#^Parameter \#4 \$default_color of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' identifier: argument.type count: 8 path: classes/Visualizer/Render/Sidebar/Type/DataTable/Tabular.php @@ -4063,7 +3895,7 @@ parameters: path: classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Area.php - - message: '#^Parameter \#4 \$default of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' + message: '#^Parameter \#4 \$default_color of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' identifier: argument.type count: 1 path: classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Area.php @@ -4111,7 +3943,7 @@ parameters: path: classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Bubble.php - - message: '#^Parameter \#4 \$default of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' + message: '#^Parameter \#4 \$default_color of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' identifier: argument.type count: 1 path: classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Bubble.php @@ -4159,7 +3991,7 @@ parameters: path: classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Candlestick.php - - message: '#^Parameter \#4 \$default of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' + message: '#^Parameter \#4 \$default_color of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' identifier: argument.type count: 5 path: classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Candlestick.php @@ -4459,7 +4291,7 @@ parameters: path: classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Geo.php - - message: '#^Parameter \#4 \$default of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' + message: '#^Parameter \#4 \$default_color of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' identifier: argument.type count: 1 path: classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Geo.php @@ -4573,7 +4405,7 @@ parameters: path: classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Pie.php - - message: '#^Parameter \#4 \$default of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' + message: '#^Parameter \#4 \$default_color of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' identifier: argument.type count: 1 path: classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Pie.php @@ -4699,7 +4531,7 @@ parameters: path: classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Tabular.php - - message: '#^Parameter \#4 \$default of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' + message: '#^Parameter \#4 \$default_color of static method Visualizer_Render_Sidebar\:\:_renderColorPickerItem\(\) expects string, null given\.$#' identifier: argument.type count: 14 path: classes/Visualizer/Render/Sidebar/Type/GoogleCharts/Tabular.php @@ -5041,7 +4873,7 @@ parameters: path: classes/Visualizer/Source/Json.php - - message: '#^Method Visualizer_Source_Json\:\:getNextPage\(\) has parameter \$array with no type specified\.$#' + message: '#^Method Visualizer_Source_Json\:\:getNextPage\(\) has parameter \$data with no type specified\.$#' identifier: missingType.parameter count: 1 path: classes/Visualizer/Source/Json.php @@ -5059,7 +4891,7 @@ parameters: path: classes/Visualizer/Source/Json.php - - message: '#^Method Visualizer_Source_Json\:\:getRootElements\(\) has parameter \$array with no type specified\.$#' + message: '#^Method Visualizer_Source_Json\:\:getRootElements\(\) has parameter \$data with no type specified\.$#' identifier: missingType.parameter count: 1 path: classes/Visualizer/Source/Json.php @@ -5071,7 +4903,7 @@ parameters: path: classes/Visualizer/Source/Json.php - - message: '#^Method Visualizer_Source_Json\:\:getRootElements\(\) has parameter \$parent with no type specified\.$#' + message: '#^Method Visualizer_Source_Json\:\:getRootElements\(\) has parameter \$parent_key with no type specified\.$#' identifier: missingType.parameter count: 1 path: classes/Visualizer/Source/Json.php diff --git a/phpstan.neon b/phpstan.neon index d0545aa5c..971b4a6ce 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,6 @@ parameters: level: 6 + reportUnmatchedIgnoredErrors: false paths: - %currentWorkingDirectory%/index.php - %currentWorkingDirectory%/classes @@ -10,10 +11,6 @@ parameters: - %currentWorkingDirectory%/vendor/neitanod/forceutf8 - %currentWorkingDirectory%/vendor/openspout/openspout - %currentWorkingDirectory%/vendor/codeinwp/themeisle-sdk - ignoreErrors: - - - identifiers: - - requireOnce.fileNotFound includes: - %currentWorkingDirectory%/vendor/szepeviktor/phpstan-wordpress/extension.neon - %currentWorkingDirectory%/phpstan-baseline.neon diff --git a/templates/support.php b/templates/support.php index 31b570b00..07e8c043f 100644 --- a/templates/support.php +++ b/templates/support.php @@ -21,17 +21,17 @@ class="dashicons dashicons-cart">More features
      diff --git a/tests/bootstrap.php b/tests/bootstrap.php index dd2ad1e19..230071c9a 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -5,6 +5,11 @@ * @package Visualizer */ $_tests_dir = getenv( 'WP_TESTS_DIR' ); + +if ( class_exists( '\Yoast\PHPUnitPolyfills\Autoload' ) === false ) { + require_once dirname( dirname( __FILE__ ) ) . '/vendor/yoast/phpunit-polyfills/phpunitpolyfills-autoload.php'; +} + if ( ! $_tests_dir ) { $_tests_dir = '/tmp/wordpress-tests-lib'; } diff --git a/tests/test-ajax.php b/tests/test-ajax.php index 11fb33962..1b197b603 100644 --- a/tests/test-ajax.php +++ b/tests/test-ajax.php @@ -84,8 +84,8 @@ public function test_ajax_response_get_query_data_valid_query() { $response = json_decode( $this->_last_response ); $this->assertIsObject( $response ); - $this->assertObjectHasAttribute( 'success', $response ); - $this->assertObjectHasAttribute( 'data', $response ); + $this->assertTrue( property_exists( $response, 'success' ) ); + $this->assertTrue( property_exists( $response, 'data' ) ); $this->assertTrue( $response->success ); } @@ -112,8 +112,8 @@ public function test_ajax_response_get_query_data_invalid_query() { $response = json_decode( $this->_last_response ); $this->assertIsObject( $response ); - $this->assertObjectHasAttribute( 'success', $response ); - $this->assertObjectHasAttribute( 'data', $response ); + $this->assertTrue( property_exists( $response, 'success' ) ); + $this->assertTrue( property_exists( $response, 'data' ) ); $this->assertEquals( 'Only SELECT queries are allowed', $response->data->msg ); $this->assertFalse( $response->success ); } @@ -141,8 +141,8 @@ public function test_ajax_response_get_query_data_valid_query_with_filtered_colu $response = json_decode( $this->_last_response ); $this->assertIsObject( $response ); - $this->assertObjectHasAttribute( 'success', $response ); - $this->assertObjectHasAttribute( 'data', $response ); + $this->assertTrue( property_exists( $response, 'success' ) ); + $this->assertTrue( property_exists( $response, 'data' ) ); $this->assertFalse( $response->success ); $this->assertTrue( strpos( $response->data->msg, ".wp_insert' doesn't exist" ) !== false ); } @@ -169,8 +169,8 @@ public function test_ajax_response_get_query_data_contributor_dissallow() { $response = json_decode( $this->_last_response ); $this->assertIsObject( $response ); - $this->assertObjectHasAttribute( 'success', $response ); - $this->assertObjectHasAttribute( 'data', $response ); + $this->assertTrue( property_exists( $response, 'success' ) ); + $this->assertTrue( property_exists( $response, 'data' ) ); $this->assertEquals( 'Action not allowed for this user.', $response->data->msg ); $this->assertFalse( $response->success ); } @@ -197,8 +197,8 @@ public function test_ajax_response_get_query_data_subcriber_dissallow() { $response = json_decode( $this->_last_response ); $this->assertIsObject( $response ); - $this->assertObjectHasAttribute( 'success', $response ); - $this->assertObjectHasAttribute( 'data', $response ); + $this->assertTrue( property_exists( $response, 'success' ) ); + $this->assertTrue( property_exists( $response, 'data' ) ); $this->assertEquals( 'Action not allowed for this user.', $response->data->msg ); $this->assertFalse( $response->success ); } @@ -226,8 +226,8 @@ public function test_ajax_response_get_query_data_invalid_query_subquery() { $response = json_decode( $this->_last_response ); $this->assertIsObject( $response ); - $this->assertObjectHasAttribute( 'success', $response ); - $this->assertObjectHasAttribute( 'data', $response ); + $this->assertTrue( property_exists( $response, 'success' ) ); + $this->assertTrue( property_exists( $response, 'data' ) ); $this->assertEquals( 'Only SELECT queries are allowed', $response->data->msg ); $this->assertFalse( $response->success ); } @@ -255,8 +255,8 @@ public function test_ajax_response_get_query_data_invalid_query_comment() { $response = json_decode( $this->_last_response ); $this->assertIsObject( $response ); - $this->assertObjectHasAttribute( 'success', $response ); - $this->assertObjectHasAttribute( 'data', $response ); + $this->assertTrue( property_exists( $response, 'success' ) ); + $this->assertTrue( property_exists( $response, 'data' ) ); $this->assertEquals( 'Only SELECT queries are allowed', $response->data->msg ); $this->assertFalse( $response->success ); } @@ -296,8 +296,8 @@ public function test_sql_save_chart_subscriber() { $response = json_decode( $this->_last_response ); $this->assertIsObject( $response ); - $this->assertObjectHasAttribute( 'success', $response ); - $this->assertObjectHasAttribute( 'data', $response ); + $this->assertTrue( property_exists( $response, 'success' ) ); + $this->assertTrue( property_exists( $response, 'data' ) ); $this->assertEquals( 'Action not allowed for this user.', $response->data->msg ); $this->assertFalse( $response->success ); } @@ -324,8 +324,8 @@ public function test_sql_save_chart_admin() { $response = json_decode( $this->_last_response ); $this->assertIsObject( $response ); - $this->assertObjectHasAttribute( 'success', $response ); - $this->assertObjectHasAttribute( 'data', $response ); + $this->assertTrue( property_exists( $response, 'success' ) ); + $this->assertTrue( property_exists( $response, 'data' ) ); $this->assertEquals( 'Feature is not available.', $response->data->msg ); $this->assertFalse( $response->success ); } diff --git a/tests/test-export.php b/tests/test-export.php index 3452ebab6..7f47aeb60 100644 --- a/tests/test-export.php +++ b/tests/test-export.php @@ -58,35 +58,109 @@ private function create_chart() { $this->chart = $query->posts[0]; } + /** + * Runs the export AJAX action and returns the decoded response. + * + * @since 3.11.0 + * + * @access private + * @return object|null + */ + private function run_export() { + $_GET = array( + 'security' => wp_create_nonce( Visualizer_Plugin::ACTION_EXPORT_DATA . Visualizer_Plugin::VERSION ), + 'chart' => $this->chart, + ); + + ob_start(); + try { + $this->_handleAjax( 'visualizer-export-data' ); + } catch ( WPAjaxDieContinueException $e ) { + // We expected this, do nothing. + } catch ( WPAjaxDieStopException $ee ) { + // We expected this, do nothing. + } + ob_end_clean(); + + return json_decode( $this->_last_response ); + } + /** * Testing export * + * @since 2.0.0 + * * @access public */ public function test_download_export() { $this->create_chart(); $this->_setRole( 'administrator' ); - $_GET = array( - 'security' => wp_create_nonce( Visualizer_Plugin::ACTION_EXPORT_DATA . Visualizer_Plugin::VERSION ), - 'chart' => $this->chart, + $response = $this->run_export(); + $this->assertIsObject( $response ); + $this->assertTrue( property_exists( $response, 'success' ) ); + $this->assertTrue( property_exists( $response, 'data' ) ); + $this->assertTrue( $response->success ); + } + + /** + * CSV response contains the expected keys from _getCSV. + * + * @since 3.11.0 + * + * @access public + */ + public function test_csv_export_response_structure() { + $this->create_chart(); + $this->_setRole( 'administrator' ); + + $response = $this->run_export(); + $this->assertIsObject( $response ); + $this->assertTrue( property_exists( $response, 'success' ) ); + $this->assertTrue( property_exists( $response, 'data' ) ); + $this->assertTrue( $response->success ); + + $data = $response->data; + $this->assertTrue( property_exists( $data, 'csv' ) ); + $this->assertTrue( property_exists( $data, 'name' ) ); + $this->assertTrue( property_exists( $data, 'string' ) ); + $this->assertIsString( $data->csv ); + $this->assertIsString( $data->name ); + $this->assertIsString( $data->string ); + // filename must end with .csv + $this->assertStringEndsWith( '.csv', $data->name ); + // string is csv without the BOM + $bom = chr( 0xEF ) . chr( 0xBB ) . chr( 0xBF ); + $this->assertStringNotContainsString( $bom, $data->string ); + } + + /** + * Export must fail gracefully for non-existent chart ids. + * + * @since 3.11.0 + * + * @access public + */ + public function test_csv_export_invalid_chart_returns_no_success() { + $this->_setRole( 'administrator' ); + + $_GET = array( + 'security' => wp_create_nonce( Visualizer_Plugin::ACTION_EXPORT_DATA . Visualizer_Plugin::VERSION ), + 'chart' => PHP_INT_MAX, ); - // swallow the output ob_start(); try { $this->_handleAjax( 'visualizer-export-data' ); - } catch ( WPAjaxDieContinueException $e ) { + } catch ( WPAjaxDieContinueException $e ) { // We expected this, do nothing. } catch ( WPAjaxDieStopException $ee ) { // We expected this, do nothing. } ob_end_clean(); + // No success JSON should have been emitted for a missing chart. $response = json_decode( $this->_last_response ); - $this->assertIsObject( $response ); - $this->assertObjectHasAttribute( 'success', $response ); - $this->assertObjectHasAttribute( 'data', $response ); - $this->assertTrue( $response->success ); + $this->assertTrue( empty( $response ) || empty( $response->success ) ); } }