Plugin Directory

Changeset 3444257


Ignore:
Timestamp:
01/21/2026 04:29:39 PM (4 weeks ago)
Author:
anand_kumar
Message:

fix: Permission system to use 'unfiltered_html' capability.
feat: Add wp_body_open hook support, user role permissions for script insertion, and a post-specific script meta box, while updating plugin options and documentation.
feat: Introduce global and per-post script management, add wp_body_open hook support, and refactor codebase to jamify_hfs_ naming standards.
refactor: Restructure plugin with dedicated files for options, meta, and sidebar UI, enhance code documentation, and implement conditional uninstall data removal.
improvement: Enhanced WPCS compliance with comprehensive DocBlocks and formatting fixes.

Location:
header-and-footer-scripts
Files:
11 added
5 edited

Legend:

Unmodified
Added
Removed
  • header-and-footer-scripts/trunk/inc/meta.php

    r3442622 r3444257  
    55 * @package    Header and Footer Scripts
    66 * @author     Anand Kumar <[email protected]>
    7  * @copyright  Copyright (c) 2013 - 2025, Anand Kumar
     7 * @copyright  Copyright (c) 2013 - 2026, Anand Kumar
    88 * @link       https://github.com/anandkumar/header-and-footer-scripts
    99 * @license    http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
    10  */?>
    11  <div class="shfs_meta_control">
     10 *
     11 */
     12
     13if ( ! defined( 'ABSPATH' ) ) {
     14    exit;
     15}?>
     16 <div class="jamify_hfs_meta_control">
    1217
    1318    <p><?php esc_html_e('The script in the following textbox will be inserted to the &lt;head&gt; section', 'header-and-footer-scripts'); ?>.</p>
    1419    <p>
    15         <textarea name="_inpost_head_script[synth_header_script]" rows="5" style="width:98%;font-family:monospace;"><?php if(!empty($meta['synth_header_script'])) echo esc_textarea( $meta['synth_header_script'] ); ?></textarea>
     20        <textarea id="jamify_hfs_inpost_head_script" name="_inpost_head_script[synth_header_script]" rows="5" style="width:98%;font-family:monospace;"><?php if(!empty($meta['synth_header_script'])) echo esc_textarea( $meta['synth_header_script'] ); ?></textarea>
    1621    </p>
    1722</div>
  • header-and-footer-scripts/trunk/inc/options.php

    r3442622 r3444257  
    55 * @package    Header and Footer Scripts
    66 * @author     Anand Kumar <[email protected]>
    7  * @copyright  Copyright (c) 2013 - 2025, Anand Kumar
     7 * @copyright  Copyright (c) 2013 - 2026, Anand Kumar
    88 * @link       https://github.com/anandkumar/header-and-footer-scripts
    99 * @license    http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
    10  */?>
     10 */
     11
     12if ( ! defined( 'ABSPATH' ) ) {
     13    exit;
     14}?>
    1115<div class="wrap">
    12   <h2><?php esc_html_e( 'Header and Footer Scripts - Options', 'header-and-footer-scripts'); ?> <a class="add-new-h2" target="_blank" href="<?php echo esc_url( "https://digitalliberation.org/docs/header-and-footer-scripts/?utm_source=wpdash_hfs" ); ?>"><?php esc_html_e( 'Read Tutorial', 'header-and-footer-scripts'); ?></a></h2>
     16  <h2><?php esc_html_e( 'Header and Footer Scripts - Options', 'header-and-footer-scripts'); ?> <a class="add-new-h2" target="_blank" href="<?php echo esc_url( "https://github.com/anandkumar/header-and-footer-scripts/wiki" ); ?>"><?php esc_html_e( 'Read Tutorial', 'header-and-footer-scripts'); ?></a></h2>
    1317
    1418  <hr />
     
    2226            <?php settings_fields( 'header-and-footer-scripts' ); ?>
    2327
    24             <h3 class="shfs-labels" for="shfs_script_access_level"><?php esc_html_e( 'Who can add scripts to posts?', 'header-and-footer-scripts'); ?></h3>
    25              <p>
    26                  <select name="shfs_script_access_level" id="shfs_script_access_level">
    27                      <option value="manage_options" <?php selected( get_option( 'shfs_script_access_level', 'manage_options' ), 'manage_options' ); ?>><?php esc_html_e('Administrator Only', 'header-and-footer-scripts'); ?></option>
    28                      <option value="edit_others_posts" <?php selected( get_option( 'shfs_script_access_level', 'manage_options' ), 'edit_others_posts' ); ?>><?php esc_html_e('Administrator & Editor', 'header-and-footer-scripts'); ?></option>
    29                      <option value="publish_posts" <?php selected( get_option( 'shfs_script_access_level', 'manage_options' ), 'publish_posts' ); ?>><?php esc_html_e('Administrator, Editor & Author', 'header-and-footer-scripts'); ?></option>
    30                  </select>
    31              </p>
    32              <p class="description"><?php esc_html_e( 'Select the minimum capability required to add scripts to posts using the meta box.', 'header-and-footer-scripts'); ?></p>
    33              <hr />
     28            <h3 class="shfs-labels"><?php esc_html_e( 'Who can insert scripts?', 'header-and-footer-scripts'); ?></h3>
     29            <p><?php esc_html_e( 'By default, only Administrators can add scripts. You can grant this ability to other roles below.', 'header-and-footer-scripts'); ?></p>
     30           
     31            <fieldset>
     32                <label for="jamify_hfs_allow_author">
     33                    <input type="checkbox" name="jamify_hfs_allow_author" id="jamify_hfs_allow_author" value="yes" <?php checked( 'yes', get_option( 'jamify_hfs_allow_author' ) ); ?>>
     34                    <?php esc_html_e( 'Allow Authors to add scripts (Grants unfiltered_html capability)', 'header-and-footer-scripts'); ?>
     35                </label>
     36                <br>
     37                <label for="jamify_hfs_allow_contributor">
     38                    <input type="checkbox" name="jamify_hfs_allow_contributor" id="jamify_hfs_allow_contributor" value="yes" <?php checked( 'yes', get_option( 'jamify_hfs_allow_contributor' ) ); ?>>
     39                    <?php esc_html_e( 'Allow Contributors to add scripts (Grants unfiltered_html capability)', 'header-and-footer-scripts'); ?>
     40                </label>
     41            </fieldset>
    3442
    35             <h3 class="shfs-labels" for="shfs_insert_header"><?php esc_html_e( 'Scripts in header:', 'header-and-footer-scripts'); ?></h3>
     43            <p class="description" style="color: #ea580c; font-weight: bold;">
     44                <?php esc_html_e( 'Caution: Enabling these options grants the "unfiltered_html" capability, allowing users to execute arbitrary JavaScript on your site. Only enable for trusted users.', 'header-and-footer-scripts'); ?>
     45            </p>
     46            <hr />
     47
     48            <h3 class="shfs-labels" for="jamify_hfs_insert_header"><?php esc_html_e( 'Scripts in header:', 'header-and-footer-scripts'); ?></h3>
    3649            <p><?php esc_html_e( 'The following script, if any, will be inserted into the &lt;head&gt; section using wp_head hook.', 'header-and-footer-scripts'); ?></p>
    37             <textarea style="width:98%;font-family:monospace;" rows="10" cols="57" id="insert_header" name="shfs_insert_header"><?php echo esc_html( get_option( 'shfs_insert_header' ) ); ?></textarea>
     50            <textarea style="width:98%;font-family:monospace;" rows="10" cols="57" id="jamify_hfs_insert_header" name="jamify_hfs_insert_header"><?php echo esc_html( get_option( 'jamify_hfs_insert_header' ) ); ?></textarea>
    3851
    39             <p><label for="shfs_insert_header_priority"><?php esc_html_e('Priority', 'header-and-footer-scripts'); ?></label>
    40             <input type="number" value="<?php echo \esc_html( \get_option( 'shfs_insert_header_priority', 10 ) ); ?>" name="shfs_insert_header_priority" id="shfs_insert_header_priority" style="width:6em;" /> <?php \esc_html_e('Default', 'header-and-footer-scripts'); ?>: 10</p><hr />
     52            <p><label for="jamify_hfs_insert_header_priority"><?php esc_html_e('Priority', 'header-and-footer-scripts'); ?></label>
     53            <input type="number" value="<?php echo \esc_html( \get_option( 'jamify_hfs_insert_header_priority', 10 ) ); ?>" name="jamify_hfs_insert_header_priority" id="jamify_hfs_insert_header_priority" style="width:6em;" /> <?php \esc_html_e('Default', 'header-and-footer-scripts'); ?>: 10</p><hr />
    4154
    42             <h3 class="shfs-labels footerlabel" for="shfs_insert_footer"><?php esc_html_e( 'Scripts in footer:', 'header-and-footer-scripts'); ?></h3>
     55            <h3 class="shfs-labels" for="jamify_hfs_insert_body"><?php esc_html_e( 'Scripts in body:', 'header-and-footer-scripts'); ?></h3>
     56            <p><?php esc_html_e( 'The following script, if any, will be inserted immediately after the &lt;body&gt; tag using wp_body_open hook.', 'header-and-footer-scripts'); ?></p>
     57            <textarea style="width:98%;font-family:monospace;" rows="10" cols="57" id="jamify_hfs_insert_body" name="jamify_hfs_insert_body"><?php echo esc_html( get_option( 'jamify_hfs_insert_body' ) ); ?></textarea>
     58
     59            <p><label for="jamify_hfs_insert_body_priority"><?php esc_html_e('Priority', 'header-and-footer-scripts'); ?></label>
     60            <input type="number" value="<?php echo \esc_html( \get_option( 'jamify_hfs_insert_body_priority', 10 ) ); ?>" name="jamify_hfs_insert_body_priority" id="jamify_hfs_insert_body_priority" style="width:6em;" /> <?php \esc_html_e('Default', 'header-and-footer-scripts'); ?>: 10</p><hr />
     61
     62            <h3 class="shfs-labels footerlabel" for="jamify_hfs_insert_footer"><?php esc_html_e( 'Scripts in footer:', 'header-and-footer-scripts'); ?></h3>
    4363            <p><?php esc_html_e( 'The following script, if any, will be inserted before &lt;/body&gt; tag using wp_footer hook.', 'header-and-footer-scripts'); ?></p>
    44             <textarea style="width:98%;font-family:monospace;" rows="10" cols="57" id="shfs_insert_footer" name="shfs_insert_footer"><?php echo esc_html( get_option( 'shfs_insert_footer' ) ); ?></textarea>
     64            <textarea style="width:98%;font-family:monospace;" rows="10" cols="57" id="jamify_hfs_insert_footer" name="jamify_hfs_insert_footer"><?php echo esc_html( get_option( 'jamify_hfs_insert_footer' ) ); ?></textarea>
    4565
    46             <p><label for="shfs_insert_footer_priority"><?php _e('Priority'); ?></label>
    47             <input type="number" value="<?php echo \esc_html( \get_option( 'shfs_insert_footer_priority', 10 ) ); ?>" name="shfs_insert_footer_priority" id="shfs_insert_footer_priority" style="width:6em;" /> <?php \esc_html_e('Default', 'header-and-footer-scripts'); ?>: 10</p>
     66            <p><label for="jamify_hfs_insert_footer_priority"><?php esc_html_e('Priority', 'header-and-footer-scripts'); ?></label>
     67            <input type="number" value="<?php echo \esc_html( \get_option( 'jamify_hfs_insert_footer_priority', 10 ) ); ?>" name="jamify_hfs_insert_footer_priority" id="jamify_hfs_insert_footer_priority" style="width:6em;" /> <?php \esc_html_e('Default', 'header-and-footer-scripts'); ?>: 10</p><hr />
     68
     69            <h3 class="shfs-labels"><?php esc_html_e( 'Uninstall Settings', 'header-and-footer-scripts'); ?></h3>
     70            <fieldset>
     71                <label for="jamify_hfs_clean_on_uninstall">
     72                    <input type="checkbox" name="jamify_hfs_clean_on_uninstall" id="jamify_hfs_clean_on_uninstall" value="yes" <?php checked( 'yes', get_option( 'jamify_hfs_clean_on_uninstall' ) ); ?>>
     73                    <?php esc_html_e( 'Delete all data on uninstall', 'header-and-footer-scripts'); ?>
     74                </label>
     75            </fieldset>
     76            <p class="description" style="color: #ea580c; font-weight: bold;">
     77                <?php esc_html_e( 'Warning: If checked, all scripts and settings will be permanently deleted when you delete this plugin. This cannot be undone.', 'header-and-footer-scripts'); ?>
     78            </p>
    4879
    4980          <p class="submit">
     
    5687    </div>
    5788
    58     <?php require_once(SHFS_PLUGIN_DIR . '/inc/sidebar.php'); ?>
     89    <?php require_once(JAMIFY_HFS_PLUGIN_DIR . '/inc/sidebar.php'); ?>
    5990    </div>
    6091  </div>
  • header-and-footer-scripts/trunk/inc/sidebar.php

    r3442622 r3444257  
    55 * @package    Header and Footer Scripts
    66 * @author     Anand Kumar <[email protected]>
    7  * @copyright  Copyright (c) 2013 - 2025, Anand Kumar
     7 * @copyright  Copyright (c) 2013 - 2026, Anand Kumar
    88 * @link       https://github.com/anandkumar/header-and-footer-scripts
    99 * @license    http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
    10  */?>
     10 */
     11
     12if ( ! defined( 'ABSPATH' ) ) {
     13    exit;
     14}?>
    1115<div id="postbox-container-1" class="postbox-container">
    1216
     
    2024
    2125  <div class="postbox">
    22     <h3 class="hndle"><?php esc_html_e( 'Contribute or Donate!', 'header-and-footer-scripts'); ?></h3>
     26    <h3 class="hndle"><?php esc_html_e( 'Contribute!', 'header-and-footer-scripts'); ?></h3>
    2327    <div class="inside">
    24       <p><?php esc_html_e( 'Help us to make this plugin even better. Contributions not necessarily be monetary. Please follow the link to know more and contribute.', 'header-and-footer-scripts'); ?></p>
     28      <p><?php esc_html_e( 'Help us to make this plugin even better. Please follow the link to know more and contribute.', 'header-and-footer-scripts'); ?></p>
    2529      <p><a href="<?php echo esc_url( "https://github.com/anandkumar/header-and-footer-scripts" ); ?>" class="button"><?php esc_html_e( 'Contribute', 'header-and-footer-scripts'); ?></a></p>
    2630    </div>
     
    3135    <div class="inside">
    3236      <p><?php esc_html_e( 'Find this plugin useful rate it 5 stars and leave a nice little comment at wordpress.org. I would really appreciate that.', 'header-and-footer-scripts'); ?></p>
    33       <p><a href="<?php echo esc_url( "https://wordpress.org/support/plugin/header-and-footer-scripts/reviews/?filter=5#new-post" ); ?>" class="button"><?php esc_html_e( 'Rate 5 Stars', 'header-and-footer-scripts'); ?></a></p>
     37      <p><a href="<?php echo esc_url( "https://wordpress.org/support/plugin/header-and-footer-scripts/reviews/" ); ?>" class="button"><?php esc_html_e( 'Rate 5 Stars', 'header-and-footer-scripts'); ?></a></p>
    3438    </div>
    3539  </div>
     
    3842    <h3 class="hndle"><?php esc_html_e( 'Join Our Community', 'header-and-footer-scripts'); ?></h3>
    3943    <div class="inside">
    40       <p><?php esc_html_e( 'We are small WordPress community who welcomes you to join us. Here you will find and share more plugins and themes or even ideas. Ideas are not limited to WordPress. It could be vague or liberal. This is why we are "Digital Liberation .ORG', 'header-and-footer-scripts'); ?></p>
    41       <p><a href="<?php echo esc_url( "https://github.com/anandkumar/header-and-footer-scripts" ); ?>" class="button"><?php esc_html_e( 'Join Digital Liberation', 'header-and-footer-scripts'); ?></a></p>
     44      <p><?php esc_html_e( 'Join the discussions and share your ideas.', 'header-and-footer-scripts'); ?></p>
     45      <p><a href="<?php echo esc_url( "https://github.com/anandkumar/header-and-footer-scripts/discussions" ); ?>" class="button"><?php esc_html_e( 'Join Discussions', 'header-and-footer-scripts'); ?></a></p>
    4246    </div>
    4347  </div>
  • header-and-footer-scripts/trunk/readme.txt

    r3442629 r3444257  
    11=== Header and Footer Scripts ===
    22
    3 Contributors: anand_kumar
     3Contributors: anand_kumar, jamify
    44Donate link: https://github.com/anandkumar/header-and-footer-scripts
    55Tags: head, header, footer, scripts, post
    66Requires at least: 4.6
    77Tested up to: 6.9
    8 Stable tag: 2.3.0
     8Stable tag: 2.4.1
    99Requires PHP: 8.3
    1010License: GPLv2 or later
     
    7676== Changelog ==
    7777
     78= 2.4.1 =
     79* New Feature: Added "Clean on Uninstall" option to allow users to remove all data upon deletion.
     80* Fix: Resolved issue where sidebar was not loading on settings page due to deprecated constant.
     81* Improvement: Enhanced WPCS compliance with comprehensive DocBlocks and formatting fixes.
     82* Improvement: Added strict sanitization to settings authentication to resolve Plugin Check warnings.
     83
     84= 2.4.0 =
     85* Internal: Refactored codebase to "Jamify HFS" naming standards (`jamify_hfs_` prefix) while maintaining full backward compatibility.
     86* New Feature: Added support for wp_body_open hook to insert scripts immediately after body tag.
     87* New Feature: Added Syntax Highlighting for script editors in settings page.
     88* Improvement: Modernized permission system to use 'unfiltered_html' capability.
     89* Improvement: Added settings to allow Authors and Contributors to add scripts.
     90* Improvement: Added admin notice for backward compatibility migration.
     91
     92= 2.3.1 =
     93* Security: Hardened nonce implementation with static action names.
     94* Security: Added strict sanitization for access level settings.
     95* Security: Improved input validation with isset() checks and wp_unslash().
     96* Security: Replaced __FILE__ menu slug to prevent path exposure.
     97* Security: Added security warning for privilege delegation.
     98* New: Added uninstall.php for clean database removal.
     99* Fix: Added proper ABSPATH checks to all files.
     100* Improvement: Added phpcs:ignore comments for intentional raw output.
     101
    78102= 2.3.0 =
    79103* Fix: Stored Cross-Site Scripting (XSS) vulnerability.
  • header-and-footer-scripts/trunk/shfs.php

    r3442622 r3444257  
    44 * Plugin URI: https://github.com/anandkumar/header-and-footer-scripts
    55 * Description: Essential WordPress plugin for almost every website to insert codes like Javascript and CSS. Inserting script to your wp_head and wp_footer made easy.
    6  * Version: 2.2.2
     6 * Version: 2.4.1
    77 * Author: Anand Kumar
    88 * Author URI: http://www.anandkumar.net
     
    1414/*
    1515Header and Footer Scripts
    16 Copyright (C) 2013 - 2025, Anand Kumar <[email protected]>
     16Copyright (C) 2013 - 2026, Anand Kumar <[email protected]>
    1717
    1818This program is free software; you can redistribute it and/or modify
     
    3030*/
    3131
    32 define('SHFS_PLUGIN_DIR',str_replace('\\','/',dirname(__FILE__)));
     32if ( ! defined( 'ABSPATH' ) ) {
     33    exit;
     34}
     35
     36define( 'JAMIFY_HFS_PLUGIN_DIR', str_replace( '\\', '/', dirname( __FILE__ ) ) );
    3337
    3438if ( !class_exists( 'HeaderAndFooterScripts' ) ) {
     
    3640    class HeaderAndFooterScripts {
    3741
    38         function __construct() {
    39 
    40             add_action( 'init', array( &$this, 'init' ) );
    41             add_action( 'admin_init', array( &$this, 'admin_init' ) );
    42             add_action( 'admin_menu', array( &$this, 'admin_menu' ) );
    43             add_action( 'wp_head', array( &$this, 'wp_head' ), \get_option('shfs_insert_header_priority', 10) );
    44             add_action( 'wp_footer', array( &$this, 'wp_footer' ), \get_option('shfs_insert_footer_priority', 10) );
    45 
    46         }
    47 
    48         function init() {
    49 
    50             load_plugin_textdomain( 'header-and-footer-scripts', false, dirname( plugin_basename ( __FILE__ ) ).'/lang' );
    51         }
    52 
    53         function admin_init() {
     42        /**
     43         * Constructor.
     44         */
     45        public function __construct() {
     46
     47            add_action( 'init', array( $this, 'init' ) );
     48            add_action( 'admin_init', array( $this, 'admin_init' ) );
     49            add_action( 'admin_menu', array( $this, 'admin_menu' ) );
     50            add_action( 'admin_notices', array( $this, 'admin_notices' ) );
     51            add_action( 'update_option_jamify_hfs_allow_author', array( $this, 'update_role_author' ), 10, 2 );
     52            add_action( 'update_option_jamify_hfs_allow_contributor', array( $this, 'update_role_contributor' ), 10, 2 );
     53            add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
     54            add_action( 'wp_head', array( $this, 'wp_head' ), \get_option( 'jamify_hfs_insert_header_priority', 10 ) );
     55            add_action( 'wp_body_open', array( $this, 'wp_body_open' ), \get_option( 'jamify_hfs_insert_body_priority', 10 ) );
     56            add_action( 'wp_footer', array( $this, 'wp_footer' ), \get_option( 'jamify_hfs_insert_footer_priority', 10 ) );
     57
     58        }
     59
     60        /**
     61         * Load textdomain for internationalization.
     62         */
     63        public function init() {
     64
     65            load_plugin_textdomain( 'header-and-footer-scripts', false, dirname( plugin_basename( __FILE__ ) ) . '/lang' );
     66        }
     67
     68        /**
     69         * Initialize admin settings, migration logic, and meta boxes.
     70         */
     71        public function admin_init() {
     72
     73            // Migration Logic
     74            $options_to_migrate = array(
     75                'shfs_insert_header'          => 'jamify_hfs_insert_header',
     76                'shfs_insert_body'            => 'jamify_hfs_insert_body',
     77                'shfs_insert_footer'          => 'jamify_hfs_insert_footer',
     78                'shfs_insert_header_priority' => 'jamify_hfs_insert_header_priority',
     79                'shfs_insert_body_priority'   => 'jamify_hfs_insert_body_priority',
     80                'shfs_insert_footer_priority' => 'jamify_hfs_insert_footer_priority',
     81                'shfs_allow_author'           => 'jamify_hfs_allow_author',
     82                'shfs_allow_contributor'      => 'jamify_hfs_allow_contributor',
     83            );
     84
     85            foreach ( $options_to_migrate as $old => $new ) {
     86                if ( false === get_option( $new ) && false !== get_option( $old ) ) {
     87                    update_option( $new, get_option( $old ) );
     88                }
     89            }
    5490
    5591            // register settings for sitewide script
    56             register_setting( 'header-and-footer-scripts', 'shfs_insert_header', 'trim' );
    57             register_setting( 'header-and-footer-scripts', 'shfs_insert_footer', 'trim' );
    58             register_setting( 'header-and-footer-scripts', 'shfs_insert_header_priority', 'intval' );
    59             register_setting( 'header-and-footer-scripts', 'shfs_insert_footer_priority', 'intval' );
    60             register_setting( 'header-and-footer-scripts', 'shfs_script_access_level' );
     92            register_setting( 'header-and-footer-scripts', 'jamify_hfs_insert_header', 'trim' );
     93            register_setting( 'header-and-footer-scripts', 'jamify_hfs_insert_body', 'trim' );
     94            register_setting( 'header-and-footer-scripts', 'jamify_hfs_insert_footer', 'trim' );
     95            register_setting( 'header-and-footer-scripts', 'jamify_hfs_insert_header_priority', 'intval' );
     96            register_setting( 'header-and-footer-scripts', 'jamify_hfs_insert_body_priority', 'intval' );
     97            register_setting( 'header-and-footer-scripts', 'jamify_hfs_insert_footer_priority', 'intval' );
     98            register_setting( 'header-and-footer-scripts', 'jamify_hfs_allow_author', 'sanitize_text_field' );
     99            register_setting( 'header-and-footer-scripts', 'jamify_hfs_allow_contributor', 'sanitize_text_field' );
     100            register_setting( 'header-and-footer-scripts', 'jamify_hfs_clean_on_uninstall', 'sanitize_text_field' );
    61101
    62102
    63103            // add meta box to all post types
    64104            foreach ( get_post_types( '', 'names' ) as $type ) {
    65                 $access_level = get_option( 'shfs_script_access_level', 'manage_options' );
    66                 if ( current_user_can( $access_level ) ) {
    67                     add_meta_box('shfs_all_post_meta', esc_html__('Insert Script to &lt;head&gt;', 'header-and-footer-scripts'), 'shfs_meta_setup', $type, 'normal', 'high');
    68                 }
    69             }
    70 
    71             add_action('save_post','shfs_post_meta_save');
    72         }
    73 
    74         // adds menu item to wordpress admin dashboard
    75         function admin_menu() {
    76             $page = add_submenu_page( 'options-general.php', esc_html__('Header and Footer Scripts', 'header-and-footer-scripts'), esc_html__('Header and Footer Scripts', 'header-and-footer-scripts'), 'manage_options', __FILE__, array( &$this, 'shfs_options_panel' ) );
    77             }
    78 
    79         function wp_head() {
    80             $meta = get_option( 'shfs_insert_header', '' );
    81             if ( $meta != '' ) {
    82                 echo $meta, "\n";
    83             }
    84 
    85             $shfs_post_meta = get_post_meta( get_the_ID(), '_inpost_head_script' , TRUE );
    86             if ( is_singular() && $shfs_post_meta != '' ) {
    87                 echo $shfs_post_meta['synth_header_script'], "\n";
    88             }
    89 
    90         }
    91 
    92         function wp_footer() {
    93             if ( !is_admin() && !is_feed() && !is_robots() && !is_trackback() ) {
    94                 $text = get_option( 'shfs_insert_footer', '' );
     105                if ( current_user_can( 'unfiltered_html' ) ) {
     106                    add_meta_box( 'jamify_hfs_all_post_meta', esc_html__( 'Insert Script to &lt;head&gt;', 'header-and-footer-scripts' ), array( $this, 'meta_setup' ), $type, 'normal', 'high' );
     107                }
     108            }
     109
     110            add_action( 'save_post', array( $this, 'post_meta_save' ) );
     111        }
     112
     113        /**
     114         * Register the options page.
     115         */
     116        public function admin_menu() {
     117            $page = add_submenu_page( 'options-general.php', esc_html__( 'Header and Footer Scripts', 'header-and-footer-scripts' ), esc_html__( 'Header and Footer Scripts', 'header-and-footer-scripts' ), 'manage_options', 'header-and-footer-scripts', array( $this, 'jamify_hfs_options_panel' ) );
     118        }
     119
     120        /**
     121         * Enqueue admin scripts (CodeMirror).
     122         *
     123         * @param string $hook Current admin page hook.
     124         */
     125        public function admin_enqueue_scripts( $hook ) {
     126            if ( 'settings_page_header-and-footer-scripts' !== $hook && 'post.php' !== $hook && 'post-new.php' !== $hook ) {
     127                return;
     128            }
     129
     130            // Enqueue code editor for syntax highlighting
     131            $settings = wp_enqueue_code_editor( array( 'type' => 'text/html' ) );
     132
     133            // If the code editor is enabled, we need to initialize it.
     134            if ( false !== $settings ) {
     135                wp_add_inline_script(
     136                    'code-editor',
     137                    sprintf(
     138                        'jQuery( function() {
     139                            if ( jQuery("#jamify_hfs_insert_header").length ) { wp.codeEditor.initialize( "jamify_hfs_insert_header", %1$s ); }
     140                            if ( jQuery("#jamify_hfs_insert_body").length ) { wp.codeEditor.initialize( "jamify_hfs_insert_body", %1$s ); }
     141                            if ( jQuery("#jamify_hfs_insert_footer").length ) { wp.codeEditor.initialize( "jamify_hfs_insert_footer", %1$s ); }
     142                            if ( jQuery("#jamify_hfs_inpost_head_script").length ) { wp.codeEditor.initialize( "jamify_hfs_inpost_head_script", %1$s ); }
     143                        } );',
     144                        wp_json_encode( $settings )
     145                    )
     146                );
     147            }
     148        }
     149
     150        /**
     151         * Output scripts in wp_head.
     152         */
     153        public function wp_head() {
     154            $meta = get_option( 'jamify_hfs_insert_header', '' );
     155            if ( '' !== $meta ) {
     156                echo $meta, "\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
     157            }
     158
     159            $shfs_post_meta = get_post_meta( get_the_ID(), '_inpost_head_script', true );
     160            if ( is_singular() && '' !== $shfs_post_meta ) {
     161                echo $shfs_post_meta['synth_header_script'], "\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
     162            }
     163        }
     164
     165        /**
     166         * Output scripts in wp_body_open.
     167         */
     168        public function wp_body_open() {
     169            if ( ! is_admin() && ! is_feed() && ! is_robots() && ! is_trackback() ) {
     170                $meta = get_option( 'jamify_hfs_insert_body', '' );
     171                if ( '' !== $meta ) {
     172                    echo $meta, "\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
     173                }
     174            }
     175        }
     176
     177        /**
     178         * Output scripts in wp_footer.
     179         */
     180        public function wp_footer() {
     181            if ( ! is_admin() && ! is_feed() && ! is_robots() && ! is_trackback() ) {
     182                $text = get_option( 'jamify_hfs_insert_footer', '' );
    95183                $text = convert_smilies( $text );
    96184                $text = do_shortcode( $text );
    97185
    98                 if ( $text != '' ) {
    99                     echo $text, "\n";
    100                 }
    101             }
    102         }
    103 
    104         function shfs_options_panel() {
    105                 // Load options page
    106                 require_once(SHFS_PLUGIN_DIR . '/inc/options.php');
     186                if ( '' !== $text ) {
     187                    echo $text, "\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
     188                }
     189            }
     190        }
     191
     192        /**
     193         * Render the plugin options page.
     194         */
     195        public function jamify_hfs_options_panel() {
     196            // Load options page
     197            require_once JAMIFY_HFS_PLUGIN_DIR . '/inc/options.php';
     198        }
     199
     200        /**
     201         * Display admin notices (e.g. migration warning).
     202         */
     203        public function admin_notices() {
     204            // Check for previous version option to show notice
     205            if ( get_option( 'shfs_script_access_level' ) ) {
     206                $dismiss_link = add_query_arg( 'shfs_dismiss_notice', 'true' );
     207                if ( isset( $_GET['shfs_dismiss_notice'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     208                    delete_option( 'shfs_script_access_level' );
     209                } else {
     210                    ?>
     211                    <div class="notice notice-warning is-dismissible">
     212                        <p>
     213                            <?php esc_html_e( 'Header and Footer Scripts permission system has been updated. Please check the ', 'header-and-footer-scripts' ); ?>
     214                             <a href="<?php echo esc_url( admin_url( 'options-general.php?page=header-and-footer-scripts' ) ); ?>"><?php esc_html_e( 'Settings', 'header-and-footer-scripts' ); ?></a>
     215                            <?php esc_html_e( 'to configure Author/Contributor access if needed.', 'header-and-footer-scripts' ); ?>
     216                            <a href="<?php echo esc_url( $dismiss_link ); ?>" style="float:right; text-decoration:none;">X</a>
     217                        </p>
     218                    </div>
     219                    <?php
     220                }
     221            }
     222        }
     223
     224        /**
     225         * Update 'author' role capabilities when option changes.
     226         *
     227         * @param mixed $old_value Old option value.
     228         * @param mixed $new_value New option value.
     229         */
     230        public function update_role_author( $old_value, $new_value ) {
     231            $role = get_role( 'author' );
     232            if ( 'yes' === $new_value ) {
     233                $role->add_cap( 'unfiltered_html' );
     234            } else {
     235                $role->remove_cap( 'unfiltered_html' );
     236            }
     237        }
     238
     239        /**
     240         * Update 'contributor' role capabilities when option changes.
     241         *
     242         * @param mixed $old_value Old option value.
     243         * @param mixed $new_value New option value.
     244         */
     245        public function update_role_contributor( $old_value, $new_value ) {
     246            $role = get_role( 'contributor' );
     247            if ( 'yes' === $new_value ) {
     248                $role->add_cap( 'unfiltered_html' );
     249            } else {
     250                $role->remove_cap( 'unfiltered_html' );
     251            }
     252        }
     253
     254        /**
     255         * Render the post meta box.
     256         */
     257        public function meta_setup() {
     258            global $post;
     259
     260            // using an underscore, prevents the meta variable
     261            // from showing up in the custom fields section
     262            $meta = get_post_meta( $post->ID, '_inpost_head_script', true );
     263
     264            // instead of writing HTML here, lets do an include
     265            include_once JAMIFY_HFS_PLUGIN_DIR . '/inc/meta.php';
     266
     267            // create a custom nonce for submit verification later
     268            echo '<input type="hidden" name="jamify_hfs_post_meta_noncename" value="' . esc_attr( wp_create_nonce( 'jamify_hfs_post_meta_save' ) ) . '" />';
     269        }
     270
     271        /**
     272         * Save post meta data.
     273         *
     274         * @param int $post_id The ID of the post being saved.
     275         * @return int Post ID.
     276         */
     277        public function post_meta_save( $post_id ) {
     278            // authentication checks
     279
     280            // make sure data came from our meta box
     281            if ( ! isset( $_POST['jamify_hfs_post_meta_noncename'] )
     282                 || ! wp_verify_nonce( sanitize_key( $_POST['jamify_hfs_post_meta_noncename'] ), 'jamify_hfs_post_meta_save' ) ) {
     283                return $post_id;
     284            }
     285
     286            // check user permissions
     287            if ( isset( $_POST['post_type'] ) && 'page' === $_POST['post_type'] ) {
     288
     289                if ( ! current_user_can( 'edit_page', $post_id ) ) {
     290                    return $post_id;
     291                }
     292
     293            } else {
     294
     295                if ( ! current_user_can( 'edit_post', $post_id ) ) {
     296                    return $post_id;
     297                }
     298
     299            }
     300
     301            // check configured access level
     302            if ( ! current_user_can( 'unfiltered_html' ) ) {
     303                return $post_id;
     304            }
     305
     306            $current_data = get_post_meta( $post_id, '_inpost_head_script', true );
     307
     308            $new_data = isset( $_POST['_inpost_head_script'] ) ? wp_unslash( $_POST['_inpost_head_script'] ) : null; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Intentional raw input for script insertion.
     309
     310            $this->post_meta_clean( $new_data );
     311
     312            if ( $current_data ) {
     313
     314                if ( is_null( $new_data ) ) {
     315                    delete_post_meta( $post_id, '_inpost_head_script' );
     316                } else {
     317                    update_post_meta( $post_id, '_inpost_head_script', $new_data );
     318                }
     319
     320            } elseif ( ! is_null( $new_data ) ) {
     321
     322                add_post_meta( $post_id, '_inpost_head_script', $new_data, true );
     323
     324            }
     325
     326            return $post_id;
     327        }
     328
     329        /**
     330         * Clean empty values from the meta array.
     331         *
     332         * @param array $arr The array to clean.
     333         */
     334        public function post_meta_clean( &$arr ) {
     335
     336            if ( is_array( $arr ) ) {
     337
     338                foreach ( $arr as $i => $v ) {
     339
     340                    if ( is_array( $arr[ $i ] ) ) {
     341                        $this->post_meta_clean( $arr[ $i ] );
     342
     343                        if ( ! count( $arr[ $i ] ) ) {
     344                            unset( $arr[ $i ] );
     345                        }
     346
     347                    } else {
     348
     349                        if ( trim( $arr[ $i ] ) == '' ) {
     350                            unset( $arr[ $i ] );
     351                        }
     352                    }
     353                }
     354
     355                if ( ! count( $arr ) ) {
     356                    $arr = null;
     357                }
     358            }
    107359        }
    108360    }
    109361
     362    $jamify_hfs = new HeaderAndFooterScripts();
     363   
     364    // Legacy global for backward compatibility
     365    $GLOBALS['shfs_header_and_footer_scripts'] = $jamify_hfs;
     366}
     367
     368/**
     369 * Backward Compatibility Shims
     370 * These functions ensure that external code calling the old global functions
     371 * continues to work by delegating to the new class instance.
     372 */
     373
     374if ( ! function_exists( 'shfs_meta_setup' ) ) {
    110375    function shfs_meta_setup() {
    111         global $post;
    112 
    113         // using an underscore, prevents the meta variable
    114         // from showing up in the custom fields section
    115         $meta = get_post_meta($post->ID,'_inpost_head_script',TRUE);
    116 
    117         // instead of writing HTML here, lets do an include
    118         include_once(SHFS_PLUGIN_DIR . '/inc/meta.php');
    119 
    120         // create a custom nonce for submit verification later
    121         echo '<input type="hidden" name="shfs_post_meta_noncename" value="' . wp_create_nonce(__FILE__) . '" />';
     376        global $jamify_hfs;
     377        if ( isset( $jamify_hfs ) ) {
     378            $jamify_hfs->meta_setup();
     379        }
    122380    }
    123 
    124     function shfs_post_meta_save($post_id) {
    125         // authentication checks
    126 
    127         // make sure data came from our meta box
    128         if ( ! isset( $_POST['shfs_post_meta_noncename'] )
    129             || !wp_verify_nonce($_POST['shfs_post_meta_noncename'],__FILE__)) return $post_id;
    130 
    131         // check user permissions
    132         if ( $_POST['post_type'] == 'page' ) {
    133 
    134             if (!current_user_can('edit_page', $post_id))
    135                 return $post_id;
    136 
    137         } else {
    138 
    139             if (!current_user_can('edit_post', $post_id))
    140                 return $post_id;
    141 
    142         }
    143 
    144         // check configured access level
    145         $access_level = get_option( 'shfs_script_access_level', 'manage_options' );
    146         if ( ! current_user_can( $access_level ) ) {
    147             return $post_id;
    148         }
    149 
    150         $current_data = get_post_meta($post_id, '_inpost_head_script', TRUE);
    151 
    152         $new_data = $_POST['_inpost_head_script'];
    153 
    154         shfs_post_meta_clean($new_data);
    155 
    156         if ($current_data) {
    157 
    158             if (is_null($new_data)) delete_post_meta($post_id,'_inpost_head_script');
    159 
    160             else update_post_meta($post_id,'_inpost_head_script',$new_data);
    161 
    162         } elseif (!is_null($new_data)) {
    163 
    164             add_post_meta($post_id,'_inpost_head_script',$new_data,TRUE);
    165 
    166         }
    167 
     381}
     382
     383if ( ! function_exists( 'shfs_post_meta_save' ) ) {
     384    function shfs_post_meta_save( $post_id ) {
     385        global $jamify_hfs;
     386        if ( isset( $jamify_hfs ) ) {
     387            return $jamify_hfs->post_meta_save( $post_id );
     388        }
    168389        return $post_id;
    169390    }
    170 
    171     function shfs_post_meta_clean(&$arr) {
    172 
    173         if (is_array($arr)) {
    174 
    175             foreach ($arr as $i => $v) {
    176 
    177                 if (is_array($arr[$i])) {
    178                     shfs_post_meta_clean($arr[$i]);
    179 
    180                     if (!count($arr[$i])) {
    181                         unset($arr[$i]);
    182                     }
    183 
    184                 } else {
    185 
    186                     if (trim($arr[$i]) == '') {
    187                         unset($arr[$i]);
    188                     }
    189                 }
    190             }
    191 
    192             if (!count($arr)) {
    193                 $arr = NULL;
    194             }
     391}
     392
     393if ( ! function_exists( 'shfs_post_meta_clean' ) ) {
     394    function shfs_post_meta_clean( &$arr ) {
     395        global $jamify_hfs;
     396        if ( isset( $jamify_hfs ) ) {
     397            $jamify_hfs->post_meta_clean( $arr );
    195398        }
    196399    }
    197 
    198     $shfs_header_and_footer_scripts = new HeaderAndFooterScripts();
    199400}
Note: See TracChangeset for help on using the changeset viewer.