get_option('opanda_facebook_app_id'), 'lang' => get_option('opanda_lang', 'en_US') ); wp_localize_script( 'opanda-lockers', 'facebookSDK', $facebookSDK ); do_action('opanda_connect_locker_assets'); } /** * Prints variables required for the locker script. */ public static function printLockerScriptVars() { $resToPrint = array(); foreach( self::$_requestedTextRes as $res ) { $value = get_option('opanda_res_' . $res, false ); if ( false === $value ) continue; $resToPrint[$res] = $value; } wp_localize_script( 'opanda-lockers', '__pandalockers', array( 'lang' => $resToPrint, 'postId' => get_the_ID(), 'visibility' => self::$_definedVisibilityVars, 'managedInitHook' => get_option('opanda_managed_hook', false) )); } /** * Prints a script that creates lockers. * * @since 1.0.0 * @return void */ public static function printLockerCreatorScript() { do_action('opanda_before_locker_creator_script'); $args = array(); $args[opanda_get_robust_key()] = opanda_get_robust_script_key(); $robustLoader = add_query_arg($args, site_url() ); ?> $id) { if ( self::autoUnlock( $id ) ) continue; $lockData = self::getLockerDataToPrint( $id ); $data[$id] = array( 'name' => $name, 'options' => $lockData ); } ?> $item ) { ?> self::getLockerOption($id, 'always', false, false), 'actualUrls' => get_option('opanda_actual_urls', false), 'text' => array( 'header' => self::getLockerOption($id, 'header'), 'message' => self::getLockerOption($id, 'message') ), 'theme' => self::getLockerOption($id, 'style'), 'lang' => get_option('opanda_lang', 'en_US'), 'agreement' => array( 'checkbox' => self::getLockerOption($id, 'agreement_checkbox_position'), 'note' => self::getLockerOption($id, 'agreement_note'), 'termsUrl' => opanda_terms_url(), 'privacyPolicyUrl' => opanda_privacy_policy_url(), 'showInPopup' => !get_option('opanda_terms_use_pages', false) ? array( 'width' => 570, 'height' => 400 ) : false ), 'overlap' => array( 'mode' => self::getLockerOption($id, 'overlap', false, 'full'), 'position' => self::getLockerOption($id, 'overlap_position', false, 'middle'), 'altMode' => get_option('opanda_alt_overlap_mode', 'transparence') ), 'highlight' => self::getLockerOption($id, 'highlight'), 'googleAnalytics' => get_option('opanda_google_analytics', 1), 'locker' => array( 'scope' => $hasScope ? 'global' : '', 'counter' => self::getLockerOption($id, 'show_counters', false, 1), 'loadingTimeout' => get_option('opanda_timeout', 20000), 'tumbler' => get_option('opanda_tumbler', false), 'naMode' => get_option('opanda_na_mode', 'show-error'), 'inAppBrowsers' => get_option( 'opanda_in_app_browsers', 'visible_with_warning'), 'inAppBrowsersWarning' => get_option( 'opanda_in_app_browsers_warning', __( 'You are viewing this page in the {browser}. The locker may work incorrectly in this browser. Please open this page in a standard browser.', 'bizpanda' )) ) ); $visibilityMode = self::getLockerOption($id, 'visibility_mode', false, 'simple'); $params['locker']['close'] = self::getLockerOption($id, 'close'); $params['locker']['timer'] = self::getLockerOption($id, 'timer'); $params['locker']['delay'] = self::getLockerOption($id, 'delay'); if ( 'simple' === $visibilityMode ) { $params['locker']['mobile'] = self::getLockerOption($id, 'mobile'); $params['locker']['expires'] = self::getLockerOption($id, 'relock_interval_in_seconds', false, false); } if ( 'advanced' === $visibilityMode ) { $visabilityConditions = self::getLockerOption($id, 'visibility_filters'); if ( !empty( $visabilityConditions ) ) $visabilityConditions = json_decode($visabilityConditions); $params['locker']['visibility'] = $visabilityConditions; } $params['proxy'] = [ 'consumer' => [ 'company' => [ 'title' => get_bloginfo('name'), 'url' => home_url() ], 'privacyPolicy' => [ 'title' => get_option('opanda_res_misc_privacy_policy', __('Privacy Policy', 'bizpanda') ), 'url' => opanda_privacy_policy_url( true ) ] ] ]; // by default uses the social locker apps to perform social actions $params['socialProxy'] = [ 'endpoint' => opanda_remote_social_proxy_url() ]; // but all the data have to be saved locally $params['actionsProxy'] = [ 'url' => opanda_local_proxy_url(), 'paramPrefix' => 'opanda' ]; // - Replaces shortcodes in the locker message global $post; $postTitle = $post != null ? $post->post_title : ''; $postUrl = $post != null ? get_permalink($post->ID) : ''; if ( !empty( $params['text']['message'] ) ) { $params['text']['message'] = str_replace('[post_title]', $postTitle, $params['text']['message']); $params['text']['message'] = str_replace('[post_url]', $postUrl, $params['text']['message']); } return $params; } /** * Returns data to print. */ public static function getLockerDataToPrint( $id, $lockData = array() ) { global $post; $lockData['lockerId'] = $id; // options for tracking $lockData['tracking'] = get_option('opanda_tracking', true); $lockData['postId'] = !empty($post) ? $post->ID : false; $lockData['ajaxUrl'] = admin_url( 'admin-ajax.php' ); // the pande item option $baseOptions = self::getBaseOptions( $id ); $itemType = OPanda_Items::getItemNameById( $id ); $options = apply_filters("opanda_{$itemType}_item_options", $baseOptions, $id ); $options = apply_filters("opanda_item_options", $options, $id ); // normilize options self::_normilizeLockerOptions( $options ); if ( !isset($options['text']['header']) ) $options['text']['header'] = ''; if ( !isset($options['text']['message']) ) $options['text']['message'] = ''; $lockData['options'] = $options; $lockData['_theme'] = self::getLockerOption($id, 'style' ); $lockData['_style'] = self::getLockerOption($id, 'style_profile' ); return $lockData; } /** * Returns locker options. * * @since 1.0.0 * @param integer $lockerId * @return mixed */ public static function getLockerOptions( $lockerId ) { if ( isset( self::$_lockerOptions[$lockerId] ) ) return self::$_lockerOptions[$lockerId]; $options = get_post_meta($lockerId, ''); if ( empty($options) ) return $options; $real = array(); foreach($options as $key => $values) { $real[$key] = $values[0]; } self::$_lockerOptions[$lockerId] = $real; return $real; } /** * Returns a locker option. * * @since 1.0.0 * @param integer $lockerId * @param string $name * @param boolean $isArray * @param mixed $default */ public static function getLockerOption( $lockerId, $name, $isArray = false, $default = null ) { $options = self::getLockerOptions($lockerId); $value = isset( $options['opanda_' . $name] ) ? $options['opanda_' . $name] : null; return ($value === null || $value === '') ? $default : ( $isArray ? maybe_unserialize($value) : stripslashes( $value ) ); } /** * Normalized locker options. * * @since 1.0.0 * @param type $params */ private static function _normilizeLockerOptions( &$params ) { foreach( $params as $key => &$item ) { if ( $item === '' || $item === null || $item === 0 ) { unset( $params[$key] ); continue; } if ( $item === 'true' ) { $params[$key] = true; continue; } if ( $item === '1' ) { $params[$key] = 1; continue; } if ( $item === 'false' ) { $params[$key] = false; continue; } if ( $item === '0' ) { $params[$key] = 0; continue; } if ( gettype($item) == 'array' ) { self::_normilizeLockerOptions( $params[$key] ); } } } // ----------------------------------------------- // Markup Normilizer // ----------------------------------------------- /** * Normilizes the shortcode and html markup to make sure that the locker * shortcode was pasted correctly * * @since 1.1.3 * @return string */ public static function normilizerMarkup( $contentBefore, $contentInside, $shortcodeStart, $shortcodeEnd ) { $normalizeMarkup = get_option('opanda_normalize_markup', false); if ( !$normalizeMarkup ) return $contentBefore . $shortcodeStart . $contentInside . $shortcodeEnd; list( $endingElements, $endingTags ) = self::findMarkupElements( true, $contentInside ); $allowedNames = array(); foreach( $endingElements as $element ) $allowedNames[] = $element['name']; list( $startingElements, $startingTags ) = self::findMarkupElements( false, $contentBefore, $allowedNames ); $end = implode("", $endingTags); $start = implode("", $startingTags); $content = $contentBefore . $end . $shortcodeStart . $start . $contentInside . $shortcodeEnd; return $content; } /** * Finds closing and opening shortcodes and html elements without pairs. * * @since 1.1.3 * @return mixed[] */ public static function findMarkupElements( $closing = false, $content, $allowedNames = null ) { $result = array( array(), array() ); $regex = array(); $regex[] = '(\[(\/)?([^\[\]]*)\])'; $regex[] = '(<(\/)?\s*([a-z0-9\-\_]+[^<>]*)>)'; if ( !preg_match_all( '/' . implode('|', $regex) . '/', $content, $matches, PREG_SET_ORDER ) ) return $result; $elements = array(); $tags = array(); $stack = array(); foreach( $matches as $match ) { $keyShift = empty( $match[3] ) ? 3 : 0; $attrs = explode( ' ', trim( $match[3+$keyShift] ) ); $name = trim( $attrs[0] ); $matchClosing = !empty( $match[2+$keyShift] ); $tag = trim( $match[1+$keyShift] ); if ( !ctype_lower( $name ) ) continue; if ( in_array( $name, array( 'img', 'intense_hover_box', 'Don' ) ) ) continue; if ( strpos($name, 'locker-bulk-') > 0 ) continue; $lastStack = end( $stack ); if ( $lastStack['name'] === $name && $lastStack['closing'] !== $matchClosing ) { array_pop( $stack ); } else { array_push( $stack, array('name' => $name, 'closing' => $matchClosing, 'tag' => $tag ) ); } } foreach( $stack as $element ) { if ( $closing !== $element['closing'] ) continue; $elements[] = $element; $tags[] = $element['tag']; } if ( !empty( $allowedNames ) ) { $filteredElements = array(); $filteredTags = array(); for( $i = 0; $i < count( $elements ); $i++ ) { if ( !in_array( $elements[$i]['name'], $allowedNames ) ) continue; $filteredElements[] = $elements[$i]; $filteredTags[] = $elements[$i]['tag']; } return array( $filteredElements, $filteredTags ); } return array( $elements, $tags ); } // ----------------------------------------------- // Bulk Locking // ----------------------------------------------- /** * Init bulk lockers. * * The method gets array of all bulk lockers and tries to understand which of them * are suitable for a current page. If a bulk locker is suitable, then the assets will be * included in the
section of a current page. * * @since 3.0.0 * @return void */ public static function initBulkLocking() { $bulkLockers = get_option('onp_sl_bulk_lockers', array()); if ( empty($bulkLockers) ) return; require_once OPANDA_BIZPANDA_DIR . '/includes/panda-items.php'; foreach($bulkLockers as $id => $options) { if ( self::autoUnlock( $id ) ) continue; $itemType = get_post_meta( $id, 'opanda_item', true ); if ( !OPanda_Items::isAvailable( $itemType ) ) continue; // if we have bulk lockers based on css selectors, then we have to include // assets on every page and also print which css selectors we will use for the // Opt-In Panda creater script if ( $options['way'] == 'css-selector' ) { $lockData = self::getLockerDataToPrint($id); self::$_lockerOptionsToPrint['css-selector-' . $id] = $id; self::$_cssOptionsToPrint[] = array( 'locker-options-id' => 'css-selector-' . $id, 'css-selector' => $options['css_selector'], 'overlap-mode' => $lockData['options']['overlap']['mode'] ); self::requestAssets( $id ); // if we have lockers based on the 'skip-lock' and 'more-tag' rules, // we need check if a current page is excluded } else { if ( !is_singular( $options['post_types'] ) ) continue; if ( !self::isPageExcluded( $id, $options ) ) { self::requestAssets( $id ); continue; } } } if ( !empty( self::$_cssOptionsToPrint ) ) { add_action( 'wp_head', 'OPanda_AssetsManager::printCssSelectorOptions' ); add_action( 'wp_head', 'OPanda_AssetsManager::printLockerOptions' ); } add_filter('the_content', 'OPanda_AssetsManager::addSocialLockerShortcodes', 1); } /** * Cache for the method isPageExcluded. * * @since 3.0.0 * @var mixed */ private static $_cache_isPageExcluded = array(); /** * Checks if a current page is exluded to show the bulk lockers * based on the 'skip-lock' and 'more-tag' rules * * @since 3.0.0 * @param mixed $options * @return boolean */ private static function isPageExcluded( $id, $options ) { global $post; if (empty($post)) return true; $key = $id . '' . $post->ID; if ( isset( self::$_cache_isPageExcluded[$key] ) ) return self::$_cache_isPageExcluded[$key]; if ( !in_array( $post->post_type, $options['post_types'] ) ) { self::$_cache_isPageExcluded[$key] = true; return true; } if ( empty( $options['exclude_posts'] ) && empty( $options['exclude_categories'] ) ) { self::$_cache_isPageExcluded[$key] = false; return false; } if ( in_array( $post->ID, $options['exclude_posts'] ) ) { self::$_cache_isPageExcluded[$key] = true; return true; } $isPostCategoryExcluded = false; foreach(get_the_category() as $category) { if ( in_array( $category->cat_ID, $options['exclude_categories'] ) ) { $isPostCategoryExcluded = true; } } self::$_cache_isPageExcluded[$key] = $isPostCategoryExcluded; return $isPostCategoryExcluded; } /** * Adds a locker shortcodes on the flight if bulk locking are turned on. * * @param type $content * @return type */ public static function addSocialLockerShortcodes( $content ) { $bulkLockers = get_option('onp_sl_bulk_lockers', array()); if ( empty($bulkLockers) ) return $content; global $bizpanda; $shortcodeEnds = array(); $bulkIndex = 0; $ignoredShortcodes = array(); foreach($bulkLockers as $id => $options) { if ( !in_array( $options['way'], array('skip-lock', 'more-tag') ) ) continue; if ( self::isPageExcluded( $id, $options ) ) continue; $lockerStatus = get_post_status( $id ); if ( 'publish' !== $lockerStatus ) continue; $itemType = get_post_meta( $id, 'opanda_item', true ); if ( 'social-locker' == $itemType && !BizPanda::hasPlugin('sociallocker') ) continue; if ( 'email-locker' == $itemType && !BizPanda::hasPlugin('optinpanda') ) continue; $bulkIndex++; switch ( $itemType ) { case 'email-locker': $shortcodeName = 'emaillocker-bulk-' . $bulkIndex; break; case 'signin-locker': $shortcodeName = 'signinlocker-bulk-' . $bulkIndex; break; default: $shortcodeName = 'sociallocker-bulk-' . $bulkIndex; break; } $shortcode = new OPanda_LockerShortcode( $bizpanda ); add_shortcode($shortcodeName, array($shortcode, 'render')); if ( $options['way'] == 'skip-lock' ) { if ( $options['skip_number'] == 0 ) {; $content = "[$shortcodeName id='$id']" . $content; if ( !isset( $shortcodeEnds[0] ) ) $shortcodeEnds[0] = array(); $shortcodeEnds[0][] = "[/$shortcodeName]"; } else { $counter = 0; $offset = 0; while( preg_match('/[^\s]+((<\/p>)|(\n\r){2,}|(\r\n){2,}|(\n){2,}|(\r){2,})/i', $content, $matches, PREG_OFFSET_CAPTURE, $offset ) ) { $counter++; $offset = $matches[0][1] + strlen( $matches[0][0] ); if ( $counter == $options['skip_number'] ) { $beforeShortcode = substr($content, 0, $offset); $insideShortcode = substr($content, $offset); $content = self::normilizerMarkup( $beforeShortcode, $insideShortcode, "[$shortcodeName id='$id']", "" ); if ( !isset( $shortcodeEnds[$offset] ) ) $shortcodeEnds[$offset] = array(); $shortcodeEnds[$offset][] = "[/$shortcodeName]"; break; } } } } elseif( $options['way'] == 'more-tag' && is_singular( $options['post_types'] ) ) { global $post; $label = ''; $pos = strpos( $content, $label ); if ( $pos === false ) return $content; $offset = $pos + strlen( $label ); if ( substr($content, $offset, 4) == '' ) $offset += 4; $content = substr($content, 0, $offset) . "[$shortcodeName id='$id']" . substr($content, $offset); if ( !isset( $shortcodeEnds[$offset] ) ) $shortcodeEnds[$offset] = array(); $shortcodeEnds[$offset][] = "[/$shortcodeName]"; } } if ( !empty( $shortcodeEnds ) ) { krsort($shortcodeEnds); foreach( $shortcodeEnds as $shortcodeEndItem ) { foreach( $shortcodeEndItem as $shortcodeEnd ) { $content .= $shortcodeEnd; } } } return $content; } private static function deleteBulkLocker( $id ) { $bulkLockers = get_option('onp_sl_bulk_lockers', array()); if ( isset($bulkLockers[$id]) ) unset( $bulkLockers[$id] ); delete_option('onp_sl_bulk_lockers'); add_option('onp_sl_bulk_lockers', $bulkLockers); } // ----------------------------------------------- // Dynamic Themes // ----------------------------------------------- /** * Inits support for dynamic themes. * * @since 1.0.0 * @return void */ public static function iniDynamicThemes() { $dynamicTheme = get_option('opanda_dynamic_theme', false); if ( !$dynamicTheme ) return; add_action( 'wp_head', 'OPanda_AssetsManager::printDynamicThemesOptions' ); require_once OPANDA_BIZPANDA_DIR . '/includes/panda-items.php'; $lockers = get_posts(array( 'post_type' => OPANDA_POST_TYPE, 'meta_key' => 'opanda_item', 'meta_value' => OPanda_Items::getAvailableNames(), 'numberposts' => -1 )); foreach( $lockers as $locker ) { self::requestAssets( $locker->ID ); } } /** * Prints options required for dynamic themes. * * @since 1.0.0 * @return void */ public static function printDynamicThemesOptions() { $isDynamic = get_option('opanda_dynamic_theme', false); $event = get_option('opanda_dynamic_theme_event', ''); ?> (function(){ if ( !window.bizpanda ) window.bizpanda = {}; window.bizpanda.bp_can_store_localy = function() { return false; if ( !window.localStorage || !window.localStorage.getItem || !window.localStorage.setItem ) return false; var salt = '' + Math.floor((Math.random() * 1000) + 1); try { window.localStorage.setItem('bp_ut_test', salt); var checkSalt = window.localStorage.getItem('bp_ut_test'); window.localStorage.removeItem('bp_ut_test'); return checkSalt === salt; } catch(e) { return false; } }; window.bizpanda.bp_ut_get_cookie = function getCookie(cname) { var name = cname + "="; var ca = document.cookie.split(';'); for(var i=0; i