diff --git a/.distignore b/.distignore new file mode 100755 index 0000000000000000000000000000000000000000..de45f50cb1a7a08e1da5aa43d801213aa7e23503 --- /dev/null +++ b/.distignore @@ -0,0 +1,35 @@ +# A set of files you probably don't want in your WordPress.org distribution +.distignore +.editorconfig +.git +.gitignore +.gitlab-ci.yml +.travis.yml +.DS_Store +Thumbs.db +behat.yml +bitbucket-pipelines.yml +bin +.circleci/config.yml +composer.json +composer.lock +Gruntfile.js +package.json +package-lock.json +phpunit.xml +phpunit.xml.dist +multisite.xml +multisite.xml.dist +.phpcs.xml +phpcs.xml +.phpcs.xml.dist +phpcs.xml.dist +README.md +wp-cli.local.yml +yarn.lock +tests +vendor +node_modules +*.sql +*.tar.gz +*.zip diff --git a/.editorconfig b/.editorconfig new file mode 100755 index 0000000000000000000000000000000000000000..79207a40cb9326b8c6b8c958fa864b5345f94e68 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,22 @@ +# This file is for unifying the coding style for different editors and IDEs +# editorconfig.org + +# WordPress Coding Standards +# https://make.wordpress.org/core/handbook/coding-standards/ + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = tab +indent_size = 4 + +[{.jshintrc,*.json,*.yml}] +indent_style = space +indent_size = 2 + +[{*.txt,wp-config-sample.php}] +end_of_line = crlf diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000000000000000000000000000000000000..6f68bc7f65c25ceae8e856eb9ab25fa815acf0cd --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +phpcs.xml +phpunit.xml +Thumbs.db +wp-cli.local.yml +node_modules/ +*.sql +*.tar.gz +*.zip diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100755 index 0000000000000000000000000000000000000000..0b16bd614d78a376a1333c838df0389915485f72 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,35 @@ +variables: + # Configure mysql service (https://hub.docker.com/_/mysql/) + MYSQL_DATABASE: wordpress_tests + MYSQL_ROOT_PASSWORD: mysql + +cache: + paths: + - $HOME/.composer + - /root/.composer + +before_script: + # Set up WordPress tests + - bash bin/install-wp-tests.sh $MYSQL_DATABASE root $MYSQL_ROOT_PASSWORD mysql latest true + + # PHPUnit + - | + if [[ $(php -v) =~ "PHP 7." ]]; then + composer global require "phpunit/phpunit=6.1.*" + else + composer global require "phpunit/phpunit=4.8.*" + fi + + # Install PHPCS and WPCS + - composer global require automattic/vipwpcs + - composer global require phpcompatibility/phpcompatibility-wp + - phpcs --config-set installed_paths $HOME/.composer/vendor/wp-coding-standards/wpcs,$HOME/.composer/vendor/automattic/vipwpcs,$HOME/.composer/vendor/phpcompatibility/php-compatibility,$HOME/.composer/vendor/phpcompatibility/phpcompatibility-paragonie,$HOME/.composer/vendor/phpcompatibility/phpcompatibility-wp + +PHPunit:PHP7.2:MySQL: + image: containers.ethitter.com:443/docker/images/php:7.2 + services: + - mysql:5.6 + script: + - find . -type "f" -iname "*.php" | xargs -L "1" php -l + - phpcs -n + - phpunit diff --git a/.phpcs.xml.dist b/.phpcs.xml.dist new file mode 100644 index 0000000000000000000000000000000000000000..489f8c5656b4e66a30011c71dad78110d098b443 --- /dev/null +++ b/.phpcs.xml.dist @@ -0,0 +1,50 @@ +<?xml version="1.0"?> +<ruleset name="View All Posts Pages"> + <description>Generally-applicable sniffs for WordPress plugins.</description> + + <!-- What to scan --> + <file>.</file> + <exclude-pattern>/vendor/</exclude-pattern> + <exclude-pattern>/node_modules/</exclude-pattern> + <exclude-pattern>/tests/*</exclude-pattern> + + <!-- How to scan --> + <!-- Usage instructions: https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage --> + <!-- Annotated ruleset: https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml --> + <arg value="sp"/> <!-- Show sniff and progress --> + <arg name="basepath" value="./"/><!-- Strip the file paths down to the relevant bit --> + <arg name="colors"/> + <arg name="extensions" value="php"/> + <arg name="parallel" value="8"/><!-- Enables parallel processing when available for faster results. --> + + <!-- Rules: Check PHP version compatibility --> + <!-- https://github.com/PHPCompatibility/PHPCompatibility#sniffing-your-code-for-compatibility-with-specific-php-versions --> + <config name="testVersion" value="7.2-"/> + <!-- https://github.com/PHPCompatibility/PHPCompatibilityWP --> + <rule ref="PHPCompatibilityWP"/> + + <!-- Rules: WordPress Coding Standards --> + <!-- https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards --> + <!-- https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/wiki/Customizable-sniff-properties --> + <config name="minimum_supported_wp_version" value="3.2.1"/> + <rule ref="WordPress" /> + <rule ref="WordPressVIPMinimum" /> + <rule ref="WordPress-VIP-Go" /> + <rule ref="WordPress.NamingConventions.PrefixAllGlobals"> + <properties> + <!-- Value: replace the function, class, and variable prefixes used. Separate multiple prefixes with a comma. --> + <property name="prefixes" type="array" value="view_all_posts_pages,vapp"/> + </properties> + </rule> + <rule ref="WordPress.WP.I18n"> + <properties> + <!-- Value: replace the text domain used. --> + <property name="text_domain" type="array" value="view_all_posts_pages"/> + </properties> + </rule> + <rule ref="WordPress.WhiteSpace.ControlStructureSpacing"> + <properties> + <property name="blank_line_check" value="true"/> + </properties> + </rule> +</ruleset> diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100755 index 0000000000000000000000000000000000000000..c3f111825b4e16cf82ab53735601ae4f2e0f1419 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,56 @@ +module.exports = function( grunt ) { + + 'use strict'; + + // Project configuration + grunt.initConfig( { + + pkg: grunt.file.readJSON( 'package.json' ), + + addtextdomain: { + options: { + textdomain: 'view_all_posts_pages', + }, + update_all_domains: { + options: { + updateDomains: true + }, + src: [ '*.php', '**/*.php', '!\.git/**/*', '!bin/**/*', '!node_modules/**/*', '!tests/**/*' ] + } + }, + + wp_readme_to_markdown: { + your_target: { + files: { + 'README.md': 'readme.txt' + } + }, + }, + + makepot: { + target: { + options: { + domainPath: '/languages', + exclude: [ '\.git/*', 'bin/*', 'node_modules/*', 'tests/*' ], + mainFile: 'view-all-posts-pages.php', + potFilename: 'view-all-posts-pages.pot', + potHeaders: { + poedit: true, + 'x-poedit-keywordslist': true + }, + type: 'wp-plugin', + updateTimestamp: true + } + } + }, + } ); + + grunt.loadNpmTasks( 'grunt-wp-i18n' ); + grunt.loadNpmTasks( 'grunt-wp-readme-to-markdown' ); + grunt.registerTask( 'default', [ 'i18n','readme' ] ); + grunt.registerTask( 'i18n', ['addtextdomain', 'makepot'] ); + grunt.registerTask( 'readme', ['wp_readme_to_markdown'] ); + + grunt.util.linefeed = '\n'; + +}; diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f64a8229c008531c7aaceb332e2c6d148359aa24 --- /dev/null +++ b/README.md @@ -0,0 +1,139 @@ +# View All Post's Pages # +**Contributors:** ethitter, thinkoomph +**Donate link:** http://www.thinkoomph.com/plugins-modules/view-all-posts-pages/ +**Tags:** view all, pages, paged, paged post, multipage, single view, single page, wp_link_pages, nextpage, next page, quicktag +**Requires at least:** 3.2.1 +**Tested up to:** 5.0 +**Stable tag:** 0.9.1 +**License:** GPLv2 or later +**License URI:** http://www.gnu.org/licenses/gpl-2.0.html + +Provides a "view all" (single page) option for content paged using WordPress' <!--nextpage--> Quicktag (multipage posts). +## Description ## + +Provides a "view all" (single page) option for posts, pages, and custom post types paged using WordPress' <a href="http://codex.wordpress.org/Write_Post_SubPanel#Quicktags" target="_blank"><code><!--nextpage--></code> Quicktag</a> (multipage posts). + +Your theme must use `wp_link_pages()` to generate post page links, or you must use either the automatic or manual link capabilities provided in the plugin. + +**IMPORTANT**: There are certain plugins that may interfere with this plugin's functionality. See the **FAQ** for more information. + +## Installation ## + +1. Upload view-all-posts-pages.php to /wp-content/plugins/. +2. Activate plugin through the WordPress Plugins menu. +3. Navigate to Options > Permalinks and click *Save Changes* to update navigation. + +## Frequently Asked Questions ## + +### Links don't work ### +First, navigate to Options > Permalinks in WP Admin, click *Save Changes*, and try again. + +If clicking on a link takes you back to the post or page where the link appeared, see the **Known Plugin Conflicts** item below. + +If, after reviewing the remaining FAQ, you are still experiencing problems, visit [http://www.thinkoomph.com/plugins-modules/view-all-posts-pages/](http://www.thinkoomph.com/plugins-modules/view-all-posts-pages/) and leave a comment detailing the problem. + +### How do I add a link to my template? ### +The function `vapp_the_link` will add a link to the full-content version of whatever page it appears on. This function accepts the following arguments: + +* **$link_text**: Set to text that should appear for the link. Defaults to *View All*. +* **$class**: Specifies the CSS class for the link. Defaults to *vapp*. + +### Known Plugin Conflicts ### +This plugin is known to conflict with certain plugins, many pertaining to SEO and permalinks. Conflicting plugins include, but are not limited to, the following: + +* **WordPress SEO by Yoast:** This plugin's `Permalink` options, particularly *Redirect attachment URL's to parent post URL* and *Redirect ugly URL's to clean permalinks. (Not recommended in many cases!)*, interfere with View All Post's Pages' ability to display full content. Both must be disabled, and the site's rewrite rules regenerated (by visiting Options > Permalinks and clicking *Save Changes*), for View All Post's Pages to function. + +## Changelog ## + +### 0.9.2 ### +* Introduce PHPCS tests +* Update plugin based on PHPCS results + +### 0.9.1 ### +* Security update: correct misuse of `add_query_arg()` as identified by Sucuri: https://blog.sucuri.net/2015/04/security-advisory-xss-vulnerability-affecting-multiple-wordpress-plugins.html. + +### 0.9 ### +* Move conditional registration of some filters to `init`, both to ensure external code can interact with filters and to avoid PHP notices. + +### 0.8.1 ### +* Correct translation implementation issue introduced in v0.8. + +### 0.8 ### +* When WordPress determines a request is a 404, don't activate the plugin's functionality. +* Convert the plugin to a singleton. +* Audit entire plugin for translation readyness. +* Correct phpdoc. + +### 0.7 ### +* Further ensure that WordPress doesn't think a post is paged when viewing the full post content unpaged. Ensures that code checking the `$multipage` variable will function properly. Props @batmoo. + +### 0.6.1 ### +* Revert change in is_view_all() method made in version 0.6 as it breaks the method, rendering the plugin inoperable. + +### 0.6 ### +* Add additional rewrite rules for situations where verbose page rules are required. +* Disable canonical redirect when print template is requested. +* Update is_print() method to use WordPress API. +* Correct translation string implementation. + +### 0.5 ### +* Change how post content is modified for View All display. Rather than using the `the_content` filter, global variables are overridden in the `the_post` action. Ensures that infinite loops don't result from shortcode processing and other uses of the `the_content` filter. Props to the WordPress.com VIP Support team (batmoo) and stevenkword. +* Introduces the `vapp_display_link` filter to allow plugins and themes to suppress the automatic View All link on specific posts. Return `false` to suppress the link. Filter also passes post ID, plugin options, and post object. + +### 0.4.1 ### +* Eliminate use of plugins_loaded action since plugin has no dependencies on other plugins. All code previously located in the associated method has been moved to the class's constructor. Props danielbachhuber. + +### 0.4 ### +* Add filter to disable rewrite rules notice. +* Apply esc_html() to link text during output. +* Update code to conform to WordPress Coding Standards. + +### 0.3 ### +* Simplify rewrite rule creation, resolving 404 errors in most cases. + +### 0.2 ### +* Change how wp_link_pages arguments are filtered to better support as-needed filtering. + +### 0.1 ### +* Initial release + +## Upgrade Notice ## + +### 0.9.2 ### +Adds support for PHP 7.3 and fixes various PHPCS errors, neither of which should impact the plugin's functionality. + +### 0.9.1 ### +Security update: correct misuse of `add_query_arg()` as identified by Sucuri: https://blog.sucuri.net/2015/04/security-advisory-xss-vulnerability-affecting-multiple-wordpress-plugins.html. + +### 0.9 ### +Recommended update for anyone hoping to use plugin's filters to modify its behaviour. + +### 0.8.1 ### +Recommended upgrade for anyone translating plugin's interface. + +### 0.8 ### +Plugin won't unnecessarily execute its functionality if no posts are available and is now more thoroughly translatable. + +### 0.7 ### +Further ensures plugins and themes correctly see a "View All" page as full post content. + +### 0.6.1 ### +Resolves a problem where requests for view-all templates redirect to the article. + +### 0.6 ### +Adds better support for sites that use verbose page rules, resolving situations where requests for view-all template redirect to the post. + +### 0.5 ### +Infinite loops may result from previous method used to display entire post's content for the View All display. This update eliminates that possibility by using the the_post action rather than the the_content filter. Props to the WordPress.com VIP Support team (batmoo) and stevenkword. + +### 0.4.1 ### +Eliminates use of plugins_loaded action since plugin has no dependencies on other plugins. All code previously located in the associated method has been moved to the class's constructor. props danielbachhuber. + +### 0.4 ### +Adds filter to disable rewrite rules notice. Also applies esc_html() to link text when output since HTML isn't permitted in the link text. + +### 0.3 ### +Simplifies rewrite rules, resolving 404 errors in most cases. + +### 0.2 ### +Introduces helper function for wp_link_pages arguments and split filtering from plugin options. diff --git a/bin/install-wp-tests.sh b/bin/install-wp-tests.sh new file mode 100755 index 0000000000000000000000000000000000000000..5ceac4b84b4d05ad6b3525cc9d8b2fd055c32554 --- /dev/null +++ b/bin/install-wp-tests.sh @@ -0,0 +1,155 @@ +#!/usr/bin/env bash + +if [ $# -lt 3 ]; then + echo "usage: $0 <db-name> <db-user> <db-pass> [db-host] [wp-version] [skip-database-creation]" + exit 1 +fi + +DB_NAME=$1 +DB_USER=$2 +DB_PASS=$3 +DB_HOST=${4-localhost} +WP_VERSION=${5-latest} +SKIP_DB_CREATE=${6-false} + +TMPDIR=${TMPDIR-/tmp} +TMPDIR=$(echo $TMPDIR | sed -e "s/\/$//") +WP_TESTS_DIR=${WP_TESTS_DIR-$TMPDIR/wordpress-tests-lib} +WP_CORE_DIR=${WP_CORE_DIR-$TMPDIR/wordpress/} + +download() { + if [ `which curl` ]; then + curl -s "$1" > "$2"; + elif [ `which wget` ]; then + wget -nv -O "$2" "$1" + fi +} + +if [[ $WP_VERSION =~ ^[0-9]+\.[0-9]+\-(beta|RC)[0-9]+$ ]]; then + WP_BRANCH=${WP_VERSION%\-*} + WP_TESTS_TAG="branches/$WP_BRANCH" + +elif [[ $WP_VERSION =~ ^[0-9]+\.[0-9]+$ ]]; then + WP_TESTS_TAG="branches/$WP_VERSION" +elif [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; then + if [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0] ]]; then + # version x.x.0 means the first release of the major version, so strip off the .0 and download version x.x + WP_TESTS_TAG="tags/${WP_VERSION%??}" + else + WP_TESTS_TAG="tags/$WP_VERSION" + fi +elif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then + WP_TESTS_TAG="trunk" +else + # http serves a single offer, whereas https serves multiple. we only want one + download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json + grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json + LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//') + if [[ -z "$LATEST_VERSION" ]]; then + echo "Latest WordPress version could not be found" + exit 1 + fi + WP_TESTS_TAG="tags/$LATEST_VERSION" +fi +set -ex + +install_wp() { + + if [ -d $WP_CORE_DIR ]; then + return; + fi + + mkdir -p $WP_CORE_DIR + + if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then + mkdir -p $TMPDIR/wordpress-nightly + download https://wordpress.org/nightly-builds/wordpress-latest.zip $TMPDIR/wordpress-nightly/wordpress-nightly.zip + unzip -q $TMPDIR/wordpress-nightly/wordpress-nightly.zip -d $TMPDIR/wordpress-nightly/ + mv $TMPDIR/wordpress-nightly/wordpress/* $WP_CORE_DIR + else + if [ $WP_VERSION == 'latest' ]; then + local ARCHIVE_NAME='latest' + elif [[ $WP_VERSION =~ [0-9]+\.[0-9]+ ]]; then + # https serves multiple offers, whereas http serves single. + download https://api.wordpress.org/core/version-check/1.7/ $TMPDIR/wp-latest.json + if [[ $WP_VERSION =~ [0-9]+\.[0-9]+\.[0] ]]; then + # version x.x.0 means the first release of the major version, so strip off the .0 and download version x.x + LATEST_VERSION=${WP_VERSION%??} + else + # otherwise, scan the releases and get the most up to date minor version of the major release + local VERSION_ESCAPED=`echo $WP_VERSION | sed 's/\./\\\\./g'` + LATEST_VERSION=$(grep -o '"version":"'$VERSION_ESCAPED'[^"]*' $TMPDIR/wp-latest.json | sed 's/"version":"//' | head -1) + fi + if [[ -z "$LATEST_VERSION" ]]; then + local ARCHIVE_NAME="wordpress-$WP_VERSION" + else + local ARCHIVE_NAME="wordpress-$LATEST_VERSION" + fi + else + local ARCHIVE_NAME="wordpress-$WP_VERSION" + fi + download https://wordpress.org/${ARCHIVE_NAME}.tar.gz $TMPDIR/wordpress.tar.gz + tar --strip-components=1 -zxmf $TMPDIR/wordpress.tar.gz -C $WP_CORE_DIR + fi + + download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php +} + +install_test_suite() { + # portable in-place argument for both GNU sed and Mac OSX sed + if [[ $(uname -s) == 'Darwin' ]]; then + local ioption='-i.bak' + else + local ioption='-i' + fi + + # set up testing suite if it doesn't yet exist + if [ ! -d $WP_TESTS_DIR ]; then + # set up testing suite + mkdir -p $WP_TESTS_DIR + svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes + svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/data/ $WP_TESTS_DIR/data + fi + + if [ ! -f wp-tests-config.php ]; then + download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php + # remove all forward slashes in the end + WP_CORE_DIR=$(echo $WP_CORE_DIR | sed "s:/\+$::") + sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php + fi + +} + +install_db() { + + if [ ${SKIP_DB_CREATE} = "true" ]; then + return 0 + fi + + # parse DB_HOST for port or socket references + local PARTS=(${DB_HOST//\:/ }) + local DB_HOSTNAME=${PARTS[0]}; + local DB_SOCK_OR_PORT=${PARTS[1]}; + local EXTRA="" + + if ! [ -z $DB_HOSTNAME ] ; then + if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then + EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp" + elif ! [ -z $DB_SOCK_OR_PORT ] ; then + EXTRA=" --socket=$DB_SOCK_OR_PORT" + elif ! [ -z $DB_HOSTNAME ] ; then + EXTRA=" --host=$DB_HOSTNAME --protocol=tcp" + fi + fi + + # create database + mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA +} + +install_wp +install_test_suite +install_db diff --git a/languages/view-all-posts-pages.pot b/languages/view-all-posts-pages.pot new file mode 100644 index 0000000000000000000000000000000000000000..3c2d1edcf5680d36318d0cc3cbecfe7e2480ad93 --- /dev/null +++ b/languages/view-all-posts-pages.pot @@ -0,0 +1,161 @@ +# Copyright (C) 2019 Erick Hitter & Oomph, Inc. +# This file is distributed under the same license as the View All Posts Pages package. +msgid "" +msgstr "" +"Project-Id-Version: View All Posts Pages 0.9.2\n" +"Report-Msgid-Bugs-To: " +"https://wordpress.org/support/plugin/view-all-posts-pages\n" +"POT-Creation-Date: 2019-02-05 18:43:53+00:00\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"PO-Revision-Date: 2019-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"X-Generator: grunt-wp-i18n 0.5.4\n" +"X-Poedit-KeywordsList: " +"__;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_" +"attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c;\n" +"Language: en\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Poedit-Country: United States\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-Basepath: ../\n" +"X-Poedit-SearchPath-0: .\n" +"X-Poedit-Bookmarks: \n" +"X-Textdomain-Support: yes\n" + +#: view-all-posts-pages.php:179 view-all-posts-pages.php:186 +msgid "View All" +msgstr "" + +#: view-all-posts-pages.php:464 view-all-posts-pages.php:495 +#. translators: 1: Plugin name. +#. translators: 1: WordPress function name. +msgid "%s Options" +msgstr "" + +#: view-all-posts-pages.php:499 +msgid "" +"A \"view all\" link can be appended to WordPress' standard page navigation " +"using the options below." +msgstr "" + +#: view-all-posts-pages.php:503 +msgid "Automatically append link to post's page navigation?" +msgstr "" + +#: view-all-posts-pages.php:505 view-all-posts-pages.php:548 +msgid "Yes" +msgstr "" + +#: view-all-posts-pages.php:506 view-all-posts-pages.php:549 +msgid "No" +msgstr "" + +#: view-all-posts-pages.php:510 view-all-posts-pages.php:576 +msgid "Link text:" +msgstr "" + +#: view-all-posts-pages.php:516 view-all-posts-pages.php:582 +msgid "Link's CSS class(es):" +msgstr "" + +#: view-all-posts-pages.php:520 view-all-posts-pages.php:586 +msgid "" +"Be aware that Internet Explorer will only interpret the first two CSS " +"classes." +msgstr "" + +#: view-all-posts-pages.php:524 view-all-posts-pages.php:561 +msgid "Display automatically on:" +msgstr "" + +#: view-all-posts-pages.php:540 +msgid "Standalone Link Options" +msgstr "" + +#: view-all-posts-pages.php:542 +msgid "" +"In addition to appending the \"view all\" link to WordPress' standard " +"navigation, link(s) can be added above and below post content." +msgstr "" + +#: view-all-posts-pages.php:546 +msgid "Automatically add links based on settings below?" +msgstr "" + +#: view-all-posts-pages.php:553 +msgid "Automatically place link:" +msgstr "" + +#: view-all-posts-pages.php:555 +msgid "Above content" +msgstr "" + +#: view-all-posts-pages.php:556 +msgid "Below content" +msgstr "" + +#: view-all-posts-pages.php:557 +msgid "Above and below content" +msgstr "" + +#: view-all-posts-pages.php:590 +msgid "Link's priority:" +msgstr "" + +#: view-all-posts-pages.php:594 +msgid "" +"Priority determines when the link is added to a post's content. You can use " +"the above setting to modulate the link's placement." +msgstr "" + +#: view-all-posts-pages.php:595 +msgid "" +"The default value is <strong>10</strong>. Lower values mean the link will " +"be added earlier, while higher values will add the link later." +msgstr "" + +#: view-all-posts-pages.php:739 +msgid "View All Post's Pages" +msgstr "" + +#: view-all-posts-pages.php:744 +#. translators: 1: Permalinks settings page URL. +msgid "" +"You must refresh your site's permalinks before <em>View All Post's " +"Pages</em> is fully activated. To do so, go to <a " +"href=\"%s\">Permalinks</a> and click the <strong><em>Save " +"Changes</em></strong> button at the bottom of the screen." +msgstr "" + +#: view-all-posts-pages.php:756 +#. translators: 1: URL to dismiss admin notice. +msgid "When finished, click <a href=\"%s\">here</a> to hide this message." +msgstr "" + +#. Plugin Name of the plugin/theme +msgid "View All Posts Pages" +msgstr "" + +#. Plugin URI of the plugin/theme +msgid "http://www.oomphinc.com/plugins-modules/view-all-posts-pages/" +msgstr "" + +#. Description of the plugin/theme +msgid "" +"Provides a \"view all\" (single page) option for posts, pages, and custom " +"post types paged using WordPress' <a " +"href=\"http://codex.wordpress.org/Write_Post_SubPanel#Quicktags\" " +"target=\"_blank\"><code><!--nextpage--></code> Quicktag</a> " +"(multipage posts)." +msgstr "" + +#. Author of the plugin/theme +msgid "Erick Hitter & Oomph, Inc." +msgstr "" + +#. Author URI of the plugin/theme +msgid "http://www.oomphinc.com/" +msgstr "" \ No newline at end of file diff --git a/package.json b/package.json new file mode 100755 index 0000000000000000000000000000000000000000..10bf3ecebcdbc0112897f630659cc032eddc01dd --- /dev/null +++ b/package.json @@ -0,0 +1,11 @@ +{ + "name": "view-all-posts-pages", + "version": "0.1.0", + "main": "Gruntfile.js", + "author": "Erick Hitter & Oomph, Inc.", + "devDependencies": { + "grunt": "~0.4.5", + "grunt-wp-i18n": "~0.5.0", + "grunt-wp-readme-to-markdown": "~1.0.0" + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000000000000000000000000000000000000..16a39027e72be2cf0a2656056074b6e6ed818be1 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<phpunit + bootstrap="tests/bootstrap.php" + backupGlobals="false" + colors="true" + convertErrorsToExceptions="true" + convertNoticesToExceptions="true" + convertWarningsToExceptions="true" + > + <testsuites> + <testsuite> + <directory prefix="test-" suffix=".php">./tests/</directory> + <exclude>./tests/test-sample.php</exclude> + </testsuite> + </testsuites> +</phpunit> diff --git a/readme.txt b/readme.txt index d3a9dc0710d2916cc929a595aadcaee61c0e3591..402e5416c93ba92317927f1aecc8a7f32b992804 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: ethitter, thinkoomph Donate link: http://www.thinkoomph.com/plugins-modules/view-all-posts-pages/ Tags: view all, pages, paged, paged post, multipage, single view, single page, wp_link_pages, nextpage, next page, quicktag Requires at least: 3.2.1 -Tested up to: 4.6 +Tested up to: 5.0 Stable tag: 0.9.1 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -45,6 +45,10 @@ This plugin is known to conflict with certain plugins, many pertaining to SEO an == Changelog == += 0.9.2 = +* Introduce PHPCS tests +* Update plugin based on PHPCS results + = 0.9.1 = * Security update: correct misuse of `add_query_arg()` as identified by Sucuri: https://blog.sucuri.net/2015/04/security-advisory-xss-vulnerability-affecting-multiple-wordpress-plugins.html. @@ -95,6 +99,9 @@ This plugin is known to conflict with certain plugins, many pertaining to SEO an == Upgrade Notice == += 0.9.2 = +Adds support for PHP 7.3 and fixes various PHPCS errors, neither of which should impact the plugin's functionality. + = 0.9.1 = Security update: correct misuse of `add_query_arg()` as identified by Sucuri: https://blog.sucuri.net/2015/04/security-advisory-xss-vulnerability-affecting-multiple-wordpress-plugins.html. diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100755 index 0000000000000000000000000000000000000000..7dc0c88ef7d679634cf3e4481b57c922c982fe77 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,31 @@ +<?php +/** + * PHPUnit bootstrap file + * + * @package View_All_Posts_Pages + */ + +$_tests_dir = getenv( 'WP_TESTS_DIR' ); + +if ( ! $_tests_dir ) { + $_tests_dir = rtrim( sys_get_temp_dir(), '/\\' ) . '/wordpress-tests-lib'; +} + +if ( ! file_exists( $_tests_dir . '/includes/functions.php' ) ) { + echo "Could not find $_tests_dir/includes/functions.php, have you run bin/install-wp-tests.sh ?" . PHP_EOL; // WPCS: XSS ok. + exit( 1 ); +} + +// Give access to tests_add_filter() function. +require_once $_tests_dir . '/includes/functions.php'; + +/** + * Manually load the plugin being tested. + */ +function _manually_load_plugin() { + require dirname( dirname( __FILE__ ) ) . '/view-all-posts-pages.php'; +} +tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' ); + +// Start up the WP testing environment. +require $_tests_dir . '/includes/bootstrap.php'; diff --git a/tests/test-sample.php b/tests/test-sample.php new file mode 100755 index 0000000000000000000000000000000000000000..0c4fb886fd0df0d09250e5cc869c188ceab6c7be --- /dev/null +++ b/tests/test-sample.php @@ -0,0 +1,20 @@ +<?php +/** + * Class SampleTest + * + * @package View_All_Posts_Pages + */ + +/** + * Sample test case. + */ +class SampleTest extends WP_UnitTestCase { + + /** + * A single example test. + */ + public function test_sample() { + // Replace this with some actual testing code. + $this->assertTrue( true ); + } +} diff --git a/view-all-posts-pages.php b/view-all-posts-pages.php old mode 100644 new mode 100755 index 739dfef54335c81920dba5913ce81fbb45e3a20c..95e06dfe48b70ce659f8b5e15cd0ed08ffcd6b9d --- a/view-all-posts-pages.php +++ b/view-all-posts-pages.php @@ -1,44 +1,77 @@ -<?php -/* -Plugin Name: View All Post's Pages -Plugin URI: http://www.oomphinc.com/plugins-modules/view-all-posts-pages/ -Description: Provides a "view all" (single page) option for posts, pages, and custom post types paged using WordPress' <a href="http://codex.wordpress.org/Write_Post_SubPanel#Quicktags" target="_blank"><code><!--nextpage--></code> Quicktag</a> (multipage posts). -Author: Erick Hitter & Oomph, Inc. -Version: 0.9.1 -Author URI: http://www.oomphinc.com/ -Text Domain: view_all_posts_pages - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -class view_all_posts_pages { +<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName +/** + * View All Posts Pages + * + * Plugin Name: View All Posts Pages + * Plugin URI: http://www.oomphinc.com/plugins-modules/view-all-posts-pages/ + * Description: Provides a "view all" (single page) option for posts, pages, and custom post types paged using WordPress' <a href="http://codex.wordpress.org/Write_Post_SubPanel#Quicktags" target="_blank"><code><!--nextpage--></code> Quicktag</a> (multipage posts). + * Author: Erick Hitter & Oomph, Inc. + * Author URI: http://www.oomphinc.com/ + * Text Domain: view_all_posts_pages + * Domain Path: /languages + * Version: 0.9.2 + * + * @package View_All_Posts_Pages + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * Class view_all_posts_pages + */ +class view_all_posts_pages { // phpcs:ignore PEAR.NamingConventions.ValidClassName, Generic.Classes.OpeningBraceSameLine.ContentAfterBrace /** * Singleton + * + * @var self */ private static $__instance = null; /** * Class variables + * + * @var string */ private $query_var = 'view-all'; + /** + * Namespace. + * + * @var string + */ private $ns = 'view_all_posts_pages'; + /** + * Option name. + * + * @var string + */ private $settings_key = 'vapp'; + + /** + * Default settings + * + * @var array|null + */ private $settings_defaults = null; + /** + * Option indicating admin notice was dismissed. + * + * @var string + */ private $notice_key = 'vapp_admin_notice_dismissed'; /** @@ -54,7 +87,7 @@ class view_all_posts_pages { */ public static function get_instance() { if ( ! is_a( self::$__instance, __CLASS__ ) ) { - self::$__instance = new self; + self::$__instance = new self(); self::$__instance->setup(); } @@ -67,7 +100,6 @@ class view_all_posts_pages { * * @uses register_deactivation_hook * @uses add_action - * @return null */ private function setup() { register_deactivation_hook( __FILE__, array( $this, 'deactivation_hook' ) ); @@ -87,10 +119,9 @@ class view_all_posts_pages { * @uses flush_rewrite_rules * @uses delete_option * @action register_deactivation_hook - * @return null */ public function deactivation_hook() { - flush_rewrite_rules(); + flush_rewrite_rules(); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules, WordPressVIPMinimum.VIP.RestrictedFunctions.rewrite_rules_flush_rewrite_rules delete_option( $this->settings_key ); delete_option( $this->notice_key ); @@ -98,17 +129,22 @@ class view_all_posts_pages { /** * Register plugin option and disable rewrite rule flush warning. + * * @uses register_setting * @uses apply_filters * @uses update_option * @action admin_init - * @return null */ public function action_admin_init() { register_setting( $this->settings_key, $this->settings_key, array( $this, 'admin_options_validate' ) ); - if ( isset( $_GET[ $this->notice_key ] ) && apply_filters( 'vapp_display_rewrite_rules_notice', true ) ) + if ( + isset( $_GET[ $this->notice_key ], $_GET[ $this->notice_key . '_nonce' ] ) && + wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET[ $this->notice_key . '_nonce' ] ) ), $this->notice_key ) && + apply_filters( 'vapp_display_rewrite_rules_notice', true ) + ) { update_option( $this->notice_key, 1 ); + } } /** @@ -135,23 +171,22 @@ class view_all_posts_pages { * @uses add_action * @uses add_rewrite_endpoint * @action init - * @return null */ public function action_init() { - // Populate default settings, with translation support + // Populate default settings, with translation support. $this->settings_defaults = array( 'wlp' => true, 'wlp_text' => __( 'View All', 'view_all_posts_pages' ), 'wlp_class' => 'vapp', 'wlp_post_types' => array( - 'post' + 'post', ), 'link' => false, 'link_position' => 'below', 'link_text' => __( 'View All', 'view_all_posts_pages' ), 'link_class' => 'vapp', 'link_post_types' => array( - 'post' + 'post', ), 'link_priority' => 10, ); @@ -159,27 +194,30 @@ class view_all_posts_pages { // Register additional plugin actions if settings call for them. $options = $this->get_options(); - if ( array_key_exists( 'wlp', $options ) && true === $options[ 'wlp' ] ) + if ( array_key_exists( 'wlp', $options ) && true === $options['wlp'] ) { add_filter( 'wp_link_pages_args', array( $this, 'filter_wp_link_pages_args_early' ), 0 ); + } - if ( $options[ 'link' ] ) - add_filter( 'the_content', array( $this, 'filter_the_content_auto' ), $options[ 'link_priority' ] ); + if ( $options['link'] ) { + add_filter( 'the_content', array( $this, 'filter_the_content_auto' ), $options['link_priority'] ); + } - if ( apply_filters( 'vapp_display_rewrite_rules_notice', true ) && ! get_option( $this->notice_key ) ) + if ( apply_filters( 'vapp_display_rewrite_rules_notice', true ) && ! get_option( $this->notice_key ) ) { add_action( 'admin_notices', array( $this, 'action_admin_notices_activation' ) ); + } - // Register rewrite endpoint, which handles most of our rewrite needs + // Register rewrite endpoint, which handles most of our rewrite needs. add_rewrite_endpoint( $this->query_var, EP_ALL ); - //Extra rules needed if verbose page rules are requested + // Extra rules needed if verbose page rules are requested. global $wp_rewrite; if ( $wp_rewrite->use_verbose_page_rules ) { - //Build regex - $regex = substr( str_replace( $wp_rewrite->rewritecode, $wp_rewrite->rewritereplace, $wp_rewrite->permalink_structure ), 1 ); - $regex = trailingslashit( $regex ); + // Build regex. + $regex = substr( str_replace( $wp_rewrite->rewritecode, $wp_rewrite->rewritereplace, $wp_rewrite->permalink_structure ), 1 ); + $regex = trailingslashit( $regex ); $regex .= $this->query_var . '/?$'; - //Build corresponding query string + // Build corresponding query string. $query = substr( str_replace( $wp_rewrite->rewritecode, $wp_rewrite->queryreplace, $wp_rewrite->permalink_structure ), 1 ); $query = explode( '/', $query ); $query = array_filter( $query ); @@ -194,7 +232,7 @@ class view_all_posts_pages { $query = implode( '&', $query ); - //Add rule + // Add rule. add_rewrite_rule( $regex, $wp_rewrite->index . '?' . $query, 'top' ); } } @@ -202,14 +240,15 @@ class view_all_posts_pages { /** * Prevent canonical redirect if full-post page is requested. * - * @param string $url + * @param string $url Canonical URL. * @uses this::is_view_all * @filter redirect_canonical - * @return string or false + * @return string|false */ public function filter_redirect_canonical( $url ) { - if ( $this->is_view_all() ) + if ( $this->is_view_all() ) { $url = false; + } return $url; } @@ -218,10 +257,9 @@ class view_all_posts_pages { * Modify post variables to display entire post on one page. * * @global $pages, $more - * @param object $post + * @param WP_Post $post Post object. * @uses this::is_view_all * @action the_post - * @return null */ public function action_the_post( $post ) { if ( $this->is_view_all() ) { @@ -230,12 +268,12 @@ class view_all_posts_pages { $post->post_content = str_replace( "\n<!--nextpage-->\n", "\n\n", $post->post_content ); $post->post_content = str_replace( "\n<!--nextpage-->", "\n", $post->post_content ); $post->post_content = str_replace( "<!--nextpage-->\n", "\n", $post->post_content ); - $post->post_content = str_replace( "<!--nextpage-->", ' ', $post->post_content ); + $post->post_content = str_replace( '<!--nextpage-->', ' ', $post->post_content ); - $pages = array( $post->post_content ); + $pages = array( $post->post_content ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited - $more = 1; - $multipage = 0; + $more = 1; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited + $multipage = 0; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited } } @@ -244,7 +282,7 @@ class view_all_posts_pages { * Automatic inclusion can be disabled by passing false through the vapp_display_link filter. * * @global $post - * @param array $args + * @param array $args wp_link_pages arguments. * @uses this::get_options * @uses apply_filters * @uses add_filter @@ -256,8 +294,9 @@ class view_all_posts_pages { $options = $this->get_options(); - if ( in_array( $post->post_type, $options[ 'wlp_post_types' ] ) && apply_filters( 'vapp_display_link', true, (int) $post->ID, $options, $post ) ) + if ( in_array( $post->post_type, $options['wlp_post_types'], true ) && apply_filters( 'vapp_display_link', true, (int) $post->ID, $options, $post ) ) { add_filter( 'wp_link_pages_args', array( $this, 'filter_wp_link_pages_args' ), 999 ); + } return $args; } @@ -266,7 +305,7 @@ class view_all_posts_pages { * Filter wp_link_pages arguments to append "View all" link to output. * * @global $more - * @param array $args + * @param array $args wp_link_pages arguments. * @uses this::get_options * @uses this::is_view_all * @uses esc_attr @@ -277,26 +316,28 @@ class view_all_posts_pages { $options = $this->get_options(); if ( is_array( $options ) ) { - extract( $options ); + extract( $options, EXTR_OVERWRITE ); - //Set global $more to false so that wp_link_pages outputs links for all pages when viewing full post page - if ( $this->is_view_all() ) - $GLOBALS[ 'more' ] = false; + // Set global $more to false so that wp_link_pages outputs links for all pages when viewing full post page. + if ( $this->is_view_all() ) { + $GLOBALS['more'] = false; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited + } - //Process link text, respecting pagelink parameter. - $link_text = str_replace( '%', $wlp_text, $args[ 'pagelink' ] ); + // Process link text, respecting pagelink parameter. + $link_text = str_replace( '%', $wlp_text, $args['pagelink'] ); - //View all - $link = ' ' . $args[ 'link_before' ]; + // View all. + $link = ' ' . $args['link_before']; - if ( $this->is_view_all() ) + if ( $this->is_view_all() ) { $link .= '<span class="' . esc_attr( $wlp_class ) . '">' . $link_text . '</span><!-- .' . esc_attr( $wlp_class ) . ' -->'; - else + } else { $link .= '<a class="' . esc_attr( $wlp_class ) . '" href="' . esc_url( $this->url() ) . '">' . $link_text . '</a><!-- .' . esc_attr( $wlp_class ) . ' -->'; + } - $link .= $args[ 'link_after' ] . ' '; + $link .= $args['link_after'] . ' '; - $args[ 'after' ] = $link . $args[ 'after' ]; + $args['after'] = $link . $args['after']; } return $args; @@ -306,7 +347,7 @@ class view_all_posts_pages { * Filter the content if automatic link inclusion is selected. * * @global $post - * @param string $content + * @param string $content Post content. * @uses this::get_options * @uses this::is_view_all * @uses esc_attr @@ -320,17 +361,18 @@ class view_all_posts_pages { global $post; - if ( ! $this->is_view_all() && is_array( $options ) && array_key_exists( 'link', $options ) && true === $options[ 'link' ] && in_array( $post->post_type, $options[ 'link_post_types' ] ) ) { - extract( $options ); + if ( ! $this->is_view_all() && is_array( $options ) && array_key_exists( 'link', $options ) && true === $options['link'] && in_array( $post->post_type, $options['link_post_types'] ) ) { + extract( $options, EXTR_OVERWRITE ); $link = '<p class="vapp_wrapper"><a class="' . esc_attr( $link_class ) . '" href="' . esc_url( $this->url() ) . '">' . esc_html( $link_text ) . '</a></p><!-- .vapp_wrapper -->'; - if ( 'above' == $link_position ) + if ( 'above' === $link_position ) { $content = $link . $content; - elseif ( 'below' == $link_position ) + } elseif ( 'below' === $link_position ) { $content = $content . $link; - elseif ( 'both' == $link_position ) + } elseif ( 'both' === $link_position ) { $content = $link . $content . $link; + } } return $content; @@ -341,7 +383,7 @@ class view_all_posts_pages { * * @global $post * @global $wp_rewrite - * @param int $post_id + * @param int|false $post_id Post ID. * @uses is_singular * @uses in_the_loop * @uses get_permalink @@ -364,7 +406,7 @@ class view_all_posts_pages { public function url( $post_id = false ) { $link = false; - //Get link base specific to page type being viewed + // Get link base specific to page type being viewed. if ( is_singular() || in_the_loop() ) { $post_id = intval( $post_id ); @@ -373,48 +415,36 @@ class view_all_posts_pages { $post_id = $post->ID; } - if ( ! $post_id ) + if ( ! $post_id ) { return false; + } $link = get_permalink( $post_id ); - } - elseif ( is_home() || is_front_page() ) + } elseif ( is_home() || is_front_page() ) { $link = home_url( '/' ); - elseif ( is_category() ) + } elseif ( is_category() ) { $link = get_category_link( get_query_var( 'cat' ) ); - elseif ( is_tag() ) + } elseif ( is_tag() ) { $link = get_tag_link( get_query_var( 'tag_id' ) ); - /** DISABLED FOR NOW AS PRINTING OF DATE-BASED ARCHIVES DOESN'T WORK YET - elseif ( is_date() ) { - $year = get_query_var( 'year' ); - $monthnum = get_query_var( 'monthnum' ); - $day = get_query_var( 'day' ); - - if ( $day ) - $link = get_day_link( $year, $monthnum, $day ); - elseif ( $monthnum ) - $link = get_month_link( $year, $monthnum ); - else - $link = get_year_link( $year ); - }*/ - elseif ( is_tax() ) { + } elseif ( is_tax() ) { $queried_object = get_queried_object(); - if ( is_object( $queried_object ) && property_exists( $queried_object, 'taxonomy' ) && property_exists( $queried_object, 'term_id' ) ) - $link = get_term_link( (int)$queried_object->term_id, $queried_object->taxonomy ); + if ( is_object( $queried_object ) && property_exists( $queried_object, 'taxonomy' ) && property_exists( $queried_object, 'term_id' ) ) { + $link = get_term_link( (int) $queried_object->term_id, $queried_object->taxonomy ); + } } - //If link base is set, build link + // If link base is set, build link. if ( false !== $link ) { global $wp_rewrite; if ( $wp_rewrite->using_permalinks() ) { $link = path_join( $link, $this->query_var ); - if ( $wp_rewrite->use_trailing_slashes ) + if ( $wp_rewrite->use_trailing_slashes ) { $link = trailingslashit( $link ); - } - else { + } + } else { $link = add_query_arg( $this->query_var, 1, $link ); } } @@ -428,9 +458,9 @@ class view_all_posts_pages { * @uses __ * @uses add_options_page * @action admin_menu - * @return null */ public function action_admin_menu() { + /* translators: 1: Plugin name. */ add_options_page( sprintf( __( '%s Options', 'view_all_posts_pages' ), "View All Post's Pages" ), "View All Post's Pages", 'manage_options', $this->ns, array( $this, 'admin_options' ) ); } @@ -445,10 +475,9 @@ class view_all_posts_pages { * @uses checked * @uses esc_attr * @uses submit_button - * @return string */ public function admin_options() { - ?> + ?> <div class="wrap"> <h2>View All Post's Pages</h2> @@ -460,91 +489,110 @@ class view_all_posts_pages { $post_types = $this->post_types_array(); ?> - <h3><?php printf( __( '%s Options', 'view_all_posts_pages' ), '<em>wp_link_pages</em>' ); ?></h3> + <h3> + <?php + /* translators: 1: WordPress function name. */ + printf( wp_kses_post( __( '%s Options', 'view_all_posts_pages' ) ), '<em>wp_link_pages</em>' ); + ?> + </h3> - <p class="description"><?php _e( 'A "view all" link can be appended to WordPress\' standard page navigation using the options below.', 'view_all_posts_pages' ); ?></p> + <p class="description"><?php esc_html_e( 'A "view all" link can be appended to WordPress\' standard page navigation using the options below.', 'view_all_posts_pages' ); ?></p> <table class="form-table"> <tr> - <th scope="row"><?php _e( 'Automatically append link to post\'s page navigation?', 'view_all_posts_pages' ); ?></th> + <th scope="row"><?php esc_html_e( 'Automatically append link to post\'s page navigation?', 'view_all_posts_pages' ); ?></th> <td> - <input type="radio" name="<?php echo $this->settings_key; ?>[wlp]" id="wlp-true" value="1"<?php checked( $options[ 'wlp' ], true, true ); ?> /> <label for="wlp-true"><?php _e( 'Yes', 'view_all_posts_pages' ); ?></label><br /> - <input type="radio" name="<?php echo $this->settings_key; ?>[wlp]" id="wlp-false" value="0"<?php checked( $options[ 'wlp' ], false, true ); ?> /> <label for="wlp-false"><?php _e( 'No', 'view_all_posts_pages' ); ?></label> + <input type="radio" name="<?php echo esc_attr( $this->settings_key ); ?>[wlp]" id="wlp-true" value="1"<?php checked( $options['wlp'], true, true ); ?> /> <label for="wlp-true"><?php esc_html_e( 'Yes', 'view_all_posts_pages' ); ?></label><br /> + <input type="radio" name="<?php echo esc_attr( $this->settings_key ); ?>[wlp]" id="wlp-false" value="0"<?php checked( $options['wlp'], false, true ); ?> /> <label for="wlp-false"><?php esc_html_e( 'No', 'view_all_posts_pages' ); ?></label> </td> </tr> <tr> - <th scope="row"><label for="wlp_text"><?php _e( 'Link text:', 'view_all_posts_pages' ); ?></label></th> + <th scope="row"><label for="wlp_text"><?php esc_html_e( 'Link text:', 'view_all_posts_pages' ); ?></label></th> <td> - <input type="text" name="<?php echo $this->settings_key; ?>[wlp_text]" id="wlp_text" value="<?php echo esc_attr( $options[ 'wlp_text' ] ); ?>" class="regular-text" /> + <input type="text" name="<?php echo esc_attr( $this->settings_key ); ?>[wlp_text]" id="wlp_text" value="<?php echo esc_attr( $options['wlp_text'] ); ?>" class="regular-text" /> </td> </tr> <tr> - <th scope="row"><label for="wlp_class"><?php _e( 'Link\'s CSS class(es):', 'view_all_posts_pages' ); ?></label></th> + <th scope="row"><label for="wlp_class"><?php esc_html_e( 'Link\'s CSS class(es):', 'view_all_posts_pages' ); ?></label></th> <td> - <input type="text" name="<?php echo $this->settings_key;?>[wlp_class]" id="wlp_class" value="<?php echo esc_attr( $options[ 'wlp_class' ] ); ?>" class="regular-text" /> + <input type="text" name="<?php echo esc_attr( $this->settings_key ); ?>[wlp_class]" id="wlp_class" value="<?php echo esc_attr( $options['wlp_class'] ); ?>" class="regular-text" /> - <p class="description"><?php _e( 'Be aware that Internet Explorer will only interpret the first two CSS classes.', 'view_all_posts_pages' ); ?></p> + <p class="description"><?php esc_html_e( 'Be aware that Internet Explorer will only interpret the first two CSS classes.', 'view_all_posts_pages' ); ?></p> </td> </tr> <tr> - <th scope="row"><?php _e( 'Display automatically on:', 'view_all_posts_pages' ); ?></th> + <th scope="row"><?php esc_html_e( 'Display automatically on:', 'view_all_posts_pages' ); ?></th> <td> <?php foreach ( $post_types as $post_type ) : ?> - <input type="checkbox" name="<?php echo $this->settings_key; ?>[wlp_post_types][]" id="wlp-pt-<?php echo $post_type->name; ?>" value="<?php echo $post_type->name; ?>"<?php if ( in_array( $post_type->name, $options[ 'wlp_post_types' ] ) ) echo ' checked="checked"'; ?> /> <label for="wlp-pt-<?php echo $post_type->name; ?>"><?php echo $post_type->labels->name; ?></label><br /> + <input type="checkbox" name="<?php echo esc_attr( $this->settings_key ); ?>[wlp_post_types][]" id="wlp-pt-<?php echo esc_attr( $post_type->name ); ?>" value="<?php echo esc_attr( $post_type->name ); ?>" + <?php + if ( in_array( $post_type->name, $options['wlp_post_types'], true ) ) { + echo ' checked="checked"'; + } + ?> + /> + <label for="wlp-pt-<?php echo esc_attr( $post_type->name ); ?>"><?php echo esc_html( $post_type->labels->name ); ?></label><br /> <?php endforeach; ?> </td> </tr> </table> - <h3><?php _e( 'Standalone Link Options', 'view_all_posts_pages' ); ?></h3> + <h3><?php esc_html_e( 'Standalone Link Options', 'view_all_posts_pages' ); ?></h3> - <p class="description"><?php _e( 'In addition to appending the "view all" link to WordPress\' standard navigation, link(s) can be added above and below post content.', 'view_all_posts_pages' ); ?></p> + <p class="description"><?php esc_html_e( 'In addition to appending the "view all" link to WordPress\' standard navigation, link(s) can be added above and below post content.', 'view_all_posts_pages' ); ?></p> <table class="form-table"> <tr> - <th scope="row"><?php _e( 'Automatically add links based on settings below?', 'view_all_posts_pages' ); ?></th> + <th scope="row"><?php esc_html_e( 'Automatically add links based on settings below?', 'view_all_posts_pages' ); ?></th> <td> - <input type="radio" name="<?php echo $this->settings_key; ?>[link]" id="link-true" value="1"<?php checked( $options[ 'link' ], true, true ); ?> /> <label for="link-true"><?php _e( 'Yes', 'view_all_posts_pages' ); ?></label><br /> - <input type="radio" name="<?php echo $this->settings_key; ?>[link]" id="link-false" value="0"<?php checked( $options[ 'link' ], false, true ); ?> /> <label for="link-false"><?php _e( 'No', 'view_all_posts_pages' ); ?></label> + <input type="radio" name="<?php echo esc_attr( $this->settings_key ); ?>[link]" id="link-true" value="1"<?php checked( $options['link'], true, true ); ?> /> <label for="link-true"><?php esc_html_e( 'Yes', 'view_all_posts_pages' ); ?></label><br /> + <input type="radio" name="<?php echo esc_attr( $this->settings_key ); ?>[link]" id="link-false" value="0"<?php checked( $options['link'], false, true ); ?> /> <label for="link-false"><?php esc_html_e( 'No', 'view_all_posts_pages' ); ?></label> </td> </tr> <tr> - <th scope="row"><?php _e( 'Automatically place link:', 'view_all_posts_pages' ); ?></th> + <th scope="row"><?php esc_html_e( 'Automatically place link:', 'view_all_posts_pages' ); ?></th> <td> - <input type="radio" name="<?php echo $this->settings_key; ?>[link_position]" id="link_position-above" value="above"<?php checked( $options[ 'link_position' ], 'above', true ); ?> /> <label for="link_position-above"><?php _e( 'Above content', 'view_all_posts_pages' ); ?></label><br /> - <input type="radio" name="<?php echo $this->settings_key; ?>[link_position]" id="link_position-below" value="below"<?php checked( $options[ 'link_position' ], 'below', true ); ?> /> <label for="link_position-below"><?php _e( 'Below content', 'view_all_posts_pages' ); ?></label><br /> - <input type="radio" name="<?php echo $this->settings_key; ?>[link_position]" id="link_position-both" value="both"<?php checked( $options[ 'link_position' ], 'both', true ); ?> /> <label for="link_position-both"><?php _e( 'Above and below content', 'view_all_posts_pages' ); ?></label> + <input type="radio" name="<?php echo esc_attr( $this->settings_key ); ?>[link_position]" id="link_position-above" value="above"<?php checked( $options['link_position'], 'above', true ); ?> /> <label for="link_position-above"><?php esc_html_e( 'Above content', 'view_all_posts_pages' ); ?></label><br /> + <input type="radio" name="<?php echo esc_attr( $this->settings_key ); ?>[link_position]" id="link_position-below" value="below"<?php checked( $options['link_position'], 'below', true ); ?> /> <label for="link_position-below"><?php esc_html_e( 'Below content', 'view_all_posts_pages' ); ?></label><br /> + <input type="radio" name="<?php echo esc_attr( $this->settings_key ); ?>[link_position]" id="link_position-both" value="both"<?php checked( $options['link_position'], 'both', true ); ?> /> <label for="link_position-both"><?php esc_html_e( 'Above and below content', 'view_all_posts_pages' ); ?></label> </td> </tr> <tr> - <th scope="row"><?php _e( 'Display automatically on:', 'view_all_posts_pages' ); ?></th> + <th scope="row"><?php esc_html_e( 'Display automatically on:', 'view_all_posts_pages' ); ?></th> <td> <?php foreach ( $post_types as $post_type ) : ?> - <input type="checkbox" name="<?php echo $this->settings_key; ?>[link_post_types][]" id="link-pt-<?php echo $post_type->name; ?>" value="<?php echo $post_type->name; ?>"<?php if ( in_array( $post_type->name, $options[ 'link_post_types' ] ) ) echo ' checked="checked"'; ?> /> <label for="link-pt-<?php echo $post_type->name; ?>"><?php echo $post_type->labels->name; ?></label><br /> + <input type="checkbox" name="<?php echo esc_attr( $this->settings_key ); ?>[link_post_types][]" id="link-pt-<?php echo esc_attr( $post_type->name ); ?>" value="<?php echo esc_attr( $post_type->name ); ?>" + <?php + if ( in_array( $post_type->name, $options['link_post_types'], true ) ) { + echo ' checked="checked"'; + } + ?> + /> + <label for="link-pt-<?php echo esc_attr( $post_type->name ); ?>"><?php echo esc_html( $post_type->labels->name ); ?></label><br /> <?php endforeach; ?> </td> </tr> <tr> - <th scope="row"><label for="link_text"><?php _e( 'Link text:', 'view_all_posts_pages' ); ?></label></th> + <th scope="row"><label for="link_text"><?php esc_html_e( 'Link text:', 'view_all_posts_pages' ); ?></label></th> <td> - <input type="text" name="<?php echo $this->settings_key; ?>[link_text]" id="link_text" value="<?php echo esc_attr( $options[ 'link_text' ] ); ?>" class="regular-text" /> + <input type="text" name="<?php echo esc_attr( $this->settings_key ); ?>[link_text]" id="link_text" value="<?php echo esc_attr( $options['link_text'] ); ?>" class="regular-text" /> </td> </tr> <tr> - <th scope="row"><label for="link_class"><?php _e( 'Link\'s CSS class(es):', 'view_all_posts_pages' ); ?></label></th> + <th scope="row"><label for="link_class"><?php esc_html_e( 'Link\'s CSS class(es):', 'view_all_posts_pages' ); ?></label></th> <td> - <input type="text" name="<?php echo $this->settings_key; ?>[link_class]" id="link_class" value="<?php echo esc_attr( $options[ 'link_class' ] ); ?>" class="regular-text" /> + <input type="text" name="<?php echo esc_attr( $this->settings_key ); ?>[link_class]" id="link_class" value="<?php echo esc_attr( $options['link_class'] ); ?>" class="regular-text" /> - <p class="description"><?php _e( 'Be aware that Internet Explorer will only interpret the first two CSS classes.', 'view_all_posts_pages' ); ?></p> + <p class="description"><?php esc_html_e( 'Be aware that Internet Explorer will only interpret the first two CSS classes.', 'view_all_posts_pages' ); ?></p> </td> </tr> <tr> - <th scope="row"><label for="link_priority"><?php _e( 'Link\'s priority:', 'view_all_posts_pages' ); ?></label></th> + <th scope="row"><label for="link_priority"><?php esc_html_e( 'Link\'s priority:', 'view_all_posts_pages' ); ?></label></th> <td> - <input type="text" name="<?php echo $this->settings_key; ?>[link_priority]" id="link_priority" class="small-text code" value="<?php echo esc_attr( $options[ 'link_priority' ] ); ?>" /> + <input type="text" name="<?php echo esc_attr( $this->settings_key ); ?>[link_priority]" id="link_priority" class="small-text code" value="<?php echo esc_attr( $options['link_priority'] ); ?>" /> - <p class="description"><?php _e( 'Priority determines when the link is added to a post\'s content. You can use the above setting to modulate the link\'s placement.', 'view_all_posts_pages' ); ?></p> - <p class="description"><?php _e( 'The default value is <strong>10</strong>. Lower values mean the link will be added earlier, while higher values will add the link later.', 'view_all_posts_pages' ); ?></p> + <p class="description"><?php esc_html_e( 'Priority determines when the link is added to a post\'s content. You can use the above setting to modulate the link\'s placement.', 'view_all_posts_pages' ); ?></p> + <p class="description"><?php echo wp_kses_post( __( 'The default value is <strong>10</strong>. Lower values mean the link will be added earlier, while higher values will add the link later.', 'view_all_posts_pages' ) ); ?></p> </td> </tr> </table> @@ -553,13 +601,13 @@ class view_all_posts_pages { </form> </div><!-- .wrap --> - <?php + <?php } /** * Validate options * - * @param array $options + * @param array $options Plugin options. * @uses this::get_options * @uses this::post_types_array * @uses sanitize_text_field @@ -571,21 +619,21 @@ class view_all_posts_pages { if ( is_array( $options ) ) { foreach ( $options as $key => $value ) { - switch( $key ) { + switch ( $key ) { case 'wlp': case 'link': - $new_options[ $key ] = (bool)$value; - break; + $new_options[ $key ] = (bool) $value; + break; case 'link_position': $placements = array( 'above', 'below', - 'both' + 'both', ); - $new_options[ $key ] = in_array( $value, $placements ) ? $value : 'below'; - break; + $new_options[ $key ] = in_array( $value, $placements, true ) ? $value : 'below'; + break; case 'wlp_post_types': case 'link_post_types': @@ -595,11 +643,12 @@ class view_all_posts_pages { if ( is_array( $value ) && is_array( $post_types ) ) { foreach ( $post_types as $post_type ) { - if ( in_array( $post_type->name, $value ) ) + if ( in_array( $post_type->name, $value, true ) ) { $new_options[ $key ][] = $post_type->name; + } } } - break; + break; case 'wlp_text': case 'wlp_class': @@ -607,20 +656,21 @@ class view_all_posts_pages { case 'link_class': $value = sanitize_text_field( $value ); - if ( ( 'wlp_text' == $key || 'link_text' == $key ) && empty( $value ) ) + if ( ( 'wlp_text' === $key || 'link_text' === $key ) && empty( $value ) ) { $value = 'View all'; + } $new_options[ $key ] = $value; - break; + break; case 'link_priority': $value = absint( $value ); $new_options[ $key ] = $value; - break; + break; default: - break; + break; } } } @@ -638,14 +688,17 @@ class view_all_posts_pages { private function get_options() { $options = get_option( $this->settings_key, $this->settings_defaults ); - if ( ! is_array( $options ) ) + if ( ! is_array( $options ) ) { $options = array(); + } - if ( ! array_key_exists( 'wlp_post_types', $options ) ) - $options[ 'wlp_post_types' ] = array(); + if ( ! array_key_exists( 'wlp_post_types', $options ) ) { + $options['wlp_post_types'] = array(); + } - if ( ! array_key_exists( 'link_post_types', $options ) ) - $options[ 'link_post_types' ] = array(); + if ( ! array_key_exists( 'link_post_types', $options ) ) { + $options['link_post_types'] = array(); + } return wp_parse_args( $options, $this->settings_defaults ); } @@ -659,8 +712,9 @@ class view_all_posts_pages { private function post_types_array() { $post_types = array(); foreach ( get_post_types( array(), 'objects' ) as $post_type ) { - if ( false == $post_type->_builtin || 'post' == $post_type->name || 'page' == $post_type->name ) + if ( false === $post_type->_builtin || 'post' === $post_type->name || 'page' === $post_type->name ) { $post_types[] = $post_type; + } } return $post_types; @@ -676,21 +730,35 @@ class view_all_posts_pages { * @uses admin_url * @uses add_query_arg * @action admin_notices - * @return html or null */ public function action_admin_notices_activation() { if ( ! get_option( $this->notice_key ) && apply_filters( 'vapp_display_rewrite_rules_notice', true ) ) : - ?> + ?> <div id="wpf-rewrite-flush-warning" class="error fade"> - <p><strong><?php _e( 'View All Post\'s Pages', 'view_all_posts_pages' ); ?></strong></p> + <p><strong><?php esc_html_e( 'View All Post\'s Pages', 'view_all_posts_pages' ); ?></strong></p> - <p><?php printf( __( 'You must refresh your site\'s permalinks before <em>View All Post\'s Pages</em> is fully activated. To do so, go to <a href="%s">Permalinks</a> and click the <strong><em>Save Changes</em></strong> button at the bottom of the screen.', 'view_all_posts_pages' ), esc_url( admin_url( 'options-permalink.php' ) ) ); ?></p> + <p> + <?php + /* translators: 1: Permalinks settings page URL. */ + printf( wp_kses_post( __( 'You must refresh your site\'s permalinks before <em>View All Post\'s Pages</em> is fully activated. To do so, go to <a href="%s">Permalinks</a> and click the <strong><em>Save Changes</em></strong> button at the bottom of the screen.', 'view_all_posts_pages' ) ), esc_url( admin_url( 'options-permalink.php' ) ) ); + ?> + </p> - <p><?php printf( __( 'When finished, click <a href="%s">here</a> to hide this message.', 'view_all_posts_pages' ), esc_url( admin_url( add_query_arg( $this->notice_key, 1, 'index.php' ) ) ) ); ?></p> + <p> + <?php + $query_args = array( + $this->notice_key => 1, + $this->notice_key . '_nonce' => wp_create_nonce( $this->notice_key ), + ); + + /* translators: 1: URL to dismiss admin notice. */ + printf( wp_kses_post( __( 'When finished, click <a href="%s">here</a> to hide this message.', 'view_all_posts_pages' ) ), esc_url( admin_url( add_query_arg( $query_args, 'index.php' ) ) ) ); + ?> + </p> </div> - <?php + <?php endif; } } @@ -704,7 +772,7 @@ $GLOBALS['vapp'] = view_all_posts_pages::get_instance(); /** * Shortcut to public function for generating full post view URL * - * @param int $post_id + * @param int|false $post_id Post ID. * @uses view_all_posts_pages::get_instance * @return string or bool */ @@ -716,13 +784,12 @@ function vapp_get_url( $post_id = false ) { * Output link to full post view. * * @global $post - * @param string $link_text - * @param string $class + * @param string $link_text Link text. + * @param string $class Link class. * @uses vapp_get_url * @uses esc_attr * @uses esc_url * @uses esc_html - * @return string or null */ function vapp_the_link( $link_text = 'View All', $class = 'vapp' ) { global $post; @@ -731,7 +798,7 @@ function vapp_the_link( $link_text = 'View All', $class = 'vapp' ) { if ( $url ) { $link = '<a ' . ( $class ? 'class="' . esc_attr( $class ) . '"' : '' ) . ' href="' . esc_url( $url ) . '">' . esc_html( $link_text ) . '</a>'; - echo $link; + echo wp_kses_post( $link ); } } @@ -739,7 +806,7 @@ function vapp_the_link( $link_text = 'View All', $class = 'vapp' ) { * Filter wp_link_pages args. * Function is a shortcut to class' filter. * - * @param array $args + * @param array $args wp_link_pages args. * @uses view_all_posts_pages::get_instance * @return array */ @@ -754,7 +821,7 @@ if ( ! function_exists( 'is_view_all' ) ) { * @uses view_all_posts_pages::get_instance * @return bool */ - function is_view_all() { + function is_view_all() { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound return view_all_posts_pages::get_instance()->is_view_all(); } }