diff --git a/.distignore b/.distignore new file mode 100644 index 0000000..30128dd --- /dev/null +++ b/.distignore @@ -0,0 +1,31 @@ +# 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 +bin +circle.yml +composer.json +composer.lock +Gruntfile.js +package.json +phpunit.xml +phpunit.xml.dist +multisite.xml +multisite.xml.dist +phpcs.ruleset.xml +LICENSE +wp-cli.local.yml +tests +vendor +node_modules +*.sql +*.tar.gz +*.zip +authors.txt +composer.* diff --git a/.github/workflows/release-handler.yml b/.github/workflows/release-handler.yml new file mode 100644 index 0000000..6ccd91d --- /dev/null +++ b/.github/workflows/release-handler.yml @@ -0,0 +1,46 @@ +name: Release Handler + +# Action runs when a new release is published. +on: + release: + types: [published] + +jobs: + release-new: + name: Issue new release + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Build Plugin + run: | + composer install --no-dev --optimize-autoloader + composer run build + + - name: Create release archive + uses: montudor/action-zip@v0.1.0 + with: + args: zip -X -r dist/footnotes-${{ github.event.release.tag_name }}.zip dist + + - name: Upload archive as artifact + uses: actions/upload-artifact@v2 + with: + name: footnotes-${{ github.event.release.tag_name }} + path: dist/footnotes-${{ github.event.release.tag_name }}.zip + + - name: Upload archive to release + uses: JasonEtco/upload-to-release@master + with: + args: dist/footnotes-${{ github.event.release.tag_name }}.zip application/zip + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + #- name: Deploy release to Wordpress.org + # uses: 10up/action-wordpress-plugin-deploy@stable + # with: + # generate-zip: true + # env: + # SVN_USERNAME: ${{ secrets.SVN_USERNAME }} + # SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} diff --git a/.gitignore b/.gitignore index bff37e1..64eb6cc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ .phpdoc/ +vendor/ +dist/ +tmp/ +*.bak authors.txt diff --git a/README.md b/README.md index a6ce5b3..99d11c2 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## Description -Featured on [wpmudev](http://premium.wpmudev.org/blog/12-surprisingly-useful-wordpress-plugins-you-dont-know-about/) --- cheers for the review, folks! +Featured on [wpmudev](http://premium.wpmudev.org/blog/12-surprisingly-useful-wordpress-plugins-you-dont-know-about/) — cheers for the review, folks! **footnotes** aims to be the all-in-one solution for displaying an automatically generated list of references on your Page or Post. The Plugin ships with a set of defaults while also empowering you to control how your footnotes are being displayed. @@ -14,21 +14,19 @@ Featured on [wpmudev](http://premium.wpmudev.org/blog/12-surprisingly-useful-wor 1. Read the contributing guidelines 1. Clone this repository (`git clone git@github.com:markcheret/footnotes.git`) - - We recommend that you use [VVV](https://varyingvagrantvagrants.org/) for your development environment + - We recommend that you use [VVV](https://varyingvagrantvagrants.org/) for your local testing environment 1. Install [Composer](https://getcomposer.org/download/), if you don't have it already 1. Install dependencies (`composer install`) -1. Create a new branch from `main` (`git checkout -b `) -1. When you're finished, commit your changes to the remote version of your branch - and submit a [pull request](https://github.com/markcheret/footnotes/pulls). + - You will have to install `php-mbstring` manually if you do not already have it. -## Checking WP Coding Standard Compliance +## Code Formatting -1. Run PHP_CodeSniffer on the file(s) you want to check (`./vendor/bin/phpcs --standard="WordPress" --colors --encoding=utf-8 -n -p `) -1. (If applicable) run the PHP Code Beautifier and Formatter to attempt to automatically fix any errors (`./vendor/bin/phpcbf --standard="WordPress" --encoding=utf-8 -p `) - - Add the `-n` flag to ignore warnings (i.e., show only errors) - - Add the `-s` flag to show sniff codes (used for disabling errors in the code with `phpcs disable:` — MAKE SURE THAT YOU HAVE `phpcs enable` AT THE EARLIEST POINT POSSIBLE, and provide a justification for disabling the sniff code) - - You can run either across the entire project by adding the argument `--ignore=*/vendor/*` and targetting the file `./**/*.php` - - You may have to enable double-wildcards in your console first (`shopt -s globstar`) +1. Run `composer run lint-php` to lint all PHP files +1. Run `composer run lint-php:fix` to attempt to automatically fix errors and warnings + +## Releasing + +1. Run `composer run release` ## Building @@ -44,43 +42,12 @@ Featured on [wpmudev](http://premium.wpmudev.org/blog/12-surprisingly-useful-wor ## Updating Documentation -1. Install [phpDocumentor](https://phpdoc.org/) -1. Run it (`phpDocumentor -d . -t docs`) +1. Run `composer run docs` ## Testing Unit tests are TODO. -## Getting Started - -1. Read the contributing guidelines -1. Clone this repository (`git clone git@github.com:Rumperuu/footnotes.git`) -1. Install [Composer](https://getcomposer.org/download/), if you don't have it already -1. Install dependencies (`composer install`) -1. Create a new branch from `main` (`git checkout -b `) -1. When you're finished, commit your changes to the remote version of your branch - and submit a [pull request](https://github.com/Rumperuu/footnotes/pulls). - -## Updating Documentation - -1. Install [phpDocumentor](https://phpdoc.org/) -1. Run it (`phpDocumentor -d . -t docs`) - -## Getting Started - -1. Read the contributing guidelines -1. Clone this repository (`git clone git@github.com:Rumperuu/footnotes.git`) -1. Install [Composer](https://getcomposer.org/download/), if you don't have it already -1. Install dependencies (`composer install`) -1. Create a new branch from `main` (`git checkout -b `) -1. When you're finished, commit your changes to the remote version of your branch - and submit a [pull request](https://github.com/Rumperuu/footnotes/pulls). - -## Updating Documentation - -1. Install [phpDocumentor](https://phpdoc.org/) -1. Run it (`phpDocumentor -d . -t docs`) - ## Main Features - Fully customizable **footnotes** start and end shortcodes; @@ -96,8 +63,8 @@ Unit tests are TODO. These are a few examples of possible ways to delimit footnotes: -1. Your awesome text((with an awesome footnote)) -2. Your awesome text[ref]with an awesome footnote[/ref] +1. Your awesome text`((`with an awesome footnote`))` +2. Your awesome text`[ref]`with an awesome footnote`[/ref]` 3. Your awesome text``with an awesome footnote`` 4. Your awesome text`custom-shortcode`with an awesome footnote`custom-shortcode` diff --git a/_tools/build-stylesheets.sh b/_tools/build-stylesheets.sh new file mode 100755 index 0000000..2d14f33 --- /dev/null +++ b/_tools/build-stylesheets.sh @@ -0,0 +1,94 @@ +#!/bin/bash + +# Concatenates, minifies (TODO) and deploys stylesheets for distribution. +# +# 12 unified stylesheets are concatenated out of these files: +# - `dev-common.css` +# - `dev-tooltips.css` +# - `dev-tooltips-alternative.css` +# - `dev-layout-reference-container.css` +# - `dev-layout-entry-content.css` +# - `dev-layout-main-content.css` + +echo "Running $(dirname "$0")/build-stylesheets.sh" + +if [[ $1 == "-c" ]]; then + + echo "Concatenating files and placing in \`css/tmp/\`..." + + mkdir -p ./css/tmp + cat ./css/dev-common.css > ./css/tmp/footnotes-nottbrpl0.css + cat ./css/dev-{common,layout-reference-container}.css > ./css/tmp/footnotes-nottbrpl1.css + cat ./css/dev-{common,layout-entry-content}.css > ./css/tmp/footnotes-nottbrpl2.css + cat ./css/dev-{common,layout-main-content}.css > ./css/tmp/footnotes-nottbrpl3.css + cat ./css/dev-{common,tooltips}.css > ./css/tmp/footnotes-jqttbrpl0.css + cat ./css/dev-{common,tooltips,layout-reference-container}.css > ./css/tmp/footnotes-jqttbrpl1.css + cat ./css/dev-{common,tooltips,layout-entry-content}.css > ./css/tmp/footnotes-jqttbrpl2.css + cat ./css/dev-{common,tooltips,layout-main-content}.css > ./css/tmp/footnotes-jqttbrpl3.css + cat ./css/dev-{common,tooltips,tooltips-alternative}.css > ./css/tmp/footnotes-alttbrpl0.css + cat ./css/dev-{common,tooltips,tooltips-alternative,layout-reference-container}.css > ./css/tmp/footnotes-alttbrpl1.css + cat ./css/dev-{common,tooltips,tooltips-alternative,layout-entry-content}.css > ./css/tmp/footnotes-alttbrpl2.css + cat ./css/dev-{common,tooltips,tooltips-alternative,layout-main-content}.css > ./css/tmp/footnotes-alttbrpl3.css + cat ./css/settings.css > ./css/tmp/settings.css + + echo "Stylesheet concatenation complete." + exit 0 + +elif [[ $1 == "-m" ]]; then + + # TODO: this should automatically minifiy all files, outputting into `.min.css` + # files and deleting the original concatenated `.css` files in `css/tmp/`. + # Once that's done, we can change the `rm -r` command in the deploy step to + # `rmdir`, which will throw us an error if we have any minified files that + # haven't been moved over to `dist/css/` for whatever reason. As it currently + # stands, we have no error checking in place. + echo "Please minify the stylesheets in \`css/tmp/\`, saving them in the same location with the \`.min.css\` file extension." + read -p "Are you ready to continue? (Y/N): " CONFIRM && [[ $CONFIRM == [yY] || $CONFIRM == [yY][eE][sS] ]] || exit 1 + exit 0 + +elif [[ $1 == "-d" ]]; then + + # NOTE: I've temporarily replaced the `mv` command + # with `cp` and disabled the `rm` command, so the minified + # files won't be removed from the source directory. + echo "Deploying minified stylesheets to \`dist/css/\`..." + rm -r ./dist + mkdir -p ./dist/css + for f in ./css/tmp/*.min.css; do + filename=$(basename $f .css) + cp $f ./dist/css + #mv $f ./dist/css + echo -e '\t' $filename".css moved." + done + + # NB: We currently distribute both the minified + concatenated and the + # unminified + unconcatenated stylesheets with the Plugin. + echo "Deploying development stylesheets to \`dist/css/\`..." + for f in ./css/dev-*.css; do + filename=$(basename $f .css) + cp $f ./dist/css + #mv $f ./dist/css + echo -e '\t' $filename".css moved." + done + + #echo "Deleting temporary files..." + #rm -r ./css/tmp + echo "All stylesheets added to build." + exit 0 + +else + + echo -e "Concatenates, minifies (TODO) and deploys stylesheets for distribution.\n" + echo -e "12 unified style sheets are concatenated out of these files:\n" + echo "\`dev-common.css\`" + echo "\`dev-tooltips.css\`" + echo "\`dev-tooltips-alternative.css\`" + echo "\`dev-layout-reference-container.css\`" + echo "\`dev-layout-entry-content.css\`" + echo -e "\`dev-layout-main-content.css\`\n" + echo "Command: \`-c\`: Concatenate \`dev-*\` CSS files into temporary directory." + echo "Command: \`-m\`: Minify files (TODO)." + echo "Command: \`-d\`: Deploy minified files to \`dist/css/\` and remove temporary files." + echo "No command, \"--help\", or anything else: Output this help section." + +fi diff --git a/_tools/build.sh b/_tools/build.sh new file mode 100755 index 0000000..e4b908b --- /dev/null +++ b/_tools/build.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +echo "Building Plugin..." + +# Moves everything including the style sheets over to `dist/` +echo "Copying directories..." +cp -r -t dist class/ css/ js/ languages/ templates/ +# Among the images, only 2 out of 3 are distributed. +echo "Copying the needed images..." +mkdir dist/img +cp -t dist/img img/fn-wysiwyg.png img/main-menu.png +echo "Copying files..." +cp -t dist features.txt license.txt readme.txt includes.php wpml-config.xml customized-documentation-schema.txt customized-template-stack.txt CONTRIBUTING.md README.md SECURITY.md +echo "Setting production flag..." +sed "s/'C_BOOL_CSS_PRODUCTION_MODE', false/'C_BOOL_CSS_PRODUCTION_MODE', true/g" footnotes.php > dist/footnotes.php +echo "Production flag set." + +# TODO: once automatic minification is implemented, this should handle that. +# For now, we shall have to assume that this command is being run on a repo. with +# minimised stylesheet files already in `dist/css/`. +echo "Building stylesheets..." +./_tools/build-stylesheets.sh -c +if [ $? != 0 ]; then echo "Concatenation failed!"; exit 1; fi +./_tools/build-stylesheets.sh -m +if [ $? != 0 ]; then echo "Minification failed!"; exit 1; fi +./_tools/build-stylesheets.sh -d +if [ $? != 0 ]; then echo "Deployment failed!"; exit 1; fi +echo "Stylesheet build complete." + +echo "Build complete." +exit 0 diff --git a/_tools/release.sh b/_tools/release.sh new file mode 100755 index 0000000..11d74f0 --- /dev/null +++ b/_tools/release.sh @@ -0,0 +1,246 @@ +#!/bin/bash + +# This is a release helper script aimed at walking maintainers through the +# process of issuing new releases of the Plugin, both to reduce the risk of +# procedural errors and to provide a framework for future incremental +# automation. +# +# Step 1: Ensure the local copy has checked out the `main` branch +# Step 2: Ensure local copy of `main` is up-to-date with remote +# Step 3: Check versioning +# Step 3(a): Get all version declarations +# Step 3(b): Check that all version declarations exists +# Step 3(c)(1): Check that all development versions match +# Step 3(c)(2): Check that all stable versions match +# Step 3(d): Check that the development version is correctly flagged as such +# Step 3(e): Check that the 'Stable Tag' field is set to a stable version +# Step 3(f): Check that the 'Stable Tag' field points to a real tag on the SVN repo. +# Step 3(g): Check that the changelog is up-to-date +# Step 4: Build the Plugin +# Step 5: Update the version to pre-release +# Step 6: Tag the release + +echo "Welcome to the footnotes release helper!" +echo "========================================" + +if [[ $1 == "-c" ]]; then + read -p "You have passed the \`commit\` flag (\`-c\`). Did you mean to do this? (Y/N): " CONFIRM && [[ $CONFIRM == [yY] || $CONFIRM == [yY][eE][sS] ]] || exit 1 +fi + +# NB: To run on a branch other than `main`, uncomment this line: +#if false; then + +# Step 1: Ensure the local copy has checked out the `main` branch + +if [[ "$(git rev-parse --abbrev-ref HEAD)" != "main" ]]; then + echo "ERR: You are not on the \`main\` branch, please check it out and re-run this command." + exit 1 +else + echo "- \`main\` branch is checked out." +fi + +# Step 2: Ensure local copy of `main` is up-to-date with remote + +if [[ "$(git status | grep -c 'Your branch is up to date')" != 1 ]]; then + echo "ERR: Your local copy is not up-to-date with the remote, please update it and re-run this command." + exit 1 +else + echo "- Local copy of \`main\` is up-to-date with remote." +fi + +# NB: To run on a branch other than `main`, uncomment this line: +#fi + +# Step 3: Check versioning + +# Step 3(a): Get all version declarations + +# NOTE: I'm not sure why, but if you try to get the root header +# version without piping it through the second `grep` command, +# you'll end up with a list of files before the version +# declaration. + +echo "- Checking versions..." + +STABLE_TAG="$(grep "Stable Tag:" readme.txt)" +ROOT_HEADER_VERSION="$(grep " Version:" footnotes.php | grep -Po " Version: \d+\.\d+(\.\d+)?[a-z]?$")" +JS_VERSION="$(grep "version :" js/wysiwyg-editor.js)" + +# Step 3(b): Check that all version declarations exists + +if [[ -z $STABLE_TAG ]]; then + echo "ERR: No 'Stable Tag' field found in \`readme.txt\`!" + exit 1 +else echo "- 'Stable Tag' field set in \`readme.txt\`." +fi +if [[ -z $ROOT_HEADER_VERSION ]]; then + echo "ERR: No 'Version' field found in \`footnotes.php\` file header!" + exit 1 +else echo "- 'Version' field set in \`footnotes.php\` file header." +fi +if [[ -z $JS_VERSION ]]; then + echo "ERR: No \`version\` variable found in \`js/wysiwyg-editor.js\`!" + exit 1 +else echo "- \`version\` variable set in \`js/wysiwyg-editor.js\`." +fi + +# Step 3(c)(1): Check that all development versions match +# NB: This doesn't currently do anything as there is only one place where the +# development version is listed. + +if [[ "$(echo $JS_VERSION | grep -Poc '\d+\.\d+(\.\d+)?')" != 1 ]]; then + echo "ERR: Development version mismatch!" + echo -e "The following versions were found:\n" + echo -e '\t' $JS_VERSION '\n' + echo "Please ensure that all development versions match and re-run this command." + exit 1 +else echo "- Development versions match." +fi + +# Step 3(c)(2): Check that all stable versions match + +if [[ "$(echo $ROOT_HEADER_VERSION $STABLE_TAG | grep -Poc '\d+\.\d+(\.\d+)?')" != 1 ]]; then + echo "ERR: Stable version mismatch!" + echo -e "The following versions were found:\n" + echo -e '\t' $ROOT_HEADER_VERSION + echo -e '\t' $STABLE_TAG '\n' + echo "Please ensure that all stable versions match and re-run this command." + exit 1 +else echo "- Stable versions match." +fi + +# Step 3(d): Check that the development version is correctly flagged as such + +if [[ "$(echo $JS_VERSION | grep -Poc '\d+d')" != 1 ]]; then + echo "ERR: Development version flag not set!" + echo -e "The following version was found:\n" + echo -e '\t' $JS_VERSION '\n' + echo "Please ensure that the development flag ('d') is set and re-run this command." + exit 1 +else echo "- Development version flag is set." +fi + +DEVELOPMENT_VERSION="$(echo $JS_VERSION | grep -Po '\d+\.\d+(\.\d+)?')" + +echo -e "- Development version:" $DEVELOPMENT_VERSION + +# Step 3(e): Check that the 'Stable Tag' field is set to a stable version + +if [[ "$(echo $STABLE_TAG | grep -Poc '\d+\.\d+(\.\d+)?$')" != 1 ]]; then + echo "ERR: 'Stable Tag' not set to a stable version!" + echo -e "The 'Stable Tag' field is set to the following:\n" + echo -e '\t' $STABLE_TAG '\n' + echo "Please ensure that the 'Stable Tag' field is set to a stable version and re-run this command." + exit 1 +else echo "- 'Stable Tag' field set to stable version." +fi + +STABLE_VERSION="$(echo $STABLE_TAG | grep -Po '\d+\.\d+(\.\d+)?$')" + +echo "- Stable version:" $STABLE_VERSION + +# Step 3(f): Check that the 'Stable Tag' field points to a real tag on the SVN repo. + +echo "- Checking stable tag exists..." +git svn tag --dry-run $STABLE_VERSION &>/dev/null + +if [ $? -ne 1 ]; then + echo "ERR: 'Stable Tag' does not point to an existing tag!" + echo "Please ensure that the 'Stable Tag' field points to an existing stable version and re-run this command." + exit 1 +else echo "- 'Stable Tag' field is set to existing tag." +fi + +# Step 3(g): Check that the changelog is up-to-date + +CHANGELOG_LATEST="$(awk -e '/== Changelog ==/,/= [0-9]+\.[0-9]+(\.[0-9]+)? =/' readme.txt | grep -Po '\d+\.\d+(\.\d+)?')" +if [[ $CHANGELOG_LATEST != $DEVELOPMENT_VERSION ]]; then + echo "ERR: Changelog is not up-to-date!" + echo "Current version is $DEVELOPMENT_VERSION" + echo "Latest version in changelog is $CHANGELOG_LATEST" + echo "Please ensure that the changelog is up-to-date and re-run this command." + exit 1 +else echo "- Changelog is up-to-date." +fi + +echo -e "- Version check complete.\n" + +# Step 4: Build the Plugin + +echo "- Building Plugin..." +composer run build +if [ $? != 0 ]; then echo "Build failed!"; exit 1; fi +echo -e "- Build complete.\n" + +# Step 5: Update the version to pre-release + +echo "- Setting pre-release version flags..." +PRERELEASE_VERSION=$DEVELOPMENT_VERSION'p' +sed -i "s/$JS_VERSION/version : \"$PRERELEASE_VERSION\"/g" dist/js/wysiwyg-editor.js +echo "- Pre-release flags set." + +# Step 6: Tag the release + +echo "- Tagging release..." +git tag -a $DEVELOPMENT_VERSION -m "Pre-release of version $DEVELOPMENT_VERSION" +git push --tags +echo "- Release tagged." + +# Step 7: Push release to SVN repo. + +# Step 7(a): Create a new local copy of the SVN repo. + +echo -e "\nThe helper will now guide you through the steps to push the new release to the WordPress Plugin Directory SVN repository." +echo "For the time being, this part of the process shall remain (mostly) manual." +read -p "Are you ready to continue? (Y/N): " CONFIRM && [[ $CONFIRM == [yY] || $CONFIRM == [yY][eE][sS] ]] || exit 1 + +echo "Creating local copy of SVN repo..." +svn checkout https://plugins.svn.wordpress.org/footnotes tmp --depth immediates +svn update --quiet tmp/trunk --set-depth infinity +svn update --quiet tmp/tags/$PRERELEASE_VERSION --set-depth infinity +echo -e "Local copy created.\n" + +# Step 7(b): Update `trunk/` +echo -e "Copying files from \`dist/\` to SVN \`trunk/\`...\n" +rsync -avhic dist/ tmp/trunk/ --delete | grep -v "^\." +read -p "Does the above list of changes look correct? (Y/N): " CONFIRM && [[ $CONFIRM == [yY] || $CONFIRM == [yY][eE][sS] ]] || exit 1 +echo -e "Copying complete.\n" + +# Step 7(c): Set a release message + +echo "Getting commit message from changelog..." +CHANGELOG_MESSAGE="$(awk -e "/= $DEVELOPMENT_VERSION =/,/= $STABLE_VERSION =/" readme.txt | grep '^-')" +echo -e "The changelog message for this version is:\n" +echo -e "$CHANGELOG_MESSAGE\n" +read -p "Is this correct? (Y/N): " CONFIRM && [[ $CONFIRM == [yY] || $CONFIRM == [yY][eE][sS] ]] || exit 1 +echo -e "Commit message set.\n" + +# Step 7(d): Review + +clear +echo "Let's review before pushing to the SVN..." +echo -e "Here is my current state:\n" +echo "Current version:" +echo -e '\t' $PRERELEASE_VERSION +echo "Stable version:" +echo -e '\t' $STABLE_VERSION '\n' +echo "Commit message:\n" +echo -e "$CHANGELOG_MESSAGE" '\n' +echo -e "Changes made to local \`trunk/\`:\n" +svn stat tmp/trunk/ +echo "" +echo -e "\`readme.txt\` header:\n" +head tmp/trunk/readme.txt +echo "" +read -p "Is this all correct? (Y/N): " CONFIRM && [[ $CONFIRM == [yY] || $CONFIRM == [yY][eE][sS] ]] || exit 1 + +# Step 7(d): Push to remote `trunk/` (provided the flag is set) + +if [[ $1 == "-c" ]]; then + svn ci -m "$CHANGELOG_MESSAGE" +else echo "- Commit flag not set, skipping commit step." +fi + +# Step 8: Cleanup + +rm -rf {dist/,tmp/} diff --git a/_tools/setup.sh b/_tools/setup.sh new file mode 100755 index 0000000..fd4c786 --- /dev/null +++ b/_tools/setup.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cp contrib/pre-commit .git/hooks/pre-commit +chmod +x .git/hooks/pre-commit diff --git a/class/dashboard/init.php b/class/dashboard/init.php new file mode 100644 index 0000000..c3f505e --- /dev/null +++ b/class/dashboard/init.php @@ -0,0 +1,207 @@ +a_arr_sub_page_classes[ $l_obj_class->get_priority() ] = $l_obj_class; + } + } + ksort( $this->a_arr_sub_page_classes ); + + // Register hooks/actions. + add_action( 'admin_init', array( $this, 'initialize_settings' ) ); + add_action( 'admin_menu', array( $this, 'register_main_menu' ) ); + // Register AJAX callbacks for Plugin information. + add_action( 'wp_ajax_nopriv_footnotes_get_plugin_info', array( $this, 'get_plugin_meta_information' ) ); + add_action( 'wp_ajax_footnotes_get_plugin_info', array( $this, 'get_plugin_meta_information' ) ); + } + + /** + * Initializes all sub pages and registers the settings. + * + * @since 1.5.0 + */ + public function initialize_settings() { + MCI_Footnotes_Settings::instance()->register_settings(); + // Iterate though each sub class of the layout engine and register their sections. + foreach ( $this->a_arr_sub_page_classes as $l_obj_layout_engine_sub_class ) { + $l_obj_layout_engine_sub_class->register_sections(); + } + } + + /** + * Registers the new main menu for the WordPress dashboard. + * Registers all sub menu pages for the new main menu. + * + * @since 1.5.0 + * @see http://codex.wordpress.org/Function_Reference/add_menu_page + */ + public function register_main_menu() { + global $menu; + // Iterate through each main menu. + foreach ( $menu as $l_arr_main_menu ) { + // 3terate through each main menu attribute. + foreach ( $l_arr_main_menu as $l_str_attribute ) { + // Main menu already added, append sub pages and stop. + if ( self::C_STR_MAIN_MENU_SLUG === $l_str_attribute ) { + $this->register_sub_pages(); + return; + } + } + } + + // Add a new main menu page to the WordPress dashboard. + add_menu_page( + self::C_STR_MAIN_MENU_TITLE, // Page title. + self::C_STR_MAIN_MENU_TITLE, // Menu title. + 'manage_options', // Capability. + self::C_STR_MAIN_MENU_SLUG, // Menu slug. + array( $this, 'display_other_plugins' ), // Function. + plugins_url( 'footnotes/img/main-menu.png' ), // Icon URL. + null // Position. + ); + $this->register_sub_pages(); + } + + /** + * Registers all SubPages for this Plugin. + * + * @since 1.5.0 + */ + private function register_sub_pages() { + // First registered sub menu page MUST NOT contain a unique slug suffix. + // Iterate though each sub class of the layout engine and register their sub page. + foreach ( $this->a_arr_sub_page_classes as $l_obj_layout_engine_sub_class ) { + $l_obj_layout_engine_sub_class->register_sub_page(); + } + } + + /** + * Displays other Plugins from the developers. + * + * @since 1.5.0 + */ + public function display_other_plugins() { + printf( '

' ); + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'manfisher' ); + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped + + printf( 'visit Mark Cheret' ); + printf( '

' ); + + printf( '' ); + } + + // phpcs:disable WordPress.Security.NonceVerification.Missing + /** + * AJAX call. returns a JSON string containing meta information about a specific WordPress Plugin. + * + * @since 1.5.0 + */ + public function get_plugin_meta_information() { + // TODO: add nonce verification. + + // Get plugin internal name from POST data. + if ( isset( $_POST['plugin'] ) ) { + $l_str_plugin_name = wp_unslash( $_POST['plugin'] ); + } + + if ( empty( $l_str_plugin_name ) ) { + echo wp_json_encode( array( 'error' => 'Plugin name invalid.' ) ); + exit; + } + $l_str_url = 'https://api.wordpress.org/plugins/info/1.0/' . $l_str_plugin_name . '.json'; + // Call URL and collect data. + $l_arr_response = wp_remote_get( $l_str_url ); + // Check if response is valid. + if ( is_wp_error( $l_arr_response ) ) { + echo wp_json_encode( array( 'error' => 'Error receiving Plugin Information from WordPress.' ) ); + exit; + } + if ( ! array_key_exists( 'body', $l_arr_response ) ) { + echo wp_json_encode( array( 'error' => 'Error reading WordPress API response message.' ) ); + exit; + } + // Get the body of the response. + $l_str_response = $l_arr_response['body']; + // Get plugin object. + $l_arr_plugin = json_decode( $l_str_response, true ); + if ( empty( $l_arr_plugin ) ) { + echo wp_json_encode( array( 'error' => 'Error reading Plugin meta information.
URL: ' . $l_str_url . '
Response: ' . $l_str_response ) ); + exit; + } + + $l_int_num_ratings = array_key_exists( 'num_ratings', $l_arr_plugin ) ? intval( $l_arr_plugin['num_ratings'] ) : 0; + $l_int_rating = array_key_exists( 'rating', $l_arr_plugin ) ? floatval( $l_arr_plugin['rating'] ) : 0.0; + $l_int_stars = round( 5 * $l_int_rating / 100.0, 1 ); + + // Return Plugin information as JSON encoded string. + echo wp_json_encode( + array( + 'error' => '', + 'PluginDescription' => array_key_exists( 'short_description', $l_arr_plugin ) ? html_entity_decode( $l_arr_plugin['short_description'] ) : 'Error reading Plugin information', + 'PluginAuthor' => array_key_exists( 'author', $l_arr_plugin ) ? html_entity_decode( $l_arr_plugin['author'] ) : 'unknown', + 'PluginRatingText' => $l_int_stars . ' ' . __( 'rating based on', 'footnotes' ) . ' ' . $l_int_num_ratings . ' ' . __( 'ratings', 'footnotes' ), + 'PluginRating1' => $l_int_stars >= 0.5 ? 'star-full' : 'star-empty', + 'PluginRating2' => $l_int_stars >= 1.5 ? 'star-full' : 'star-empty', + 'PluginRating3' => $l_int_stars >= 2.5 ? 'star-full' : 'star-empty', + 'PluginRating4' => $l_int_stars >= 3.5 ? 'star-full' : 'star-empty', + 'PluginRating5' => $l_int_stars >= 4.5 ? 'star-full' : 'star-empty', + 'PluginRating' => $l_int_num_ratings, + 'PluginLastUpdated' => array_key_exists( 'last_updated', $l_arr_plugin ) ? $l_arr_plugin['last_updated'] : 'unknown', + 'PluginDownloads' => array_key_exists( 'downloaded', $l_arr_plugin ) ? $l_arr_plugin['downloaded'] : '---', + ) + ); + exit; + } + // phpcs:enable WordPress.Security.NonceVerification.Missing +} diff --git a/class/dashboard/layout.php b/class/dashboard/layout.php new file mode 100644 index 0000000..668453a --- /dev/null +++ b/class/dashboard/layout.php @@ -0,0 +1,579 @@ + MCI_Footnotes_Config::C_STR_PLUGIN_NAME . '-' . $p_str_id, + 'title' => $p_str_title, + 'submit' => $p_bool_has_submit_button, + 'container' => $p_int_settings_container_index, + ); + } + + /** + * Returns an array describing a meta box. + * + * @since 1.5.0 + * @param string $p_str_section_id Parent Section ID. + * @param string $p_str_id Unique ID suffix. + * @param string $p_str_title Title for the meta box. + * @param string $p_str_callback_function_name Class method name for callback. + * @return array meta box description to be able to append a meta box to the output. + */ + protected function add_meta_box( $p_str_section_id, $p_str_id, $p_str_title, $p_str_callback_function_name ) { + return array( + 'parent' => MCI_Footnotes_Config::C_STR_PLUGIN_NAME . '-' . $p_str_section_id, + 'id' => $p_str_id, + 'title' => $p_str_title, + 'callback' => $p_str_callback_function_name, + ); + } + + /** + * Registers a sub page. + * + * @since 1.5.0 + */ + public function register_sub_page() { + global $submenu; + + if ( array_key_exists( plugin_basename( MCI_Footnotes_Layout_Init::C_STR_MAIN_MENU_SLUG ), $submenu ) ) { + foreach ( $submenu[ plugin_basename( MCI_Footnotes_Layout_Init::C_STR_MAIN_MENU_SLUG ) ] as $l_arr_sub_menu ) { + if ( plugin_basename( MCI_Footnotes_Layout_Init::C_STR_MAIN_MENU_SLUG . $this->get_sub_page_slug() ) === $l_arr_sub_menu[2] ) { + remove_submenu_page( MCI_Footnotes_Layout_Init::C_STR_MAIN_MENU_SLUG, MCI_Footnotes_Layout_Init::C_STR_MAIN_MENU_SLUG . $this->get_sub_page_slug() ); + } + } + } + + $this->a_str_sub_page_hook = add_submenu_page( + MCI_Footnotes_Layout_Init::C_STR_MAIN_MENU_SLUG, + $this->get_sub_page_title(), + $this->get_sub_page_title(), + 'manage_options', + MCI_Footnotes_Layout_Init::C_STR_MAIN_MENU_SLUG . $this->get_sub_page_slug(), + array( $this, 'display_content' ) + ); + } + + /** + * Registers all sections for a sub page. + * + * @since 1.5.0 + */ + public function register_sections() { + foreach ( $this->get_sections() as $l_arr_section ) { + // Append tab to the tab-array. + $this->a_arr_sections[ $l_arr_section['id'] ] = $l_arr_section; + add_settings_section( + $l_arr_section['id'], + '', + array( $this, 'Description' ), + $l_arr_section['id'] + ); + $this->register_meta_boxes( $l_arr_section['id'] ); + } + } + + /** + * Registers all Meta boxes for a sub page. + * + * @since 1.5.0 + * @param string $p_str_parent_id Parent section unique id. + */ + private function register_meta_boxes( $p_str_parent_id ) { + // Iterate through each meta box. + foreach ( $this->get_meta_boxes() as $l_arr_meta_box ) { + if ( $p_str_parent_id !== $l_arr_meta_box['parent'] ) { + continue; + } + add_meta_box( + $p_str_parent_id . '-' . $l_arr_meta_box['id'], + $l_arr_meta_box['title'], + array( $this, $l_arr_meta_box['callback'] ), + $p_str_parent_id, + 'main' + ); + } + } + + /** + * Append javascript and css files for specific sub page. + * + * @since 1.5.0 + */ + private function append_scripts() { + wp_enqueue_script( 'postbox' ); + wp_enqueue_style( 'wp-color-picker' ); + wp_enqueue_script( 'wp-color-picker' ); + + /** + * Registers and enqueues the dashboard stylesheet. + * + * - Bugfix: Stylesheets: minify to shrink the carbon footprint, increase speed and implement best practice, thanks to @docteurfitness issue report. + * + * @since 2.5.5 + * @date 2021-02-14T1928+0100 + * + * @reporter @docteurfitness + * @link https://wordpress.org/support/topic/simply-speed-optimisation/ + * + * See the public stylesheet enqueuing: + * @see class/init.php + * + * added version # after changes started to settings.css from 2.1.2 on. + * automated update of version number for cache busting. + * No need to use '-styles' in the handle, as '-css' is appended automatically. + */ + if ( C_BOOL_CSS_PRODUCTION_MODE === true ) { + + wp_register_style( + 'mci-footnotes-admin', + plugins_url( 'footnotes/css/settings.min.css' ), + array(), + filemtime( + plugin_dir_path( + dirname( __FILE__ ) + ) . 'css/settings.min.css' + ) + ); + + } else { + + wp_register_style( + 'mci-footnotes-admin', + plugins_url( 'footnotes/css/settings.css' ), + array(), + filemtime( + plugin_dir_path( + dirname( __FILE__ ) + ) . 'css/settings.css' + ) + ); + + } + + wp_enqueue_style( 'mci-footnotes-admin' ); + } + + // phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing + /** + * Displays the content of specific sub page. + * + * @since 1.5.0 + */ + public function display_content() { + $this->append_scripts(); + + // TODO: add nonce verification. + + // Get the current section. + reset( $this->a_arr_sections ); + $l_str_active_section_id = isset( $_GET['t'] ) ? wp_unslash( $_GET['t'] ) : key( $this->a_arr_sections ); + $l_arr_active_section = $this->a_arr_sections[ $l_str_active_section_id ]; + + // Store settings. + $l_bool_settings_updated = false; + if ( array_key_exists( 'save-settings', $_POST ) ) { + if ( 'save' === $_POST['save-settings'] ) { + unset( $_POST['save-settings'] ); + unset( $_POST['submit'] ); + $l_bool_settings_updated = $this->save_settings(); + } + } + + // Display all sections and highlight the active section. + echo '
'; + echo '
'; + + if ( $l_bool_settings_updated ) { + echo sprintf( '
%s
', __( 'Settings saved', 'footnotes' ) ); + } + + // Form to submit the active section. + echo '
'; + echo ''; + // Outputs the settings field of the active section. + do_settings_sections( $l_arr_active_section['id'] ); + do_meta_boxes( $l_arr_active_section['id'], 'main', null ); + + // Add submit button to active section if defined. + if ( $l_arr_active_section['submit'] ) { + submit_button(); + } + echo '
'; + echo '
'; + + // Echo JavaScript for the expand/collapse function of the meta boxes. + echo ''; + } + // phpcs:enable WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing + + // phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing + /** + * Save all Plugin settings. + * + * @since 1.5.0 + * @return bool + */ + private function save_settings() { + $l_arr_new_settings = array(); + + // TODO: add nonce verification. + + // Get current section. + reset( $this->a_arr_sections ); + $l_str_active_section_id = isset( $_GET['t'] ) ? wp_unslash( $_GET['t'] ) : key( $this->a_arr_sections ); + $l_arr_active_section = $this->a_arr_sections[ $l_str_active_section_id ]; + + foreach ( MCI_Footnotes_Settings::instance()->get_defaults( $l_arr_active_section['container'] ) as $l_str_key => $l_mixed_value ) { + if ( array_key_exists( $l_str_key, $_POST ) ) { + $l_arr_new_settings[ $l_str_key ] = wp_unslash( $_POST[ $l_str_key ] ); + } else { + // Setting is not defined in the POST array, define it to avoid the Default value. + $l_arr_new_settings[ $l_str_key ] = ''; + } + } + // Update settings. + return MCI_Footnotes_Settings::instance()->save_options( $l_arr_active_section['container'], $l_arr_new_settings ); + } + // phpcs:enable WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing + + /** + * Output the Description of a section. May be overwritten in any section. + * + * @since 1.5.0 + */ + public function description() { + // Default no description will be displayed. + } + + /** + * Loads specific setting and returns an array with the keys [id, name, value]. + * + * @since 1.5.0 + * @param string $p_str_setting_key_name Settings Array key name. + * @return array Contains Settings ID, Settings Name and Settings Value. + */ + protected function load_setting( $p_str_setting_key_name ) { + // Get current section. + reset( $this->a_arr_sections ); + $p_arr_return = array(); + $p_arr_return['id'] = sprintf( '%s', $p_str_setting_key_name ); + $p_arr_return['name'] = sprintf( '%s', $p_str_setting_key_name ); + $p_arr_return['value'] = MCI_Footnotes_Settings::instance()->get( $p_str_setting_key_name ); + return $p_arr_return; + } + + /** + * Returns a line break to start a new line. + * + * @since 1.5.0 + * @return string + */ + protected function add_newline() { + return '
'; + } + + /** + * Returns a line break to have a space between two lines. + * + * @since 1.5.0 + * @return string + */ + protected function add_line_space() { + return '

