diff --git a/.eslintrc.js b/.eslintrc.js index 7d2e8b509e5..7978d61f289 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -78,7 +78,6 @@ module.exports = { 'amp-settings', 'amp-themes', 'amp-plugins', - 'amp-support', 'amp-block-validation', 'amp-site-scan-notice', ], diff --git a/.github/workflows/build-test-measure.yml b/.github/workflows/build-test-measure.yml index a3943e7dc46..74ee4579318 100644 --- a/.github/workflows/build-test-measure.yml +++ b/.github/workflows/build-test-measure.yml @@ -573,197 +573,3 @@ jobs: - name: Run tests run: ./vendor/bin/behat - -#----------------------------------------------------------------------------------------------------------------------- - -# build-zip: -# name: 'Build: ${{ matrix.build }} build ZIP' -# needs: pre-run -# # Only run if the PR was not authored by Dependabot and it is not a draft or not from a fork. -# if: > -# needs.pre-run.outputs.changed-file-count > 0 && -# github.event.pull_request.draft == false && -# github.event.pull_request.head.repo.fork == false && -# github.event.pull_request.user.login != 'dependabot[bot]' -# runs-on: ubuntu-latest -# permissions: -# actions: write -# outputs: -# branch-name: ${{ steps.retrieve-branch-name.outputs.branch_name }} -# git-sha-8: ${{ steps.retrieve-git-sha-8.outputs.sha8 }} -# strategy: -# matrix: -# build: ['dev', 'prod'] -# steps: -# - name: Checkout -# uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 -# -# - name: Setup NodeJS and NPM -# uses: ./.github/actions/setup-node-npm -# -# - name: Setup PHP and Composer -# uses: ./.github/actions/setup-php-composer -# with: -# php-version: '7.4' -# -# - name: Create destination directories -# run: mkdir -p builds/${{ matrix.build }} -# -# - name: Build plugin -# run: | -# npm run package:${{ matrix.build }} -# mv amp.zip builds/${{ matrix.build }}/amp.zip -# env: -# LAST_PR_COMMIT_HASH: ${{ github.event.pull_request.head.sha }} -# -# - name: Generate checksum file -# working-directory: builds/${{ matrix.build }} -# run: | -# mkdir -p $RUNNER_TEMP/plugin-checksums -# find . -type f -print0 | sort -z | xargs -r0 shasum -a 256 -b | sed 's# \*\./# *#' > $RUNNER_TEMP/plugin-checksums/checksums.txt -# shasum -a 256 -U -c $RUNNER_TEMP/plugin-checksums/checksums.txt -# cat $RUNNER_TEMP/plugin-checksums/checksums.txt | while read sum file; do echo "$sum $file" > ${file#\*}.sha256; done -# -# - name: Retrieve branch name -# id: retrieve-branch-name -# run: echo "branch_name=$(REF=${GITHUB_HEAD_REF:-$GITHUB_REF} && echo ${REF#refs/heads/} | sed 's/\//-/g')" >> $GITHUB_OUTPUT -# -# - name: Retrieve git SHA-8 string -# id: retrieve-git-sha-8 -# run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT -# -# - name: Upload build as artifact -# uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 #v4.4.3 -# with: -# name: amp-${{ steps.retrieve-branch-name.outputs.branch_name }}-${{ steps.retrieve-git-sha-8.outputs.sha8 }}-${{ matrix.build }} -# path: builds/${{ matrix.build }} - -#----------------------------------------------------------------------------------------------------------------------- - -# upload-to-gcs: -# name: Upload plugin ZIPs to Google Cloud Storage -# runs-on: ubuntu-latest -# permissions: -# actions: write -# needs: -# - build-zip -# outputs: -# dev-checksum: ${{ steps.output-checksums.outputs.dev-checksum }} -# prod-checksum: ${{ steps.output-checksums.outputs.prod-checksum }} -# steps: -# - name: Download dev build -# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e #v4.1.7 -# with: -# name: amp-${{ needs.build-zip.outputs.branch-name }}-${{ needs.build-zip.outputs.git-sha-8 }}-dev -# path: builds/dev -# -# - name: Download prod build -# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e #v4.1.7 -# with: -# name: amp-${{ needs.build-zip.outputs.branch-name }}-${{ needs.build-zip.outputs.git-sha-8 }}-prod -# path: builds/prod -# -# - name: Setup Google Cloud SDK -# uses: google-github-actions/setup-gcloud@20c93dacc1d70ddbce76c63ab32c35595345bdd1 #v0 -# with: -# project_id: ${{ secrets.GCS_PROJECT_ID }} -# service_account_key: ${{ secrets.GCS_APPLICATION_CREDENTIALS }} -# -# - name: Output checksums -# id: output-checksums -# run: | -# echo "dev-checksum=$(cat builds/dev/*.sha256)" >> $GITHUB_OUTPUT -# echo "prod-checksum=$(cat builds/prod/*.sha256)" >> $GITHUB_OUTPUT -# -# - name: Upload dev build to bucket -# run: gsutil cp -r builds/dev/amp.zip gs://ampwp_github_artifacts/${{ github.ref }}/dev/amp.zip -# -# - name: Upload dev build checksums to bucket -# if: ${{ github.ref == 'refs/heads/develop' }} -# run: gsutil cp -r builds/dev/*.sha256 gs://ampwp_github_artifacts/${{ github.ref }}/dev/ -# -# - name: Upload prod build to bucket -# run: gsutil cp -r builds/prod/amp.zip gs://ampwp_github_artifacts/${{ github.ref }}/prod/amp.zip -# -# - name: Upload prod build checksums to bucket -# if: ${{ github.ref == 'refs/heads/develop' }} -# run: gsutil cp -r builds/prod/*.sha256 gs://ampwp_github_artifacts/${{ github.ref }}/prod/ - -#----------------------------------------------------------------------------------------------------------------------- - -# comment-on-pr: -# name: Comment on PR with links to plugin ZIPs -# # Only run this job if it's a PR. One way to check for that is if `github.head_ref` is not empty. -# if: ${{ github.head_ref && github.head_ref != null }} -# runs-on: ubuntu-latest -# needs: upload-to-gcs -# permissions: -# pull-requests: write -# steps: -# - name: Check if a comment was already made -# id: find-comment -# uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 -# with: -# script: | -# const { data: comments } = await github.rest.issues.listComments({ -# owner: context.repo.owner, -# repo: context.repo.repo, -# issue_number: context.issue.number, -# }); -# -# const comment = comments.find((comment) => comment.body.includes('Plugin builds for')); -# -# return comment ? comment.id : null; -# -# - name: Get comment body -# id: get-comment-body -# # Setting a multi-line output requires escaping line-feeds. See . -# run: | -# body="Plugin builds for ${{ github.event.pull_request.head.sha }} are ready :bellhop_bell:! -# - Download [development build](https://storage.googleapis.com/ampwp_github_artifacts/${{ github.ref }}/dev/amp.zip?${{ github.sha }}) -# - Download [production build](https://storage.googleapis.com/ampwp_github_artifacts/${{ github.ref }}/prod/amp.zip?${{ github.sha }}) -# -#
-# Checksums -# -#
-#          # Development build checksums
-#          ${{ needs.upload-to-gcs.outputs.dev-checksum }}
-#
-#          # Production build checksums
-#          ${{ needs.upload-to-gcs.outputs.prod-checksum }}
-#          
-# -#
-# -# > [!WARNING] -# > These builds are for testing purposes only and should not be used in production." -# -# delimiter="${body//$'\n'/'%0A'}" -# echo "body<<${delimiter}" >> $GITHUB_OUTPUT -# echo "$body" >> $GITHUB_OUTPUT -# echo "${delimiter}" >> $GITHUB_OUTPUT -# -# - name: Create comment on PR with links to plugin builds -# if: ${{ steps.find-comment.outputs.result == 'null' }} -# uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 -# with: -# script: | -# github.rest.issues.createComment({ -# owner: context.repo.owner, -# repo: context.repo.repo, -# issue_number: context.issue.number, -# body: `${{ steps.get-comment-body.outputs.body }}`, -# }); -# -# - name: Update comment on PR with links to plugin builds -# if: ${{ steps.find-comment.outputs.result != 'null' }} -# uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 -# with: -# script: | -# github.rest.issues.updateComment({ -# owner: context.repo.owner, -# repo: context.repo.repo, -# comment_id: ${{ steps.find-comment.outputs.result }}, -# body: `${{ steps.get-comment-body.outputs.body }}`, -# }); diff --git a/.phpstorm.meta.php b/.phpstorm.meta.php index a1a9ce1089f..31cfe09e52f 100644 --- a/.phpstorm.meta.php +++ b/.phpstorm.meta.php @@ -15,7 +15,6 @@ 'admin.options_menu' => \AmpProject\AmpWP\Admin\OptionsMenu::class, 'admin.paired_browsing' => \AmpProject\AmpWP\Admin\PairedBrowsing::class, 'admin.plugin_row_meta' => \AmpProject\AmpWP\Admin\PluginRowMeta::class, - 'admin.support_screen' => \AmpProject\AmpWP\Admin\SupportScreen::class, 'admin.support' => \AmpProject\AmpWP\Admin\SupportLink::class, 'admin.polyfills' => \AmpProject\AmpWP\Admin\Polyfills::class, 'admin.user_rest_endpoint_extension' => \AmpProject\AmpWP\Admin\UserRESTEndpointExtension::class, @@ -59,8 +58,6 @@ 'sandboxing' => \AmpProject\AmpWP\Sandboxing::class, 'server_timing' => \AmpProject\AmpWP\Instrumentation\ServerTiming::class, 'site_health_integration' => \AmpProject\AmpWP\Admin\SiteHealth::class, - 'support' => \AmpProject\AmpWP\Support\SupportCliCommand::class, - 'support_rest_controller' => \AmpProject\AmpWP\Support\SupportRESTController::class, 'url_validation_cron' => \AmpProject\AmpWP\Validation\URLValidationCron::class, 'url_validation_rest_controller' => \AmpProject\AmpWP\Validation\URLValidationRESTController::class, 'validated_url_stylesheet_gc' => \AmpProject\AmpWP\BackgroundTask\ValidatedUrlStylesheetDataGarbageCollection::class, diff --git a/assets/src/components/amp-support/details.js b/assets/src/components/amp-support/details.js deleted file mode 100644 index 65ff59ee33f..00000000000 --- a/assets/src/components/amp-support/details.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * External dependencies - */ -import PropTypes from 'prop-types'; - -/** - * Wrapper component to render
. - * - * @param {Object} props Component props. - * @param {boolean} props.open Flag to whether open summary or not. - * @param {string} props.title Title of details. - * @param {string} props.description Description message. - * @return {JSX.Element|null} HTML markup. - */ -export function Details({ open = false, title, description }) { - return ( - title && - description && ( -
- {title} -
-

{description}

-
-
- ) - ); -} - -Details.propTypes = { - open: PropTypes.bool, - title: PropTypes.string.isRequired, - description: PropTypes.string.isRequired, -}; diff --git a/assets/src/components/amp-support/index.js b/assets/src/components/amp-support/index.js deleted file mode 100644 index d8568f84593..00000000000 --- a/assets/src/components/amp-support/index.js +++ /dev/null @@ -1,237 +0,0 @@ -/** - * External dependencies - */ -import PropTypes from 'prop-types'; - -/** - * WordPress dependencies - */ -import { - createInterpolateElement, - useState, - useEffect, -} from '@wordpress/element'; -import { Button, ExternalLink } from '@wordpress/components'; -import apiFetch from '@wordpress/api-fetch'; -import { __, sprintf } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import './style.scss'; -import { Selectable } from '../selectable'; -import { - AMPNotice, - NOTICE_SIZE_SMALL, - NOTICE_TYPE_ERROR, - NOTICE_TYPE_INFO, -} from '../amp-notice'; -import ClipboardButton from '../clipboard-button'; -import { Details } from './details'; -import { Plugins } from './plugins'; -import { RawData } from './raw-data'; -import { SiteInfo } from './site-info'; -import { Themes } from './themes'; -import { ValidatedUrls } from './validated-urls'; -import { ValidationResultsNotice } from './validation-results-notice'; - -/** - * AMP Support component. - * - * @param {Object} props Props for component. - * @return {JSX.Element} Markup for AMP support component - */ -export function AMPSupport(props) { - const { data, restEndpoint, args, ampValidatedPostCount } = props; - - const [sending, setSending] = useState(false); - const [uuid, setUuid] = useState(null); - const [error, setError] = useState(null); - const [hasCopied, setHasCopied] = useState(false); - const [submitSupportRequest, setSubmitSupportRequest] = useState(false); - - /** - * Event callback for send button. - */ - useEffect(() => { - (async () => { - if (!submitSupportRequest || uuid || sending) { - return; - } - - setSending(true); - setUuid(null); - setError(null); - - try { - const response = await apiFetch({ - url: restEndpoint, - method: 'POST', - data: { - args, - }, - }); - - if ( - undefined !== response.success && - undefined !== response?.data?.uuid - ) { - setUuid(response.data.uuid); - } else { - throw new Error( - __( - 'Failed to send support request. Please try again later.', - 'amp' - ) - ); - } - } catch (exception) { - setSubmitSupportRequest(false); - setError(exception.message); - } finally { - setSending(false); - } - })(); - }, [submitSupportRequest, uuid, sending, restEndpoint, args]); - - return ( -
- -

- {__('AMP Support', 'amp')} -

-

- {createInterpolateElement( - __( - 'In order to best assist you, please tap the Send Data button below to send the following site information to our private database. Once you have done so, copy the the resulting Support UUID in the blue box that appears and include the ID in a new support forum topic. You do not have to submit data to get support, but our team will be able to help you more effectively if you do so.', - 'amp' - ), - { - a: ( - // eslint-disable-next-line jsx-a11y/anchor-has-content -- Anchor has content defined in the translated string. - - ), - } - )} -

- - - -
- {data.site_info && } - - {data.themes && } - - {data.plugins && } - - {data?.errors?.length > 0 && ( -
- )} - - {data?.error_sources?.length > 0 && ( -
- )} - - {data?.urls?.length > 0 && ( - - )} - - {data && } -
-
- - {uuid && ( - - {__('Create support topic', 'amp')} - - )} - {error && ( - - {error} - - )} -
- {uuid && ( - - {__('Support UUID:', 'amp')} - {uuid} - setHasCopied(true)} - onFinishCopy={() => setHasCopied(false)} - > - {hasCopied - ? __('Copied!', 'amp') - : __('Copy UUID', 'amp')} - - - )} -
-
- ); -} - -AMPSupport.propTypes = { - restEndpoint: PropTypes.string.isRequired, - args: PropTypes.any, - data: PropTypes.shape({ - error_sources: PropTypes.array.isRequired, - errors: PropTypes.array.isRequired, - plugins: PropTypes.array, - site_info: PropTypes.object, - themes: PropTypes.array, - urls: PropTypes.array, - }), - ampValidatedPostCount: PropTypes.shape({ - all: PropTypes.number.isRequired, - fresh: PropTypes.number.isRequired, - stale: PropTypes.number.isRequired, - }), -}; diff --git a/assets/src/components/amp-support/plugins.js b/assets/src/components/amp-support/plugins.js deleted file mode 100644 index 481802bcbad..00000000000 --- a/assets/src/components/amp-support/plugins.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * External dependencies - */ -import PropTypes from 'prop-types'; - -/** - * WordPress dependencies - */ -import { __, sprintf } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import { ListItems } from '../list-items'; - -/** - * Render plugins information on site support page. - * - * @param {Object} props Component props. - * @param {Array} props.plugins Plugins data. - * @return {JSX.Element|null} HTML markup for plugins data. - */ -export function Plugins({ plugins }) { - if (!Array.isArray(plugins)) { - return null; - } - - const items = plugins.map((item) => { - return { - value: `${item.name} ${ - item.version ? '(' + item.version + ')' : '' - }`, - }; - }); - - return ( -
- - {sprintf( - /* translators: Placeholder is the number of plugins */ - __('Plugins (%s)', 'amp'), - plugins.length - )} - -
- -
-
- ); -} - -Plugins.propTypes = { - plugins: PropTypes.array.isRequired, -}; diff --git a/assets/src/components/amp-support/raw-data.js b/assets/src/components/amp-support/raw-data.js deleted file mode 100644 index 2a4ea403cf8..00000000000 --- a/assets/src/components/amp-support/raw-data.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * External dependencies - */ -import PropTypes from 'prop-types'; - -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; - -/** - * Render raw data on site support page. - * - * @param {Object} props Component props. - * @param {Object} props.data AMP Support data. - * @return {JSX.Element|null} HTML markup for raw data. - */ -export function RawData({ data }) { - return ( -
- {__('Raw Data', 'amp')} -
-				{JSON.stringify(data, null, 4)}
-			
-
- ); -} - -RawData.propTypes = { - data: PropTypes.object.isRequired, -}; diff --git a/assets/src/components/amp-support/site-info.js b/assets/src/components/amp-support/site-info.js deleted file mode 100644 index 938c7b48866..00000000000 --- a/assets/src/components/amp-support/site-info.js +++ /dev/null @@ -1,136 +0,0 @@ -/** - * External dependencies - */ -import PropTypes from 'prop-types'; - -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import { ListItems } from '../list-items'; - -/** - * Render site information. - * - * @param {Object} props Component props. - * @param {Object} props.siteInfo Site information data. - * @return {JSX.Element} Site information markup. - */ -export function SiteInfo({ siteInfo }) { - if ('object' !== typeof siteInfo) { - return null; - } - - return ( -
- {__('Site Information', 'amp')} -
- - - -
-
- ); -} - -SiteInfo.propTypes = { - siteInfo: PropTypes.object.isRequired, -}; diff --git a/assets/src/components/amp-support/style.scss b/assets/src/components/amp-support/style.scss deleted file mode 100644 index bcc273268e3..00000000000 --- a/assets/src/components/amp-support/style.scss +++ /dev/null @@ -1,95 +0,0 @@ -/* Welcome section. */ -.amp-support { - margin: 2.5rem 0; -} - -.amp-support h2 { - align-items: center; - display: flex; - font-size: 1.5rem; - margin-bottom: 1.5rem; - line-height: 1; - margin-top: 0; -} - -.amp-support .amp-support__raw-data { - border: 1px solid #dedede; - border-radius: 5px; - padding: 15px; - max-height: 510px; - overflow: scroll; - font-size: 12px; - line-height: 2; -} - -.amp-support .amp-support__footer { - margin-top: 1.5rem; - display: flex; -} - -.amp-support .amp-support__footer .components-external-link { - display: flex; - align-items: center; -} - -.amp-support .components-button--send-button { - margin-right: 1rem; -} - -.amp-support .amp-notice { - align-items: center; -} - -.amp-support .amp-notice--info.amp-notice--uuid { - margin-top: 1rem; -} - -.amp-support .components-clipboard-button { - box-shadow: none; - text-decoration: none; - padding: 0.25rem .5rem; - margin: 0 .5rem; - outline: none !important; - height: auto; -} - -.amp-support__body details { - margin: 1rem 0; -} - -.amp-support__body details[disabled] summary, -.amp-support__body details.disabled summary { - pointer-events: none; /* prevents click events */ -} - -.amp-support__body details > summary { - font-size: 1rem; -} - -.amp-support__body details .detail-body { - font-size: .8rem; - margin: .5rem 1.5rem 1.5rem; - overflow-x: auto; -} - -.amp-support__body details .detail-body .detail-body-text { - font-size: .8rem; - font-style: italic; -} - -.amp-support__body details .external-link { - margin-left: .3rem; - text-decoration: none; -} - -.amp-support__body details .external-link .dashicons { - font-size: .9rem; - width: 1rem; - height: 1rem; - vertical-align: bottom; -} - -.amp-support__body details ul.list-group { - margin-left: 1rem; - list-style-type: disc; -} diff --git a/assets/src/components/amp-support/themes.js b/assets/src/components/amp-support/themes.js deleted file mode 100644 index a8b55675031..00000000000 --- a/assets/src/components/amp-support/themes.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * External dependencies - */ -import PropTypes from 'prop-types'; - -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import { ListItems } from '../list-items'; - -/** - * Render theme information on site support page. - * - * @param {Object} props Component props. - * @param {Array} props.themes Theme data. - * @return {JSX.Element|null} HTML markup for theme data. - */ -export function Themes({ themes }) { - if (!Array.isArray(themes)) { - return null; - } - - const items = themes.map((item) => { - return { - value: `${item.name} ${ - item.version ? '(' + item.version + ')' : '' - }`, - }; - }); - - return ( -
- {__('Themes', 'amp')} -
- -
-
- ); -} - -Themes.propTypes = { - themes: PropTypes.array.isRequired, -}; diff --git a/assets/src/components/amp-support/validated-urls.js b/assets/src/components/amp-support/validated-urls.js deleted file mode 100644 index 0adb07c6b84..00000000000 --- a/assets/src/components/amp-support/validated-urls.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * External dependencies - */ -import PropTypes from 'prop-types'; - -/** - * WordPress dependencies - */ -import { __, sprintf } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import { ListItems } from '../list-items'; - -/** - * Render validated urls information on site support page. - * - * @param {Object} props Component props. - * @param {Array} props.validatedUrls List of validated URLs. - * @return {JSX.Element|null} HTML markup for validated urls data. - */ -export function ValidatedUrls({ validatedUrls }) { - if (!Array.isArray(validatedUrls)) { - return null; - } - - const items = validatedUrls.map((item) => ({ - url: item.url ?? null, - })); - - return ( -
- - {sprintf( - /* translators: Placeholder is the number of validated URLs. */ - __('Validated URLs (%d)', 'amp'), - validatedUrls.length - )} - -
- -
-
- ); -} - -ValidatedUrls.propTypes = { - validatedUrls: PropTypes.array.isRequired, -}; diff --git a/assets/src/components/amp-support/validation-results-notice.js b/assets/src/components/amp-support/validation-results-notice.js deleted file mode 100644 index 83320dcfd60..00000000000 --- a/assets/src/components/amp-support/validation-results-notice.js +++ /dev/null @@ -1,121 +0,0 @@ -/** - * External dependencies - */ -import PropTypes from 'prop-types'; - -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import { - AMPNotice, - NOTICE_SIZE_SMALL, - NOTICE_TYPE_INFO, - NOTICE_TYPE_SUCCESS, - NOTICE_TYPE_WARNING, -} from '../amp-notice'; - -/** - * Render notices on site support page. - * - * @param {Object} props Component props. - * @param {Object} props.data Support data. - * @param {Object} props.args Support argument. - * @param {Object} props.ampValidatedPostCount AMP validated post counts. - * @return {JSX.Element|null} HTML markup for notice data. - */ -export function ValidationResultsNotice({ data, args, ampValidatedPostCount }) { - const isSpecificUrlRequest = 0 < args?.urls?.length; - const hasErrors = 0 < data.errors?.length || 0 < data.urls?.length; - const hasAllStaleResults = - 0 < ampValidatedPostCount.all && - ampValidatedPostCount.all === ampValidatedPostCount.stale; - const hasSomeStaleResults = - 0 < ampValidatedPostCount.fresh && 0 < ampValidatedPostCount.stale; - const hasAllFreshResults = - 0 < ampValidatedPostCount.all && - ampValidatedPostCount.all === ampValidatedPostCount.fresh; - - // The site doesn't have any validated URLs. - if (!isSpecificUrlRequest && 0 === ampValidatedPostCount.all) { - return ( - - {__( - 'The site has no validation data. Go to the AMP Settings page and scan you site before sending a support request.', - 'amp' - )} - - ); - } - - // All validated URLs of site are stale. - if (!isSpecificUrlRequest && hasAllStaleResults) { - return ( - - {__( - 'The validation data is stale. Go to the AMP Settings page and rescan you site before sending a support request.', - 'amp' - )} - - ); - } - - // The site doesn't have any AMP errors but there are some stale results. - if (!isSpecificUrlRequest && !hasErrors && hasSomeStaleResults) { - return ( - - {__( - 'We found no issues on your site but there are some stale validation results. Browse your site to ensure everything is working as expected.', - 'amp' - )} - - ); - } - - // All validated URLs are stale. - if (!isSpecificUrlRequest && !hasErrors && hasAllFreshResults) { - return ( - - {__( - 'We found no issues on your site. Browse your site to ensure everything is working as expected.', - 'amp' - )} - - ); - } - - // If requested URL doesn't have AMP related errors. - if (isSpecificUrlRequest && !hasErrors) { - return ( - - {__( - 'The requested URL does not have any AMP validation errors.', - 'amp' - )} - - ); - } - - return null; -} - -ValidationResultsNotice.propTypes = { - args: PropTypes.any, - data: PropTypes.shape({ - error_sources: PropTypes.array.isRequired, - errors: PropTypes.array.isRequired, - plugins: PropTypes.array, - site_info: PropTypes.object, - themes: PropTypes.array, - urls: PropTypes.array, - }), - ampValidatedPostCount: PropTypes.shape({ - all: PropTypes.number.isRequired, - fresh: PropTypes.number.isRequired, - stale: PropTypes.number.isRequired, - }), -}; diff --git a/assets/src/support-page/index.js b/assets/src/support-page/index.js deleted file mode 100644 index 858437ddb4e..00000000000 --- a/assets/src/support-page/index.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * External dependencies - */ -import { restEndpoint, args, data, ampValidatedPostCount } from 'amp-support'; // From WP inline script. - -/** - * WordPress dependencies - */ -import domReady from '@wordpress/dom-ready'; -import { createRoot } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import '../css/variables.css'; -import '../css/elements.css'; -import '../css/core-components.css'; -import './style.css'; -import { ErrorContextProvider } from '../components/error-context-provider'; -import { AMPSupport } from '../components/amp-support'; -import { ErrorScreen } from '../components/error-screen'; -import { ErrorBoundary } from '../components/error-boundary'; - -domReady(() => { - const root = document.getElementById('amp-support-root'); - const errorHandler = (event) => { - // Handle only own errors. - if (event.filename && /amp-support(\.min)?\.js/.test(event.filename)) { - createRoot(root).render(); - } - }; - - global.addEventListener('error', errorHandler); - - if (root) { - createRoot(root).render( - - - - - - ); - } -}); diff --git a/assets/src/support-page/style.css b/assets/src/support-page/style.css deleted file mode 100644 index 6ccc7954c87..00000000000 --- a/assets/src/support-page/style.css +++ /dev/null @@ -1,24 +0,0 @@ -html { - scroll-behavior: smooth; -} - -@media screen and (max-width: 400px) { - - .wrap { - margin-left: 0; - margin-right: 10px; - } -} - -@media screen and (min-width: 401px) and (max-width: 782px) { - - .wrap { - margin-left: 10px; - margin-right: 20px; - } -} - -#amp-support { - max-width: 1060px; - margin: auto; -} diff --git a/src/Admin/SupportLink.php b/src/Admin/SupportLink.php index 2e3d511ce45..dc0a02f6c4b 100644 --- a/src/Admin/SupportLink.php +++ b/src/Admin/SupportLink.php @@ -21,7 +21,7 @@ * @since 2.2 * @internal */ -class SupportLink implements Service, Delayed, Conditional, Registerable { +class SupportLink implements Service, Delayed, Registerable { /** * Get the action to use for registering the service. @@ -32,15 +32,6 @@ public static function get_registration_action() { return 'wp_loaded'; } - /** - * Check whether the conditional object is currently needed. - * - * @return bool Whether the conditional object is needed. - */ - public static function is_needed() { - return SupportScreen::has_cap(); - } - /** * Adds hooks. * @@ -81,15 +72,7 @@ public function admin_bar_menu( WP_Admin_Bar $wp_admin_bar ) { 'parent' => 'amp', 'title' => esc_html__( 'Get support', 'amp' ), 'id' => 'amp-support', - 'href' => esc_url( - add_query_arg( - [ - 'page' => 'amp-support', - 'url' => rawurlencode( amp_get_current_url() ), - ], - admin_url( 'admin.php' ) - ) - ), + 'href' => esc_url( 'https://wordpress.org/support/plugin/amp/' ), ] ); } @@ -108,14 +91,9 @@ public function amp_validated_url_status_actions( $actions, WP_Post $post ) { return $actions; } - $query_args = [ - 'page' => 'amp-support', - 'url' => rawurlencode( AMP_Validated_URL_Post_Type::get_url_from_post( $post ) ), - ]; - $actions['amp-support'] = sprintf( '
%s', - esc_url( add_query_arg( $query_args, admin_url( 'admin.php' ) ) ), + esc_url( 'https://wordpress.org/support/plugin/amp/' ), esc_html__( 'Get Support', 'amp' ) ); @@ -136,14 +114,9 @@ public function post_row_actions( $actions, WP_Post $post ) { return $actions; } - $query_args = [ - 'page' => 'amp-support', - 'url' => rawurlencode( AMP_Validated_URL_Post_Type::get_url_from_post( $post ) ), - ]; - $actions['amp-support'] = sprintf( '%s', - esc_url( add_query_arg( $query_args, admin_url( 'admin.php' ) ) ), + esc_url( 'https://wordpress.org/support/plugin/amp/' ), esc_html__( 'Get Support', 'amp' ) ); @@ -164,12 +137,7 @@ public function plugin_row_meta( $plugin_meta, $plugin_file ) { if ( 'amp/amp.php' === $plugin_file ) { $plugin_meta[] = sprintf( '%s', - esc_url( - add_query_arg( - [ 'page' => 'amp-support' ], - admin_url( 'admin.php' ) - ) - ), + esc_url( 'https://wordpress.org/support/plugin/amp/' ), esc_html__( 'Get support', 'amp' ) ); } diff --git a/src/Admin/SupportScreen.php b/src/Admin/SupportScreen.php deleted file mode 100644 index b6ef4d07ff7..00000000000 --- a/src/Admin/SupportScreen.php +++ /dev/null @@ -1,274 +0,0 @@ -injector = $injector; - - $this->parent_menu_slug = $options_menu->get_menu_slug(); - - $this->google_fonts = $google_fonts; - } - - /** - * Determine whether the user has the capability to access the support screen. - * - * @return bool Whether user has the capability. - */ - public static function has_cap() { - return ( - current_user_can( 'view_site_health_checks' ) - && - current_user_can( 'manage_options' ) - && - AMP_Validation_Manager::has_cap() - ); - } - - /** - * Check whether the conditional object is currently needed. - * - * @return bool Whether the conditional object is needed. - */ - public static function is_needed() { - return ( - is_admin() - && - self::has_cap() - ); - } - - /** - * Adds hooks. - */ - public function register() { - - add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] ); - add_action( 'admin_menu', [ $this, 'add_menu_items' ], 9 ); - } - - /** - * Returns the slug for the support page. - * - * @return string - */ - public function get_menu_slug() { - - return 'amp-support'; - } - - /** - * Provides the support screen handle. - * - * @return string - */ - public function screen_handle() { - - return sprintf( 'amp_page_%s', $this->get_menu_slug() ); - } - - /** - * Add menu. - */ - public function add_menu_items() { - - require_once ABSPATH . '/wp-admin/includes/plugin.php'; - - add_submenu_page( - $this->parent_menu_slug, - esc_html__( 'Support', 'amp' ), - esc_html__( 'Support', 'amp' ), - 'manage_options', - $this->get_menu_slug(), - [ $this, 'render_screen' ], - 10 - ); - } - - /** - * Enqueues settings page assets. - * - * @param string $hook_suffix The current admin page. - * - * @return void - */ - public function enqueue_assets( $hook_suffix ) { - - if ( $this->screen_handle() !== $hook_suffix ) { - return; - } - - /** This action is documented in src/Admin/OptionsMenu.php */ - do_action( 'amp_register_polyfills' ); - - $asset_file = AMP__DIR__ . '/assets/js/' . self::ASSET_HANDLE . '.asset.php'; - $asset = require $asset_file; - $dependencies = $asset['dependencies']; - $version = $asset['version']; - - wp_enqueue_script( - self::ASSET_HANDLE, - amp_get_asset_url( 'js/' . self::ASSET_HANDLE . '.js' ), - $dependencies, - $version, - true - ); - - wp_enqueue_style( - self::ASSET_HANDLE, - amp_get_asset_url( 'css/amp-support.css' ), - [ - $this->google_fonts->get_handle(), - 'wp-components', - ], - AMP__VERSION - ); - - $args = []; - // phpcs:ignore WordPress.Security.NonceVerification.Recommended - $amp_url = isset( $_GET['url'] ) ? esc_url_raw( wp_unslash( $_GET['url'] ) ) : ''; - - if ( ! empty( $amp_url ) ) { - $args = [ - 'urls' => [ $amp_url ], - ]; - } - - $support_data = $this->injector->make( SupportData::class, compact( 'args' ) ); - $data = $support_data->get_data(); - - wp_add_inline_script( - self::ASSET_HANDLE, - sprintf( - 'var ampSupport = %s;', - wp_json_encode( - [ - 'restEndpoint' => get_rest_url( null, 'amp/v1/send-diagnostic' ), - 'args' => $args, - 'data' => $data, - 'ampValidatedPostCount' => $this->get_amp_validated_post_counts(), - ] - ) - ), - 'before' - ); - } - - /** - * Get count of amp validated post. - * - * @return array [ - * @type int $all Count of all AMP validated URL post. - * @type int $valid Count of non-stale AMP validated URL posts. - * @type int $stale Count of stale AMP validated URL posts. - * ] - */ - public function get_amp_validated_post_counts() { - - $amp_validated_post_count = wp_count_posts( AMP_Validated_URL_Post_Type::POST_TYPE_SLUG ); - - $query_args = [ - 'post_type' => AMP_Validated_URL_Post_Type::POST_TYPE_SLUG, - 'posts_per_page' => 1, - 'post_status' => 'publish', - 'meta_key' => AMP_Validated_URL_Post_Type::VALIDATED_ENVIRONMENT_POST_META_KEY, - 'meta_value' => maybe_serialize( AMP_Validated_URL_Post_Type::get_validated_environment() ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value - ]; - $query = new WP_Query( $query_args ); - - $all = intval( $amp_validated_post_count->publish ); - $fresh = intval( $query->found_posts ); - $stale = $all - $fresh; - - return compact( 'all', 'fresh', 'stale' ); - } - - /** - * Display Settings. - * - * @return void - */ - public function render_screen() { - - ?> -
-
-
-
-
-
-
- Admin\OptionsMenu::class, 'admin.paired_browsing' => Admin\PairedBrowsing::class, 'admin.plugin_row_meta' => Admin\PluginRowMeta::class, - 'admin.support_screen' => Admin\SupportScreen::class, 'admin.support' => Admin\SupportLink::class, 'admin.polyfills' => Admin\Polyfills::class, 'admin.user_rest_endpoint_extension' => Admin\UserRESTEndpointExtension::class, @@ -120,8 +119,6 @@ final class AmpWpPlugin extends ServiceBasedPlugin { 'sandboxing' => Sandboxing::class, 'server_timing' => Instrumentation\ServerTiming::class, 'site_health_integration' => Admin\SiteHealth::class, - 'support' => SupportCliCommand::class, - 'support_rest_controller' => SupportRESTController::class, 'url_validation_cron' => URLValidationCron::class, 'url_validation_rest_controller' => Validation\URLValidationRESTController::class, 'validated_url_stylesheet_gc' => BackgroundTask\ValidatedUrlStylesheetDataGarbageCollection::class, diff --git a/src/Support/SupportCliCommand.php b/src/Support/SupportCliCommand.php deleted file mode 100644 index 85bc20cee8d..00000000000 --- a/src/Support/SupportCliCommand.php +++ /dev/null @@ -1,183 +0,0 @@ -injector = $injector; - } - - /** - * Get the name under which to register the CLI command. - * - * @return string The name under which to register the CLI command. - */ - public static function get_command_name() { - - return 'amp support'; - } - - /** - * Sends support data to endpoint. - * - * ## OPTIONS - * - * [--is-synthetic] - * : Whether or not it is synthetic data. - * --- - * default: false - * options: - * - true - * - false - * - * [--print] - * : To print support data. - * --- - * default: json-pretty - * options: - * - json - * - json-pretty - * - * [--endpoint=] - * : Support endpoint. Where support data will send. - * - * [--urls=] - * : List of URL for which support data need to send. Use comma separator for multiple URLs. - * - * [--post_ids=] - * : List of Post for which support data need to send. Use comma separator for multiple post ids. - * - * [--term_ids=] - * : List of term for which support data need to send. Use comma separator for multiple term ids. - * - * ## EXAMPLES - * - * wp amp support send-diagnostic - * - * @subcommand send-diagnostic - * - * @codeCoverageIgnore - * - * @param array $args Positional args. - * @param array $assoc_args Associative args. - */ - public function send_diagnostic( /** @noinspection PhpUnusedParameterInspection */ $args, $assoc_args ) { - - $is_print = filter_var( get_flag_value( $assoc_args, 'print', false ), FILTER_SANITIZE_STRING ); - $is_synthetic = filter_var( get_flag_value( $assoc_args, 'is-synthetic', false ), FILTER_SANITIZE_STRING ); - $endpoint = filter_var( get_flag_value( $assoc_args, 'endpoint', '' ), FILTER_SANITIZE_STRING ); - $endpoint = untrailingslashit( $endpoint ); - - $urls = filter_var( get_flag_value( $assoc_args, 'urls', false ), FILTER_SANITIZE_STRING ); - $post_ids = filter_var( get_flag_value( $assoc_args, 'post_ids', false ), FILTER_SANITIZE_STRING ); - $term_ids = filter_var( get_flag_value( $assoc_args, 'term_ids', false ), FILTER_SANITIZE_STRING ); - - $args = [ - 'urls' => ( ! empty( $urls ) ) ? explode( ',', $urls ) : [], - 'post_ids' => ( ! empty( $post_ids ) ) ? explode( ',', $post_ids ) : [], - 'term_ids' => ( ! empty( $term_ids ) ) ? explode( ',', $term_ids ) : [], - 'endpoint' => $endpoint, - 'is_synthetic' => $is_synthetic, - ]; - - $support_data = $this->injector->make( SupportData::class, [ 'args' => $args ] ); - $data = $support_data->get_data(); - - if ( $is_print ) { - - // Print the data. - $print = strtolower( trim( $is_print ) ); - if ( 'json' === $print ) { - echo wp_json_encode( $data ) . PHP_EOL; - } else { - echo wp_json_encode( $data, JSON_PRETTY_PRINT ) . PHP_EOL; - } - } else { - - $response = $support_data->send_data(); - - if ( is_wp_error( $response ) ) { - $error_message = $response->get_error_message(); - WP_CLI::warning( "Something went wrong: $error_message" ); - } elseif ( empty( $response['status'] ) || 'ok' !== $response['status'] ) { - WP_CLI::warning( 'Failed to send diagnostic data.' ); - } elseif ( isset( $response['data']['uuid'] ) ) { - WP_CLI::success( 'UUID : ' . $response['data']['uuid'] ); - } - } - - /* - * Summary of data. - */ - $url_error_relationship = []; - - foreach ( $data['urls'] as $url ) { - foreach ( $url['errors'] as $error ) { - foreach ( $error['sources'] as $source ) { - $url_error_relationship[] = $url['url'] . '-' . $error['error_slug'] . '-' . $source; - } - } - } - - $plugin_count = count( $data['plugins'] ); - - if ( $is_synthetic ) { - $plugin_count_text = ( $plugin_count - 3 ) . " - Excluding common plugins of synthetic sites. ( $plugin_count - 3 )"; - } else { - $plugin_count_text = $plugin_count; - } - - $summary = [ - 'Site URL' => SupportData::get_home_url(), - 'Plugin count' => $plugin_count_text, - 'Themes' => count( $data['themes'] ), - 'Errors' => count( array_values( $data['errors'] ) ), - 'Error Sources' => count( array_values( $data['error_sources'] ) ), - 'Validated URL' => count( array_values( $data['urls'] ) ), - 'URL Error Relationship' => count( array_values( $url_error_relationship ) ), - ]; - - if ( $is_synthetic ) { - $summary['Synthetic Data'] = 'Yes'; - } - - WP_CLI::log( sprintf( PHP_EOL . "%'=100s", '' ) ); - WP_CLI::log( 'Summary of AMP data' ); - WP_CLI::log( sprintf( "%'=100s", '' ) ); - foreach ( $summary as $key => $value ) { - WP_CLI::log( sprintf( '%-25s : %s', $key, $value ) ); - } - WP_CLI::log( sprintf( "%'=100s" . PHP_EOL, '' ) ); - } -} diff --git a/src/Support/SupportData.php b/src/Support/SupportData.php deleted file mode 100644 index dd288df26b0..00000000000 --- a/src/Support/SupportData.php +++ /dev/null @@ -1,1072 +0,0 @@ -args = ( ! empty( $args ) && is_array( $args ) ) ? $args : []; - - $this->parse_args(); - - $this->data = []; - } - - /** - * To parse args for AMP data that will send. - * - * @since 2.2 - * - * @return void - */ - public function parse_args() { - - if ( ! empty( $this->args['urls'] ) && is_array( $this->args['urls'] ) ) { - $this->urls = array_merge( $this->urls, $this->args['urls'] ); - } - - if ( ! empty( $this->args['term_ids'] ) && is_array( $this->args['term_ids'] ) ) { - $this->args['term_ids'] = array_map( 'intval', $this->args['term_ids'] ); - $this->args['term_ids'] = array_filter( $this->args['term_ids'] ); - - foreach ( $this->args['term_ids'] as $term_id ) { - $url = get_term_link( $term_id ); - - if ( ! empty( $url ) && ! is_wp_error( $url ) ) { - $this->urls[] = $url; - } - } - } - - if ( ! empty( $this->args['post_ids'] ) && is_array( $this->args['post_ids'] ) ) { - - $this->args['post_ids'] = array_map( 'intval', $this->args['post_ids'] ); - $this->args['post_ids'] = array_filter( $this->args['post_ids'] ); - - foreach ( $this->args['post_ids'] as $post_id ) { - - $url = get_permalink( $post_id ); - - if ( ! empty( $url ) && ! is_wp_error( $url ) ) { - $this->urls[] = $url; - } - } - } - - if ( ! empty( $this->args['amp_validated_post_ids'] ) && is_array( $this->args['amp_validated_post_ids'] ) ) { - $this->args['amp_validated_post_ids'] = array_map( 'intval', $this->args['amp_validated_post_ids'] ); - $this->args['amp_validated_post_ids'] = array_filter( $this->args['amp_validated_post_ids'] ); - - foreach ( $this->args['amp_validated_post_ids'] as $post_id ) { - $post = get_post( $post_id ); - - if ( ! empty( $post->post_title ) ) { - $this->urls[] = $post->post_title; - } - } - } - - $this->urls = array_map( - static function ( $url ) { - - if ( filter_var( $url, FILTER_VALIDATE_URL ) ) { - return AMP_Validated_URL_Post_Type::normalize_url_for_storage( $url ); - } - - return false; - }, - $this->urls - ); - $this->urls = array_values( array_unique( array_filter( $this->urls ) ) ); - - } - - /** - * To send support data to insight server. - * - * @return array|WP_Error WP_Error on fail, Otherwise server response. - */ - public function send_data() { - - $data = ( ! empty( $this->data ) ) ? $this->data : $this->get_data(); - $endpoint = ( ! empty( $this->args['endpoint'] ) ) ? $this->args['endpoint'] : self::SUPPORT_ENDPOINT; - $endpoint = untrailingslashit( $endpoint ); - - // Send data to server. - $response = wp_remote_post( - sprintf( '%s/api/v1/support/', $endpoint ), - [ - // We need long timeout here, in case the data being sent is large or the network connection is slow. - 'timeout' => 30, // phpcs:ignore WordPressVIPMinimum.Performance.RemoteRequestTimeout.timeout_timeout - 'body' => $data, - 'compress' => true, - ] - ); - - if ( ! is_wp_error( $response ) ) { - - $response_body = wp_remote_retrieve_body( $response ); - $response = json_decode( $response_body, true ); - $json_last_error = json_last_error(); - - if ( JSON_ERROR_NONE !== $json_last_error ) { - return new WP_Error( - 'malformed_json_amp_insight_endpoint', - json_last_error_msg() - ); - } - } - - return $response; - } - - /** - * To get amp data to send it to compatibility server. - * - * @since 2.2 - * - * @return array - */ - public function get_data() { - - $amp_urls = $this->get_amp_urls(); - - $request_data = [ - 'site_url' => static::get_home_url(), - 'site_info' => $this->get_site_info(), - 'plugins' => $this->get_plugin_info(), - 'themes' => $this->get_theme_info(), - 'errors' => array_values( $amp_urls['errors'] ), - 'error_sources' => array_values( $amp_urls['error_sources'] ), - 'urls' => array_values( $amp_urls['urls'] ), - 'error_log' => $this->get_error_log(), - ]; - - if ( ! empty( $this->args['is_synthetic'] ) ) { - $request_data['site_info']['is_synthetic_data'] = true; - } - - $this->data = $request_data; - - return $request_data; - } - - /** - * To get site info. - * - * @since 2.2 - * - * @return array Site information. - */ - public function get_site_info() { - - global $wpdb; - - $wp_type = 'single'; - - if ( is_multisite() && ( defined( 'SUBDOMAIN_INSTALL' ) && SUBDOMAIN_INSTALL ) ) { - $wp_type = 'subdomain'; - } elseif ( is_multisite() ) { - $wp_type = 'subdir'; - } - - $active_theme = wp_get_theme(); - $active_theme = static::normalize_theme_info( $active_theme ); - - $amp_settings = AMP_Options_Manager::get_options(); - $amp_settings = ( ! empty( $amp_settings ) && is_array( $amp_settings ) ) ? $amp_settings : []; - - $loopback_status = ''; - - if ( class_exists( 'WP_Site_Health' ) ) { - $loopback_status = ( new WP_Site_Health() )->can_perform_loopback(); - $loopback_status = ( ! empty( $loopback_status->status ) ) ? $loopback_status->status : ''; - } - - if ( function_exists( 'wp_get_https_detection_errors' ) ) { - $https_errors = wp_get_https_detection_errors(); - $is_ssl = empty( $https_errors ); - } elseif ( function_exists( 'wp_is_https_supported' ) ) { - $is_ssl = wp_is_https_supported(); - } else { - $is_ssl = is_ssl(); - } - - $site_info = [ - 'site_url' => static::get_home_url(), - 'site_title' => get_bloginfo( 'site_title' ), - 'php_version' => phpversion(), - 'mysql_version' => $wpdb->db_version(), - 'wp_version' => get_bloginfo( 'version' ), - 'wp_language' => get_bloginfo( 'language' ), - 'wp_https_status' => $is_ssl, - 'wp_multisite' => $wp_type, - 'wp_active_theme' => $active_theme, - 'object_cache_status' => wp_using_ext_object_cache(), - 'libxml_version' => ( defined( 'LIBXML_VERSION' ) ) ? LIBXML_VERSION : '', - 'is_defined_curl_multi' => ( function_exists( 'curl_multi_init' ) ), - 'loopback_requests' => $loopback_status, - 'amp_mode' => ( ! empty( $amp_settings['theme_support'] ) ) ? $amp_settings['theme_support'] : '', - 'amp_version' => ( ! empty( $amp_settings['version'] ) ) ? $amp_settings['version'] : '', - 'amp_plugin_configured' => ( ! empty( $amp_settings['plugin_configured'] ) ) ? true : false, - 'amp_all_templates_supported' => ( ! empty( $amp_settings['all_templates_supported'] ) ) ? true : false, - 'amp_supported_post_types' => ( ! empty( $amp_settings['supported_post_types'] ) && is_array( $amp_settings['supported_post_types'] ) ) ? $amp_settings['supported_post_types'] : [], - 'amp_supported_templates' => ( ! empty( $amp_settings['supported_templates'] ) && is_array( $amp_settings['supported_templates'] ) ) ? $amp_settings['supported_templates'] : [], - 'amp_mobile_redirect' => ( ! empty( $amp_settings['mobile_redirect'] ) ) ? true : false, - 'amp_reader_theme' => ( ! empty( $amp_settings['reader_theme'] ) ) ? $amp_settings['reader_theme'] : '', - ]; - - return $site_info; - } - - /** - * To get list of active plugin's information. - * - * @since 2.2 - * - * @return array List of plugin detail. - */ - public function get_plugin_info() { - - $active_plugins = get_option( 'active_plugins' ); - - if ( is_multisite() ) { - $network_wide_activate_plugins = get_site_option( 'active_sitewide_plugins' ); - $active_plugins = array_merge( $active_plugins, $network_wide_activate_plugins ); - } - - $active_plugins = array_values( array_unique( $active_plugins ) ); - $plugin_info = array_map( - static function ( $active_plugin ) { - return self::normalize_plugin_info( $active_plugin ); - }, - $active_plugins - ); - $plugin_info = array_filter( $plugin_info ); - - return array_values( $plugin_info ); - } - - /** - * To get active theme info. - * - * @since 2.2 - * - * @return array List of theme information. - */ - public function get_theme_info() { - - $themes = [ - wp_get_theme(), - ]; - if ( wp_get_theme()->parent() ) { - $themes[] = wp_get_theme()->parent(); - } - - $themes = array_filter( - $themes, - static function ( WP_Theme $theme ) { - return ! $theme->errors(); - } - ); - - $response = array_map( - static function( WP_Theme $theme ) { - return self::normalize_theme_info( $theme ); - }, - $themes - ); - - return array_values( $response ); - } - - /** - * To get error log. - * - * @since 2.2 - * - * @return array Error log contents and log_errors ini setting. - */ - public function get_error_log() { - - $error_log_path = ini_get( 'error_log' ); - - // $error_log_path might be a relative path/filename. - // In this case, we would have to iterate many directories to find them. - if ( empty( $error_log_path ) || ! file_exists( $error_log_path ) ) { - return [ - 'log_errors' => ini_get( 'log_errors' ), - 'contents' => '', - ]; - } - - $max_lines = 200; - - // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_fopen - $file = @fopen( $error_log_path, 'r' ); - $lines = []; - $current_line = ''; - $position = 0; - - if ( is_resource( $file ) ) { - - while ( -1 !== fseek( $file, $position, SEEK_END ) ) { - $char = fgetc( $file ); - - if ( PHP_EOL === $char ) { - $lines[] = $current_line; - $current_line = ''; - - if ( count( $lines ) > $max_lines ) { - break; - } - } else { - $current_line = $char . $current_line; - } - - $position--; - } - - $lines[] = $current_line; - - fclose( $file ); - } - - $lines = array_filter( $lines ); - $lines = array_reverse( $lines ); - - return [ - 'log_errors' => ini_get( 'log_errors' ), - 'contents' => implode( "\n", $lines ), - ]; - } - - /** - * To get plugin information by plugin file. - * - * @since 2.2 - * - * @param string $plugin_file Plugin file. - * - * @return array Plugin detail. - */ - public static function normalize_plugin_info( $plugin_file ) { - - $absolute_plugin_file = WP_PLUGIN_DIR . '/' . $plugin_file; - if ( 0 !== validate_file( $absolute_plugin_file ) || ! file_exists( $absolute_plugin_file ) ) { - return []; - } - - require_once ABSPATH . '/wp-admin/includes/plugin.php'; - - /** @var array */ - $plugin_data = get_plugin_data( $absolute_plugin_file ); - - $slug = explode( '/', $plugin_file ); - $slug = $slug[0]; - - $amp_options = get_option( 'amp-options' ); - $suppressed_plugins = ( ! empty( $amp_options['suppressed_plugins'] ) && is_array( $amp_options['suppressed_plugins'] ) ) ? $amp_options['suppressed_plugins'] : []; - - $suppressed_plugin_list = array_keys( $suppressed_plugins ); - - if ( empty( $plugin_data['Name'] ) ) { - return []; - } - - return [ - 'name' => $plugin_data['Name'], - 'slug' => $slug, - 'plugin_url' => array_key_exists( 'PluginURI', $plugin_data ) ? $plugin_data['PluginURI'] : '', - 'version' => array_key_exists( 'Version', $plugin_data ) ? $plugin_data['Version'] : '', - 'author' => array_key_exists( 'AuthorName', $plugin_data ) ? $plugin_data['AuthorName'] : '', - 'author_url' => array_key_exists( 'AuthorURI', $plugin_data ) ? $plugin_data['AuthorURI'] : '', - 'requires_wp' => array_key_exists( 'RequiresWP', $plugin_data ) ? $plugin_data['RequiresWP'] : '', - 'requires_php' => array_key_exists( 'RequiresPHP', $plugin_data ) ? $plugin_data['RequiresPHP'] : '', - 'is_active' => is_plugin_active( $plugin_file ), - 'is_network_active' => is_plugin_active_for_network( $plugin_file ), - 'is_suppressed' => in_array( $slug, $suppressed_plugin_list, true ) ? $suppressed_plugins[ $slug ]['last_version'] : '', - ]; - - } - - /** - * To normalize theme information. - * - * @since 2.2 - * - * @param WP_Theme $theme_object Theme object. - * - * @return array Normalize theme information. - */ - public static function normalize_theme_info( WP_Theme $theme_object ) { - $active_theme = wp_get_theme(); - - $tags = $theme_object->get( 'Tags' ); - $tags = ( ! empty( $tags ) && is_array( $tags ) ) ? $tags : []; - - $theme_data = [ - 'name' => $theme_object->get( 'Name' ), - 'slug' => $theme_object->get_stylesheet(), - 'version' => $theme_object->get( 'Version' ), - 'status' => $theme_object->get( 'Status' ), - 'tags' => $tags, - 'text_domain' => $theme_object->get( 'TextDomain' ), - 'requires_wp' => $theme_object->get( 'RequiresWP' ), - 'requires_php' => $theme_object->get( 'RequiresPHP' ), - 'theme_url' => $theme_object->get( 'ThemeURI' ), - 'author' => $theme_object->get( 'Author' ), - 'author_url' => $theme_object->get( 'AuthorURI' ), - 'is_active' => ( $theme_object->get_stylesheet() === $active_theme->get_stylesheet() ), - 'parent_theme' => $theme_object->parent() ? $theme_object->get_template() : null, - ]; - - return $theme_data; - } - - /** - * Normalize error data. - * - * @since 2.2 - * - * @param array $error_data Error data array. - * - * @return array - */ - public static function normalize_error( $error_data ) { - - if ( empty( $error_data ) || ! is_array( $error_data ) ) { - return []; - } - - unset( $error_data['sources'] ); - - $error_data['text'] = ( ! empty( $error_data['text'] ) ) ? trim( $error_data['text'] ) : ''; - - $error_data = static::remove_domain( $error_data ); - - /** - * Generate new slug after removing site specific data. - */ - $error_data['error_slug'] = static::generate_hash( $error_data ); - - return $error_data; - } - - /** - * To normalize the error source data. - * - * @since 2.2 - * - * @param array $source Error source detail. - * - * @return array Normalized error source data. - */ - public static function normalize_error_source( $source ) { - - if ( empty( $source ) || ! is_array( $source ) ) { - return []; - } - - static $plugin_versions = []; - - /** - * All plugin info - */ - if ( empty( $plugin_versions ) || ! is_array( $plugin_versions ) ) { - - $plugin_list = get_plugins(); - $plugin_list = array_keys( $plugin_list ); - $plugin_list = array_values( array_unique( $plugin_list ) ); - $plugin_list = array_map( - static function ( $plugin ) { - return self::normalize_plugin_info( $plugin ); - }, - $plugin_list - ); - - foreach ( $plugin_list as $plugin ) { - $plugin_versions[ $plugin['slug'] ] = $plugin['version']; - } - } - - /** - * Normalize error source. - */ - - $allowed_types = [ 'plugin', 'theme' ]; - $source['type'] = ( ! empty( $source['type'] ) ) ? strtolower( trim( $source['type'] ) ) : ''; - - if ( ! empty( $source['sources'] ) && is_array( $source['sources'] ) ) { - foreach ( $source['sources'] as $index => $inner_source ) { - $source['sources'][ $index ] = self::normalize_error_source( $inner_source ); - } - - $source['sources'] = array_values( array_filter( $source['sources'] ) ); - } - - - /** - * Do not include wp-core sources. - * But allow if source have sub sources. - */ - if ( - ( empty( $source['type'] ) || ! in_array( $source['type'], $allowed_types, true ) ) - && - empty( $source['sources'] ) - ) { - return []; - } - - if ( ! empty( $source['type'] ) ) { - if ( 'plugin' === $source['type'] ) { - $source['version'] = isset( $plugin_versions[ $source['name'] ] ) ? $plugin_versions[ $source['name'] ] : 'n/a'; - } elseif ( 'theme' === $source['type'] ) { - $theme = wp_get_theme( $source['name'] ); - $source['version'] = ! $theme->errors() ? $theme->get( 'Version' ) : 'n/a'; - } - } - - if ( ! empty( $source['text'] ) ) { - $source['text'] = trim( $source['text'] ); - $source['text'] = static::remove_domain( $source['text'] ); - } - - // Generate error source slug. - $error_source_slug = self::generate_hash( $source ); - - // Update source information. Add error_slug and source_slug. - $source['error_source_slug'] = $error_source_slug; - - ksort( $source ); - - return $source; - } - - /** - * To get amp validated URLs. - * - * @since 2.2 - * - * @return array [ - * List amp validated URLs. - * @type array $errors List of error for given instance of Validated post. - * @type array $error_sources List of error sources for given instance of Validated post. - * @type string[] $urls List of front-end URL. - * ] - */ - public function get_amp_urls() { - - /** - * List of invalid AMP URLs. - * - * @var string[] - */ - $amp_invalid_urls = []; - - /** - * Error Information - * - * @var array - */ - $errors = []; - - /** - * Error Source information. - * - * @var array - */ - $error_sources = []; - - if ( empty( $this->urls ) ) { - - /** - * If argument provided and we don't have URL data. - * then return empty values. - */ - if ( - ! empty( $this->args['post_ids'] ) - || - ! empty( $this->args['term_ids'] ) - || - ! empty( $this->args['urls'] ) - || - ! empty( $this->args['amp_validated_post_ids'] ) - ) { - return [ - 'errors' => [], - 'error_sources' => [], - 'urls' => [], - ]; - } - - // If no specific URL requested. - $query_args = [ - 'post_type' => AMP_Validated_URL_Post_Type::POST_TYPE_SLUG, - 'posts_per_page' => 100, - 'post_status' => 'publish', - 'meta_key' => AMP_Validated_URL_Post_Type::VALIDATED_ENVIRONMENT_POST_META_KEY, - 'meta_value' => maybe_serialize( AMP_Validated_URL_Post_Type::get_validated_environment() ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value - 's' => 'term_slug', - ]; - - $query = new WP_Query( $query_args ); - $amp_validated_posts = $query->posts; - - foreach ( $amp_validated_posts as $amp_validated_post ) { - $validation_data = $this->process_raw_post_errors( $amp_validated_post ); - - if ( - ! empty( $validation_data['errors'] ) - && - ! empty( $validation_data['error_sources'] ) - && - ! empty( $validation_data['url'] ) - ) { - $errors = array_merge( $errors, $validation_data['errors'] ); - $error_sources = array_merge( $error_sources, $validation_data['error_sources'] ); - $amp_invalid_urls[] = $validation_data['url']; - } - } - } else { // If we have specific URL requested. - - foreach ( $this->urls as $url ) { - - // Check request URL have validated data if not then validate URL. - $amp_validated_post = AMP_Validated_URL_Post_Type::get_invalid_url_post( $url ); - - if ( ! $amp_validated_post ) { - $validity = AMP_Validation_Manager::validate_url_and_store( $url ); - - if ( is_wp_error( $validity ) || ! is_array( $validity ) ) { - continue; - } - - $amp_validated_post = get_post( $validity['post_id'] ); - } - - // If validation data is exists for URL then check if it is stale or not. If it is stale, then revalidate. - $is_stale = ! empty( AMP_Validated_URL_Post_Type::get_post_staleness( $amp_validated_post ) ); - if ( $is_stale ) { - AMP_Validation_Manager::validate_url_and_store( $url, $amp_validated_post ); - } - - $validation_data = $this->process_raw_post_errors( $amp_validated_post ); - - if ( - ! empty( $validation_data['errors'] ) - && - ! empty( $validation_data['error_sources'] ) - && - ! empty( $validation_data['url'] ) - ) { - $errors = array_merge( $errors, $validation_data['errors'] ); - $error_sources = array_merge( $error_sources, $validation_data['error_sources'] ); - $amp_invalid_urls[] = $validation_data['url']; - } - } - } - - return [ - 'errors' => $errors, - 'error_sources' => $error_sources, - 'urls' => $amp_invalid_urls, - ]; - - } - - /** - * Process AMP errors for single AMP validated post. - * - * @param WP_Post $amp_validated_post Instance of AMP Validated Post. - * - * @return array [ - * @type array $errors List of error for given instance of Validated post. - * @type array $error_sources List of error sources for given instance of Validated post. - * @type string $url Front-end URL. - * ] - */ - protected function process_raw_post_errors( WP_Post $amp_validated_post ) { - - if ( AMP_Validated_URL_Post_Type::POST_TYPE_SLUG !== $amp_validated_post->post_type ) { - return []; - } - - // Empty array for post staleness means post is NOT stale. - if ( ! empty( AMP_Validated_URL_Post_Type::get_post_staleness( $amp_validated_post ) ) ) { - return []; - } - - /** - * Error Information - * - * @var array - */ - $error_list = []; - - /** - * Error Source information. - * - * @var array - */ - $error_source_list = []; - - $validation_errors_raw = json_decode( $amp_validated_post->post_content, true ); - if ( ! is_array( $validation_errors_raw ) ) { - $validation_errors_raw = []; - } - - /** - * Error loop. - * - * @var array - */ - $validation_errors = []; - foreach ( $validation_errors_raw as $validation_error ) { - - $error_data = ( ! empty( $validation_error['data'] ) && is_array( $validation_error['data'] ) ) ? $validation_error['data'] : []; - $error_sources = ( ! empty( $error_data['sources'] ) && is_array( $error_data['sources'] ) ) ? $error_data['sources'] : []; - - if ( empty( $error_data ) || empty( $error_sources ) ) { - continue; - } - - unset( $error_data['sources'] ); - $error_data = static::normalize_error( $error_data ); - - /** - * Store error data in all error list. - */ - if ( ! empty( $error_data ) && is_array( $error_data ) ) { - $error_list[ $error_data['error_slug'] ] = $error_data; - } - - /** - * Source loop. - */ - foreach ( $error_sources as $index => $source ) { - $source['error_slug'] = $error_data['error_slug']; - $error_sources[ $index ] = static::normalize_error_source( $source ); - - /** - * Store error source in all error_source list. - */ - if ( ! empty( $error_sources[ $index ] ) && is_array( $error_sources[ $index ] ) ) { - $error_source_list[ $error_sources[ $index ]['error_source_slug'] ] = $error_sources[ $index ]; - } - } - - $error_sources = array_filter( $error_sources ); - $error_source_slugs = wp_list_pluck( $error_sources, 'error_source_slug' ); - $error_source_slugs = array_values( array_unique( $error_source_slugs ) ); - - if ( ! empty( $error_source_slugs ) ) { - $validation_errors[] = [ - 'error_slug' => $error_data['error_slug'], - 'sources' => $error_source_slugs, - ]; - } - } - - // Object information. - $amp_queried_object = get_post_meta( $amp_validated_post->ID, '_amp_queried_object', true ); - $object_type = ( ! empty( $amp_queried_object['type'] ) ) ? $amp_queried_object['type'] : ''; - $object_subtype = ''; - - if ( empty( $object_type ) ) { - $amp_validated_post_url = AMP_Validated_URL_Post_Type::get_url_from_post( $amp_validated_post ); - if ( false !== strpos( $amp_validated_post_url, '?s=' ) ) { - $object_type = 'search'; - } - } - - switch ( $object_type ) { - case 'post': - $post_object = get_post( $amp_queried_object['id'] ); - $object_subtype = ( ! empty( $post_object ) && $post_object instanceof WP_Post ) ? $post_object->post_type : ''; - break; - case 'term': - $term_object = get_term( $amp_queried_object['id'] ); - $object_subtype = ( ! empty( $term_object ) && $term_object instanceof WP_Term ) ? $term_object->taxonomy : ''; - break; - case 'user': - break; - } - - // Stylesheet info. - $stylesheet_info = static::get_stylesheet_info( $amp_validated_post->ID ); - $css_budget_percentage = ( ! empty( $stylesheet_info['css_budget_percentage'] ) ) ? $stylesheet_info['css_budget_percentage'] : 0; - $css_budget_percentage = intval( $css_budget_percentage ); - - if ( empty( $validation_errors ) && $css_budget_percentage < 100 ) { - return []; - } - - $amp_invalid_url = [ - 'url' => AMP_Validated_URL_Post_Type::get_url_from_post( $amp_validated_post ), - 'object_type' => $object_type, - 'object_subtype' => $object_subtype, - 'css_size_before' => ( ! empty( $stylesheet_info['css_size_before'] ) ) ? $stylesheet_info['css_size_before'] : '', - 'css_size_after' => ( ! empty( $stylesheet_info['css_size_after'] ) ) ? $stylesheet_info['css_size_after'] : '', - 'css_size_excluded' => ( ! empty( $stylesheet_info['css_size_excluded'] ) ) ? $stylesheet_info['css_size_excluded'] : '', - 'css_budget_percentage' => $css_budget_percentage, - 'errors' => $validation_errors, - ]; - - return [ - 'errors' => $error_list, - 'error_sources' => $error_source_list, - 'url' => $amp_invalid_url, - ]; - - } - - /** - * Get style sheet info of the post. - * - * @since 2.2 - * - * Reference: AMP_Validated_URL_Post_Type::print_stylesheets_meta_box() - * - * @param int $post_id Post ID. - * - * @return array AMP stylesheet used info. - */ - public static function get_stylesheet_info( $post_id ) { - - $stylesheets = get_post_meta( $post_id, AMP_Validated_URL_Post_Type::STYLESHEETS_POST_META_KEY, true ); - - if ( empty( $stylesheets ) ) { - return []; - } - - $stylesheets = json_decode( $stylesheets, true ); - $style_custom_cdata_spec = null; - - foreach ( \AMP_Allowed_Tags_Generated::get_allowed_tag( 'style' ) as $spec_rule ) { - if ( isset( $spec_rule[ \AMP_Rule_Spec::TAG_SPEC ]['spec_name'] ) && \AMP_Style_Sanitizer::STYLE_AMP_CUSTOM_SPEC_NAME === $spec_rule[ \AMP_Rule_Spec::TAG_SPEC ]['spec_name'] ) { - $style_custom_cdata_spec = $spec_rule[ \AMP_Rule_Spec::CDATA ]; - } - } - - $included_final_size = 0; - $included_original_size = 0; - $excluded_final_size = 0; - $excluded_original_size = 0; - $excluded_stylesheets = 0; - $max_final_size = 0; - - $included_status = 1; - $excessive_status = 2; - $excluded_status = 3; - - // Determine which stylesheets are included based on their priorities. - $pending_stylesheet_indices = array_keys( $stylesheets ); - usort( - $pending_stylesheet_indices, - static function ( $a, $b ) use ( $stylesheets ) { - - return $stylesheets[ $a ]['priority'] - $stylesheets[ $b ]['priority']; - } - ); - - foreach ( $pending_stylesheet_indices as $i ) { - - if ( ! isset( $stylesheets[ $i ]['group'] ) || 'amp-custom' !== $stylesheets[ $i ]['group'] || ! empty( $stylesheets[ $i ]['duplicate'] ) ) { - continue; - } - - $max_final_size = max( $max_final_size, $stylesheets[ $i ]['final_size'] ); - if ( $stylesheets[ $i ]['included'] ) { - $included_final_size += $stylesheets[ $i ]['final_size']; - $included_original_size += $stylesheets[ $i ]['original_size']; - - if ( $included_final_size >= $style_custom_cdata_spec['max_bytes'] ) { - $stylesheets[ $i ]['status'] = $excessive_status; - } else { - $stylesheets[ $i ]['status'] = $included_status; - } - } else { - $excluded_final_size += $stylesheets[ $i ]['final_size']; - $excluded_original_size += $stylesheets[ $i ]['original_size']; - $excluded_stylesheets ++; - $stylesheets[ $i ]['status'] = $excluded_status; - } - } - - $percentage_budget_used = ( ( $included_final_size + $excluded_final_size ) / $style_custom_cdata_spec['max_bytes'] ) * 100; - $response = [ - 'css_size_before' => intval( $included_original_size + $excluded_original_size ), - 'css_size_after' => intval( $included_final_size + $excluded_final_size ), - 'css_size_excluded' => intval( $excluded_stylesheets ), - 'css_budget_percentage' => round( $percentage_budget_used, 1 ), - ]; - - return $response; - - } - - /** - * To get home url of the site. - * Note: It will give home url without protocol. - * - * @since 2.2 - * - * @return string Home URL. - */ - public static function get_home_url() { - - $home_url = home_url(); - $home_url = strtolower( trim( $home_url ) ); - - $http_protocol = wp_parse_url( $home_url, PHP_URL_SCHEME ); - - $home_url = str_replace( "$http_protocol://", '', $home_url ); - $home_url = untrailingslashit( $home_url ); - - return $home_url; - } - - /** - * To remove home url from the content. - * - * @since 2.2 - * - * @param mixed $content Content from home_url need to remove. - * - * @return string|array Content after removing home_url. - */ - public static function remove_domain( $content ) { - - if ( empty( $content ) ) { - return ''; - } elseif ( is_numeric( $content ) ) { - return $content; - } - - $home_url = static::get_home_url(); - $home_url = str_replace( [ '.', '/' ], [ '\.', '\\\\{1,5}\/' ], $home_url ); - - /** - * Reference: https://regex101.com/r/c25pNF/1 - */ - $regex = "/http[s]?:\\\\{0,5}\/\\\\{0,5}\/$home_url/mU"; - - if ( is_string( $content ) ) { - return preg_replace( $regex, '', $content ); - } - - if ( is_object( $content ) ) { - $content = (array) $content; - } - - if ( is_array( $content ) ) { - return array_map( - static function ( $item ) { - return self::remove_domain( $item ); - }, - $content - ); - } - - return $content; - } - - /** - * To generate hash of object. - * - * @since 2.2 - * - * @param string|array|object $object Object for that hash need to generate. - * - * @return string Hash value of provided object. - */ - public static function generate_hash( $object ) { - - if ( empty( $object ) ) { - return ''; - } - - if ( is_object( $object ) ) { - $object = (array) $object; - } - - if ( is_array( $object ) ) { - ksort( $object ); - $object = wp_json_encode( $object ); - } - - $object = trim( $object ); - $hash = hash( 'sha256', $object ); - - return $hash; - } -} diff --git a/src/Support/SupportRESTController.php b/src/Support/SupportRESTController.php deleted file mode 100644 index ab79f08a3d7..00000000000 --- a/src/Support/SupportRESTController.php +++ /dev/null @@ -1,128 +0,0 @@ -injector = $injector; - } - - /** - * Get the action to use for registering the service. - * - * @return string Registration action to use. - */ - public static function get_registration_action() { - - return 'rest_api_init'; - } - - /** - * Registers all routes for the controller. - */ - public function register() { - - register_rest_route( - $this->namespace, - '/send-diagnostic', - [ - [ - 'methods' => WP_REST_Server::CREATABLE, - 'args' => [], - 'permission_callback' => [ $this, 'permission_callback' ], - 'callback' => [ $this, 'callback' ], - ], - ] - ); - } - - /** - * Permission check to send support data. - * - * @return bool True if user have permission. Otherwise False. - */ - public function permission_callback() { - - return current_user_can( 'manage_options' ); - } - - /** - * Send AMP support data to insight server. - * - * @param WP_REST_Request $request REST API request. - * - * @return WP_Error|WP_HTTP_Response|WP_REST_Response REST API response. - */ - public function callback( WP_REST_Request $request ) { - - $request_args = $request->get_param( 'args' ); - $request_args = ( ! empty( $request_args ) && is_array( $request_args ) ) ? $request_args : []; - - $support_data = $this->injector->make( SupportData::class, [ 'args' => $request_args ] ); - $support_response = $support_data->send_data(); - - $response = new WP_Error( - 'fail_to_send_data', - __( 'Failed to send support request. Please try again later.', 'amp' ), - [ 'status' => 500 ] - ); - - if ( ! empty( $support_response ) && is_wp_error( $support_response ) ) { - $response = $support_response; - } - - if ( 'ok' === $support_response['status'] && ! empty( $support_response['data']['uuid'] ) ) { - $response = [ - 'success' => true, - 'data' => $support_response['data'], - ]; - } - - return rest_ensure_response( $response ); - } -} diff --git a/src/Validation/URLValidationRESTController.php b/src/Validation/URLValidationRESTController.php index b585f715b8e..beeedfa1b08 100644 --- a/src/Validation/URLValidationRESTController.php +++ b/src/Validation/URLValidationRESTController.php @@ -214,15 +214,10 @@ public function validate_post_url( $request ) { return $validity; } - $query_args = [ - 'page' => 'amp-support', - 'url' => rawurlencode( get_permalink( $post_id ) ), - ]; - $data = [ 'results' => [], 'review_link' => get_edit_post_link( $validity['post_id'], 'raw' ), - 'support_link' => add_query_arg( $query_args, admin_url( 'admin.php' ) ), + 'support_link' => 'https://wordpress.org/support/plugin/amp/#new-topic-0', ]; foreach ( AMP_Validated_URL_Post_Type::get_invalid_url_validation_errors( $validity['post_id'] ) as $result ) { diff --git a/tests/features/support-request.feature b/tests/features/support-request.feature deleted file mode 100644 index 9de9bfb2472..00000000000 --- a/tests/features/support-request.feature +++ /dev/null @@ -1,27 +0,0 @@ -Feature: AMP Support Request - - Background: - Given a WP installation with the AMP plugin - - Scenario: Check AMP Support request data. - When I run the WP-CLI command `amp support send-diagnostic --print=json-pretty` - - Then STDERR should be empty - - And STDOUT should contain following STRINGS: - | "site_info": { | - | "site_url": | - | "site_title": | - | "php_version": | - | "mysql_version": | - | "wp_version": | - | "wp_language": | - | "wp_https_status": | - | "wp_multisite": | - | "wp_active_theme": { | - | "plugins": [ | - | "themes": [ | - | "errors": [ | - | "error_sources": [ | - | "urls": [ | - | "error_log": { | diff --git a/tests/php/src/Admin/SupportLinkTest.php b/tests/php/src/Admin/SupportLinkTest.php index 32ef491f078..14b5d164cac 100644 --- a/tests/php/src/Admin/SupportLinkTest.php +++ b/tests/php/src/Admin/SupportLinkTest.php @@ -59,20 +59,6 @@ public function test_get_registration_action() { ); } - /** - * @covers ::is_needed() - */ - public function test_is_needed() { - - // Test 1: Test for users that don't have permission. - $this->assertFalse( SupportLink::is_needed() ); - - // Test 2: Test with admin user. - $this->mock_admin_user(); - - $this->assertTrue( SupportLink::is_needed() ); - } - /** * @covers ::register() */ @@ -134,7 +120,7 @@ public function test_admin_bar_menu() { $node = $admin_bar->get_node( 'amp-support' ); $this->assertInstanceOf( 'stdClass', $node ); - $this->assertStringContainsString( 'page=amp-support', $node->href ); + $this->assertStringContainsString( 'https://wordpress.org/support/plugin/amp/', $node->href ); } /** @@ -151,12 +137,7 @@ public function test_amp_validated_url_status_actions() { $actions = $this->instance->amp_validated_url_status_actions( [], $post ); $this->assertStringContainsString( - 'page=amp-support', - $actions['amp-support'] - ); - - $this->assertStringContainsString( - sprintf( 'url=%s', rawurlencode( $post->post_title ) ), + 'https://wordpress.org/support/plugin/amp/', $actions['amp-support'] ); } @@ -184,12 +165,7 @@ public function test_post_row_actions() { $actions = $this->instance->post_row_actions( [], $post ); $this->assertStringContainsString( - 'page=amp-support', - $actions['amp-support'] - ); - - $this->assertStringContainsString( - sprintf( 'url=%s', rawurlencode( $post->post_title ) ), + 'https://wordpress.org/support/plugin/amp/', $actions['amp-support'] ); } @@ -208,12 +184,7 @@ public function test_plugin_row_meta() { $should_have = sprintf( '%s', - esc_url( - add_query_arg( - [ 'page' => 'amp-support' ], - admin_url( 'admin.php' ) - ) - ), + esc_url( 'https://wordpress.org/support/plugin/amp/' ), esc_html__( 'Get support', 'amp' ) ); diff --git a/tests/php/src/Admin/SupportScreenTest.php b/tests/php/src/Admin/SupportScreenTest.php deleted file mode 100644 index 160cc6e08ea..00000000000 --- a/tests/php/src/Admin/SupportScreenTest.php +++ /dev/null @@ -1,259 +0,0 @@ -markTestSkipped( 'Test requires Site Health.' ); - } - - global $wp_version; - $this->original_wp_version = $wp_version; - - $this->instance = $this->injector->make( SupportScreen::class ); - - $this->add_home_url_loopback_request_mocking(); - } - - /** - * Tear down. - * - * @inheritDoc - */ - public function tear_down() { - parent::tear_down(); - - global $wp_version; - $wp_version = $this->original_wp_version; - } - - /** @covers ::__construct() */ - public function test__construct() { - - $this->assertInstanceOf( Conditional::class, $this->instance ); - $this->assertInstanceOf( Delayed::class, $this->instance ); - $this->assertInstanceOf( Registerable::class, $this->instance ); - $this->assertInstanceOf( Service::class, $this->instance ); - $this->assertInstanceOf( SupportScreen::class, $this->instance ); - } - - /** - * @covers ::get_registration_action - */ - public function test_get_registration_action() { - $this->assertEquals( 'init', SupportScreen::get_registration_action() ); - } - - /** - * @covers ::is_needed() - * @covers ::has_cap() - */ - public function test_is_needed() { - - // Without mocking. - $this->assertFalse( SupportScreen::is_needed() ); - $this->assertFalse( SupportScreen::has_cap() ); - - // Mock the is_admin() with required user caps. - $this->mock_admin_user(); - - $this->assertFalse( SupportScreen::is_needed() ); - $this->assertTrue( SupportScreen::has_cap() ); - - set_current_screen( $this->instance->screen_handle() ); - $this->assertTrue( SupportScreen::is_needed() ); - $this->assertTrue( SupportScreen::has_cap() ); - - // Access denied when user cannot validate. - add_filter( - 'map_meta_cap', - function ( $caps, $cap ) { - if ( AMP_Validation_Manager::VALIDATE_CAPABILITY === $cap ) { - $caps[] = 'do_not_allow'; - } - return $caps; - }, - 10, - 3 - ); - $this->assertFalse( SupportScreen::is_needed() ); - $this->assertFalse( SupportScreen::has_cap() ); - - // Reset data. - unset( $GLOBALS['current_screen'] ); - } - - /** - * @covers ::register - */ - public function test_register() { - - $this->instance->register(); - - $this->assertEquals( 10, has_action( 'admin_enqueue_scripts', [ $this->instance, 'enqueue_assets' ] ) ); - $this->assertEquals( 9, has_action( 'admin_menu', [ $this->instance, 'add_menu_items' ] ) ); - } - - /** - * @covers ::get_menu_slug - */ - public function test_get_menu_slug() { - - $this->assertEquals( 'amp-support', $this->instance->get_menu_slug() ); - } - - /** - * @covers ::screen_handle - */ - public function test_screen_handle() { - - $this->assertEquals( - sprintf( 'amp_page_%s', $this->instance->get_menu_slug() ), - $this->instance->screen_handle() - ); - } - - /** - * @covers ::add_menu_items - */ - public function test_add_menu_items() { - - global $submenu; - - wp_set_current_user( - self::factory()->user->create( - [ - 'role' => 'administrator', - ] - ) - ); - - $this->instance->add_menu_items(); - - $this->assertArrayHasKey( 'amp-options', $submenu ); - $this->assertContains( - [ - 'Support', - 'manage_options', - 'amp-support', - 'Support', - ], - $submenu['amp-options'] - ); - } - - /** - * @covers ::enqueue_assets - */ - public function test_enqueue_assets() { - - $wp_scripts = wp_scripts(); - $wp_styles = wp_styles(); - - $this->instance->enqueue_assets( '' ); - - $this->assertArrayNotHasKey( SupportScreen::ASSET_HANDLE, $wp_scripts->registered ); - $this->assertArrayNotHasKey( SupportScreen::ASSET_HANDLE, $wp_styles->registered ); - - $this->instance->enqueue_assets( $this->instance->screen_handle() ); - - $this->assertArrayHasKey( SupportScreen::ASSET_HANDLE, $wp_scripts->registered ); - $this->assertArrayHasKey( SupportScreen::ASSET_HANDLE, $wp_styles->registered ); - } - - /** - * @covers ::render_screen - */ - public function test_render_screen() { - - ob_start(); - $this->instance->render_screen(); - $content = ob_get_clean(); - - $this->assertStringContainsString( '
', $content ); - } - - /** - * @covers ::get_amp_validated_post_counts() - */ - public function test_get_amp_validated_post_counts() { - - $validated_environment = AMP_Validated_URL_Post_Type::get_validated_environment(); - - $this->factory()->post->create_and_get( - [ - 'post_title' => home_url( 'sample-page-for-amp-validation' ), - 'post_type' => AMP_Validated_URL_Post_Type::POST_TYPE_SLUG, - 'meta_input' => [ - AMP_Validated_URL_Post_Type::VALIDATED_ENVIRONMENT_POST_META_KEY => $validated_environment, - ], - ] - ); - - $stale_validated_environment = $validated_environment; - $stale_validated_environment['options']['theme_support'] = 'standard'; - - $this->factory()->post->create_and_get( - [ - 'post_title' => home_url( 'sample-page-for-amp-validation-stale' ), - 'post_type' => AMP_Validated_URL_Post_Type::POST_TYPE_SLUG, - 'meta_input' => [ - AMP_Validated_URL_Post_Type::VALIDATED_ENVIRONMENT_POST_META_KEY => $stale_validated_environment, - ], - ] - ); - - $this->assertEquals( - [ - 'all' => 2, - 'fresh' => 1, - 'stale' => 1, - ], - $this->instance->get_amp_validated_post_counts() - ); - } -} diff --git a/tests/php/src/Support/SupportCliCommandTest.php b/tests/php/src/Support/SupportCliCommandTest.php deleted file mode 100644 index ddf975e05e7..00000000000 --- a/tests/php/src/Support/SupportCliCommandTest.php +++ /dev/null @@ -1,28 +0,0 @@ -assertEquals( 'amp support', SupportCliCommand::get_command_name() ); - } -} diff --git a/tests/php/src/Support/SupportDataTest.php b/tests/php/src/Support/SupportDataTest.php deleted file mode 100644 index 9232cf19809..00000000000 --- a/tests/php/src/Support/SupportDataTest.php +++ /dev/null @@ -1,739 +0,0 @@ - null, - 'log_errors' => null, - ]; - - /** - * Set up. - * - * @inheritdoc - */ - public function set_up() { - - parent::set_up(); - - $this->instance = $this->injector->make( SupportData::class ); - - foreach ( array_keys( $this->previous_ini_config ) as $key ) { - $this->previous_ini_config[ $key ] = ini_get( $key ); - } - - ini_set( 'log_errors', 1 ); // phpcs:ignore WordPress.PHP.IniSet.log_errors_Blacklisted, WordPress.PHP.IniSet.Risky - ini_set( 'error_log', $this->temp_filename() ); // phpcs:ignore WordPress.PHP.IniSet.log_errors_Blacklisted, WordPress.PHP.IniSet.Risky - - $this->add_home_url_loopback_request_mocking(); - } - - /** - * Tear down. - * - * @inheritdoc - */ - public function tear_down() { - parent::tear_down(); - foreach ( $this->previous_ini_config as $key => $value ) { - ini_set( $key, $value ); // phpcs:ignore WordPress.PHP.IniSet.log_errors_Blacklisted, WordPress.PHP.IniSet.Risky - } - } - - /** - * @covers ::__construct() - * @covers ::parse_args() - */ - public function test_parse_args() { - - $url_post_id = $this->factory()->post->create( [] ); - $post_id = $this->factory()->post->create( [] ); - $term_id = $this->factory()->category->create( [] ); - $amp_validated_post = $this->factory()->post->create_and_get( - [ - 'post_title' => home_url( 'sample-page-for-amp-validation' ), - 'post_type' => AMP_Validated_URL_Post_Type::POST_TYPE_SLUG, - ] - ); - - $input = [ - 'urls' => [ get_permalink( $url_post_id ) ], - 'post_ids' => [ $post_id ], - 'term_ids' => [ $term_id ], - 'amp_validated_post_ids' => [ $amp_validated_post->ID ], - ]; - - $expected = array_map( - static function ( $url ) { - return AMP_Validated_URL_Post_Type::normalize_url_for_storage( $url ); - }, - [ - get_permalink( $url_post_id ), - get_term_link( $term_id ), - get_permalink( $post_id ), - $amp_validated_post->post_title, - ] - ); - - $instance = new SupportData( $input ); - - $this->assertEquals( $expected, $instance->urls ); - - } - - /** - * Create validated URL. - * - * @return array Validated URL posts. - */ - public function create_validated_url() { - - $plugin_info = SupportData::normalize_plugin_info( 'amp/amp.php' ); - - $post = $this->factory()->post->create_and_get( - [ - 'post_content' => 'Some post content', - ] - ); - - $term = $this->factory()->term->create_and_get(); - - $validated_url_post_content = wp_json_encode( - [ - [ - 'term_slug' => '1', - 'data' => [ - 'node_name' => 'script', - 'parent_name' => 'head', - 'code' => 'DISALLOWED_TAG', - 'type' => 'js_error', - 'node_attributes' => [ - 'src' => home_url( '/wp-includes/js/jquery/jquery.js?ver=__normalized__' ), - 'id' => 'jquery-core-js', - ], - 'node_type' => 1, - 'sources' => [ - [ - 'type' => 'plugin', - 'name' => $plugin_info['slug'], - 'file' => $plugin_info['slug'], - 'line' => 350, - 'function' => 'dummy_function', - 'hook' => 'wp_enqueue_scripts', - 'priority' => 10, - 'dependency_type' => 'script', - 'handle' => 'hello-script', - 'dependency_handle' => 'jquery-core', - 'text' => 'Start of the content. ' . home_url( '/additional.css' ) . ' End of the content', - ], - ], - ], - ], - ] - ); - - $validated_posts = []; - - $post_url = AMP_Validated_URL_Post_Type::normalize_url_for_storage( get_permalink( $post ) ); - $validated_posts['post'] = $this->factory()->post->create_and_get( - [ - 'post_title' => $post_url, - 'post_name' => md5( $post_url ), - 'post_type' => AMP_Validated_URL_Post_Type::POST_TYPE_SLUG, - 'post_content' => $validated_url_post_content, - 'meta_input' => [ - '_amp_queried_object' => [ - 'id' => $post->ID, - 'type' => 'post', - ], - AMP_Validated_URL_Post_Type::VALIDATED_ENVIRONMENT_POST_META_KEY => AMP_Validated_URL_Post_Type::get_validated_environment(), - ], - ] - ); - - $term_url = AMP_Validated_URL_Post_Type::normalize_url_for_storage( get_term_link( $term ) ); - $validated_posts['term'] = $this->factory()->post->create_and_get( - [ - 'post_title' => $term_url, - 'post_name' => md5( $term_url ), - 'post_type' => AMP_Validated_URL_Post_Type::POST_TYPE_SLUG, - 'post_content' => $validated_url_post_content, - 'meta_input' => [ - '_amp_queried_object' => [ - 'id' => $term->term_id, - 'type' => 'term', - ], - AMP_Validated_URL_Post_Type::VALIDATED_ENVIRONMENT_POST_META_KEY => AMP_Validated_URL_Post_Type::get_validated_environment(), - ], - ] - ); - - $search_url = AMP_Validated_URL_Post_Type::normalize_url_for_storage( home_url( '?s=example' ) ); - $validated_posts['search'] = $this->factory()->post->create_and_get( - [ - 'post_title' => $search_url, - 'post_name' => md5( $search_url ), - 'post_type' => AMP_Validated_URL_Post_Type::POST_TYPE_SLUG, - 'post_content' => $validated_url_post_content, - 'meta_input' => [ - '_amp_queried_object' => [ - 'type' => 'search', - ], - AMP_Validated_URL_Post_Type::VALIDATED_ENVIRONMENT_POST_META_KEY => AMP_Validated_URL_Post_Type::get_validated_environment(), - ], - ] - ); - - return $validated_posts; - } - - /** - * @covers ::send_data() - * @covers ::get_data() - * @covers ::process_raw_post_errors() - */ - public function test_send_data() { - - $this->create_validated_url(); - - // Mock http request. - $support_data = []; - $expected_response = [ - 'status' => 'ok', - 'data' => [ - 'uuid' => 'ampwp-563e5de8-3129-55fb-af71-a6fbd9ef5026', - ], - ]; - - $callback_wp_remote = static function ( $preempt, $parsed_args ) use ( &$support_data, $expected_response ) { - - $support_data = $parsed_args['body']; - - return [ - 'body' => wp_json_encode( $expected_response ), - ]; - }; - - add_filter( 'pre_http_request', $callback_wp_remote, 10, 2 ); - - $instance = new SupportData( [] ); - $instance->send_data(); - - $support_data_keys = [ - 'site_url', - 'site_info', - 'plugins', - 'themes', - 'errors', - 'error_sources', - 'urls', - 'error_log', - ]; - - foreach ( $support_data_keys as $key ) { - $this->assertArrayHasKey( $key, $support_data ); - } - - $this->assertEquals( SupportData::get_home_url(), $support_data['site_url'] ); - - remove_filter( 'pre_http_request', $callback_wp_remote ); - } - - /** - * @covers ::get_data() - * @covers ::get_amp_urls() - * @covers ::process_raw_post_errors() - */ - public function test_get_data_with_specific_url() { - - $amp_validated_posts = $this->create_validated_url(); - - $search_urls = home_url( '?s=example' ); - - $instance = new SupportData( - [ - 'urls' => [ - $search_urls, - ], - ] - ); - - $output = $instance->get_data(); - - $this->assertCount( 1, $output['urls'] ); - $this->assertEquals( - AMP_Validated_URL_Post_Type::get_url_from_post( $amp_validated_posts['search'] ), - $output['urls'][0]['url'] - ); - } - - /** - * @covers ::send_data() - */ - public function test_send_data_with_error() { - $callback_wp_remote = static function ( $preempt, $parsed_args ) use ( &$support_data ) { - - $support_data = $parsed_args['body']; - - return [ - 'body' => 'some invalid string', - ]; - }; - add_filter( 'pre_http_request', $callback_wp_remote, 10, 2 ); - - $instance = new SupportData( [] ); - $response = $instance->send_data(); - - $this->assertInstanceOf( WP_Error::class, $response ); - - remove_filter( 'pre_http_request', $callback_wp_remote ); - } - - /** - * Test get_error_log method. - * - * @covers ::get_error_log() - */ - public function test_get_error_log() { - $instance = new SupportData( [] ); - $output = $instance->get_error_log(); - - $log_path = ini_get( 'error_log' ); - $this->assertArrayHasKey( 'log_errors', $output ); - $this->assertArrayHasKey( 'contents', $output ); - - $this->assertTrue( is_writable( $log_path ) ); - - $input_content = ''; - $expected_content = ''; - - for ( $i = 1; $i <= 300; $i ++ ) { - $input_content .= "Line: $i\n"; - } - - for ( $i = 101; $i <= 300; $i ++ ) { - $expected_content .= "Line: $i\n"; - } - $expected_content = trim( $expected_content, "\n" ); - - file_put_contents( $log_path, $input_content ); - $output = $instance->get_error_log(); - - $this->assertEquals( $expected_content, $output['contents'] ); - } - - /** - * @covers ::get_site_info() - */ - public function test_get_site_info() { - - $site_info = $this->instance->get_site_info(); - - $site_info_keys = [ - 'site_url', - 'site_title', - 'php_version', - 'mysql_version', - 'wp_version', - 'wp_language', - 'wp_https_status', - 'wp_multisite', - 'wp_active_theme', - 'object_cache_status', - 'libxml_version', - 'is_defined_curl_multi', - 'loopback_requests', - 'amp_mode', - 'amp_version', - 'amp_plugin_configured', - 'amp_all_templates_supported', - 'amp_supported_post_types', - 'amp_supported_templates', - 'amp_mobile_redirect', - 'amp_reader_theme', - ]; - - foreach ( $site_info_keys as $key ) { - $this->assertArrayHasKey( $key, $site_info ); - } - } - - /** - * @covers ::get_plugin_info() - * @covers ::normalize_plugin_info() - */ - public function test_get_plugin_info() { - - $original_active_plugins = get_option( 'active_plugins' ); - $original_active_plugins = ( ! empty( $original_active_plugins ) && is_array( $original_active_plugins ) ) ? $original_active_plugins : []; - - // Mock the data - update_option( 'active_plugins', [ 'amp/amp.php' ] ); - - $plugin_info = $this->instance->get_plugin_info(); - $this->assertTrue( count( $plugin_info ) >= 1 ); - $plugin_info = array_filter( - $plugin_info, - static function ( $plugin ) { - return 'amp' === $plugin['slug']; - } - ); - - $expected_plugin_info = SupportData::normalize_plugin_info( 'amp/amp.php' ); - - $this->assertEquals( 'AMP', $plugin_info[0]['name'] ); - $this->assertEquals( 'amp', $plugin_info[0]['slug'] ); - - $plugin_keys = [ - 'name', - 'slug', - 'plugin_url', - 'version', - 'author', - 'author_url', - 'requires_wp', - 'requires_php', - 'is_active', - 'is_network_active', - 'is_suppressed', - ]; - - foreach ( $plugin_keys as $key ) { - $this->assertArrayHasKey( $key, $plugin_info[0] ); - $this->assertEquals( $expected_plugin_info[ $key ], $plugin_info[0][ $key ] ); - } - - // Restore data. - update_option( 'active_plugins', $original_active_plugins ); - } - - /** - * @covers ::get_theme_info() - * @covers ::normalize_theme_info() - */ - public function test_get_theme_info() { - - $theme_info = $this->instance->get_theme_info(); - if ( ! isset( $theme_info[0] ) ) { - $this->markTestSkipped( 'No active theme.' ); - } - - $active_theme = SupportData::normalize_theme_info( wp_get_theme() ); - - $theme_keys = [ - 'name', - 'slug', - 'version', - 'status', - 'tags', - 'text_domain', - 'requires_wp', - 'requires_php', - 'theme_url', - 'author', - 'author_url', - 'is_active', - 'parent_theme', - ]; - - foreach ( $theme_keys as $key ) { - $this->assertArrayHasKey( $key, $theme_info[0] ); - $this->assertEquals( $active_theme[ $key ], $theme_info[0][ $key ] ); - } - - } - - /** - * Data provider for $this->test_normalize_error_data() - * - * @return array - */ - public function normalize_error_data_provider() { - - return [ - 'empty' => [ - 'input' => [], - 'expected' => [], - ], - 'normalize' => [ - 'input' => [ - 'node_name' => 'script', - 'parent_name' => 'head', - 'code' => 'DISALLOWED_TAG', - 'type' => 'js_error', - 'node_attributes' => [ - 'src' => home_url( '/wp-includes/js/jquery/jquery.js?ver=__normalized__' ), - 'id' => 'jquery-core-js', - ], - 'node_type' => 1, - 'sources' => [ 'some data' ], - ], - 'expected' => [ - 'node_name' => 'script', - 'parent_name' => 'head', - 'code' => 'DISALLOWED_TAG', - 'node_attributes' => [ - 'src' => '/wp-includes/js/jquery/jquery.js?ver=__normalized__', - 'id' => 'jquery-core-js', - ], - 'node_type' => 1, - 'text' => '', - 'type' => 'js_error', - 'error_slug' => 'dc023279738b7ab0fd76fd6a6e004320039cba2f2eee04b30a5f3843262c2d0b', - ], - ], - ]; - } - - /** - * @dataProvider normalize_error_data_provider - * @covers ::normalize_error() - * @covers ::remove_domain() - * @covers ::generate_hash() - */ - public function test_normalize_error( $input, $expected ) { - - $this->assertEquals( $expected, SupportData::normalize_error( $input ) ); - } - - /** - * Data provider for $this->test_normalize_error_source() - * - * @return array - */ - public function normalize_error_source_data_provider() { - - $plugin_info = SupportData::normalize_plugin_info( 'amp/amp.php' ); - - $themes = wp_get_themes(); - $theme_info = array_pop( $themes ); - $theme_info = SupportData::normalize_theme_info( $theme_info ); - - $data = [ - 'empty' => [ - 'input' => [], - 'expected' => [], - ], - 'core' => [ - 'input' => [ - 'type' => 'core', - 'name' => 'wp-includes', - 'file' => 'script-loader.php', - 'line' => 2021, - 'function' => 'wp_enqueue_scripts', - 'hook' => 'wp_head', - 'priority' => 1, - 'dependency_type' => 'script', - 'handle' => 'jquery-blockui', - 'dependency_handle' => 'jquery-core', - ], - 'expected' => [], - ], - 'plugin' => [ - 'input' => [ - 'type' => 'plugin', - 'name' => $plugin_info['slug'], - 'file' => $plugin_info['slug'], - 'line' => 350, - 'function' => 'dummy_function', - 'hook' => 'wp_enqueue_scripts', - 'priority' => 10, - 'dependency_type' => 'script', - 'handle' => 'hello-script', - 'dependency_handle' => 'jquery-core', - 'text' => 'Start of the content. ' . home_url( '/additional.css' ) . ' End of the content', - ], - 'expected' => [ - 'dependency_handle' => 'jquery-core', - 'dependency_type' => 'script', - 'file' => $plugin_info['slug'], - 'function' => 'dummy_function', - 'handle' => 'hello-script', - 'hook' => 'wp_enqueue_scripts', - 'line' => 350, - 'name' => $plugin_info['slug'], - 'priority' => 10, - 'text' => 'Start of the content. /additional.css End of the content', - 'type' => 'plugin', - 'version' => $plugin_info['version'], - ], - ], - 'theme' => [ - 'input' => [ - 'type' => 'theme', - 'name' => $theme_info['slug'], - 'file' => 'inc/template-functions.php', - 'line' => 403, - 'function' => 'theme_post_content', - 'hook' => 'theme_loop_post', - 'priority' => 30, - ], - 'expected' => [ - 'file' => 'inc/template-functions.php', - 'function' => 'theme_post_content', - 'hook' => 'theme_loop_post', - 'line' => 403, - 'name' => $theme_info['slug'], - 'priority' => 30, - 'type' => 'theme', - 'version' => $theme_info['version'], - ], - ], - ]; - - foreach ( [ 'plugin', 'theme' ] as $key ) { - $data[ $key ]['expected']['error_source_slug'] = SupportData::generate_hash( $data[ $key ]['expected'] ); - ksort( $data[ $key ]['expected'] ); - } - - return $data; - } - - /** - * @dataProvider normalize_error_source_data_provider - * @covers ::normalize_error_source() - * @covers ::generate_hash() - */ - public function test_normalize_error_source( $input, $expected ) { - - $this->assertEquals( $expected, SupportData::normalize_error_source( $input ) ); - } - - /** - * Test get_amp_urls method. - * - * @covers ::get_amp_urls() - * @covers ::get_stylesheet_info() - * @covers ::process_raw_post_errors() - */ - public function test_get_amp_urls() { - - $this->create_validated_url(); - $data = $this->instance->get_amp_urls(); - - $this->assertCount( 1, $data['errors'] ); - $this->assertCount( 1, $data['error_sources'] ); - $this->assertCount( 3, $data['urls'] ); - - $keys = [ - 'url', - 'object_type', - 'object_subtype', - 'css_size_before', - 'css_size_after', - 'css_size_excluded', - 'css_budget_percentage', - 'errors', - ]; - - foreach ( $keys as $key ) { - $this->assertArrayHasKey( $key, $data['urls'][0] ); - } - } - - /** - * @covers ::get_home_url() - */ - public function test_get_home_url() { - - $home_url = home_url(); - $home_url = strtolower( trim( $home_url ) ); - $http_protocol = wp_parse_url( $home_url, PHP_URL_SCHEME ); - $home_url = str_replace( "$http_protocol://", '', $home_url ); - $home_url = untrailingslashit( $home_url ); - - $this->assertEquals( $home_url, SupportData::get_home_url() ); - } - - /** - * @covers ::remove_domain() - */ - public function test_remove_domain() { - - // Test 1: With string. - $input = home_url( '/sample-page/' ); - $expected = '/sample-page/'; - - $this->assertEquals( $expected, SupportData::remove_domain( $input ) ); - - // Test 2: With array and object. - $input_object = new stdClass(); - $input_object->key_1 = 'value_1'; - $input_object->key_2 = 'value_2'; - $input_object->key_3 = home_url( '/example-page/' ); - $input_object->key_4 = [ - 'value 1', - home_url( '/sample-page/' ), - home_url( '/sample-page-2/' ), - ]; - $input_array = (object) $input_object; - - $expected = [ - 'key_1' => 'value_1', - 'key_2' => 'value_2', - 'key_3' => '/example-page/', - 'key_4' => [ - 'value 1', - '/sample-page/', - '/sample-page-2/', - ], - ]; - - $this->assertEquals( $expected, SupportData::remove_domain( $input_object ) ); - $this->assertEquals( $expected, SupportData::remove_domain( $input_array ) ); - } - - /** - * @covers ::generate_hash() - */ - public function test_generate_hash() { - - $this->assertEmpty( SupportData::generate_hash( '' ) ); - - $input_data = new stdClass(); - $input_data->key_1 = 'value_1'; - $input_data->key_2 = 'value_2'; - $input_data->key_3 = 'value_3'; - - $expected_data = (array) $input_data; - - ksort( $expected_data ); - - $expected = hash( 'sha256', wp_json_encode( $expected_data ) ); - - $this->assertEquals( $expected, SupportData::generate_hash( $input_data ) ); - - $this->assertEquals( $expected, SupportData::generate_hash( (array) $input_data ) ); - } -} diff --git a/tests/php/src/Support/SupportRESTControllerTest.php b/tests/php/src/Support/SupportRESTControllerTest.php deleted file mode 100644 index f4da8bb5ff9..00000000000 --- a/tests/php/src/Support/SupportRESTControllerTest.php +++ /dev/null @@ -1,186 +0,0 @@ -instance = $this->injector->make( SupportRESTController::class ); - } - - /** - * @covers ::get_registration_action() - */ - public function test_get_registration_action() { - - $this->assertEquals( - 'rest_api_init', - SupportRESTController::get_registration_action() - ); - } - - /** - * @covers ::register() - */ - public function test_register() { - - do_action( 'rest_api_init' ); - - $rest_server = rest_get_server(); - - $namespaces = $this->get_private_property( $rest_server, 'namespaces' ); - - $this->assertContains( - 'amp/v1', - $rest_server->get_namespaces() - ); - - $this->assertContains( - '/amp/v1/send-diagnostic', - array_keys( $namespaces['amp/v1'] ) - ); - } - - /** - * @covers ::permission_callback() - */ - public function test_permission_callback() { - - $this->assertFalse( $this->instance->permission_callback() ); - - // Mock User. - wp_set_current_user( - self::factory()->user->create( - [ - 'role' => 'administrator', - ] - ) - ); - - $this->assertTrue( $this->instance->permission_callback() ); - } - - /** - * Data provider for $this->test_callback() - * - * @return array[] - */ - public function callback_data_provider() { - - return [ - 'fail' => [ - 'request_response' => [ - 'status' => 'fail', - 'data' => [ - 'message' => 'Fail to generate UUID', - ], - ], - 'expected' => new \WP_Error( - 'fail_to_send_data', - 'Failed to send support request. Please try again later.', - [ 'status' => 500 ] - ), - ], - 'success' => [ - 'request_response' => [ - 'status' => 'ok', - 'data' => [ - 'uuid' => 'ampwp-563e5de8-3129-55fb-af71-a6fbd9ef5026', - ], - ], - 'expected' => [ - 'success' => true, - 'data' => [ - 'uuid' => 'ampwp-563e5de8-3129-55fb-af71-a6fbd9ef5026', - ], - ], - ], - ]; - } - - /** - * @dataProvider callback_data_provider - * - * @param array $request_response Value to mock for response for API. - * @param array|WP_Error $expected Expected AJAX response. - * - * @covers ::callback() - */ - public function test_callback( $request_response, $expected ) { - - // Mock User. - wp_set_current_user( - self::factory()->user->create( - [ - 'role' => 'administrator', - ] - ) - ); - - $this->perform_test_on_callback_with( $request_response, $expected ); - } - - /** - * To perform test on $this->ajax_callback(). - * - * @param array $request_response Value to mock for response for API. - * @param array|WP_Error $expected Expected AJAX response. - * - * @return void - */ - private function perform_test_on_callback_with( $request_response, $expected ) { - - $callback_wp_remote = static function () use ( $request_response ) { - - return [ - 'body' => wp_json_encode( $request_response ), - ]; - }; - - add_filter( 'pre_http_request', $callback_wp_remote ); - - $request = new WP_REST_Request( 'POST', $this->instance->namespace . '/send-diagnostic', [] ); - $response = $this->instance->callback( $request ); - - if ( ! is_wp_error( $response ) ) { - $response = $response->get_data(); - } - - $this->assertEquals( $expected, $response ); - - remove_filter( 'pre_http_request', $callback_wp_remote ); - } -} diff --git a/webpack.config.js b/webpack.config.js index e76c4336e09..bf9fde0e26b 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -466,58 +466,6 @@ const settingsPage = { ], }; -const supportPage = { - ...sharedConfig, - entry: { - 'wp-api-fetch': './assets/src/polyfills/api-fetch.js', - 'amp-support': './assets/src/support-page', - }, - externals: { - 'amp-support': 'ampSupport', - }, - resolve: { - alias: { - '@wordpress/api-fetch__non-shim': require.resolve( - '@wordpress/api-fetch' - ), - }, - }, - plugins: [ - ...sharedConfig.plugins.filter( - (plugin) => - plugin.constructor.name !== 'DependencyExtractionWebpackPlugin' - ), - new DependencyExtractionWebpackPlugin({ - useDefaults: false, - // Most dependencies will be bundled for the AMP setup screen for compatibility across WP versions. - requestToHandle: (handle) => { - switch (handle) { - case 'lodash': - case '@wordpress/api-fetch': - return defaultRequestToHandle(handle); - - default: - return undefined; - } - }, - requestToExternal: (external) => { - switch (external) { - case 'lodash': - case '@wordpress/api-fetch': - return defaultRequestToExternal(external); - - default: - return undefined; - } - }, - }), - new WebpackBar({ - name: 'Support Page', - color: '#67b255', - }), - ], -}; - const styles = { ...sharedConfig, entry: () => { @@ -599,7 +547,6 @@ module.exports = [ wpDomReadyPackage, onboardingWizard, settingsPage, - supportPage, styles, mobileRedirection, ];