# double-opt-in/3.0.2/core/UI.class.php

Double Opt-In for Contact Form 7 – Secure, GDPR-Compliant Email Verification, version 3.0.2. 363 lines.

- Page: https://pluginprobe.com/plugins/double-opt-in/3.0.2/code/core/UI.class.php
- Raw: https://pluginprobe.com/plugins/double-opt-in/3.0.2/raw/core/UI.class.php
- Modified: 2024-08-13T13:52:36+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/double-opt-in/3.0.2/code/core/UI.class.php#L10-L20`.

```php
<?php

namespace forge12\contactform7\CF7DoubleOptIn {
	if ( ! defined( 'ABSPATH' ) ) {
		exit;
	}
	/**
	 * dependencies
	 */
	require_once( 'UIMenu.class.php' );

	/**
	 * Class UI
	 *
	 * @package forge12\ui
	 */
	class UI {
		/**
		 * @var UI
		 */
		private static $instance = null;

		/**
		 * @var string
		 */
		private $slug = '';
		/**
		 * @var string
		 */
		private $title = '';
		/**
		 * @var string
		 */
		private $capabilities;
		/**
		 * Store all Pages
		 *
		 * @var array<UIPage>
		 */
		private $pages;
		/**
		 * Components
		 */
		private $components = [];
		/**
		 * @var TemplateHandler
		 */
		private TemplateHandler $templateHandler;

		/**
		 * @param        $slug
		 * @param string $title
		 * @param string $capabilities
		 *
		 * @return UI
		 * @deprecated
		 * @deprecated
		 */
		public static function getInstance( $slug, $title = 'Dashboard', $capabilities = 'manage_options' ) {
			if ( null == self::$instance ) {
				self::$instance = new UI( $slug, $title, $capabilities );
			}

			return self::$instance;
		}

		/**
		 * Add a Page to the UI
		 *
		 * @param $UIPage
		 *
		 * @return void
		 */
		public function addPage( $UIPage ) {
			$this->pages[] = $UIPage;

			add_action( 'forge12-plugin-content-' . $this->slug, array( $UIPage, 'renderContent' ), 10, 2 );
			add_action( 'forge12-plugin-sidebar-' . $this->slug, array( $UIPage, 'renderSidebar' ), 10, 2 );
		}

		/**
		 * @return array<UIPage>
		 */
		private function getPages() {
			return $this->pages;
		}

		/**
		 * @param $slug
		 *
		 * @return UIPage|null
		 */
		private function get( $slug ) {
			foreach ( $this->pages as $UIPage ) {
				if ( $UIPage->getSlug() == $slug ) {
					return $UIPage;
				}
			}

			return null;
		}

		/**
		 * UI constructor.
		 *
		 * @param $slug
		 */
		public function __construct( TemplateHandler $templateHandler, string $slug, string $title, string $capabilities ) {
			$this->templateHandler = $templateHandler;
			$this->slug            = $slug;
			$this->title           = $title;
			$this->capabilities    = $capabilities;

			$this->loadComponents();

			// Add Assets
			add_action( 'admin_enqueue_scripts', array( $this, 'addAssets' ) );

			// Load Components after the Pages have been initialized
			add_action( 'f12_cf7_doubleoptin_ui_after_load_pages', array( $this, 'registerComponents' ), 999999990, 2 );

			// Sort Pages after intialize
			add_action( 'f12_cf7_doubleoptin_ui_after_load_pages', array( $this, 'sortComponents' ), 999999999, 2 );

			// Called after all Pages have been initialized
			do_action( 'f12_cf7_doubleoptin_ui_after_load_pages', $this, $this->slug );

			// Create the Submenus
			add_action( 'admin_menu', array( $this, 'addSubmenuPagesToWordPress' ) );

			// Hotfix to hide the submenus that should be hidden but still callable in wordpress backend
			add_action( 'admin_head', array( $this, 'hideSubmenuPagesToWordpress' ) );
		}

		public function addAssets() {
			/**
			 * Stylesheets for the admin panel
			 */
			wp_enqueue_style( 'f12-cf7-doubleoptin-admin', plugins_url( 'assets/admin-style.css', __FILE__ ), array(), '1.3' );

			/**
			 * Toggle Button
			 */
			wp_enqueue_script( 'f12-cf7-doubleoptin-toggle', plugins_url( 'assets/toggle.js', __FILE__ ), array( 'jquery' ), '1.0' );

			/**
			 * Copy to clipboard
			 */
			wp_enqueue_script( 'f12-cf7-doubleoptin-copy', plugins_url( 'assets/copy-to-clipboard.js', __FILE__ ), array( 'jquery' ), '1.0' );

			/**
			 * External vendor scripts
			 */
			wp_enqueue_script( 'vendor-highlight', plugins_url( 'assets/vendor/highlight/highlight.min.js', __FILE__ ), array( 'jquery' ), '1.0' );
			wp_enqueue_style( 'vendor-highlight', plugins_url( 'assets/vendor/highlight/default.min.css', __FILE__ ), array(), '1.0' );
		}

		public function sortComponents( $UI, $domain ) {
			if ( ! empty( $this->pages ) ) {
				usort( $this->pages, function ( $a, $b ) {
					if ( $a->getPosition() < $b->getPosition() ) {
						return - 1;
					} else if ( $a->getPosition() > $b->getPosition() ) {
						return 1;
					} else {
						return 0;
					}
				} );
			}
		}

		/**
		 * @param UI $UI
		 * @param    $domain
		 *
		 * @return void
		 */
		public function registerComponents( $UI, $domain ) {
			/**
			 * Load all registered components
			 */
			foreach ( $this->components as $component ) {
				/**
				 * Check if the path has been defined
				 */
				if ( ! isset( $component['path'] ) ) {
					continue;
				}

				/**
				 * Check if the name has been defined
				 */
				if ( ! isset( $component['name'] ) ) {
					continue;
				}

				/**
				 * Load the file
				 */
				require_once( $component['path'] );

				/**
				 * Load the instance of the object
				 */
				$UIPage = new $component['name']( $this->templateHandler, $domain );

				/**
				 * Add the page to the user interface in the backend of wordpress.
				 */
				$UI->addPage( $UIPage );
			}
		}

		private function addComponent( $name, $path ) {
			$this->components[] = array(
				'name' => $name,
				'path' => $path
			);
		}

		/**
		 * Retrieves the directories where the components are located.
		 *
		 * This method is responsible for retrieving the directories where the components
		 * for the current application are located. It uses the 'f12_cf7_doubleoption_ui_get_component_directories'
		 * filter to allow customization of the directories. By default, it returns an array
		 * containing the 'ui' directory located two levels above the current file's directory.
		 *
		 * @return array An array containing the directories where the components are located.
		 */
		private function get_component_directories() {
			/**
			 * Component Directories
			 *
			 * This filter allows developers to add custom ui directories which will be used to display ui pages.
			 *
			 * @param array $directories
			 *
			 * @since 3.0.0
			 */
			return apply_filters( 'f12_cf7_doubleoption_ui_get_component_directories', [ dirname( __FILE__, 2 ) . '/ui' ] );
		}

		/**
		 * Load all components from the 'ui' directory.
		 *
		 * @return void
		 */
		private function loadComponents() {
			$directories = $this->get_component_directories();

			foreach ( $directories as $directory ) {
				if ( is_dir( $directory ) ) {
					$handle = opendir( $directory );

					if ( ! $handle ) {
						return;
					}

					while ( false !== ( $entry = readdir( $handle ) ) ) {
						if ( $entry != '.' && $entry != '..' ) {
							if ( preg_match( '!UI([a-zA-Z_0-9]+)\.class\.php!', $entry, $matches ) ) {
								if ( isset( $matches[1] ) ) {
									$this->addComponent( '\\' . __NAMESPACE__ . '\UI' . $matches[1], $directory . '/' . $entry );
								}
							}
						}
					}
					closedir( $handle );
				}
			}
		}

		/**
		 * Add the WordPress Page for the Settings to the WordPress CMS
		 *
		 * @private WordPress Hook
		 */
		public function addSubmenuPagesToWordPress() {
			$icon_url = plugins_url( 'assets/icon-double-opt-in-20x20.png', dirname( __FILE__ ) );
			add_menu_page( $this->title, $this->title, $this->capabilities, $this->slug, '', $icon_url );

			foreach ( $this->getPages() as /** @var UIPage $Page */ $Page ) {
				if ( $Page->isDashboard() ) {
					$slug = $this->slug;
				} else {
					$slug = $this->slug . '_' . $Page->getSlug();
				}

				add_submenu_page( $this->slug, $Page->getTitle(), $Page->getTitle(), $this->capabilities, $slug, function () {
					$this->render();
				}, $Page->getPosition() );
			}
		}

		/**
		 * This will ensure that the menu page will be removed before the rendering.
		 * This needs to be called from add_action('admin_head', ''); to be working.
		 *
		 * @return void
		 */
		public function hideSubmenuPagesToWordpress() {
			foreach ( $this->getPages() as /** @var UIPage $Page */ $Page ) {
				if ( ! $Page->hideInMenu() ) {
					continue;
				}

				if ( $Page->isDashboard() ) {
					$slug = $this->slug;
				} else {
					$slug = $this->slug . '_' . $Page->getSlug();
				}

				remove_submenu_page( $this->slug, $slug );
			}
		}

		public function render() {
			$page = sanitize_text_field( $_GET['page'] );
			$page = substr( explode( $this->slug, $page )[1], 1 );

			if ( empty( $page ) ) {
				$page = $this->slug;
			}

			$pages     = $this->getPages();
			$menuPages = array();

			foreach ( $pages as $UIPage ) {
				if ( ! $UIPage->hideInMenu() ) {
					$menuPages[] = $UIPage;
				}
			}
			?>
            <div class="forge12-plugin <?php esc_attr_e( $this->slug ); ?>">
                <div class="forge12-plugin-header">
                    <div class="forge12-plugin-header-inner">
                        <img src="<?php echo esc_url( plugin_dir_url( __FILE__ ) ); ?>/assets/logo-forge12.png"
                             alt="Forge12 Interactvie GmbH" title="Forge12 Interactive GmbH"/>
                    </div>
                </div>
                <div class="forge12-plugin-menu">
					<?php do_action( 'f12_cf7_doubleoptin_admin_menu', $menuPages, $page, $this->slug ); ?>
                </div>
                <div class="forge12-plugin-content">
                    <div class="forge12-plugin-content-main">
						<?php do_action( 'forge12-plugin-content-' . $this->slug, $this->slug, $page ) ?>
                    </div>
                    <div class="forge12-plugin-content-sidebar">
						<?php do_action( 'forge12-plugin-sidebar-' . $this->slug, $this->slug, $page ) ?>
                    </div>
                </div>
                <div class="forge12-plugin-footer">
                    <div class="forge12-plugin-footer-inner">
                        <img src="<?php echo esc_url( plugin_dir_url( __FILE__ ) ); ?>/assets/logo-forge12-dark.png"
                             alt="Forge12 Interactvie GmbH" title="Forge12 Interactive GmbH"/>
                    </div>
                </div>
            </div>
			<?php
		}
	}
}
```