'; + } + + /** + * Returns a simple text inside html text. + * + * @since 1.5.0 + * @param string $p_str_text Message to be surrounded with simple html tag (span). + * @return string + */ + protected function add_text( $p_str_text ) { + return sprintf( '%s', $p_str_text ); + } + + /** + * Returns the html tag for an input/select label. + * + * @since 1.5.0 + * @param string $p_str_setting_name Name of the Settings key to connect the Label with the input/select field. + * @param string $p_str_caption Label caption. + * @return string + */ + protected function add_label( $p_str_setting_name, $p_str_caption ) { + if ( empty( $p_str_caption ) ) { + return ''; + } + + /* + * Remove the colon causing localization issues with French, and with + * languages not using punctuation at all, and with languages using other + * punctuation marks instead of colon, e.g. Greek using a raised dot. + * In French, colon is preceded by a space, forcibly non-breaking, and + * narrow per new school. + * Add colon to label strings for inclusion in localization. Colon after + * label is widely preferred best practice, mandatory per + * [style guides](https://softwareengineering.stackexchange.com/questions/234546/colons-in-internationalized-ui). + */ + return sprintf( '', $p_str_setting_name, $p_str_caption ); + } + + /** + * Returns the html tag for an input [type = text]. + * + * @since 1.5.0 + * @param string $p_str_setting_name Name of the Settings key to pre load the input field. + * @param int $p_str_max_length Maximum length of the input, default 999 characters. + * @param bool $p_bool_readonly Set the input to be read only, default false. + * @param bool $p_bool_hidden Set the input to be hidden, default false. + * @return string + */ + protected function add_text_box( $p_str_setting_name, $p_str_max_length = 999, $p_bool_readonly = false, $p_bool_hidden = false ) { + $l_str_style = ''; + // Collect data for given settings field. + $l_arr_data = $this->load_setting( $p_str_setting_name ); + if ( $p_bool_hidden ) { + $l_str_style .= 'display:none;'; + } + return sprintf( + '', + $l_arr_data['name'], + $l_arr_data['id'], + $p_str_max_length, + $l_str_style, + $l_arr_data['value'], + $p_bool_readonly ? 'readonly="readonly"' : '' + ); + } + + /** + * Returns the html tag for an input [type = checkbox]. + * + * @since 1.5.0 + * @param string $p_str_setting_name Name of the Settings key to pre load the input field. + * @return string + */ + protected function add_checkbox( $p_str_setting_name ) { + // Collect data for given settings field. + $l_arr_data = $this->load_setting( $p_str_setting_name ); + return sprintf( + '', + $l_arr_data['name'], + $l_arr_data['id'], + MCI_Footnotes_Convert::to_bool( $l_arr_data['value'] ) ? 'checked="checked"' : '' + ); + } + + /** + * Returns the html tag for a select box. + * + * @since 1.5.0 + * @param string $p_str_setting_name Name of the Settings key to pre select the current value. + * @param array $p_arr_options Possible options to be selected. + * @return string + */ + protected function add_select_box( $p_str_setting_name, $p_arr_options ) { + // Collect data for given settings field. + $l_arr_data = $this->load_setting( $p_str_setting_name ); + $l_str_options = ''; + + foreach ( $p_arr_options as $l_str_value => $l_str_caption ) { + $l_str_options .= sprintf( + '', + $l_str_value, + $l_str_value === $l_arr_data['value'] ? 'selected' : '', + $l_str_caption + ); + } + return sprintf( + '', + $l_arr_data['name'], + $l_arr_data['id'], + $l_str_options + ); + } + + /** + * Returns the html tag for a text area. + * + * @since 1.5.0 + * @param string $p_str_setting_name Name of the Settings key to pre fill the text area. + * @return string + */ + protected function add_textarea( $p_str_setting_name ) { + // Collect data for given settings field. + $l_arr_data = $this->load_setting( $p_str_setting_name ); + return sprintf( + '', + $l_arr_data['name'], + $l_arr_data['id'], + $l_arr_data['value'] + ); + } + + /** + * Returns the html tag for an input [type = text] with color selection class. + * + * @since 1.5.6 + * @param string $p_str_setting_name Name of the Settings key to pre load the input field. + * @return string + */ + protected function add_color_selection( $p_str_setting_name ) { + // Collect data for given settings field. + $l_arr_data = $this->load_setting( $p_str_setting_name ); + return sprintf( + '', + $l_arr_data['name'], + $l_arr_data['id'], + $l_arr_data['value'] + ); + } + + /** + * Returns the html tag for an input [type = num]. + * + * @since 1.5.0 + * @param string $p_str_setting_name Name of the Settings key to pre load the input field. + * @param int $p_in_min Minimum value. + * @param int $p_int_max Maximum value. + * @param bool $p_bool_deci true if 0.1 steps and floating to string, false if integer (default). + * @return string + * + * Edited: + * @since 2.1.4 step argument and number_format() to allow decimals 2020-12-03T0631+0100..2020-12-12T1110+0100 + */ + protected function add_num_box( $p_str_setting_name, $p_in_min, $p_int_max, $p_bool_deci = false ) { + // Collect data for given settings field. + $l_arr_data = $this->load_setting( $p_str_setting_name ); + + if ( $p_bool_deci ) { + $l_str_value = number_format( floatval( $l_arr_data['value'] ), 1 ); + return sprintf( + '', + $l_arr_data['name'], + $l_arr_data['id'], + $l_str_value, + $p_in_min, + $p_int_max + ); + } else { + return sprintf( + '', + $l_arr_data['name'], + $l_arr_data['id'], + $l_arr_data['value'], + $p_in_min, + $p_int_max + ); + } + } + +} diff --git a/class/dashboard/subpage-diagnostics.php b/class/dashboard/subpage-diagnostics.php new file mode 100644 index 0000000..1a30015 --- /dev/null +++ b/class/dashboard/subpage-diagnostics.php @@ -0,0 +1,147 @@ +add_section( 'diagnostics', __( 'Diagnostics', 'footnotes' ), null, false ), + ); + } + + /** + * Returns an array of all registered meta boxes for each section of the sub page. + * + * @since 1.5.0 + * @return array + */ + protected function get_meta_boxes() { + return array( + $this->add_meta_box( 'diagnostics', 'diagnostics', __( 'Displays information about the web server, PHP and WordPress', 'footnotes' ), 'Diagnostics' ), + ); + } + + /** + * Displays a diagnostics about the web server, php and WordPress. + * + * @since 1.5.0 + */ + public function Diagnostics() { + global $wp_version; + $l_str_php_extensions = ''; + // Iterate through each PHP extension. + foreach ( get_loaded_extensions() as $l_int_index => $l_str_extension ) { + if ( $l_int_index > 0 ) { + $l_str_php_extensions .= ' | '; + } + $l_str_php_extensions .= $l_str_extension . ' ' . phpversion( $l_str_extension ); + } + + $l_obj_current_theme = wp_get_theme(); + + $l_str_wordpress_plugins = ''; + // Iterate through each installed WordPress Plugin. + foreach ( get_plugins() as $l_arr_plugin ) { + $l_str_wordpress_plugins .= ''; + $l_str_wordpress_plugins .= '' . $l_arr_plugin['Name'] . ''; + // phpcs:disable Generic.Strings.UnnecessaryStringConcat.Found + $l_str_wordpress_plugins .= '' . $l_arr_plugin['Version'] . ' [' . $l_arr_plugin['PluginURI'] . ']' . ''; + // phpcs:enable Generic.Strings.UnnecessaryStringConcat.Found + $l_str_wordpress_plugins .= ''; + } + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'diagnostics' ); + + if ( ! isset( $_SERVER['SERVER_NAME'] ) ) { + die; + } else { + $l_str_server_name = wp_unslash( $_SERVER['SERVER_NAME'] ); + } + if ( ! isset( $_SERVER['HTTP_USER_AGENT'] ) ) { + die; + } else { + $l_str_http_user_agent = wp_unslash( $_SERVER['HTTP_USER_AGENT'] ); + } + + // Replace all placeholders. + $l_obj_template->replace( + array( + 'label-server' => __( 'Server name', 'footnotes' ), + 'server' => $l_str_server_name, + + 'label-php' => __( 'PHP version', 'footnotes' ), + 'php' => phpversion(), + + 'label-user-agent' => __( 'User agent', 'footnotes' ), + 'user-agent' => $l_str_http_user_agent, + + 'label-max-execution-time' => __( 'Max execution time', 'footnotes' ), + 'max-execution-time' => ini_get( 'max_execution_time' ) . ' ' . __( 'seconds', 'footnotes' ), + + 'label-memory-limit' => __( 'Memory limit', 'footnotes' ), + 'memory-limit' => ini_get( 'memory_limit' ), + + 'label-php-extensions' => __( 'PHP extensions', 'footnotes' ), + 'php-extensions' => $l_str_php_extensions, + + 'label-wordpress' => __( 'WordPress version', 'footnotes' ), + 'wordpress' => $wp_version, + + 'label-theme' => __( 'Active Theme', 'footnotes' ), + 'theme' => $l_obj_current_theme->get( 'Name' ) . ' ' . $l_obj_current_theme->get( 'Version' ) . ', ' . $l_obj_current_theme->get( 'Author' ) . ' [' . $l_obj_current_theme->get( 'AuthorURI' ) . ']', + + 'plugins' => $l_str_wordpress_plugins, + ) + ); + // Display template with replaced placeholders. + echo $l_obj_template->get_content(); + } +} diff --git a/class/dashboard/subpage-main.php b/class/dashboard/subpage-main.php new file mode 100644 index 0000000..bfddc98 --- /dev/null +++ b/class/dashboard/subpage-main.php @@ -0,0 +1,1261 @@ +add_section( 'settings', __( 'General settings', 'footnotes' ), 0, true ); + + // Sync tab name with mirror in public function custom_css_migration(). + $l_arr_tabs[] = $this->add_section( 'customize', __( 'Referrers and tooltips', 'footnotes' ), 1, true ); + + $l_arr_tabs[] = $this->add_section( 'expert', __( 'Scope and priority', 'footnotes' ), 2, true ); + $l_arr_tabs[] = $this->add_section( 'customcss', __( 'Custom CSS', 'footnotes' ), 3, true ); + $l_arr_tabs[] = $this->add_section( 'how-to', __( 'Quick start guide', 'footnotes' ), null, false ); + + return $l_arr_tabs; + } + + /** + * Returns an array of all registered meta boxes for each section of the sub page. + * + * @since 1.5.0 + * @return array + * + * Edited for 2.0.0 and later. + * + * hyperlink_arrow meta box: + * @since 2.0.0 discontinued + * @since 2.0.4 restored to meet user demand for arrow symbol semantics + * @since 2.1.4 discontinued, content moved to Settings > Reference container > Display a backlink symbol + * + * @since 2.0.4 to reflect changes in meta box label display since WPv5.5 + * spans need position:fixed and become unlocalizable + * fix: logo is kept only in the label that doesn’t need to be translated: + * Change string "%s styling" to "Footnotes styling" to fix layout in WPv5.5 + * @see details in class/config.php + * + * @since 2.1.6 / 2.2.0 tabs reordered and renamed + */ + protected function get_meta_boxes() { + $l_arr_meta_boxes = array(); + + // Sync box name with mirror in task.php. + $l_arr_meta_boxes[] = $this->add_meta_box( 'settings', 'start-end', __( 'Footnote start and end short codes', 'footnotes' ), 'start_end' ); + $l_arr_meta_boxes[] = $this->add_meta_box( 'settings', 'numbering', __( 'Footnotes numbering', 'footnotes' ), 'Numbering' ); + $l_arr_meta_boxes[] = $this->add_meta_box( 'settings', 'scrolling', __( 'Scrolling behavior', 'footnotes' ), 'Scrolling' ); + $l_arr_meta_boxes[] = $this->add_meta_box( 'settings', 'reference-container', __( 'Reference container', 'footnotes' ), 'reference_container' ); + $l_arr_meta_boxes[] = $this->add_meta_box( 'settings', 'excerpts', __( 'Footnotes in excerpts', 'footnotes' ), 'excerpts' ); + $l_arr_meta_boxes[] = $this->add_meta_box( 'settings', 'love', MCI_Footnotes_Config::C_STR_PLUGIN_HEADING_NAME . ' ' . MCI_Footnotes_Config::C_STR_LOVE_SYMBOL_HEADING, 'Love' ); + + $l_arr_meta_boxes[] = $this->add_meta_box( 'customize', 'hyperlink-arrow', __( 'Backlink symbol', 'footnotes' ), 'hyperlink_arrow' ); + $l_arr_meta_boxes[] = $this->add_meta_box( 'customize', 'superscript', __( 'Referrer typesetting and formatting', 'footnotes' ), 'superscript' ); + $l_arr_meta_boxes[] = $this->add_meta_box( 'customize', 'mouse-over-box', __( 'Tooltips', 'footnotes' ), 'mouseover_box' ); + $l_arr_meta_boxes[] = $this->add_meta_box( 'customize', 'mouse-over-box-position', __( 'Tooltip position', 'footnotes' ), 'mouseover_box_position' ); + $l_arr_meta_boxes[] = $this->add_meta_box( 'customize', 'mouse-over-box-dimensions', __( 'Tooltip dimensions', 'footnotes' ), 'mouseover_box_dimensions' ); + $l_arr_meta_boxes[] = $this->add_meta_box( 'customize', 'mouse-over-box-timing', __( 'Tooltip timing', 'footnotes' ), 'mouseover_box_timing' ); + $l_arr_meta_boxes[] = $this->add_meta_box( 'customize', 'mouse-over-box-truncation', __( 'Tooltip truncation', 'footnotes' ), 'mouseover_box_truncation' ); + $l_arr_meta_boxes[] = $this->add_meta_box( 'customize', 'mouse-over-box-text', __( 'Tooltip text', 'footnotes' ), 'mouseover_box_text' ); + $l_arr_meta_boxes[] = $this->add_meta_box( 'customize', 'mouse-over-box-appearance', __( 'Tooltip appearance', 'footnotes' ), 'mouseover_box_appearance' ); + if ( MCI_Footnotes_Convert::to_bool( MCI_Footnotes_Settings::instance()->get( MCI_Footnotes_Settings::C_STR_CUSTOM_CSS_LEGACY_ENABLE ) ) ) { + $l_arr_meta_boxes[] = $this->add_meta_box( 'customize', 'custom-css', __( 'Your existing Custom CSS code', 'footnotes' ), 'custom_css' ); + } + + $l_arr_meta_boxes[] = $this->add_meta_box( 'expert', 'lookup', __( 'WordPress hooks with priority level', 'footnotes' ), 'lookup_hooks' ); + + if ( MCI_Footnotes_Convert::to_bool( MCI_Footnotes_Settings::instance()->get( MCI_Footnotes_Settings::C_STR_CUSTOM_CSS_LEGACY_ENABLE ) ) ) { + $l_arr_meta_boxes[] = $this->add_meta_box( 'customcss', 'custom-css-migration', __( 'Your existing Custom CSS code', 'footnotes' ), 'custom_css_migration' ); + } + $l_arr_meta_boxes[] = $this->add_meta_box( 'customcss', 'custom-css-new', __( 'Custom CSS', 'footnotes' ), 'custom_css_new' ); + + $l_arr_meta_boxes[] = $this->add_meta_box( 'how-to', 'help', __( 'Brief introduction in how to use the plugin', 'footnotes' ), 'help' ); + $l_arr_meta_boxes[] = $this->add_meta_box( 'how-to', 'donate', __( 'Help us to improve our Plugin', 'footnotes' ), 'donate' ); + + return $l_arr_meta_boxes; + } + + /** + * Displays all settings for the reference container. + * + * @since 1.5.0 + * + * Completed: + * @since 2.1.4: layout and typography options 2020-11-30T0548+0100 + * @since 2.2.5 options for label element and label bottom border, thanks to @markhillyer 2020-12-18T1447+0100 + * @link https://wordpress.org/support/topic/how-do-i-eliminate-the-horizontal-line-beneath-the-reference-container-heading/ + */ + public function reference_container() { + + // Options for the label element. + $l_arr_label_element = array( + 'p' => __( 'paragraph', 'footnotes' ), + 'h2' => __( 'heading 2', 'footnotes' ), + 'h3' => __( 'heading 3', 'footnotes' ), + 'h4' => __( 'heading 4', 'footnotes' ), + 'h5' => __( 'heading 5', 'footnotes' ), + 'h6' => __( 'heading 6', 'footnotes' ), + ); + // Options for the positioning of the reference container. + $l_arr_positions = array( + 'post_end' => __( 'at the end of the post', 'footnotes' ), + 'widget' => __( 'in the widget area', 'footnotes' ), + 'footer' => __( 'in the footer', 'footnotes' ), + ); + // Basic responsive page layout options. + $l_arr_page_layout_options = array( + 'none' => __( 'No', 'footnotes' ), + 'reference-container' => __( 'to the reference container exclusively', 'footnotes' ), + 'entry-content' => __( 'to the div element starting below the post title', 'footnotes' ), + 'main-content' => __( 'to the main element including the post title', 'footnotes' ), + ); + // Options for the separating punctuation between backlinks. + $l_arr_separators = array( + // Unicode character names are conventionally uppercase. + 'comma' => __( 'COMMA', 'footnotes' ), + 'semicolon' => __( 'SEMICOLON', 'footnotes' ), + 'en_dash' => __( 'EN DASH', 'footnotes' ), + ); + // Options for the terminating punctuation after backlinks. + // The Unicode name of RIGHT PARENTHESIS was originally more accurate because. + // This character is bidi-mirrored. Let’s use the Unicode 1.0 name. + // The wrong names were enforced in spite of Unicode, that subsequently scrambled to correct. + $l_arr_terminators = array( + 'period' => __( 'FULL STOP', 'footnotes' ), + // Unicode 1.0 name of RIGHT PARENTHESIS (represented as a left parenthesis in right-to-left scripts). + 'parenthesis' => __( 'CLOSING PARENTHESIS', 'footnotes' ), + 'colon' => __( 'COLON', 'footnotes' ), + ); + // Options for the first column width (per cent is a ratio, not a unit). + $l_arr_width_units = array( + '%' => __( 'per cent', 'footnotes' ), + 'px' => __( 'pixels', 'footnotes' ), + 'rem' => __( 'root em', 'footnotes' ), + 'em' => __( 'em', 'footnotes' ), + 'vw' => __( 'viewport width', 'footnotes' ), + ); + // Options for reference container script mode. + $l_arr_script_mode = array( + 'jquery' => __( 'jQuery', 'footnotes' ), + 'js' => __( 'plain JavaScript', 'footnotes' ), + ); + // Options for Yes/No select box. + $l_arr_enabled = array( + 'yes' => __( 'Yes', 'footnotes' ), + 'no' => __( 'No', 'footnotes' ), + ); + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'settings-reference-container' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + 'label-name' => $this->add_label( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_NAME, __( 'Heading:', 'footnotes' ) ), + 'name' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_NAME ), + + 'label-element' => $this->add_label( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_LABEL_ELEMENT, __( 'Heading’s HTML element:', 'footnotes' ) ), + 'element' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_LABEL_ELEMENT, $l_arr_label_element ), + + 'label-border' => $this->add_label( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_LABEL_BOTTOM_BORDER, __( 'Border under the heading:', 'footnotes' ) ), + 'border' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_LABEL_BOTTOM_BORDER, $l_arr_enabled ), + + 'label-collapse' => $this->add_label( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_COLLAPSE, __( 'Collapse by default:', 'footnotes' ) ), + 'collapse' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_COLLAPSE, $l_arr_enabled ), + + 'label-script' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_REFERENCE_CONTAINER_SCRIPT_MODE, __( 'Script mode:', 'footnotes' ) ), + 'script' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_REFERENCE_CONTAINER_SCRIPT_MODE, $l_arr_script_mode ), + 'notice-script' => __( 'The plain JavaScript mode does not support scroll animation and will enable hard links with scroll offset.', 'footnotes' ), + + 'label-position' => $this->add_label( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_POSITION, __( 'Default position:', 'footnotes' ) ), + 'position' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_POSITION, $l_arr_positions ), + // Translators: %s: at the end of the post. + 'notice-position' => sprintf( __( 'To use the position shortcode, please set the position to: %s', 'footnotes' ), '' . __( 'at the end of the post', 'footnotes' ) . '' ), + + 'label-shortcode' => $this->add_label( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_POSITION_SHORTCODE, __( 'Position shortcode:', 'footnotes' ) ), + 'shortcode' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_POSITION_SHORTCODE ), + 'notice-shortcode' => __( 'If present in the content, any shortcode in this text box will be replaced with the reference container.', 'footnotes' ), + + 'label-startpage' => $this->add_label( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_START_PAGE_ENABLE, __( 'Display on start page too:', 'footnotes' ) ), + 'startpage' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_START_PAGE_ENABLE, $l_arr_enabled ), + + 'label-margin-top' => $this->add_label( MCI_Footnotes_Settings::C_INT_REFERENCE_CONTAINER_TOP_MARGIN, __( 'Top margin:', 'footnotes' ) ), + 'margin-top' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_REFERENCE_CONTAINER_TOP_MARGIN, -500, 500 ), + 'notice-margin-top' => __( 'pixels; may be negative', 'footnotes' ), + + 'label-margin-bottom' => $this->add_label( MCI_Footnotes_Settings::C_INT_REFERENCE_CONTAINER_BOTTOM_MARGIN, __( 'Bottom margin:', 'footnotes' ) ), + 'margin-bottom' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_REFERENCE_CONTAINER_BOTTOM_MARGIN, -500, 500 ), + 'notice-margin-bottom' => __( 'pixels; may be negative', 'footnotes' ), + + 'label-page-layout' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_PAGE_LAYOUT_SUPPORT, __( 'Apply basic responsive page layout:', 'footnotes' ) ), + 'page-layout' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_PAGE_LAYOUT_SUPPORT, $l_arr_page_layout_options ), + 'notice-page-layout' => __( 'Most themes don’t need this fix.', 'footnotes' ), + + 'label-url-wrap' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTE_URL_WRAP_ENABLED, __( 'Allow URLs to line-wrap anywhere:', 'footnotes' ) ), + 'url-wrap' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTE_URL_WRAP_ENABLED, $l_arr_enabled ), + 'notice-url-wrap' => __( 'Unicode-conformant browsers don’t need this fix.', 'footnotes' ), + + 'label-symbol' => $this->add_label( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_BACKLINK_SYMBOL_ENABLE, __( 'Display a backlink symbol:', 'footnotes' ) ), + 'symbol-enable' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_BACKLINK_SYMBOL_ENABLE, $l_arr_enabled ), + 'notice-symbol' => __( 'Please choose or input the symbol at the top of the next dashboard tab.', 'footnotes' ), + + 'label-switch' => $this->add_label( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_BACKLINK_SYMBOL_SWITCH, __( 'Symbol appended, not prepended:', 'footnotes' ) ), + 'switch' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_BACKLINK_SYMBOL_SWITCH, $l_arr_enabled ), + + 'label-3column' => $this->add_label( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_3COLUMN_LAYOUT_ENABLE, __( 'Backlink symbol in an extra column:', 'footnotes' ) ), + '3column' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_3COLUMN_LAYOUT_ENABLE, $l_arr_enabled ), + 'notice-3column' => __( 'This legacy layout is available if identical footnotes are not combined.', 'footnotes' ), + + 'label-row-borders' => $this->add_label( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_ROW_BORDERS_ENABLE, __( 'Borders around the table rows:', 'footnotes' ) ), + 'row-borders' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_REFERENCE_CONTAINER_ROW_BORDERS_ENABLE, $l_arr_enabled ), + + 'label-separator' => $this->add_label( MCI_Footnotes_Settings::C_STR_BACKLINKS_SEPARATOR_ENABLED, __( 'Add a separator when enumerating backlinks:', 'footnotes' ) ), + 'separator-enable' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_BACKLINKS_SEPARATOR_ENABLED, $l_arr_enabled ), + 'separator-options' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_BACKLINKS_SEPARATOR_OPTION, $l_arr_separators ), + 'separator-custom' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_BACKLINKS_SEPARATOR_CUSTOM ), + 'notice-separator' => __( 'Your input overrides the selection.', 'footnotes' ), + + 'label-terminator' => $this->add_label( MCI_Footnotes_Settings::C_STR_BACKLINKS_TERMINATOR_ENABLED, __( 'Add a terminal punctuation to backlinks:', 'footnotes' ) ), + 'terminator-enable' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_BACKLINKS_TERMINATOR_ENABLED, $l_arr_enabled ), + 'terminator-options' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_BACKLINKS_TERMINATOR_OPTION, $l_arr_terminators ), + 'terminator-custom' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_BACKLINKS_TERMINATOR_CUSTOM ), + 'notice-terminator' => __( 'Your input overrides the selection.', 'footnotes' ), + + 'label-width' => $this->add_label( MCI_Footnotes_Settings::C_STR_BACKLINKS_COLUMN_WIDTH_ENABLED, __( 'Set backlinks column width:', 'footnotes' ) ), + 'width-enable' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_BACKLINKS_COLUMN_WIDTH_ENABLED, $l_arr_enabled ), + 'width-scalar' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_BACKLINKS_COLUMN_WIDTH_SCALAR, 0, 500, true ), + 'width-unit' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_BACKLINKS_COLUMN_WIDTH_UNIT, $l_arr_width_units ), + 'notice-width' => __( 'Absolute width in pixels doesn’t need to be accurate to the tenth, but relative width in rem or em may.', 'footnotes' ), + + 'label-max-width' => $this->add_label( MCI_Footnotes_Settings::C_STR_BACKLINKS_COLUMN_MAX_WIDTH_ENABLED, __( 'Set backlinks column maximum width:', 'footnotes' ) ), + 'max-width-enable' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_BACKLINKS_COLUMN_MAX_WIDTH_ENABLED, $l_arr_enabled ), + 'max-width-scalar' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_BACKLINKS_COLUMN_MAX_WIDTH_SCALAR, 0, 500, true ), + 'max-width-unit' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_BACKLINKS_COLUMN_MAX_WIDTH_UNIT, $l_arr_width_units ), + 'notice-max-width' => __( 'Absolute width in pixels doesn’t need to be accurate to the tenth, but relative width in rem or em may.', 'footnotes' ), + + 'label-line-break' => $this->add_label( MCI_Footnotes_Settings::C_STR_BACKLINKS_LINE_BREAKS_ENABLED, __( 'Stack backlinks when enumerating:', 'footnotes' ) ), + 'line-break' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_BACKLINKS_LINE_BREAKS_ENABLED, $l_arr_enabled ), + 'notice-line-break' => __( 'This option adds a line break before each added backlink when identical footnotes are combined.', 'footnotes' ), + + 'label-link' => $this->add_label( MCI_Footnotes_Settings::C_STR_LINK_ELEMENT_ENABLED, __( 'Use the link element for referrers and backlinks:', 'footnotes' ) ), + 'link' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_LINK_ELEMENT_ENABLED, $l_arr_enabled ), + 'notice-link' => __( 'The link element is needed to apply the theme’s link color.', 'footnotes' ), + 'description-link' => __( 'If the link element is not desired for styling, a simple span is used instead when the above is set to No. The link addresses have been removed. Else footnote clicks are logged in the browsing history and make the back button unusable.', 'footnotes' ), + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays all options for the footnotes start and end tag short codes. + * + * @since 1.5.0 + * + * Edited heading 2020-12-12T1412+0100 + * @since 2.2.0 start/end short codes: more predefined options 2020-12-12T1412+0100 + * @link https://wordpress.org/support/topic/doesnt-work-with-mailpoet/ + * @since 2.2.0 3 boxes for clarity 2020-12-12T1422+0100 + * @since 2.2.5 support for Ibid. notation thanks to @meglio 2020-12-17T2019+0100 + * @link https://wordpress.org/support/topic/add-support-for-ibid-notation/ + * @since 2.4.0 added warning about Block Editor escapement disruption 2021-01-02T2324+0100 + * @since 2.4.0 removed the HTML comment tag option 2021-01-02T2325+0100 + * @since 2.5.0 Shortcode syntax validation: add more information around the setting, thanks to @andreasra + * @link https://wordpress.org/support/topic/warning-unbalanced-footnote-start-tag-short-code-before/ + */ + public function start_end() { + // Footnotes start tag short code options. + $l_arr_shortcode_start = array( + '((' => '((', + '(((' => '(((', + '{{' => '{{', + '{{{' => '{{{', + '[n]' => '[n]', + '[fn]' => '[fn]', + htmlspecialchars( '' ) => htmlspecialchars( '' ), + '[ref]' => '[ref]', + htmlspecialchars( '' ) => htmlspecialchars( '' ), + // Custom (user-defined) start and end tags bracketing the footnote text inline. + 'userdefined' => __( 'custom short code', 'footnotes' ), + ); + // Footnotes end tag short code options. + $l_arr_shortcode_end = array( + '))' => '))', + ')))' => ')))', + '}}' => '}}', + '}}}' => '}}}', + '[/n]' => '[/n]', + '[/fn]' => '[/fn]', + htmlspecialchars( '' ) => htmlspecialchars( '' ), + '[/ref]' => '[/ref]', + htmlspecialchars( '' ) => htmlspecialchars( '' ), + // Custom (user-defined) start and end tags bracketing the footnote text inline. + 'userdefined' => __( 'custom short code', 'footnotes' ), + ); + // Options for the syntax validation. + $l_arr_enable = array( + 'yes' => __( 'Yes', 'footnotes' ), + 'no' => __( 'No', 'footnotes' ), + ); + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'settings-start-end' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + + 'description-escapement' => __( 'WARNING: Short codes with closing pointy brackets are disabled in the new WordPress Block Editor that disrupts the traditional balanced escapement applied by WordPress Classic Editor.', 'footnotes' ), + + 'label-short-code-start' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_START, __( 'Footnote start tag short code:', 'footnotes' ) ), + 'short-code-start' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_START, $l_arr_shortcode_start ), + 'short-code-start-user' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_START_USER_DEFINED ), + + 'label-short-code-end' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_END, __( 'Footnote end tag short code:', 'footnotes' ) ), + 'short-code-end' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_END, $l_arr_shortcode_end ), + 'short-code-end-user' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_END_USER_DEFINED ), + + // For script showing/hiding user defined text boxes. + 'short-code-start-id' => MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_START, + 'short-code-end-id' => MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_END, + 'short-code-start-user-id' => MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_START_USER_DEFINED, + 'short-code-end-user-id' => MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_END_USER_DEFINED, + + 'description-parentheses' => __( 'WARNING: Although widespread industry standard, the double parentheses are problematic because they may occur in scripts embedded in the content and be mistaken as a short code.', 'footnotes' ), + + // Option to enable syntax validation, label mirrored in task.php. + 'label-syntax' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTE_SHORTCODE_SYNTAX_VALIDATION_ENABLE, __( 'Check for balanced shortcodes:', 'footnotes' ) ), + 'syntax' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTE_SHORTCODE_SYNTAX_VALIDATION_ENABLE, $l_arr_enable ), + 'notice-syntax' => __( 'In the presence of a lone start tag shortcode, a warning displays below the post title.', 'footnotes' ), + + 'description-syntax' => __( 'If the start tag short code is ‘((’ or ‘(((’, it will not be reported as unbalanced if the following string contains braces hinting that it is a script.', 'footnotes' ), + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays all options for the footnotes numbering. + * + * @since 2.2.0 + */ + public function numbering() { + // Define some space for the output. + $l_str_space = '     '; + // Options for the combination of identical footnotes. + $l_arr_enable = array( + 'yes' => __( 'Yes', 'footnotes' ), + 'no' => __( 'No', 'footnotes' ), + ); + // Options for the numbering style of the footnotes. + $l_arr_counter_style = array( + 'arabic_plain' => __( 'plain Arabic numbers', 'footnotes' ) . $l_str_space . '1, 2, 3, 4, 5, …', + 'arabic_leading' => __( 'zero-padded Arabic numbers', 'footnotes' ) . $l_str_space . '01, 02, 03, 04, 05, …', + 'latin_low' => __( 'lowercase Latin letters', 'footnotes' ) . $l_str_space . 'a, b, c, d, e, …', + 'latin_high' => __( 'uppercase Latin letters', 'footnotes' ) . $l_str_space . 'A, B, C, D, E, …', + 'romanic' => __( 'uppercase Roman numerals', 'footnotes' ) . $l_str_space . 'I, II, III, IV, V, …', + 'roman_low' => __( 'lowercase Roman numerals', 'footnotes' ) . $l_str_space . 'i, ii, iii, iv, v, …', + ); + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'settings-numbering' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + 'label-counter-style' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_COUNTER_STYLE, __( 'Numbering style:', 'footnotes' ) ), + 'counter-style' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_COUNTER_STYLE, $l_arr_counter_style ), + + // Algorithmically combine identicals. + 'label-identical' => $this->add_label( MCI_Footnotes_Settings::C_STR_COMBINE_IDENTICAL_FOOTNOTES, __( 'Combine identical footnotes:', 'footnotes' ) ), + 'identical' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_COMBINE_IDENTICAL_FOOTNOTES, $l_arr_enable ), + 'notice-identical' => __( 'This option may require copy-pasting footnotes in multiple instances.', 'footnotes' ), + // Support for Ibid. notation added thanks to @meglio in . + 'description-identical' => __( 'Even when footnotes are combined, footnote numbers keep incrementing. This avoids suboptimal referrer and backlink disambiguation using a secondary numbering system. The Ibid. notation and the op. cit. abbreviation followed by the current page number avoid repeating the footnote content. For changing sources, shortened citations may be used. Repeating full citations is also an opportunity to add details.', 'footnotes' ), + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays all options for the scrolling behavior. + * + * @since 2.2.0 + */ + public function scrolling() { + + // Options for enabling hard links for AMP compat. + $l_arr_enable = array( + 'yes' => __( 'Yes', 'footnotes' ), + 'no' => __( 'No', 'footnotes' ), + ); + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'settings-scrolling' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + + 'label-scroll-offset' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_OFFSET, __( 'Scroll offset:', 'footnotes' ) ), + 'scroll-offset' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_OFFSET, 0, 100 ), + 'notice-scroll-offset' => __( 'per cent from the upper edge of the window', 'footnotes' ), + + 'label-scroll-duration' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_DURATION, __( 'Scroll duration:', 'footnotes' ) ), + 'scroll-duration' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_DURATION, 0, 20000 ), + 'notice-scroll-duration' => __( 'milliseconds; instantly if hard links are enabled and JavaScript is disabled', 'footnotes' ), + + // Enable hard links for AMP compat. + 'label-hard-links' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_HARD_LINKS_ENABLE, __( 'Enable hard links:', 'footnotes' ) ), + 'hard-links' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_HARD_LINKS_ENABLE, $l_arr_enable ), + 'notice-hard-links' => __( 'Hard links are indispensable for AMP compatibility and allow to link to footnotes.', 'footnotes' ), + + 'label-footnote' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTE_FRAGMENT_ID_SLUG, __( 'Fragment identifier slug for footnotes:', 'footnotes' ) ), + 'footnote' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_FOOTNOTE_FRAGMENT_ID_SLUG ), + 'notice-footnote' => __( 'This will show up in the address bar after clicking on a hard-linked footnote referrer.', 'footnotes' ), + + 'label-referrer' => $this->add_label( MCI_Footnotes_Settings::C_STR_REFERRER_FRAGMENT_ID_SLUG, __( 'Fragment identifier slug for footnote referrers:', 'footnotes' ) ), + 'referrer' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_REFERRER_FRAGMENT_ID_SLUG ), + 'notice-referrer' => __( 'This will show up in the address bar after clicking on a hard-linked backlink.', 'footnotes' ), + + 'label-separator' => $this->add_label( MCI_Footnotes_Settings::C_STR_HARD_LINK_IDS_SEPARATOR, __( 'ID separator:', 'footnotes' ) ), + 'separator' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_HARD_LINK_IDS_SEPARATOR ), + 'notice-separator' => __( 'May be empty or any string, for example _, - or +, to distinguish post number, container number and footnote number.', 'footnotes' ), + + // Enable backlink tooltips. + 'label-backlink-tooltips' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_BACKLINK_TOOLTIP_ENABLE, __( 'Enable backlink tooltips:', 'footnotes' ) ), + 'backlink-tooltips' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_BACKLINK_TOOLTIP_ENABLE, $l_arr_enable ), + 'notice-backlink-tooltips' => __( 'Hard backlinks get ordinary tooltips hinting to use the backbutton instead.', 'footnotes' ), + + 'label-backlink-tooltip-text' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_BACKLINK_TOOLTIP_TEXT, __( 'Backlink tooltip text:', 'footnotes' ) ), + 'backlink-tooltip-text' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_BACKLINK_TOOLTIP_TEXT ), + 'notice-backlink-tooltip-text' => __( 'Default text is the keyboard shortcut, but you may wish to input a descriptive hint in your language.', 'footnotes' ), + + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays all settings for 'I love Footnotes'. + * + * @since 1.5.0 + * + * Edited: + * @since 2.2.0 position-sensitive placeholders to support more locales 2020-12-11T0432+0100 + * @since 2.2.0 more options 2020-12-11T0432+0100 + */ + public function love() { + // Options for the acknowledgment display in the footer. + $l_arr_love = array( + // Logo only. + 'text-3' => sprintf( '%s', MCI_Footnotes_Config::C_STR_PLUGIN_PUBLIC_NAME ), + // Logo followed by heart symbol. + 'text-4' => sprintf( '%s %s', MCI_Footnotes_Config::C_STR_PLUGIN_PUBLIC_NAME, MCI_Footnotes_Config::C_STR_LOVE_SYMBOL ), + // Logo preceded by heart symbol. + 'text-5' => sprintf( '%s %s', MCI_Footnotes_Config::C_STR_LOVE_SYMBOL, MCI_Footnotes_Config::C_STR_PLUGIN_PUBLIC_NAME ), + // Translators: 2: heart symbol 1: footnotes logogram. + 'text-1' => sprintf( __( 'I %2$s %1$s', 'footnotes' ), MCI_Footnotes_Config::C_STR_PLUGIN_PUBLIC_NAME, MCI_Footnotes_Config::C_STR_LOVE_SYMBOL ), + // Translators: %s: Plugin logo. + 'text-6' => sprintf( __( 'This website uses %s.', 'footnotes' ), MCI_Footnotes_Config::C_STR_PLUGIN_PUBLIC_NAME ), + // Translators: %s: Plugin logo. + 'text-7' => sprintf( __( 'This website uses the %s plugin.', 'footnotes' ), MCI_Footnotes_Config::C_STR_PLUGIN_PUBLIC_NAME ), + // Translators: %s: Plugin logo. + 'text-2' => sprintf( __( 'This website uses the awesome %s plugin.', 'footnotes' ), MCI_Footnotes_Config::C_STR_PLUGIN_PUBLIC_NAME ), + 'random' => __( 'randomly determined display of either mention', 'footnotes' ), + // Translators: 1: Plugin logo.2: heart symbol. + 'no' => sprintf( __( 'no display of any “%1$s %2$s” mention in the footer', 'footnotes' ), MCI_Footnotes_Config::C_STR_PLUGIN_PUBLIC_NAME, MCI_Footnotes_Config::C_STR_LOVE_SYMBOL ), + ); + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'settings-love' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + // Translators: %s: Plugin logo. + 'label-love' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_LOVE, sprintf( __( 'Tell the world you’re using %s:', 'footnotes' ), MCI_Footnotes_Config::C_STR_PLUGIN_PUBLIC_NAME ) ), + 'love' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_LOVE, $l_arr_love ), + // Translators: %s: Plugin logo. + 'label-no-love' => $this->add_text( sprintf( __( 'Shortcode to inhibit the display of the %s mention on specific pages:', 'footnotes' ), MCI_Footnotes_Config::C_STR_PLUGIN_PUBLIC_NAME ) ), + 'no-love' => $this->add_text( MCI_Footnotes_Config::C_STR_NO_LOVE_SLUG ), + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays the excerpt setting. + * + * @since 1.5.0 + * + * Edited heading 2020-12-12T1453+0100 + * @since 2.1.1 more settings and notices, thanks to @nikelaos + * @link https://wordpress.org/support/topic/doesnt-work-any-more-11/#post-13687068 + * @link https://wordpress.org/support/topic/jquery-comes-up-in-feed-content/#post-13110879 + * @since 2.2.0 dedicated to the excerpt setting and its notices 2020-12-12T1454+0100 + */ + public function excerpts() { + // Options for Yes/No select box. + $l_arr_enabled = array( + 'yes' => __( 'Yes', 'footnotes' ), + 'no' => __( 'No', 'footnotes' ), + ); + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'settings-excerpts' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + 'label-excerpts' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_IN_EXCERPT, __( 'Display footnotes in excerpts:', 'footnotes' ) ), + 'excerpts' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_IN_EXCERPT, $l_arr_enabled ), + 'notice-excerpts' => __( 'The recommended value is No.', 'footnotes' ), + // Translators: %s: link to the Advanced Excerpt Plugin. + 'description-excerpts' => sprintf( __( 'In some themes, the %s plugin is indispensable to display footnotes in excerpts. Footnotes cannot be disabled in excerpts. A workaround is to avoid footnotes in the first 55 words.', 'footnotes' ), 'Advanced Excerpt' ), + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays all settings for the footnote referrers. + * + * @since 1.5.0 + * + * Edited heading 2020-12-12T1513+0100 + * @since 2.1.1 option for superscript (optionally baseline referrers) + * @since 2.2.0 option for link element moved here 2020-12-12T1514+0100 + */ + public function superscript() { + // Options for Yes/No select box. + $l_arr_enabled = array( + 'yes' => __( 'Yes', 'footnotes' ), + 'no' => __( 'No', 'footnotes' ), + ); + // Options for superscript normalize scope. + $l_arr_normalize_superscript = array( + 'no' => __( 'No', 'footnotes' ), + 'referrers' => __( 'Footnote referrers', 'footnotes' ), + 'all' => __( 'All superscript elements', 'footnotes' ), + ); + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'customize-superscript' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + 'label-superscript' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_REFERRER_SUPERSCRIPT_TAGS, __( 'Display footnote referrers in superscript:', 'footnotes' ) ), + 'superscript' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_REFERRER_SUPERSCRIPT_TAGS, $l_arr_enabled ), + + 'label-before' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_STYLING_BEFORE, __( 'At the start of the footnote referrers:', 'footnotes' ) ), + 'before' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_STYLING_BEFORE ), + + 'label-after' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_STYLING_AFTER, __( 'At the end of the footnote referrers:', 'footnotes' ) ), + 'after' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_STYLING_AFTER ), + + 'label-link' => $this->add_label( MCI_Footnotes_Settings::C_STR_LINK_ELEMENT_ENABLED, __( 'Use the link element for referrers and backlinks:', 'footnotes' ) ), + 'notice-link' => __( 'Please find this setting at the end of the reference container settings. The link element is needed to apply the theme’s link color.', 'footnotes' ), + + 'label-normalize' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT, __( 'Normalize vertical alignment and font size:', 'footnotes' ) ), + 'normalize' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT, $l_arr_normalize_superscript ), + 'notice-normalize' => __( 'Most themes don’t need this fix.', 'footnotes' ), + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays enabled status for the footnotes mouse-over box. + * + * @since 1.5.2 + * + * Edited: + * @since 2.2.0 5 parts to address increased settings number + * @since 2.2.5 position settings for alternative tooltips + */ + public function mouseover_box() { + // Options for Yes/No select box. + $l_arr_enabled = array( + 'yes' => __( 'Yes', 'footnotes' ), + 'no' => __( 'No', 'footnotes' ), + ); + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'mouse-over-box-display' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + + 'label-enable' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_ENABLED, __( 'Display tooltips:', 'footnotes' ) ), + 'enable' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_ENABLED, $l_arr_enabled ), + 'notice-enable' => __( 'Formatted text boxes allowing hyperlinks, displayed on mouse-over or tap and hold.', 'footnotes' ), + + 'label-alternative' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_ALTERNATIVE, __( 'Display alternative tooltips:', 'footnotes' ) ), + 'alternative' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_ALTERNATIVE, $l_arr_enabled ), + 'notice-alternative' => __( 'Intended to work around a configuration-related tooltip outage.', 'footnotes' ), + // Translators: %s: Plugin logo. + 'description-alternative' => sprintf( __( 'These alternative tooltips work around a website related jQuery UI outage. They are low-script but use the AMP incompatible onmouseover and onmouseout arguments, along with CSS transitions for fade-in/out. The very small script is inserted after Footnotes’ internal stylesheet. When this option is enabled, %s does not load jQuery UI nor jQuery Tools.', 'footnotes' ), '' . MCI_Footnotes_Config::C_STR_PLUGIN_PUBLIC_NAME . '' ), + + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays position settings for the footnotes mouse-over box. + * + * @since 2.2.0 + */ + public function mouseover_box_position() { + + // Options for the Mouse-over box position. + $l_arr_position = array( + 'top left' => __( 'top left', 'footnotes' ), + 'top center' => __( 'top center', 'footnotes' ), + 'top right' => __( 'top right', 'footnotes' ), + 'center right' => __( 'center right', 'footnotes' ), + 'bottom right' => __( 'bottom right', 'footnotes' ), + 'bottom center' => __( 'bottom center', 'footnotes' ), + 'bottom left' => __( 'bottom left', 'footnotes' ), + 'center left' => __( 'center left', 'footnotes' ), + ); + // Options for the alternative Mouse-over box position. + $l_arr_alternative_position = array( + 'top left' => __( 'top left', 'footnotes' ), + 'top right' => __( 'top right', 'footnotes' ), + 'bottom right' => __( 'bottom right', 'footnotes' ), + 'bottom left' => __( 'bottom left', 'footnotes' ), + ); + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'mouse-over-box-position' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + + 'label-position' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_POSITION, __( 'Position:', 'footnotes' ) ), + 'position' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_POSITION, $l_arr_position ), + 'position-alternative' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_POSITION, $l_arr_alternative_position ), + 'notice-position' => __( 'The second column of settings boxes is for the alternative tooltips.', 'footnotes' ), + + 'label-offset-x' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_MOUSE_OVER_BOX_OFFSET_X, __( 'Horizontal offset:', 'footnotes' ) ), + 'offset-x' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_MOUSE_OVER_BOX_OFFSET_X, -500, 500 ), + 'offset-x-alternative' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_X, -500, 500 ), + 'notice-offset-x' => __( 'pixels; negative value for a leftwards offset; alternative tooltips: direction depends on position', 'footnotes' ), + + 'label-offset-y' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_MOUSE_OVER_BOX_OFFSET_Y, __( 'Vertical offset:', 'footnotes' ) ), + 'offset-y' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_MOUSE_OVER_BOX_OFFSET_Y, -500, 500 ), + 'offset-y-alternative' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_Y, -500, 500 ), + 'notice-offset-y' => __( 'pixels; negative value for an upwards offset; alternative tooltips: direction depends on position', 'footnotes' ), + + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays dimensions setting for the footnotes mouse-over box. + * + * @since 2.2.0 + */ + public function mouseover_box_dimensions() { + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'mouse-over-box-dimensions' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + + 'label-max-width' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_MOUSE_OVER_BOX_MAX_WIDTH, __( 'Maximum width:', 'footnotes' ) ), + 'max-width' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_MOUSE_OVER_BOX_MAX_WIDTH, 0, 1280 ), + 'width' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH, 0, 1280 ), + 'notice-max-width' => __( 'pixels; set to 0 for jQuery tooltips without max width; alternative tooltips are given the value in the second box as fixed width.', 'footnotes' ), + + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays timing settings for the footnotes mouse-over box. + * + * @since 2.2.0 + */ + public function mouseover_box_timing() { + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'mouse-over-box-timing' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + + 'label-fade-in-delay' => $this->add_label( MCI_Footnotes_Settings::C_INT_MOUSE_OVER_BOX_FADE_IN_DELAY, __( 'Fade-in delay:', 'footnotes' ) ), + 'fade-in-delay' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_MOUSE_OVER_BOX_FADE_IN_DELAY, 0, 20000 ), + 'notice-fade-in-delay' => __( 'milliseconds', 'footnotes' ), + + 'label-fade-in-duration' => $this->add_label( MCI_Footnotes_Settings::C_INT_MOUSE_OVER_BOX_FADE_IN_DURATION, __( 'Fade-in duration:', 'footnotes' ) ), + 'fade-in-duration' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_MOUSE_OVER_BOX_FADE_IN_DURATION, 0, 20000 ), + 'notice-fade-in-duration' => __( 'milliseconds', 'footnotes' ), + + 'label-fade-out-delay' => $this->add_label( MCI_Footnotes_Settings::C_INT_MOUSE_OVER_BOX_FADE_OUT_DELAY, __( 'Fade-out delay:', 'footnotes' ) ), + 'fade-out-delay' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_MOUSE_OVER_BOX_FADE_OUT_DELAY, 0, 20000 ), + 'notice-fade-out-delay' => __( 'milliseconds', 'footnotes' ), + + 'label-fade-out-duration' => $this->add_label( MCI_Footnotes_Settings::C_INT_MOUSE_OVER_BOX_FADE_OUT_DURATION, __( 'Fade-out duration:', 'footnotes' ) ), + 'fade-out-duration' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_MOUSE_OVER_BOX_FADE_OUT_DURATION, 0, 20000 ), + 'notice-fade-out-duration' => __( 'milliseconds', 'footnotes' ), + + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays truncation settings for the footnotes mouse-over box. + * + * @since 2.2.0 + */ + public function mouseover_box_truncation() { + // Options for Yes/No select box. + $l_arr_enabled = array( + 'yes' => __( 'Yes', 'footnotes' ), + 'no' => __( 'No', 'footnotes' ), + ); + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'mouse-over-box-truncation' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + + 'label-truncation' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_ENABLED, __( 'Truncate the note in the tooltip:', 'footnotes' ) ), + 'truncation' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_ENABLED, $l_arr_enabled ), + + 'label-max-length' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_LENGTH, __( 'Maximum number of characters in the tooltip:', 'footnotes' ) ), + 'max-length' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_LENGTH, 3, 10000 ), + // The feature trims back until the last full word. + 'notice-max-length' => __( 'No weird cuts.', 'footnotes' ), + + 'label-readon' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_TOOLTIP_READON_LABEL, __( '‘Read on’ button label:', 'footnotes' ) ), + 'readon' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_TOOLTIP_READON_LABEL ), + + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays dedicated tooltip text settings for the footnotes mouse-over box. + * + * @since 2.2.0 + */ + public function mouseover_box_text() { + // Options for Yes/No select box. + $l_arr_enabled = array( + 'yes' => __( 'Yes', 'footnotes' ), + 'no' => __( 'No', 'footnotes' ), + ); + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'mouse-over-box-text' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + + 'description-delimiter' => __( 'Tooltips can display another content than the footnote entry in the reference container. The trigger is a shortcode in the footnote text separating the tooltip text from the note. That is consistent with what WordPress does for excerpts.', 'footnotes' ), + + 'label-delimiter' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_DELIMITER, __( 'Delimiter for dedicated tooltip text:', 'footnotes' ) ), + 'delimiter' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_DELIMITER ), + 'notice-delimiter' => __( 'If the delimiter shortcode is present, the tooltip text will be the part before it.', 'footnotes' ), + + 'label-mirror' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE, __( 'Mirror the tooltip in the reference container:', 'footnotes' ) ), + 'mirror' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE, $l_arr_enabled ), + 'notice-mirror' => __( 'Tooltips may be harder to use on mobiles. This option allows to read it in the reference container.', 'footnotes' ), + + 'label-separator' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR, __( 'Separator between tooltip text and footnote text:', 'footnotes' ) ), + 'separator' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR ), + 'notice-separator' => __( 'May be a simple space, or a line break <br />, or any string in your language.', 'footnotes' ), + + 'description-mirror' => __( 'Tooltips, even jQuery-driven, may be hard to consult on mobiles. This option allows to read the tooltip content in the reference container too.', 'footnotes' ), + + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays style settings for the footnotes mouse-over box. + * + * @since 2.2.0 + */ + public function mouseover_box_appearance() { + // Options for Yes/No select box. + $l_arr_enabled = array( + 'yes' => __( 'Yes', 'footnotes' ), + 'no' => __( 'No', 'footnotes' ), + ); + // Options for the font size unit. + $l_arr_font_size_units = array( + 'em' => __( 'em', 'footnotes' ), + 'rem' => __( 'rem', 'footnotes' ), + 'px' => __( 'pixels', 'footnotes' ), + 'pt' => __( 'points', 'footnotes' ), + 'pc' => __( 'picas', 'footnotes' ), + 'mm' => __( 'millimeters', 'footnotes' ), + '%' => __( 'per cent', 'footnotes' ), + ); + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'mouse-over-box-appearance' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + + 'label-font-size' => $this->add_label( MCI_Footnotes_Settings::C_STR_MOUSE_OVER_BOX_FONT_SIZE_ENABLED, __( 'Set font size:', 'footnotes' ) ), + 'font-size-enable' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_MOUSE_OVER_BOX_FONT_SIZE_ENABLED, $l_arr_enabled ), + 'font-size-scalar' => $this->add_num_box( MCI_Footnotes_Settings::C_FLO_MOUSE_OVER_BOX_FONT_SIZE_SCALAR, 0, 50, true ), + 'font-size-unit' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_MOUSE_OVER_BOX_FONT_SIZE_UNIT, $l_arr_font_size_units ), + 'notice-font-size' => __( 'By default, the font size is set to equal the surrounding text.', 'footnotes' ), + + 'label-color' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_COLOR, __( 'Text color:', 'footnotes' ) ), + 'color' => $this->add_color_selection( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_COLOR ), + // Translators: %s: Clear or leave empty. + 'notice-color' => sprintf( __( 'To use the current theme’s default text color: %s', 'footnotes' ), __( 'Clear or leave empty.', 'footnotes' ) ), + + 'label-background' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND, __( 'Background color:', 'footnotes' ) ), + 'background' => $this->add_color_selection( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND ), + // Translators: %s: Clear or leave empty. + 'notice-background' => sprintf( __( 'To use the current theme’s default background color: %s', 'footnotes' ), __( 'Clear or leave empty.', 'footnotes' ) ), + + 'label-border-width' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_MOUSE_OVER_BOX_BORDER_WIDTH, __( 'Border width:', 'footnotes' ) ), + 'border-width' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_MOUSE_OVER_BOX_BORDER_WIDTH, 0, 4, true ), + 'notice-border-width' => __( 'pixels; 0 for borderless', 'footnotes' ), + + 'label-border-color' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_BORDER_COLOR, __( 'Border color:', 'footnotes' ) ), + 'border-color' => $this->add_color_selection( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_BORDER_COLOR ), + // Translators: %s: Clear or leave empty. + 'notice-border-color' => sprintf( __( 'To use the current theme’s default border color: %s', 'footnotes' ), __( 'Clear or leave empty.', 'footnotes' ) ), + + 'label-border-radius' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_MOUSE_OVER_BOX_BORDER_RADIUS, __( 'Rounded corner radius:', 'footnotes' ) ), + 'border-radius' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_MOUSE_OVER_BOX_BORDER_RADIUS, 0, 500 ), + 'notice-border-radius' => __( 'pixels; 0 for sharp corners', 'footnotes' ), + + 'label-box-shadow-color' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_SHADOW_COLOR, __( 'Box shadow color:', 'footnotes' ) ), + 'box-shadow-color' => $this->add_color_selection( MCI_Footnotes_Settings::C_STR_FOOTNOTES_MOUSE_OVER_BOX_SHADOW_COLOR ), + // Translators: %s: Clear or leave empty. + 'notice-box-shadow-color' => sprintf( __( 'To use the current theme’s default box shadow color: %s', 'footnotes' ), __( 'Clear or leave empty.', 'footnotes' ) ), + + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays all settings for the backlink symbol. + * + * @since 1.5.0 + * + * Edited heading for v2.0.4 + * + * The former 'hyperlink arrow', incompatible with combined identical footnotes, + * became 'prepended arrow' in v2.0.3 after a user complaint about missing backlinking semantics + * of the footnote number. + * + * @since 2.1.4 moved to Settings > Reference container > Display a backlink symbol + * @since 2.2.1 and 2.2.4 back here + */ + public function hyperlink_arrow() { + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'customize-hyperlink-arrow' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + 'label-symbol' => $this->add_label( MCI_Footnotes_Settings::C_STR_HYPERLINK_ARROW, __( 'Select or input the backlink symbol:', 'footnotes' ) ), + 'symbol-options' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_HYPERLINK_ARROW, MCI_Footnotes_Convert::get_arrow() ), + 'symbol-custom' => $this->add_text_box( MCI_Footnotes_Settings::C_STR_HYPERLINK_ARROW_USER_DEFINED ), + 'notice-symbol' => __( 'Your input overrides the selection.', 'footnotes' ), + 'description-symbol' => __( 'This symbol is used in the reference container. But this setting pre-existed under this tab and cannot be moved to another one.', 'footnotes' ), + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays the Custom CSS box. + * + * @since 1.5.0 + * + * Edited: + * @since 2.1.6 drop localized notices for CSS classes as the number increased to 16 + * list directly in the template, as CSS is in English anyway + * @see templates/dashboard/customize-css.html + * 2020-12-09T1113+0100 + * + * @since 2.2.2 migrate Custom CSS to a dedicated tab 2020-12-15T0506+0100 + * @since 2.3.0 say 'copy-paste' instead of 'cut and paste' since cutting is not needed 2020-12-27T1257+0100 + * @since 2.5.1 mention validity while visible, thanks to @rkupadhya bug report + */ + public function custom_css() { + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'customize-css' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + 'label-css' => $this->add_label( MCI_Footnotes_Settings::C_STR_CUSTOM_CSS, __( 'Your existing Custom CSS code:', 'footnotes' ) ), + 'css' => $this->add_textarea( MCI_Footnotes_Settings::C_STR_CUSTOM_CSS ), + 'description-css' => __( 'Custom CSS migrates to a dedicated tab. This text area is intended to keep your data safe, and the code remains valid while visible. Please copy-paste the content into the new text area under the new tab.', 'footnotes' ), + + // phpcs:disable Squiz.PHP.CommentedOutCode.Found + // CSS classes are listed in the template. + // Localized notices are dropped to ease translators’ task. + + // "label-class-1" => ".footnote_plugin_tooltip_text",. + // "class-1" => $this->add_text(__("superscript, Footnotes index", MCI_Footnotes_Config::C_STR_PLUGIN_NAME)),. + + // "label-class-2" => ".footnote_tooltip",. + // "class-2" => $this->add_text(__("mouse-over box, tooltip for each superscript", MCI_Footnotes_Config::C_STR_PLUGIN_NAME)),. + + // "label-class-3" => ".footnote_plugin_index",. + // "class-3" => $this->add_text(__("1st column of the Reference Container, Footnotes index", MCI_Footnotes_Config::C_STR_PLUGIN_NAME)),. + + // "label-class-4" => ".footnote_plugin_text",. + // "class-4" => $this->add_text(__("2nd column of the Reference Container, Footnote text", MCI_Footnotes_Config::C_STR_PLUGIN_NAME)). + // phpcs:enable + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays transitional legacy Custom CSS box. + * + * @since 2.2.2 + */ + public function custom_css_migration() { + + // Options for Yes/No select box. + $l_arr_enabled = array( + 'yes' => __( 'Yes', 'footnotes' ), + 'no' => __( 'No', 'footnotes' ), + ); + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'customize-css-migration' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + 'label-css' => $this->add_label( MCI_Footnotes_Settings::C_STR_CUSTOM_CSS, __( 'Your existing Custom CSS code:', 'footnotes' ) ), + 'css' => $this->add_textarea( MCI_Footnotes_Settings::C_STR_CUSTOM_CSS ), + 'description-css' => __( 'Custom CSS migrates to a dedicated tab. This text area is intended to keep your data safe, and the code remains valid while visible. Please copy-paste the content into the new text area below. Set Show legacy to No. Save twice.', 'footnotes' ), + + 'label-show-legacy' => $this->add_label( MCI_Footnotes_Settings::C_STR_CUSTOM_CSS_LEGACY_ENABLE, 'Show legacy Custom CSS settings containers:' ), + 'show-legacy' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_CUSTOM_CSS_LEGACY_ENABLE, $l_arr_enabled ), + 'notice-show-legacy' => __( 'Please set to No when you are done migrating, for the legacy Custom CSS containers to disappear.', 'footnotes' ), + // Translators: %s: Referres and tooltips. + 'description-show-legacy' => sprintf( __( 'The legacy Custom CSS under the %s tab and its mirror here are emptied, and the select box saved as No, when the settings tab is saved while the settings container is not displayed.', 'footnotes' ), __( 'Referrers and tooltips', 'footnotes' ) ), + + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays the new Custom CSS box. + * + * @since 2.2.2 + */ + public function custom_css_new() { + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'customize-css-new' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + 'css' => $this->add_textarea( MCI_Footnotes_Settings::C_STR_CUSTOM_CSS_NEW ), + + 'headline' => $this->add_text( __( 'Recommended CSS classes:', 'footnotes' ) ), + + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays available Hooks to look for Footnote short codes. + * + * @since 1.5.5 + * + * Edited: + * @since 2.1.1 priority level setting for the_content 2020-11-16T2152+0100 + * @since 2.1.4 priority level settings for the other hooks 2020-11-19T1421+0100 + * + * priority level was initially hard-coded default + * shows "9223372036854775807" in the numbox + * empty should be interpreted as PHP_INT_MAX, + * but a numbox cannot be set to empty: + * define -1 as PHP_INT_MAX instead + * + * @since 2.2.9 removed the warning about the widget text hook 2020-12-25T0348+0100 + * @since 2.2.9 added guidance for the widget text hook 2020-12-25T0353+0100 + */ + public function lookup_hooks() { + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'expert-lookup' ); + + // Replace all placeholders. + $l_obj_template->replace( + array( + 'description-1' => __( 'The priority level determines whether Footnotes is executed timely before other plugins, and how the reference container is positioned relative to other features.', 'footnotes' ), + // Translators: 1: 99; 2: 1200. + 'description-2' => sprintf( __( 'For the_content, this figure must be lower than %1$d so that certain strings added by a plugin running at %1$d may not be mistaken as a footnote. This makes also sure that the reference container displays above a feature inserted by a plugin running at %2$d.', 'footnotes' ), 99, 1200 ), + // Translators: 1: PHP_INT_MAX; 2: 0; 3: -1; 4: 'PHP_INT_MAX'. + 'description-3' => sprintf( __( '%1$d is lowest priority, %2$d is highest. To set priority level to lowest, set it to %3$d, interpreted as %1$d, the constant %4$s.', 'footnotes' ), PHP_INT_MAX, 0, -1, 'PHP_INT_MAX' ), + 'description-4' => __( 'The widget_text hook must be enabled either when footnotes are present in theme text widgets, or when Elementor accordions or toggles shall have a reference container per section. If they should not, this hook must be disabled.', 'footnotes' ), + + 'head-hook' => __( 'WordPress hook function name', 'footnotes' ), + 'head-checkbox' => __( 'Activate', 'footnotes' ), + 'head-numbox' => __( 'Priority level', 'footnotes' ), + 'head-url' => __( 'WordPress documentation', 'footnotes' ), + + 'label-the-title' => $this->add_label( MCI_Footnotes_Settings::C_STR_EXPERT_LOOKUP_THE_TITLE, 'the_title' ), + 'the-title' => $this->add_checkbox( MCI_Footnotes_Settings::C_STR_EXPERT_LOOKUP_THE_TITLE ), + 'priority-the-title' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_EXPERT_LOOKUP_THE_TITLE_PRIORITY_LEVEL, -1, PHP_INT_MAX ), + 'url-the-title' => 'https://developer.wordpress.org/reference/hooks/the_title/', + + 'label-the-content' => $this->add_label( MCI_Footnotes_Settings::C_STR_EXPERT_LOOKUP_THE_CONTENT, 'the_content' ), + 'the-content' => $this->add_checkbox( MCI_Footnotes_Settings::C_STR_EXPERT_LOOKUP_THE_CONTENT ), + 'priority-the-content' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_EXPERT_LOOKUP_THE_CONTENT_PRIORITY_LEVEL, -1, PHP_INT_MAX ), + 'url-the-content' => 'https://developer.wordpress.org/reference/hooks/the_content/', + + 'label-the-excerpt' => $this->add_label( MCI_Footnotes_Settings::C_STR_EXPERT_LOOKUP_THE_EXCERPT, 'the_excerpt' ), + 'the-excerpt' => $this->add_checkbox( MCI_Footnotes_Settings::C_STR_EXPERT_LOOKUP_THE_EXCERPT ), + 'priority-the-excerpt' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_EXPERT_LOOKUP_THE_EXCERPT_PRIORITY_LEVEL, -1, PHP_INT_MAX ), + 'url-the-excerpt' => 'https://developer.wordpress.org/reference/functions/the_excerpt/', + + 'label-widget-title' => $this->add_label( MCI_Footnotes_Settings::C_STR_EXPERT_LOOKUP_WIDGET_TITLE, 'widget_title' ), + 'widget-title' => $this->add_checkbox( MCI_Footnotes_Settings::C_STR_EXPERT_LOOKUP_WIDGET_TITLE ), + 'priority-widget-title' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_EXPERT_LOOKUP_WIDGET_TITLE_PRIORITY_LEVEL, -1, PHP_INT_MAX ), + 'url-widget-title' => 'https://codex.wordpress.org/Plugin_API/Filter_Reference/widget_title', + + 'label-widget-text' => $this->add_label( MCI_Footnotes_Settings::C_STR_EXPERT_LOOKUP_WIDGET_TEXT, 'widget_text' ), + 'widget-text' => $this->add_checkbox( MCI_Footnotes_Settings::C_STR_EXPERT_LOOKUP_WIDGET_TEXT ), + 'priority-widget-text' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_EXPERT_LOOKUP_WIDGET_TEXT_PRIORITY_LEVEL, -1, PHP_INT_MAX ), + 'url-widget-text' => 'https://codex.wordpress.org/Plugin_API/Filter_Reference/widget_text', + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays a short introduction of the Plugin. + * + * @since 1.5.0 + */ + public function Help() { + global $g_obj_mci_footnotes; + // Load footnotes starting and end tag. + $l_arr_footnote_starting_tag = $this->load_setting( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_START ); + $l_arr_footnote_ending_tag = $this->load_setting( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_END ); + + if ( 'userdefined' === $l_arr_footnote_starting_tag['value'] || 'userdefined' === $l_arr_footnote_ending_tag['value'] ) { + // Load user defined starting and end tag. + $l_arr_footnote_starting_tag = $this->load_setting( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_START_USER_DEFINED ); + $l_arr_footnote_ending_tag = $this->load_setting( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_END_USER_DEFINED ); + } + $l_str_example = 'Hello' . $l_arr_footnote_starting_tag['value'] . + 'Lorem ipsum dolor sit amet, consetetur sadipscing ' . + 'elitr, sed diam nonumy eirmod tempor invidunt ut ' . + 'labore et dolore magna aliquyam erat, sed diam ' . + 'voluptua. At vero eos et accusam et justo duo dolores ' . + 'et ea rebum. Stet clita kasd gubergren, no sea ' . + 'takimata sanctus est Lorem ipsum dolor sit amet. ' . + 'Lorem ipsum dolor sit amet, consetetur sadipscing ' . + 'elitr, sed diam nonumy eirmod tempor invidunt ut ' . + 'labore et dolore magna aliquyam erat, sed diam ' . + 'voluptua. At vero eos et accusam et justo duo ' . + 'dolores et ea rebum. Stet clita kasd gubergren, no ' . + 'sea takimata sanctus est Lorem ipsum dolor sit amet.' . + $l_arr_footnote_ending_tag['value'] . ' World!'; + + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'how-to-help' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + 'label-start' => __( 'Start your footnote with the following short code:', 'footnotes' ), + 'start' => $l_arr_footnote_starting_tag['value'], + 'label-end' => __( '…and end your footnote with this short code:', 'footnotes' ), + 'end' => $l_arr_footnote_ending_tag['value'], + 'example-code' => $l_str_example, + 'example-string' => '
' . __( 'will be displayed as:', 'footnotes' ), + 'example' => $g_obj_mci_footnotes->a_obj_task->exec( $l_str_example, true ), + // Translators: 1: ; 2: . + 'information' => sprintf( __( 'For further information please check out our %1$ssupport forum%2$s on WordPress.org.', 'footnotes' ), '', '' ), + ) + ); + // Call wp_head function to get the Styling of the mouse-over box. + $g_obj_mci_footnotes->a_obj_task->wp_head(); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } + + /** + * Displays all Donate button to support the developers. + * + * @since 1.5.0 + */ + public function donate() { + // Load template file. + $l_obj_template = new MCI_Footnotes_Template( MCI_Footnotes_Template::C_STR_DASHBOARD, 'how-to-donate' ); + // Replace all placeholders. + $l_obj_template->replace( + array( + 'caption' => __( 'Donate now', 'footnotes' ), + ) + ); + // Display template with replaced placeholders. + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + echo $l_obj_template->get_content(); + // phpcs:enable + } +} diff --git a/class/init.php b/class/init.php index 650c0dc..af20d85 100644 --- a/class/init.php +++ b/class/init.php @@ -72,7 +72,6 @@ class MCI_Footnotes { * @since 2.4.0 * @contributor Patrizia Lutz @misfist * @var bool - * */ public static $a_bool_alternative_tooltips_enabled = false; @@ -326,7 +325,6 @@ class MCI_Footnotes { wp_enqueue_script( 'jquery-ui-tooltip' ); } - } /** @@ -341,7 +339,7 @@ class MCI_Footnotes { * The Boolean may be set at the bottom of the plugin’s main PHP file. * @see footnotes.php */ - if ( true === C_BOOL_CSS_PRODUCTION_MODE ) { + if ( C_BOOL_CSS_PRODUCTION_MODE ) { /** * Enqueues a minified united external stylesheet in production. @@ -364,6 +362,7 @@ class MCI_Footnotes { * @since 2.0.3 add versioning of public.css for cache busting. * @date 2020-10-29T1413+0100 * Plugin version number is needed for busting browser caches after each plugin update. + * * @since 2.1.4 automate passing version number for cache busting. * @date 2020-11-30T0646+0100 * The constant C_STR_PACKAGE_VERSION is defined at start of footnotes.php. @@ -387,11 +386,9 @@ class MCI_Footnotes { $l_str_tooltip_mode_long = 'jquery-tooltips'; } - } else { $l_str_tooltip_mode_short = 'nott'; $l_str_tooltip_mode_long = 'no-tooltips'; - } // Set basic responsive page layout mode for use in stylesheet name. @@ -419,7 +416,11 @@ class MCI_Footnotes { MCI_Footnotes_Config::C_STR_PLUGIN_NAME . '/css/footnotes-' . $l_str_tooltip_mode_short . 'brpl' . $l_str_layout_mode . '.min.css' ), array(), - C_STR_PACKAGE_VERSION, + filemtime( + plugin_dir_path( + dirname( __FILE__ ) + ) . 'css/footnotes-' . $l_str_tooltip_mode_short . 'ttbrpl' . $l_str_layout_mode . '.min.css' + ), 'all' ); @@ -433,15 +434,51 @@ class MCI_Footnotes { * * This optional layout fix is useful by lack of layout support. */ - wp_enqueue_style( 'mci-footnotes-common', plugins_url( MCI_Footnotes_Config::C_STR_PLUGIN_NAME . '/css/dev-common.css' ), array(), C_STR_PACKAGE_VERSION ); - wp_enqueue_style( 'mci-footnotes-tooltips', plugins_url( MCI_Footnotes_Config::C_STR_PLUGIN_NAME . '/css/dev-tooltips.css' ), array(), C_STR_PACKAGE_VERSION ); + wp_enqueue_style( + 'mci-footnotes-common', + plugins_url( MCI_Footnotes_Config::C_STR_PLUGIN_NAME . '/css/dev-common.css' ), + array(), + filemtime( + plugin_dir_path( + dirname( __FILE__ ) + ) . 'css/dev-common.css' + ) + ); + wp_enqueue_style( + 'mci-footnotes-tooltips', + plugins_url( MCI_Footnotes_Config::C_STR_PLUGIN_NAME . '/css/dev-tooltips.css' ), + array(), + filemtime( + plugin_dir_path( + dirname( __FILE__ ) + ) . 'css/dev-tooltips.css' + ) + ); if ( self::$a_bool_amp_enabled ) { - wp_enqueue_style( 'mci-footnotes-amp', plugins_url( MCI_Footnotes_Config::C_STR_PLUGIN_NAME . '/css/dev-amp-tooltips.css' ), array(), C_STR_PACKAGE_VERSION ); + wp_enqueue_style( + 'mci-footnotes-amp', + plugins_url( MCI_Footnotes_Config::C_STR_PLUGIN_NAME . '/css/dev-amp-tooltips.css' ), + array(), + filemtime( + plugin_dir_path( + dirname( __FILE__ ) + ) . 'css/dev-amp-tooltips.css' + ) + ); } if ( self::$a_bool_alternative_tooltips_enabled ) { - wp_enqueue_style( 'mci-footnotes-alternative', plugins_url( MCI_Footnotes_Config::C_STR_PLUGIN_NAME . '/css/dev-tooltips-alternative.css' ), array(), C_STR_PACKAGE_VERSION ); + wp_enqueue_style( + 'mci-footnotes-alternative', + plugins_url( MCI_Footnotes_Config::C_STR_PLUGIN_NAME . '/css/dev-tooltips-alternative.css' ), + array(), + filemtime( + plugin_dir_path( + dirname( __FILE__ ) + ) . 'css/dev-tooltips-alternative.css' + ) + ); } $l_str_page_layout_option = MCI_Footnotes_Settings::instance()->get( MCI_Footnotes_Settings::C_STR_FOOTNOTES_PAGE_LAYOUT_SUPPORT ); @@ -452,7 +489,11 @@ class MCI_Footnotes { MCI_Footnotes_Config::C_STR_PLUGIN_NAME . '/css/dev-layout-' . $l_str_page_layout_option . '.css' ), array(), - C_STR_PACKAGE_VERSION, + filemtime( + plugin_dir_path( + dirname( __FILE__ ) + ) . 'css/dev-layout-' . $l_str_page_layout_option . '.css' + ), 'all' ); } diff --git a/class/layout/abstract-engine.php b/class/layout/abstract-engine.php index e4433ee..143ad96 100644 --- a/class/layout/abstract-engine.php +++ b/class/layout/abstract-engine.php @@ -340,7 +340,7 @@ abstract class MCI_Footnotes_Layout_Engine { * @since 1.5.0 * @param string $p_str_setting_key_name Settings Array key name. * @return array Contains Settings ID, Settings Name and Settings Value. - * + * * @since 2.5.11 Remove escapement function. * When refactoring the codebase after 2.5.8, all and every output was escaped. * After noticing that the plugin was broken, all escapement functions were removed. @@ -349,7 +349,7 @@ abstract class MCI_Footnotes_Layout_Engine { * In that process, this instance of esc_attr() was removed too, so the plugin was * broken again. * @link https://github.com/markcheret/footnotes/pull/50/commits/25c3f2f12eb5de1079e9215bf624ec4289b095a5#diff-a8ed6e859c32a18fc10bbbad3b4dd8ce7f43f2378d29471c7638e314ab30f1bdL349-L354 - * + * * @since 2.5.15 To fix it, the data was escaped in add_select_box() instead. * @since 2.6.1 Restore esc_attr() in load_setting(). * @see add_select_box() @@ -482,7 +482,7 @@ abstract class MCI_Footnotes_Layout_Engine { * @param string $p_str_setting_name Name of the Settings key to pre select the current value. * @param array $p_arr_options Possible options to be selected. * @return string - * + * * @since 2.5.15 Bugfix: Dashboard: General settings: Footnote start and end short codes: debug select box for shortcodes with pointy brackets. * @since 2.6.1 Restore esc_attr() in load_setting(), remove htmlspecialchars() here. */ diff --git a/class/layout/settings.php b/class/layout/settings.php index ea93d1b..5fb3a89 100644 --- a/class/layout/settings.php +++ b/class/layout/settings.php @@ -424,7 +424,7 @@ class MCI_Footnotes_Layout_Settings extends MCI_Footnotes_Layout_Engine { $l_obj_template->replace( array( // Translators: The 2 placeholders are the <ref></ref> and <fn></fn> shortcodes. - 'description-escapement' => sprintf( __( 'The problems with shortcodes with pointy brackets have been solved. We apologize for the longlasting bugs making the %s and %s shortcodes close to unusable.', 'footnotes' ), '<ref></ref>', '<fn></fn>' ), + 'description-escapement' => sprintf( __( 'The problems with shortcodes with pointy brackets have been solved. We apologize for the longlasting bugs making the %1$s and %2$s shortcodes close to unusable.', 'footnotes' ), '<ref></ref>', '<fn></fn>' ), 'label-short-code-start' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_START, __( 'Footnote start tag short code:', 'footnotes' ) ), 'short-code-start' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SHORT_CODE_START, $l_arr_shortcode_start ), @@ -520,34 +520,34 @@ class MCI_Footnotes_Layout_Settings extends MCI_Footnotes_Layout_Engine { $l_obj_template->replace( array( - 'label-scroll-css' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_CSS_SMOOTH_SCROLLING, __( 'CSS-based smooth scrolling:', 'footnotes' ) ), - 'scroll-css' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_CSS_SMOOTH_SCROLLING, $l_arr_enable ), - 'notice-scroll-css' => __( 'May slightly disturb jQuery scrolling and is therefore disabled by default. Works in recent browsers.', 'footnotes' ), + 'label-scroll-css' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_CSS_SMOOTH_SCROLLING, __( 'CSS-based smooth scrolling:', 'footnotes' ) ), + 'scroll-css' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_CSS_SMOOTH_SCROLLING, $l_arr_enable ), + 'notice-scroll-css' => __( 'May slightly disturb jQuery scrolling and is therefore disabled by default. Works in recent browsers.', 'footnotes' ), - 'label-scroll-offset' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_OFFSET, __( 'Scroll offset:', 'footnotes' ) ), - 'scroll-offset' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_OFFSET, 0, 100 ), - 'notice-scroll-offset' => __( 'per cent viewport height from the upper edge', 'footnotes' ), + 'label-scroll-offset' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_OFFSET, __( 'Scroll offset:', 'footnotes' ) ), + 'scroll-offset' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_OFFSET, 0, 100 ), + 'notice-scroll-offset' => __( 'per cent viewport height from the upper edge', 'footnotes' ), - 'label-scroll-duration' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_DURATION, __( 'Scroll duration:', 'footnotes' ) ), - 'scroll-duration' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_DURATION, 0, 20000 ), - 'notice-scroll-duration' => __( 'milliseconds. If asymmetric scroll durations are enabled, this is the scroll-up duration.', 'footnotes' ), + 'label-scroll-duration' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_DURATION, __( 'Scroll duration:', 'footnotes' ) ), + 'scroll-duration' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_DURATION, 0, 20000 ), + 'notice-scroll-duration' => __( 'milliseconds. If asymmetric scroll durations are enabled, this is the scroll-up duration.', 'footnotes' ), // Enable scroll duration asymmetricity. - 'label-scroll-asymmetricity' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SCROLL_DURATION_ASYMMETRICITY, __( 'Enable asymmetric scroll durations:', 'footnotes' ) ), - 'scroll-asymmetricity' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SCROLL_DURATION_ASYMMETRICITY, $l_arr_enable ), - 'notice-scroll-asymmetricity' => __( 'With this option enabled, scrolling up may take longer than down, or conversely.', 'footnotes' ), + 'label-scroll-asymmetricity' => $this->add_label( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SCROLL_DURATION_ASYMMETRICITY, __( 'Enable asymmetric scroll durations:', 'footnotes' ) ), + 'scroll-asymmetricity' => $this->add_select_box( MCI_Footnotes_Settings::C_STR_FOOTNOTES_SCROLL_DURATION_ASYMMETRICITY, $l_arr_enable ), + 'notice-scroll-asymmetricity' => __( 'With this option enabled, scrolling up may take longer than down, or conversely.', 'footnotes' ), - 'label-scroll-down-duration' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_DOWN_DURATION, __( 'Scroll-down duration:', 'footnotes' ) ), - 'scroll-down-duration' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_DOWN_DURATION, 0, 20000 ), - 'notice-scroll-down-duration' => __( 'milliseconds', 'footnotes' ), + 'label-scroll-down-duration' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_DOWN_DURATION, __( 'Scroll-down duration:', 'footnotes' ) ), + 'scroll-down-duration' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_DOWN_DURATION, 0, 20000 ), + 'notice-scroll-down-duration' => __( 'milliseconds', 'footnotes' ), - 'label-scroll-down-delay' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_DOWN_DELAY, __( 'Scroll-down delay:', 'footnotes' ) ), - 'scroll-down-delay' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_DOWN_DELAY, 0, 20000 ), - 'notice-scroll-down-delay' => __( 'milliseconds. Useful to see the effect on input elements when referrers without hard links are clicked in form labels.', 'footnotes' ), + 'label-scroll-down-delay' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_DOWN_DELAY, __( 'Scroll-down delay:', 'footnotes' ) ), + 'scroll-down-delay' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_DOWN_DELAY, 0, 20000 ), + 'notice-scroll-down-delay' => __( 'milliseconds. Useful to see the effect on input elements when referrers without hard links are clicked in form labels.', 'footnotes' ), - 'label-scroll-up-delay' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_UP_DELAY, __( 'Scroll-up delay:', 'footnotes' ) ), - 'scroll-up-delay' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_UP_DELAY, 0, 20000 ), - 'notice-scroll-up-delay' => __( 'milliseconds. Less useful than the scroll-down delay.', 'footnotes' ), + 'label-scroll-up-delay' => $this->add_label( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_UP_DELAY, __( 'Scroll-up delay:', 'footnotes' ) ), + 'scroll-up-delay' => $this->add_num_box( MCI_Footnotes_Settings::C_INT_FOOTNOTES_SCROLL_UP_DELAY, 0, 20000 ), + 'notice-scroll-up-delay' => __( 'milliseconds. Less useful than the scroll-down delay.', 'footnotes' ), ) ); diff --git a/class/settings.php b/class/settings.php index 1e81c24..d83907b 100644 --- a/class/settings.php +++ b/class/settings.php @@ -147,7 +147,6 @@ class MCI_Footnotes_Settings { * - as in English or US American typesetting; * - for better UX thanks to a more button-like appearance; * - for stylistic consistency with the expand-collapse button. - * */ const C_STR_FOOTNOTES_STYLING_BEFORE = 'footnote_inputfield_custom_styling_before'; @@ -248,13 +247,13 @@ class MCI_Footnotes_Settings { * * @since 2.1.3 * @since 2.6.3 Enable by default after debugging the 'Footnotes in excerpts' setting. - * + * * - Bugfix: Hooks: default-disable the_excerpt hook with respect to theme-specific excerpt handling, thanks to @mmallett bug reports. - * + * * @reporter @mmallett * @link https://wordpress.org/support/topic/broken-662/ * @link https://wordpress.org/support/topic/update-crashed-my-website-3/#post-14260969 - * + * * @since 2.6.5 * @see C_STR_FOOTNOTES_IN_EXCERPT * @var str @@ -301,9 +300,9 @@ class MCI_Footnotes_Settings { * Settings container key for the mouse-over box to define the color. * * @since 1.5.6 - * + * * - Bugfix: Tooltips: Styling: Font color: set to black for maximum contrast with respect to white default background, thanks to 4msc bug report. - * + * * @reporter @4msc * @link https://wordpress.org/support/topic/tooltip-not-showing-on-dark-theme-with-white-text/ * @@ -577,7 +576,7 @@ class MCI_Footnotes_Settings { * @date 2020-11-20T0620+0100 * @var int */ - const C_INT_EXPERT_LOOKUP_THE_TITLE_PRIORITY_LEVEL = 'footnote_inputfield_expert_lookup_the_title_priority_level'; + const C_INT_EXPERT_LOOKUP_THE_TITLE_PRIORITY_LEVEL = 'footnote_inputfield_expert_lookup_the_title_priority_level'; /** * Settings container key for 'widget_title' hook priority level. @@ -595,7 +594,7 @@ class MCI_Footnotes_Settings { * @date 2020-11-20T0620+0100 * @var int */ - const C_INT_EXPERT_LOOKUP_WIDGET_TEXT_PRIORITY_LEVEL = 'footnote_inputfield_expert_lookup_widget_text_priority_level'; + const C_INT_EXPERT_LOOKUP_WIDGET_TEXT_PRIORITY_LEVEL = 'footnote_inputfield_expert_lookup_widget_text_priority_level'; /** * Settings container key for 'the_excerpt' hook priority level. @@ -604,7 +603,7 @@ class MCI_Footnotes_Settings { * @date 2020-11-20T0620+0100 * @var int */ - const C_INT_EXPERT_LOOKUP_THE_EXCERPT_PRIORITY_LEVEL = 'footnote_inputfield_expert_lookup_the_excerpt_priority_level'; + const C_INT_EXPERT_LOOKUP_THE_EXCERPT_PRIORITY_LEVEL = 'footnote_inputfield_expert_lookup_the_excerpt_priority_level'; /** * Settings container key for the link element option. @@ -633,7 +632,7 @@ class MCI_Footnotes_Settings { * Backlink separators and terminators are often not preferred. * But a choice must be provided along with the ability to customize. */ - const C_STR_BACKLINKS_SEPARATOR_ENABLED = 'footnotes_inputfield_backlinks_separator_enabled'; + const C_STR_BACKLINKS_SEPARATOR_ENABLED = 'footnotes_inputfield_backlinks_separator_enabled'; /** * Settings container key for the backlink separator options. @@ -641,7 +640,7 @@ class MCI_Footnotes_Settings { * @since 2.1.4 * @var str */ - const C_STR_BACKLINKS_SEPARATOR_OPTION = 'footnotes_inputfield_backlinks_separator_option'; + const C_STR_BACKLINKS_SEPARATOR_OPTION = 'footnotes_inputfield_backlinks_separator_option'; /** * Settings container key for a custom backlink separator. @@ -649,7 +648,7 @@ class MCI_Footnotes_Settings { * @since 2.1.4 * @var str */ - const C_STR_BACKLINKS_SEPARATOR_CUSTOM = 'footnotes_inputfield_backlinks_separator_custom'; + const C_STR_BACKLINKS_SEPARATOR_CUSTOM = 'footnotes_inputfield_backlinks_separator_custom'; /** * Settings container key to enable the presence of a backlink terminator. @@ -665,7 +664,7 @@ class MCI_Footnotes_Settings { * @since 2.1.4 * @var str */ - const C_STR_BACKLINKS_TERMINATOR_OPTION = 'footnotes_inputfield_backlinks_terminator_option'; + const C_STR_BACKLINKS_TERMINATOR_OPTION = 'footnotes_inputfield_backlinks_terminator_option'; /** * Settings container key for a custom backlink terminator. @@ -673,7 +672,7 @@ class MCI_Footnotes_Settings { * @since 2.1.4 * @var str */ - const C_STR_BACKLINKS_TERMINATOR_CUSTOM = 'footnotes_inputfield_backlinks_terminator_custom'; + const C_STR_BACKLINKS_TERMINATOR_CUSTOM = 'footnotes_inputfield_backlinks_terminator_custom'; /** * Settings container key to enable the backlinks column width. @@ -681,7 +680,7 @@ class MCI_Footnotes_Settings { * @since 2.1.4 * @var str */ - const C_STR_BACKLINKS_COLUMN_WIDTH_ENABLED = 'footnotes_inputfield_backlinks_column_width_enabled'; + const C_STR_BACKLINKS_COLUMN_WIDTH_ENABLED = 'footnotes_inputfield_backlinks_column_width_enabled'; /** * Settings container key for the backlinks column width scalar. @@ -689,7 +688,7 @@ class MCI_Footnotes_Settings { * @since 2.1.4 * @var int */ - const C_INT_BACKLINKS_COLUMN_WIDTH_SCALAR = 'footnotes_inputfield_backlinks_column_width_scalar'; + const C_INT_BACKLINKS_COLUMN_WIDTH_SCALAR = 'footnotes_inputfield_backlinks_column_width_scalar'; /** * Settings container key for the backlinks column width unit. @@ -697,7 +696,7 @@ class MCI_Footnotes_Settings { * @since 2.1.4 * @var str */ - const C_STR_BACKLINKS_COLUMN_WIDTH_UNIT = 'footnotes_inputfield_backlinks_column_width_unit'; + const C_STR_BACKLINKS_COLUMN_WIDTH_UNIT = 'footnotes_inputfield_backlinks_column_width_unit'; /** * Settings container key to enable a max width for the backlinks column. @@ -713,7 +712,7 @@ class MCI_Footnotes_Settings { * @since 2.1.4 * @var int */ - const C_INT_BACKLINKS_COLUMN_MAX_WIDTH_SCALAR = 'footnotes_inputfield_backlinks_column_max_width_scalar'; + const C_INT_BACKLINKS_COLUMN_MAX_WIDTH_SCALAR = 'footnotes_inputfield_backlinks_column_max_width_scalar'; /** * Settings container key for the backlinks column max width unit. @@ -721,7 +720,7 @@ class MCI_Footnotes_Settings { * @since 2.1.4 * @var str */ - const C_STR_BACKLINKS_COLUMN_MAX_WIDTH_UNIT = 'footnotes_inputfield_backlinks_column_max_width_unit'; + const C_STR_BACKLINKS_COLUMN_MAX_WIDTH_UNIT = 'footnotes_inputfield_backlinks_column_max_width_unit'; /** * Settings container key to enable line breaks between backlinks. @@ -730,7 +729,7 @@ class MCI_Footnotes_Settings { * @var str * Whether a
tag is inserted. */ - const C_STR_BACKLINKS_LINE_BREAKS_ENABLED = 'footnotes_inputfield_backlinks_line_breaks_enabled'; + const C_STR_BACKLINKS_LINE_BREAKS_ENABLED = 'footnotes_inputfield_backlinks_line_breaks_enabled'; /** * Settings container key to enable setting the tooltip font size. @@ -751,7 +750,7 @@ class MCI_Footnotes_Settings { * @since 2.1.4 * @var flo */ - const C_FLO_MOUSE_OVER_BOX_FONT_SIZE_SCALAR = 'footnotes_inputfield_mouse_over_box_font_size_scalar'; + const C_FLO_MOUSE_OVER_BOX_FONT_SIZE_SCALAR = 'footnotes_inputfield_mouse_over_box_font_size_scalar'; /** * Settings container key for the unit of the tooltip font size. @@ -759,7 +758,7 @@ class MCI_Footnotes_Settings { * @since 2.1.4 * @var str */ - const C_STR_MOUSE_OVER_BOX_FONT_SIZE_UNIT = 'footnotes_inputfield_mouse_over_box_font_size_unit'; + const C_STR_MOUSE_OVER_BOX_FONT_SIZE_UNIT = 'footnotes_inputfield_mouse_over_box_font_size_unit'; /** * Settings container key for basic responsive page layout support options. @@ -779,7 +778,7 @@ class MCI_Footnotes_Settings { * @date 2020-12-05T0538+0100 * @var int */ - const C_INT_FOOTNOTES_SCROLL_OFFSET = 'footnotes_inputfield_scroll_offset'; + const C_INT_FOOTNOTES_SCROLL_OFFSET = 'footnotes_inputfield_scroll_offset'; /** * Settings container key for scroll duration. @@ -799,7 +798,7 @@ class MCI_Footnotes_Settings { * @date 2020-12-05T0538+0100 * @var int */ - const C_INT_MOUSE_OVER_BOX_FADE_IN_DELAY = 'footnotes_inputfield_mouse_over_box_fade_in_delay'; + const C_INT_MOUSE_OVER_BOX_FADE_IN_DELAY = 'footnotes_inputfield_mouse_over_box_fade_in_delay'; /** * Settings container key for tooltip display fade-in duration. @@ -808,7 +807,7 @@ class MCI_Footnotes_Settings { * @date 2020-12-05T0538+0100 * @var int */ - const C_INT_MOUSE_OVER_BOX_FADE_IN_DURATION = 'footnotes_inputfield_mouse_over_box_fade_in_duration'; + const C_INT_MOUSE_OVER_BOX_FADE_IN_DURATION = 'footnotes_inputfield_mouse_over_box_fade_in_duration'; /** * Settings container key for tooltip display fade-out delay. @@ -817,7 +816,7 @@ class MCI_Footnotes_Settings { * @date 2020-12-05T0538+0100 * @var int */ - const C_INT_MOUSE_OVER_BOX_FADE_OUT_DELAY = 'footnotes_inputfield_mouse_over_box_fade_out_delay'; + const C_INT_MOUSE_OVER_BOX_FADE_OUT_DELAY = 'footnotes_inputfield_mouse_over_box_fade_out_delay'; /** * Settings container key for tooltip display fade-out duration. @@ -918,7 +917,7 @@ class MCI_Footnotes_Settings { * @date 2020-12-17T0746+0100 * @var int */ - const C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH = 'footnotes_inputfield_alternative_mouse_over_box_width'; + const C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH = 'footnotes_inputfield_alternative_mouse_over_box_width'; /** @@ -933,7 +932,7 @@ class MCI_Footnotes_Settings { * @date 2020-12-18T1509+0100 * @var str */ - const C_STR_REFERENCE_CONTAINER_LABEL_ELEMENT = 'footnotes_inputfield_reference_container_label_element'; + const C_STR_REFERENCE_CONTAINER_LABEL_ELEMENT = 'footnotes_inputfield_reference_container_label_element'; /** * Settings container key to enable the reference container label bottom border. @@ -975,7 +974,7 @@ class MCI_Footnotes_Settings { * @date 2020-12-29T0914+0100 * @var int */ - const C_INT_REFERENCE_CONTAINER_TOP_MARGIN = 'footnotes_inputfield_reference_container_top_margin'; + const C_INT_REFERENCE_CONTAINER_TOP_MARGIN = 'footnotes_inputfield_reference_container_top_margin'; /** * Settings container key for reference container bottom margin. @@ -1008,7 +1007,7 @@ class MCI_Footnotes_Settings { * * When the alternative reference container is enabled, hard links are too. */ - const C_STR_FOOTNOTES_HARD_LINKS_ENABLE = 'footnotes_inputfield_hard_links_enable'; + const C_STR_FOOTNOTES_HARD_LINKS_ENABLE = 'footnotes_inputfield_hard_links_enable'; /** * Settings container key for the fragment ID slug in referrers. @@ -1017,7 +1016,7 @@ class MCI_Footnotes_Settings { * @date 2020-12-29T0914+0100 * @var str */ - const C_STR_REFERRER_FRAGMENT_ID_SLUG = 'footnotes_inputfield_referrer_fragment_id_slug'; + const C_STR_REFERRER_FRAGMENT_ID_SLUG = 'footnotes_inputfield_referrer_fragment_id_slug'; /** * Settings container key for the fragment ID slug in footnotes. @@ -1026,7 +1025,7 @@ class MCI_Footnotes_Settings { * @date 2020-12-29T0914+0100 * @var str */ - const C_STR_FOOTNOTE_FRAGMENT_ID_SLUG = 'footnotes_inputfield_footnote_fragment_id_slug'; + const C_STR_FOOTNOTE_FRAGMENT_ID_SLUG = 'footnotes_inputfield_footnote_fragment_id_slug'; /** * Settings container key for the ID separator in fragment IDs. @@ -1035,7 +1034,7 @@ class MCI_Footnotes_Settings { * @date 2020-12-29T0914+0100 * @var str */ - const C_STR_HARD_LINK_IDS_SEPARATOR = 'footnotes_inputfield_hard_link_ids_separator'; + const C_STR_HARD_LINK_IDS_SEPARATOR = 'footnotes_inputfield_hard_link_ids_separator'; /** * Settings container key to enable shortcode syntax validation. @@ -1270,179 +1269,179 @@ class MCI_Footnotes_Settings { private $a_arr_default = array( // General settings. - 'footnotes_storage' => array( + 'footnotes_storage' => array( // AMP compatibility. - self::C_STR_FOOTNOTES_AMP_COMPATIBILITY_ENABLE => '', + self::C_STR_FOOTNOTES_AMP_COMPATIBILITY_ENABLE => '', // Footnote start and end short codes. - self::C_STR_FOOTNOTES_SHORT_CODE_START => '((', - self::C_STR_FOOTNOTES_SHORT_CODE_END => '))', - self::C_STR_FOOTNOTES_SHORT_CODE_START_USER_DEFINED => '', - self::C_STR_FOOTNOTES_SHORT_CODE_END_USER_DEFINED => '', - self::C_STR_FOOTNOTE_SHORTCODE_SYNTAX_VALIDATION_ENABLE => 'yes', + self::C_STR_FOOTNOTES_SHORT_CODE_START => '((', + self::C_STR_FOOTNOTES_SHORT_CODE_END => '))', + self::C_STR_FOOTNOTES_SHORT_CODE_START_USER_DEFINED => '', + self::C_STR_FOOTNOTES_SHORT_CODE_END_USER_DEFINED => '', + self::C_STR_FOOTNOTE_SHORTCODE_SYNTAX_VALIDATION_ENABLE => 'yes', // Footnotes numbering. - self::C_STR_FOOTNOTES_COUNTER_STYLE => 'arabic_plain', - self::C_STR_COMBINE_IDENTICAL_FOOTNOTES => 'yes', + self::C_STR_FOOTNOTES_COUNTER_STYLE => 'arabic_plain', + self::C_STR_COMBINE_IDENTICAL_FOOTNOTES => 'yes', // Scrolling behavior. - self::C_STR_FOOTNOTES_CSS_SMOOTH_SCROLLING => 'no', - self::C_INT_FOOTNOTES_SCROLL_OFFSET => 20, - self::C_INT_FOOTNOTES_SCROLL_DURATION => 380, - self::C_STR_FOOTNOTES_SCROLL_DURATION_ASYMMETRICITY => 'no', - self::C_INT_FOOTNOTES_SCROLL_DOWN_DURATION => 150, - self::C_INT_FOOTNOTES_SCROLL_DOWN_DELAY => 0, - self::C_INT_FOOTNOTES_SCROLL_UP_DELAY => 0, - self::C_STR_FOOTNOTES_HARD_LINKS_ENABLE => 'no', - self::C_STR_REFERRER_FRAGMENT_ID_SLUG => 'r', - self::C_STR_FOOTNOTE_FRAGMENT_ID_SLUG => 'f', - self::C_STR_HARD_LINK_IDS_SEPARATOR => '+', - self::C_STR_FOOTNOTES_BACKLINK_TOOLTIP_ENABLE => 'yes', - self::C_STR_FOOTNOTES_BACKLINK_TOOLTIP_TEXT => 'Alt+ ←', + self::C_STR_FOOTNOTES_CSS_SMOOTH_SCROLLING => 'no', + self::C_INT_FOOTNOTES_SCROLL_OFFSET => 20, + self::C_INT_FOOTNOTES_SCROLL_DURATION => 380, + self::C_STR_FOOTNOTES_SCROLL_DURATION_ASYMMETRICITY => 'no', + self::C_INT_FOOTNOTES_SCROLL_DOWN_DURATION => 150, + self::C_INT_FOOTNOTES_SCROLL_DOWN_DELAY => 0, + self::C_INT_FOOTNOTES_SCROLL_UP_DELAY => 0, + self::C_STR_FOOTNOTES_HARD_LINKS_ENABLE => 'no', + self::C_STR_REFERRER_FRAGMENT_ID_SLUG => 'r', + self::C_STR_FOOTNOTE_FRAGMENT_ID_SLUG => 'f', + self::C_STR_HARD_LINK_IDS_SEPARATOR => '+', + self::C_STR_FOOTNOTES_BACKLINK_TOOLTIP_ENABLE => 'yes', + self::C_STR_FOOTNOTES_BACKLINK_TOOLTIP_TEXT => 'Alt+ ←', // Reference container. - self::C_STR_REFERENCE_CONTAINER_NAME => 'References', - self::C_STR_REFERENCE_CONTAINER_LABEL_ELEMENT => 'p', - self::C_STR_REFERENCE_CONTAINER_LABEL_BOTTOM_BORDER => 'yes', - self::C_STR_REFERENCE_CONTAINER_COLLAPSE => 'no', - self::C_STR_FOOTNOTES_REFERENCE_CONTAINER_SCRIPT_MODE => 'jquery', - self::C_STR_REFERENCE_CONTAINER_POSITION => 'post_end', - self::C_STR_REFERENCE_CONTAINER_POSITION_SHORTCODE => '[[references]]', - self::C_STR_REFERENCE_CONTAINER_START_PAGE_ENABLE => 'yes', - self::C_INT_REFERENCE_CONTAINER_TOP_MARGIN => 24, - self::C_INT_REFERENCE_CONTAINER_BOTTOM_MARGIN => 0, - self::C_STR_FOOTNOTES_PAGE_LAYOUT_SUPPORT => 'none', - self::C_STR_FOOTNOTE_URL_WRAP_ENABLED => 'yes', - self::C_STR_REFERENCE_CONTAINER_BACKLINK_SYMBOL_ENABLE => 'yes', - self::C_STR_REFERENCE_CONTAINER_BACKLINK_SYMBOL_SWITCH => 'no', - self::C_STR_REFERENCE_CONTAINER_3COLUMN_LAYOUT_ENABLE => 'no', - self::C_STR_REFERENCE_CONTAINER_ROW_BORDERS_ENABLE => 'no', + self::C_STR_REFERENCE_CONTAINER_NAME => 'References', + self::C_STR_REFERENCE_CONTAINER_LABEL_ELEMENT => 'p', + self::C_STR_REFERENCE_CONTAINER_LABEL_BOTTOM_BORDER => 'yes', + self::C_STR_REFERENCE_CONTAINER_COLLAPSE => 'no', + self::C_STR_FOOTNOTES_REFERENCE_CONTAINER_SCRIPT_MODE => 'jquery', + self::C_STR_REFERENCE_CONTAINER_POSITION => 'post_end', + self::C_STR_REFERENCE_CONTAINER_POSITION_SHORTCODE => '[[references]]', + self::C_STR_REFERENCE_CONTAINER_START_PAGE_ENABLE => 'yes', + self::C_INT_REFERENCE_CONTAINER_TOP_MARGIN => 24, + self::C_INT_REFERENCE_CONTAINER_BOTTOM_MARGIN => 0, + self::C_STR_FOOTNOTES_PAGE_LAYOUT_SUPPORT => 'none', + self::C_STR_FOOTNOTE_URL_WRAP_ENABLED => 'yes', + self::C_STR_REFERENCE_CONTAINER_BACKLINK_SYMBOL_ENABLE => 'yes', + self::C_STR_REFERENCE_CONTAINER_BACKLINK_SYMBOL_SWITCH => 'no', + self::C_STR_REFERENCE_CONTAINER_3COLUMN_LAYOUT_ENABLE => 'no', + self::C_STR_REFERENCE_CONTAINER_ROW_BORDERS_ENABLE => 'no', - self::C_STR_BACKLINKS_SEPARATOR_ENABLED => 'yes', - self::C_STR_BACKLINKS_SEPARATOR_OPTION => 'comma', - self::C_STR_BACKLINKS_SEPARATOR_CUSTOM => '', + self::C_STR_BACKLINKS_SEPARATOR_ENABLED => 'yes', + self::C_STR_BACKLINKS_SEPARATOR_OPTION => 'comma', + self::C_STR_BACKLINKS_SEPARATOR_CUSTOM => '', - self::C_STR_BACKLINKS_TERMINATOR_ENABLED => 'no', - self::C_STR_BACKLINKS_TERMINATOR_OPTION => 'full_stop', - self::C_STR_BACKLINKS_TERMINATOR_CUSTOM => '', + self::C_STR_BACKLINKS_TERMINATOR_ENABLED => 'no', + self::C_STR_BACKLINKS_TERMINATOR_OPTION => 'full_stop', + self::C_STR_BACKLINKS_TERMINATOR_CUSTOM => '', - self::C_STR_BACKLINKS_COLUMN_WIDTH_ENABLED => 'no', - self::C_INT_BACKLINKS_COLUMN_WIDTH_SCALAR => '50', - self::C_STR_BACKLINKS_COLUMN_WIDTH_UNIT => 'px', + self::C_STR_BACKLINKS_COLUMN_WIDTH_ENABLED => 'no', + self::C_INT_BACKLINKS_COLUMN_WIDTH_SCALAR => '50', + self::C_STR_BACKLINKS_COLUMN_WIDTH_UNIT => 'px', - self::C_STR_BACKLINKS_COLUMN_MAX_WIDTH_ENABLED => 'no', - self::C_INT_BACKLINKS_COLUMN_MAX_WIDTH_SCALAR => '140', - self::C_STR_BACKLINKS_COLUMN_MAX_WIDTH_UNIT => 'px', + self::C_STR_BACKLINKS_COLUMN_MAX_WIDTH_ENABLED => 'no', + self::C_INT_BACKLINKS_COLUMN_MAX_WIDTH_SCALAR => '140', + self::C_STR_BACKLINKS_COLUMN_MAX_WIDTH_UNIT => 'px', - self::C_STR_BACKLINKS_LINE_BREAKS_ENABLED => 'no', - self::C_STR_LINK_ELEMENT_ENABLED => 'yes', + self::C_STR_BACKLINKS_LINE_BREAKS_ENABLED => 'no', + self::C_STR_LINK_ELEMENT_ENABLED => 'yes', // Footnotes in excerpts. - self::C_STR_FOOTNOTES_IN_EXCERPT => 'yes', + self::C_STR_FOOTNOTES_IN_EXCERPT => 'yes', // Footnotes love. - self::C_STR_FOOTNOTES_LOVE => 'no', + self::C_STR_FOOTNOTES_LOVE => 'no', // Deprecated. - self::C_STR_FOOTNOTES_EXPERT_MODE => 'yes', + self::C_STR_FOOTNOTES_EXPERT_MODE => 'yes', ), // Referrers and tooltips. - 'footnotes_storage_custom' => array( + 'footnotes_storage_custom' => array( // Backlink symbol. - self::C_STR_HYPERLINK_ARROW => '↑', - self::C_STR_HYPERLINK_ARROW_USER_DEFINED => '', + self::C_STR_HYPERLINK_ARROW => '↑', + self::C_STR_HYPERLINK_ARROW_USER_DEFINED => '', // Referrers. - self::C_STR_FOOTNOTES_REFERRER_SUPERSCRIPT_TAGS => 'yes', - self::C_STR_FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT => 'no', - self::C_STR_FOOTNOTES_STYLING_BEFORE => '[', - self::C_STR_FOOTNOTES_STYLING_AFTER => ']', + self::C_STR_FOOTNOTES_REFERRER_SUPERSCRIPT_TAGS => 'yes', + self::C_STR_FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT => 'no', + self::C_STR_FOOTNOTES_STYLING_BEFORE => '[', + self::C_STR_FOOTNOTES_STYLING_AFTER => ']', // Referrers in labels. - self::C_STR_FOOTNOTES_LABEL_ISSUE_SOLUTION => 'none', + self::C_STR_FOOTNOTES_LABEL_ISSUE_SOLUTION => 'none', // Tooltips. - self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_ENABLED => 'yes', - self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_ALTERNATIVE => 'no', + self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_ENABLED => 'yes', + self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_ALTERNATIVE => 'no', // Tooltip position. - self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_POSITION => 'top center', + self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_POSITION => 'top center', self::C_STR_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_POSITION => 'top right', - self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_OFFSET_X => 0, + self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_OFFSET_X => 0, self::C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_X => -50, - self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_OFFSET_Y => -7, + self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_OFFSET_Y => -7, self::C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_Y => 24, // Tooltip dimensions. - self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_MAX_WIDTH => 450, - self::C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH => 400, + self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_MAX_WIDTH => 450, + self::C_INT_FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH => 400, // Tooltip timing. - self::C_INT_MOUSE_OVER_BOX_FADE_IN_DELAY => 0, - self::C_INT_MOUSE_OVER_BOX_FADE_IN_DURATION => 200, - self::C_INT_MOUSE_OVER_BOX_FADE_OUT_DELAY => 400, - self::C_INT_MOUSE_OVER_BOX_FADE_OUT_DURATION => 200, + self::C_INT_MOUSE_OVER_BOX_FADE_IN_DELAY => 0, + self::C_INT_MOUSE_OVER_BOX_FADE_IN_DURATION => 200, + self::C_INT_MOUSE_OVER_BOX_FADE_OUT_DELAY => 400, + self::C_INT_MOUSE_OVER_BOX_FADE_OUT_DURATION => 200, // Tooltip truncation. - self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_ENABLED => 'yes', - self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_LENGTH => 200, - self::C_STR_FOOTNOTES_TOOLTIP_READON_LABEL => 'Continue reading', + self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_ENABLED => 'yes', + self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_LENGTH => 200, + self::C_STR_FOOTNOTES_TOOLTIP_READON_LABEL => 'Continue reading', // Tooltip text. - self::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_DELIMITER => '[[/tooltip]]', - self::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE => 'no', - self::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR => ' — ', + self::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_DELIMITER => '[[/tooltip]]', + self::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE => 'no', + self::C_STR_FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR => ' — ', // Tooltip appearance. - self::C_STR_MOUSE_OVER_BOX_FONT_SIZE_ENABLED => 'yes', - self::C_FLO_MOUSE_OVER_BOX_FONT_SIZE_SCALAR => 13, - self::C_STR_MOUSE_OVER_BOX_FONT_SIZE_UNIT => 'px', + self::C_STR_MOUSE_OVER_BOX_FONT_SIZE_ENABLED => 'yes', + self::C_FLO_MOUSE_OVER_BOX_FONT_SIZE_SCALAR => 13, + self::C_STR_MOUSE_OVER_BOX_FONT_SIZE_UNIT => 'px', - self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_COLOR => '#000000', - self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND => '#ffffff', - self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_BORDER_WIDTH => 1, - self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_BORDER_COLOR => '#cccc99', - self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_BORDER_RADIUS => 0, - self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_SHADOW_COLOR => '#666666', + self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_COLOR => '#000000', + self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND => '#ffffff', + self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_BORDER_WIDTH => 1, + self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_BORDER_COLOR => '#cccc99', + self::C_INT_FOOTNOTES_MOUSE_OVER_BOX_BORDER_RADIUS => 0, + self::C_STR_FOOTNOTES_MOUSE_OVER_BOX_SHADOW_COLOR => '#666666', // Your existing Custom CSS code. - self::C_STR_CUSTOM_CSS => '', + self::C_STR_CUSTOM_CSS => '', ), - // Scope and priority - 'footnotes_storage_expert' => array( + // Scope and priority. + 'footnotes_storage_expert' => array( // WordPress hooks with priority level. - self::C_STR_EXPERT_LOOKUP_THE_TITLE => '', - self::C_INT_EXPERT_LOOKUP_THE_TITLE_PRIORITY_LEVEL => PHP_INT_MAX, + self::C_STR_EXPERT_LOOKUP_THE_TITLE => '', + self::C_INT_EXPERT_LOOKUP_THE_TITLE_PRIORITY_LEVEL => PHP_INT_MAX, - self::C_STR_EXPERT_LOOKUP_THE_CONTENT => 'checked', - self::C_INT_EXPERT_LOOKUP_THE_CONTENT_PRIORITY_LEVEL => 98, + self::C_STR_EXPERT_LOOKUP_THE_CONTENT => 'checked', + self::C_INT_EXPERT_LOOKUP_THE_CONTENT_PRIORITY_LEVEL => 98, - self::C_STR_EXPERT_LOOKUP_THE_EXCERPT => '', - self::C_INT_EXPERT_LOOKUP_THE_EXCERPT_PRIORITY_LEVEL => PHP_INT_MAX, + self::C_STR_EXPERT_LOOKUP_THE_EXCERPT => '', + self::C_INT_EXPERT_LOOKUP_THE_EXCERPT_PRIORITY_LEVEL => PHP_INT_MAX, - self::C_STR_EXPERT_LOOKUP_WIDGET_TITLE => '', - self::C_INT_EXPERT_LOOKUP_WIDGET_TITLE_PRIORITY_LEVEL => PHP_INT_MAX, + self::C_STR_EXPERT_LOOKUP_WIDGET_TITLE => '', + self::C_INT_EXPERT_LOOKUP_WIDGET_TITLE_PRIORITY_LEVEL => PHP_INT_MAX, - self::C_STR_EXPERT_LOOKUP_WIDGET_TEXT => '', - self::C_INT_EXPERT_LOOKUP_WIDGET_TEXT_PRIORITY_LEVEL => 98, + self::C_STR_EXPERT_LOOKUP_WIDGET_TEXT => '', + self::C_INT_EXPERT_LOOKUP_WIDGET_TEXT_PRIORITY_LEVEL => 98, ), // Custom CSS. - 'footnotes_storage_custom_css' => array( + 'footnotes_storage_custom_css' => array( // Your existing Custom CSS code. - self::C_STR_CUSTOM_CSS_LEGACY_ENABLE => 'yes', + self::C_STR_CUSTOM_CSS_LEGACY_ENABLE => 'yes', // Custom CSS. - self::C_STR_CUSTOM_CSS_NEW => '', + self::C_STR_CUSTOM_CSS_NEW => '', ), @@ -1523,10 +1522,10 @@ class MCI_Footnotes_Settings { * @since 1.5.0 * * - Bugfix: Removed the 'trim' function to allow leading and trailing whitespace in settings text boxes, thanks to @compasscare bug report. - * + * * @reporter @compasscare * @link https://wordpress.org/support/topic/leading-space-in-footnotes-tag/ - * + * * @since 1.5.2 * @param int $p_int_index Settings container array key index. * @return array Settings loaded from defaults if container is empty (first usage). diff --git a/class/task.php b/class/task.php index 7a043c1..e61b155 100644 --- a/class/task.php +++ b/class/task.php @@ -491,7 +491,7 @@ class MCI_Footnotes_Task { } if ( MCI_Footnotes_Convert::to_bool( MCI_Footnotes_Settings::instance()->get( MCI_Footnotes_Settings::C_STR_EXPERT_LOOKUP_THE_EXCERPT ) ) ) { - add_filter( 'the_excerpt', array( $this, 'footnotes_in_excerpt' ), $l_int_the_excerpt_priority ); + add_filter( 'the_excerpt', array( $this, 'footnotes_in_excerpt' ), $l_int_the_excerpt_priority ); add_filter( 'get_the_excerpt', array( $this, 'footnotes_in_excerpt' ), $l_int_the_excerpt_priority ); } if ( MCI_Footnotes_Convert::to_bool( MCI_Footnotes_Settings::instance()->get( MCI_Footnotes_Settings::C_STR_EXPERT_LOOKUP_WIDGET_TITLE ) ) ) { @@ -868,6 +868,7 @@ class MCI_Footnotes_Task { * Dimensions of jQuery tooltips. * * Position and timing of jQuery tooltips are script defined. + * * @see templates/public/tooltip.html. */ $l_int_max_width = MCI_Footnotes_Settings::instance()->get( MCI_Footnotes_Settings::C_INT_FOOTNOTES_MOUSE_OVER_BOX_MAX_WIDTH ); @@ -877,7 +878,6 @@ class MCI_Footnotes_Task { echo "}\r\n"; } else { - /* * AMP compatible and alternative tooltips. */ @@ -935,6 +935,7 @@ class MCI_Footnotes_Task { * AMP compatible tooltips. * * To streamline internal CSS, immutable rules are in external stylesheet. + * * @see dev-amp-tooltips.css. */ if ( MCI_Footnotes::$a_bool_amp_enabled ) { @@ -949,12 +950,13 @@ class MCI_Footnotes_Task { echo 'transition-duration: ' . $l_int_fade_in_duration . 'ms;'; echo "}\r\n"; - /** - * Alternative tooltips. + /** + * Alternative tooltips. + * + * To streamline internal CSS, immutable rules are in external stylesheet. * - * To streamline internal CSS, immutable rules are in external stylesheet. - * @see dev-tooltips-alternative.css. - */ + * @see dev-tooltips-alternative.css. + */ } else { echo '.footnote_tooltip.hidden {'; @@ -1016,7 +1018,8 @@ class MCI_Footnotes_Task { document.getElementById(footnote_tooltip_id).classList.add('hidden'); } -#', $l_str_separator, $p_str_content ); - $p_str_content = preg_replace( '#
#', $l_str_separator, $p_str_content ); - $p_str_content = preg_replace( '#<(p|li|div)[^>]*>#', $l_str_separator, $p_str_content ); - $p_str_content = preg_replace( '#' . $l_str_separator . '#', '', $p_str_content, 1 ); - $p_str_content = preg_replace( '##', '', $p_str_content ); - $p_str_content = preg_replace( '#[\r\n]#', '', $p_str_content ); + $p_str_content = preg_replace( '#
#', $l_str_separator, $p_str_content ); + $p_str_content = preg_replace( '#
#', $l_str_separator, $p_str_content ); + $p_str_content = preg_replace( '#<(p|li|div)[^>]*>#', $l_str_separator, $p_str_content ); + $p_str_content = preg_replace( '#' . $l_str_separator . '#', '', $p_str_content, 1 ); + $p_str_content = preg_replace( '##', '', $p_str_content ); + $p_str_content = preg_replace( '#[\r\n]#', '', $p_str_content ); // To count words like Advanced Excerpt does it. - $l_arr_tokens = array(); - $l_str_output = ''; + $l_arr_tokens = array(); + $l_str_output = ''; $l_int_counter = 0; // Tokenize into tags and words as in Advanced Excerpt. @@ -1307,7 +1310,7 @@ class MCI_Footnotes_Task { * Replaces footnotes in the widget title. * * @since 1.5.0 - * @param string $p_str_content Widget content. + * @param string $p_str_content Widget content. * @return string $p_str_content Content with replaced footnotes. */ public function footnotes_in_widget_title( $p_str_content ) { @@ -1319,7 +1322,7 @@ class MCI_Footnotes_Task { * Replaces footnotes in the content of the current widget. * * @since 1.5.0 - * @param string $p_str_content Widget content. + * @param string $p_str_content Widget content. * @return string $p_str_content Content with replaced footnotes. */ public function footnotes_in_widget_text( $p_str_content ) { @@ -1399,6 +1402,8 @@ class MCI_Footnotes_Task { /** * Brings the delimiters and unifies their various HTML escapement schemas. * + * @param string $p_str_content TODO. + * * - Bugfix: Footnote delimiter short codes: fix numbering bug by cross-editor HTML escapement schema unification, thanks to @patrick_here @alifarahani8000 @gova bug reports. * * @reporter @patrick_here @@ -1433,27 +1438,27 @@ class MCI_Footnotes_Task { if ( preg_match( '#[&"\'<>]#', $l_str_starting_tag . $l_str_ending_tag ) ) { - $l_str_harmonized_start_tag = '{[(|fnote_stt|)]}'; - $l_str_harmonized_end_tag = '{[(|fnote_end|)]}'; + $l_str_harmonized_start_tag = '{[(|fnote_stt|)]}'; + $l_str_harmonized_end_tag = '{[(|fnote_end|)]}'; // Harmonize footnotes without escaping any HTML special characters in delimiter shortcodes. // The footnote has been added in the Block Editor code editor (doesn’t work in Classic Editor text mode). $p_str_content = str_replace( $l_str_starting_tag, $l_str_harmonized_start_tag, $p_str_content ); - $p_str_content = str_replace( $l_str_ending_tag , $l_str_harmonized_end_tag , $p_str_content ); + $p_str_content = str_replace( $l_str_ending_tag, $l_str_harmonized_end_tag, $p_str_content ); // Harmonize footnotes while escaping HTML special characters in delimiter shortcodes. // The footnote has been added in the Classic Editor visual mode. $p_str_content = str_replace( htmlspecialchars( $l_str_starting_tag ), $l_str_harmonized_start_tag, $p_str_content ); - $p_str_content = str_replace( htmlspecialchars( $l_str_ending_tag ), $l_str_harmonized_end_tag , $p_str_content ); + $p_str_content = str_replace( htmlspecialchars( $l_str_ending_tag ), $l_str_harmonized_end_tag, $p_str_content ); // Harmonize footnotes while escaping HTML special characters except greater-than sign in delimiter shortcodes. // The footnote has been added in the Block Editor visual mode. $p_str_content = str_replace( str_replace( '>', '>', htmlspecialchars( $l_str_starting_tag ) ), $l_str_harmonized_start_tag, $p_str_content ); - $p_str_content = str_replace( str_replace( '>', '>', htmlspecialchars( $l_str_ending_tag ) ), $l_str_harmonized_end_tag , $p_str_content ); + $p_str_content = str_replace( str_replace( '>', '>', htmlspecialchars( $l_str_ending_tag ) ), $l_str_harmonized_end_tag, $p_str_content ); // Assign the delimiter shortcodes. - self::$a_str_start_tag = $l_str_harmonized_start_tag; - self::$a_str_end_tag = $l_str_harmonized_end_tag; + self::$a_str_start_tag = $l_str_harmonized_start_tag; + self::$a_str_end_tag = $l_str_harmonized_end_tag; // Assign the regex-conformant shortcodes. self::$a_str_start_tag_regex = '\{\[\(\|fnote_stt\|\)\]\}'; @@ -1462,8 +1467,8 @@ class MCI_Footnotes_Task { } else { // Assign the delimiter shortcodes. - self::$a_str_start_tag = $l_str_starting_tag; - self::$a_str_end_tag = $l_str_ending_tag; + self::$a_str_start_tag = $l_str_starting_tag; + self::$a_str_end_tag = $l_str_ending_tag; // Make shortcodes conform to regex syntax. self::$a_str_start_tag_regex = preg_replace( '#([\(\)\{\}\[\]\|\*\.\?\!])#', '\\\\$1', self::$a_str_start_tag ); @@ -1629,12 +1634,12 @@ class MCI_Footnotes_Task { */ if ( 'disconnect' === $l_str_label_issue_solution ) { - $l_str_disconnect_text = 'optionally-disconnected-from-input-field-to-prevent-toggling-while-clicking-footnote-referrer_'; + $l_str_disconnect_text = 'optionally-disconnected-from-input-field-to-prevent-toggling-while-clicking-footnote-referrer_'; $p_str_content = preg_replace( '#(