JezK
Edit File: PopupChecker.php
<?php namespace sgpb; use \DateTime; use \DateTimeZone; use \SGPBConfigDataHelper; /** * Popup checker class to check if the popup must be loaded on the current page * * @since 1.0.0 * */ class PopupChecker { private static $instance; private $popup; private $isGeoAjaxModeEnabled; private $post; private $isAjaxCall; public static function instance() { if (!isset(self::$instance)) { self::$instance = new self; } return self::$instance; } public function setPopup($popup) { $this->popup = $popup; } public function getPopup() { return $this->popup; } public function setPost($post) { $this->post = $post; } public function getPost() { return $this->post; } public function setPopupGeoAjaxModeActive($ajaxMode) { $this->isGeoAjaxModeEnabled = $ajaxMode; } public function getPopupGeoAjaxMode() { return $this->isGeoAjaxModeEnabled; } public function setIsAjaxCall($isAjax) { $this->isAjaxCall = $isAjax; } public function getIsAjaxCall() { return $this->isAjaxCall; } /** * It checks whether popup should be loaded on the current page. * * @since 1.0.0 * * @param int $popupId popup id * @param object $post page post data * @param boolean $isAjax * * @return bool * */ public function isLoadable($popup, $post, $isAjax = false) { $this->setPopup($popup); $this->setPost($post); $this->setPopupGeoAjaxModeActive($popup->getOptionValue('sgpb-enable-geo-ajax-mode')); $this->setIsAjaxCall($isAjax); $popupOptions = $popup->getOptions(); $isActive = $popup->getOptionValue('sgpb-is-active', true); $saveMode = $popup->getSaveMode(); $allowToLoad = $this->allowToLoad(); if ($saveMode) { $allowToLoad['option_event'] = false; return $allowToLoad; } if (isset($popupOptions['sgpb-is-active'])) { $isActive = $popupOptions['sgpb-is-active']; if ($isActive) { $popup->setReportData($popup->getId()); } } if (!$isActive) { $allowToLoad['option_event'] = false; } return $allowToLoad; } /** * Decides whether popup data should be loaded or not * * @since 1.0.0 * * @return array * */ private function allowToLoad() { $isCustomInserted = $this->isCustomInserted(); $insertedModes = array( 'attr_event' => false, 'option_event' => false ); if ($isCustomInserted) { $insertedModes['attr_event'] = true; } $target = $this->divideTargetData(); $isPostInForbidden = $this->isPostInForbidden($target); if ($isPostInForbidden) { return $insertedModes; } if (!empty($target['forbidden']) && empty($target['permissive'])) { $conditions = $this->divideConditionsData(); $conditions = apply_filters('sgpbFilterDividedConditions', $conditions); $isSatisfyForConditions = $this->isSatisfyForConditions($conditions); if ($isSatisfyForConditions === false) { return $insertedModes; } if ($this->isSatisfyForOtherConditions() === false) { return $insertedModes; } $insertedModes['option_event'] = true; } $isPermissive = $this->isPermissive($target); //If permissive for current page check conditions if ($isPermissive) { $conditions = $this->divideConditionsData(); $conditions = apply_filters('sgpbFilterDividedConditions', $conditions); $isSatisfyForConditions = $this->isSatisfyForConditions($conditions); if ($isSatisfyForConditions === false) { return $insertedModes; } if ($this->isSatisfyForOtherConditions() === false) { return $insertedModes; } $insertedModes['option_event'] = $isPermissive; } return $insertedModes; } /** * check is Satisfy popup conditions * * @since 1.0.0 * * @param array $conditions assoc array * * @return bool * */ private function isSatisfyForConditions($conditions) { // proStartSilver // this case when selected IS NOT operator $forbiddenConditions = $conditions['forbidden']; if (!empty($forbiddenConditions)) { if (!$this->getIsAjaxCall() && $this->getPopupGeoAjaxMode()) { return false; } foreach ($forbiddenConditions as $forbiddenCondition) { $isForbiddenConditions = $this->isSatisfyForConditionsOptions($forbiddenCondition); if ($isForbiddenConditions) { return false; } else { return true; } } } // this case when selected IS operator $permissiveOptions = $conditions['permissive']; if (!empty($permissiveOptions)) { if (!$this->getIsAjaxCall() && $this->getPopupGeoAjaxMode()) { return false; } foreach ($permissiveOptions as $permissiveOption) { $isPermissiveConditions = $this->isSatisfyForConditionsOptions($permissiveOption); return $isPermissiveConditions; } } if ($this->getIsAjaxCall() && $this->getPopupGeoAjaxMode()) { return false; } return true; } private function isSatisfyForConditionsOptions($option) { global $post; $paramName = $option['param']; $defaultStatus = false; $isAllowedConditionFilters = array(); if ($paramName == 'select_role') { return true; } if (!$defaultStatus && do_action('isAllowedForConditions', $option, $post)) { $defaultStatus = true; } $isAllowedConditionFilters = apply_filters('isAllowedConditionFilters', array($option)); if (isset($isAllowedConditionFilters['status']) && $isAllowedConditionFilters['status'] === true) { $defaultStatus = true; } return $defaultStatus; } /** * Check is popup inserted via short code or class attribute * * @since 1.0.0 * * @param * * @return bool * */ private function isCustomInserted() { $customInsertData = $this->getCustomInsertedData(); $popup = $this->getPopup(); // When popup object is empty it's mean popup is not custom inserted if (empty($popup)) { return false; } $popupId = $popup->getId(); return in_array($popupId, $customInsertData); } /** * Should load data in the current page * * @since 1.0.0 * * @param array $target popup saved target data * * @return bool $isPermissive true => allow false => don't allow * */ private function isPermissive($target) { $isPermissive = false; if (empty($target['permissive'])) { $isPermissive = false; return $isPermissive; } foreach ($target['permissive'] as $targetData) { if ($this->isSatisfyForParam($targetData)) { $isPermissive = true; break; } } return $isPermissive; } /** * Check whether the target data disallows loading the popup data on the current page * * @since 1.0.0 * * @param array $target popup saved target data * * @return bool $isForbidden true => don't allow false => allow * */ private function isPostInForbidden($target) { $isForbidden = false; if (empty($target['forbidden'])) { return $isForbidden; } foreach ($target['forbidden'] as $targetData) { if ($this->isSatisfyForParam($targetData)) { $isForbidden = true; break; } } return $isForbidden; } /** * Check whether the current page is corresponding to the saved target data * * @since 1.0.0 * * @param array $targetData popup saved target data * * @return bool $isSatisfy * */ private function isSatisfyForParam($targetData) { $isSatisfy = false; if ($this->getIsAjaxCall()){ $popup = $this->getPopup(); $postId = $popup->getCurrentPageIdForAjax(); } else { $postId = get_queried_object_id(); } if (empty($targetData['param'])) { return $isSatisfy; } $targetParam = $targetData['param']; $post = $this->getPost(); if (isset($post) && empty($postId)) { $postId = $post->ID; } if ($targetParam == 'everywhere') { return true; } if (strpos($targetData['param'], '_all')) { $endIndex = strpos($targetData['param'], '_all'); $postType = substr($targetData['param'], 0, $endIndex); $currentPostType = get_post_type($postId); if ($postType == $currentPostType) { $isSatisfy = true; } } else if (strpos($targetData['param'], '_archive')) { $currentPostType = get_post_type(); if ($targetData['param'] == $currentPostType.'_archive') { if (is_post_type_archive($currentPostType)) { $isSatisfy = true; } } } else if (strpos($targetData['param'], '_selected')) { $values = array(); if (!empty($targetData['value'])) { $values = array_keys($targetData['value']); } if (in_array($postId, $values)) { $isSatisfy = true; } } else if (strpos($targetData['param'], '_categories')) { $values = array(); $isSatisfy = false; if (!empty($targetData['value'])) { $values = array_values($targetData['value']); } global $post; // get current all taxonomies of the current post $taxonomies = get_post_taxonomies($post); foreach ($taxonomies as $taxonomy) { // get current post all categories $terms = get_the_terms($post->ID, $taxonomy); if (!empty($terms)) { foreach ($terms as $term) { if (empty($term)) { continue; } if (in_array($term->term_id, $values)) { $isSatisfy = true; break; } } } } } else if ($targetData['param'] == 'post_type' && !empty($targetData['value'])) { $selectedCustomPostTypes = array_values($targetData['value']); $currentPostType = get_post_type($postId); if (in_array($currentPostType, $selectedCustomPostTypes)) { $isSatisfy = true; } } else if ($targetData['param'] == 'post_category' && !empty($targetData['value'])) { $values = $targetData['value']; $currentPostCategories = get_the_category($postId); $currentPostType = get_post_type($postId); if (empty($currentPostCategories) && $currentPostType == 'product') { $currentPostCategories = get_the_terms($postId, 'product_cat'); } foreach ($currentPostCategories as $categoryName) { if (in_array($categoryName->term_id, $values) || in_array($categoryName->term_id, array_keys($values))) { $isSatisfy = true; break; } } } else if ($targetData['param'] == 'page_type' && !empty($targetData['value'])) { $postTypes = $targetData['value']; foreach ($postTypes as $postType) { if ($postType == 'is_home_page') { if (is_front_page() && is_home()) { // Default homepage $isSatisfy = true; break; } else if ( is_front_page() ) { // static homepage $isSatisfy = true; break; } } else if (function_exists($postType) && $postType()) { $isSatisfy = true; break; } } } else if ($targetData['param'] == 'page_template' && !empty($targetData['value'])) { $currentPageTemplate = get_page_template_slug(); // Fallback to default page template if ( empty( $currentPageTemplate ) ) { $currentPageTemplate = 'page.php'; } else { $currentPageTemplate = basename( $currentPageTemplate ); } if (in_array($currentPageTemplate, $targetData['value'])) { $isSatisfy = true; } } else if ($targetData['param'] == 'post_tags') { if (has_tag()) { $isSatisfy = true; } } else if ($targetData['param'] == 'post_tags_ids') { $tagsObj = wp_get_post_tags($postId); $postTagsValues = isset($targetData['value']) ? (array)$targetData['value'] : array(); $selectedTags = array_values($postTagsValues); foreach ($tagsObj as $tagObj) { if (in_array($tagObj->slug, $selectedTags) || in_array($tagObj->slug, array_keys($postTagsValues))) { $isSatisfy = true; break; } } } if (!$isSatisfy && apply_filters('isAllowedForTarget', false, $targetData, $post) ) { $isSatisfy = true; } return $isSatisfy; } /** * Divide conditions data to Permissive and Forbidden * * @since 1.0.0 * * @return array $popupTargetData * */ private function divideConditionsData() { $popup = $this->getPopup(); $conditions = $popup->getConditions(); $conditions = $this->divideIntoPermissiveAndForbidden($conditions); return $conditions; } /** * Divide target data to Permissive and Forbidden * * @since 1.0.0 * * @return array $popupTargetData * */ public function divideTargetData() { $popup = $this->getPopup(); $targetData = $popup->getTarget(); return $this->divideIntoPermissiveAndForbidden($targetData); } /** * Divide the Popup target data into Permissive And Forbidden assoc array * * @since 1.0.0 * * @param array $postMetaData popup saved target data * * @return array $postMetaDivideData * */ public function divideIntoPermissiveAndForbidden($targetData) { $permissive = array(); $forbidden = array(); $permissiveOperators = array('=='); $forbiddenOperators = array('!='); $permissiveOperators = apply_filters('sgpbAdditionalPermissiveOperators', $permissiveOperators); $forbiddenOperators = apply_filters('sgpbAdditionalForbiddenOperators', $forbiddenOperators); if (!empty($targetData)) { foreach ($targetData as $data) { if (empty($data['operator']) && $data['param'] != 'everywhere' && !strpos($data['param'], '_all') && $data['param'] != 'post_tags') { break; } // set by default '==' (is) value for all not specific conditions like all pages/posts/other_custom_post_types for future correct detection if ($data['param'] == 'everywhere' || strpos($data['param'], '_all') || $data['param'] == 'post_tags') { $data['operator'] = '=='; } if ((isset($data['operator']) && in_array($data['operator'], $permissiveOperators))) { $permissive[] = $data; } else if (in_array($data['operator'], $forbiddenOperators)) { $forbidden[] = $data; } } } $postMetaDivideData = array( 'permissive' => $permissive, 'forbidden' => $forbidden ); return $postMetaDivideData; } /** * Get custom inserted data * * @since 1.0.0 * * @return array $insertedData */ public function getCustomInsertedData() { $post = $this->getPost(); $insertedData = array(); if (isset($post)) { $insertedData = SGPopup::getCustomInsertedDataByPostId($this->getPost()->ID); } return $insertedData; } /** * Check Popup conditions * * @since 1.0.0 * * @return array * */ private function isSatisfyForOtherConditions() { $popup = $this->getPopup(); $popupOptions = $popup->getOptions(); $popupId = $popup->getId(); $dontAlowOpenPopup = apply_filters('sgpbOtherConditions', array('id' => $popupId, 'popupOptions' => $popupOptions, 'popupObj' => $popup)); return $dontAlowOpenPopup['status']; } public static function checkUserStatus($savedStatus) { $equalStatus = true; /*When current user status and saved options does not matched popup must not open*/ if (is_user_logged_in() != (int)$savedStatus) { $equalStatus = false; } return $equalStatus; } /** * Whether WPML (SitePress) is active. * * @return bool */ public static function isWpmlActive() { return defined('ICL_SITEPRESS_VERSION') || defined('ICL_PLUGIN_PATH') || function_exists('wpml_get_current_language') || class_exists('\SitePress', false); } /** * WPML: language code assigned to a post (popup or page). * Uses element API first — wpml_get_language_information() often fails for CPT popupbuilder. * * @param int $postId Post ID. * @return string Language code (e.g. fr, en) or empty if unknown / WPML inactive. */ public static function getWpmlLanguageCodeForPost($postId) { $postId = (int) $postId; if ($postId <= 0 || !self::isWpmlActive()) { return ''; } $postType = get_post_type($postId); if (empty($postType)) { return ''; } $elementType = 'post_' . $postType; $lang = apply_filters('wpml_element_language_code', null, array( 'element_id' => $postId, 'element_type' => $elementType, )); if (!empty($lang) && is_string($lang)) { return $lang; } if (function_exists('wpml_get_language_information')) { $info = wpml_get_language_information($postId); if (!is_wp_error($info) && !empty($info['language_code'])) { return $info['language_code']; } } $details = apply_filters('wpml_post_language_details', null, $postId); if (is_array($details) && !empty($details['language_code'])) { return $details['language_code']; } return ''; } /** * WPML: active language for the current request (domains, directories, default URL). * * @return string Language code or empty. */ public static function getWpmlCurrentRequestLanguageCode() { if (!self::isWpmlActive()) { return ''; } if (function_exists('wpml_get_current_language')) { $lang = wpml_get_current_language(); if (!empty($lang) && is_string($lang)) { return $lang; } } global $sitepress; if (is_object($sitepress) && method_exists($sitepress, 'get_current_language')) { $lang = $sitepress->get_current_language(); if (!empty($lang) && is_string($lang)) { return $lang; } } $lang = apply_filters('wpml_current_language', null); if (!empty($lang) && is_string($lang)) { return $lang; } global $post; if (!empty($post) && !empty($post->ID)) { return self::getWpmlLanguageCodeForPost($post->ID); } return ''; } /** * When sgpb-icl_post_language is not set, match popup visibility to the popup post's WPML language * so only the FR popup shows on FR pages and the EN popup on EN pages. * * @param int $popupPostId Popup post ID. * @return bool True = allow load, false = block. */ public static function shouldLoadPopupForWpmlAutoLanguage($popupPostId) { if (!self::isWpmlActive()) { return true; } $popupLang = self::getWpmlLanguageCodeForPost($popupPostId); if ($popupLang === '') { if (apply_filters('sgpb_wpml_strict_popup_language', false, $popupPostId)) { return false; } return true; } $currentLang = self::getWpmlCurrentRequestLanguageCode(); if ($currentLang === '' || $currentLang === null) { return true; } return (strtolower($popupLang) === strtolower($currentLang)); } /** * Single gate for WPML vs popup (explicit icl option or auto match by post language). * * @param int $popupPostId Popup post ID. * @param array $popupOptions Popup options (meta). * @return bool True = allow load. */ public static function wpmlAllowsPopupFrontendLoad($popupPostId, $popupOptions, $filterArgs = null) { if (!self::isWpmlActive()) { return true; } $popupPostId = (int) $popupPostId; if (!empty($popupOptions['sgpb-icl_post_language'])) { return self::checkLanguage($popupOptions['sgpb-icl_post_language']); } $args = is_array($filterArgs) ? $filterArgs : array( 'id' => $popupPostId, 'popupOptions' => $popupOptions, ); if (!apply_filters('sgpb_enable_wpml_auto_popup_language_match', true, $args)) { return true; } return self::shouldLoadPopupForWpmlAutoLanguage($popupPostId); } public static function checkLanguage($popupLanguage = '') { global $post; if (!self::isWpmlActive()) { return true; } $postLanguageCode = ''; if (!empty($post) && !empty($post->ID)) { $postLanguageCode = self::getWpmlLanguageCodeForPost($post->ID); } if ($postLanguageCode === '') { $postLanguageCode = self::getWpmlCurrentRequestLanguageCode(); } if ($postLanguageCode === '' || $postLanguageCode === null) { return true; } if (!empty($_GET['lang']) && (sanitize_text_field(wp_unslash($_GET['lang'])) == $popupLanguage)) { return true; } if (strtolower($postLanguageCode) != strtolower($popupLanguage)) { return false; } return true; } public static function checkOtherConditionsActions($args) { if (empty($args['id']) || empty($args['popupOptions'])) { return false; } $popupOptions = $args['popupOptions']; if (!self::wpmlAllowsPopupFrontendLoad((int) $args['id'], $popupOptions, $args)) { return false; } // proStartSilver //User status check if (!empty($popupOptions['sgpb-user-status'])) { $restrictUserStatus = PopupChecker::checkUserStatus($popupOptions['sgpb-loggedin-user']); if ($restrictUserStatus === false) { return $restrictUserStatus; } } // proEndSilver // proStartPlatinum // proEndPlatinum // checking by popup type if (!empty($popupOptions['sgpb-type'])) { $popupClassName = SGPopup::getPopupClassNameFormType($popupOptions['sgpb-type']); $popupClassName = __NAMESPACE__.'\\'.$popupClassName; if (method_exists($popupClassName, 'allowToOpen')) { $allowToOpen = $popupClassName::allowToOpen($popupOptions, $args); return $allowToOpen; } } return apply_filters('checkOtherConditions', true); } }