true, self::ADD_NEW_EVENT_PAGE => true, self::EVENT_CATEGORY_PAGE => true, self::LESS_VARIBALES_PAGE => true, self::SETTINGS_PAGE => true, self::EVENT_PAGE_JS => true, self::CALENDAR_PAGE_JS => true, self::WIDGET_CREATOR => true, self::TICKETING => true, ); /** * Holds an instance of the settings object * * @var Ai1ec_Settings */ private $_settings; /** * @var Ai1ec_Locale */ private $_locale; /** * @var Ai1ec_Scripts */ private $_scripts_helper; /** * @var Ai1ec_Acl_Aco */ private $_aco; /** * @var Ai1ec_Template_Link_Helper */ private $_template_link_helper; /** * @var bool */ protected $_frontend_scripts_loaded = false; /** * Public constructor. * * @param Ai1ec_Registry_Object $registry * * @return void */ public function __construct( Ai1ec_Registry_Object $registry ) { $this->_registry = $registry; $this->_settings = $registry->get( 'model.settings' ); $this->_locale = $registry->get( 'p28n.wpml' ); $this->_aco = $registry->get( 'acl.aco' ); $this->_template_link_helper = $registry->get( 'template.link.helper' ); // this will need to be modified $this->_scripts_helper = $registry->get( 'script.helper' ); } /** * Load javascript files for frontend pages. * * @wp-hook ai1ec_load_frontend_js * * @param $is_calendar_page boolean Whether we are displaying the main * calendar page or not * * @return void */ public function load_frontend_js( $is_calendar_page, $is_shortcode = false ) { $page = null; // ====== // = JS = // ====== if( $this->_are_we_accessing_the_single_event_page() === true ) { $page = self::EVENT_PAGE_JS; } if( $is_calendar_page === true ) { $page = self::CALENDAR_PAGE_JS; } if( null !== $page ) { $this->add_link_to_render_js( $page, false ); } } /** * Render the javascript for the appropriate page. * * @return void */ public function render_js() { $js_path = AI1EC_ADMIN_THEME_JS_PATH . DIRECTORY_SEPARATOR; $common_js = ''; $js_cache = $this->_settings->get( 'cache_dynamic_js' ); if ( ! isset( $_GET[self::LOAD_JS_PARAMETER] ) ) { return null; } $page_to_load = $_GET[self::LOAD_JS_PARAMETER]; $scripts_updated = $this->_registry->get( 'model.option' )->get( 'calendarjsupdated' ); if ( $js_cache && $page_to_load === self::CALENDAR_PAGE_JS && '1' === $scripts_updated && $this->_registry->get( 'filesystem.checker' )->check_file_exists( AI1EC_PATH . self::CALENDAR_JS_CACHE_FILE, true ) ) { Ai1ec_Http_Response_Helper::stop( 0 ); return; } if ( isset( $_GET[self::IS_BACKEND_PARAMETER] ) && $_GET[self::IS_BACKEND_PARAMETER] === self::TRUE_PARAM ) { $common_js = file_get_contents( $js_path . 'pages/common_backend.js' ); } else if ( $page_to_load === self::EVENT_PAGE_JS || $page_to_load === self::CALENDAR_PAGE_JS || $page_to_load === self::LOAD_ONLY_FRONTEND_SCRIPTS ) { if ( $page_to_load === self::LOAD_ONLY_FRONTEND_SCRIPTS && true === $this->_frontend_scripts_loaded ) { return; } if ( false === $this->_frontend_scripts_loaded ) { $common_js = file_get_contents( $js_path . 'pages/common_frontend.js' ); $this->_frontend_scripts_loaded = true; } } // Create the config object for Require.js. $require_config = $this->create_require_js_config_object(); // Load Require.js script. $require = file_get_contents( $js_path . 'require.js' ); // Load appropriate jQuery script based on browser. $jquery = $this->get_jquery_version_based_on_browser( isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '' ); // Load the main script for the page. $page_js = ''; if ( isset( $this->_core_pages[$page_to_load] ) ) { $page_js = file_get_contents( $js_path . 'pages/' . $page_to_load ); } // Load translation module. $translation = $this->get_frontend_translation_data(); $permalink = $this->_template_link_helper ->get_permalink( $this->_settings->get( 'calendar_page_id' ) ); $full_permalink = $this->_template_link_helper ->get_full_permalink( $this->_settings->get( 'calendar_page_id' ) ); $translation['calendar_url'] = $permalink; $translation['full_calendar_url'] = $full_permalink; $translation_module = $this->create_require_js_module( self::FRONTEND_CONFIG_MODULE, $translation ); // Load Ai1ec config script. $config = $this->create_require_js_module( 'ai1ec_config', $this->get_translation_data() ); // Let extensions add their scripts. $extension_files = array(); $extension_files = apply_filters( 'ai1ec_render_js', $extension_files, $page_to_load ); $ext_js = ''; foreach ( $extension_files as $file ) { $ext_js .= file_get_contents( $file ); } // Finally, load the page_ready script to execute code that must run after // all scripts have been loaded. $page_ready = file_get_contents( $js_path . 'scripts/common_scripts/page_ready.js' ); $javascript = $require . $require_config . $translation_module . $config . $jquery . $common_js . $ext_js . $page_js . $page_ready; // add to blank spaces to fix issues with js // being truncated onn some installs $javascript .= ' '; if ( $js_cache && $page_to_load === self::CALENDAR_PAGE_JS && ( '0' === $scripts_updated || ! $this->_registry->get( 'filesystem.checker' )->check_file_exists( AI1EC_PATH . self::CALENDAR_JS_CACHE_FILE, true ) ) ) { $js_saved = false; try { $js_saved = file_put_contents( $js_path . '../js_cache/' . self::CALENDAR_PAGE_JS, $javascript ); if ( $js_saved ) { $this->_registry->get( 'model.option' )->set( 'calendarjsupdated', '1' ); } } catch ( Exception $e ) { $this->_settings->set( 'cache_dynamic_js', false ); } } $this->_echo_javascript( $javascript ); } /** * Sets the flag to revalidate cached js files on next render. */ public function revalidate_cache() { $this->_registry->get( 'model.option' )->set( 'calendarjsupdated', '0' ); } /** * Get a compiled javascript file ( used by extensions ) * * @param string $name * * @return string */ public function get_module( $name ) { $js_path = AI1EC_ADMIN_THEME_JS_PATH . DIRECTORY_SEPARATOR; return file_get_contents( $js_path . $name ); } /** * Check what file needs to be loaded and add the correct link. * * @wp-hook init * * @return void */ public function load_admin_js() { // Initialize dashboard view $script_to_load = FALSE; if ( $this->are_we_on_calendar_feeds_page() === TRUE ) { // Load script for the importer plugins $script_to_load[] = self::CALENDAR_FEEDS_PAGE; } // Start the scripts for the event category page if ( $this->_are_we_editing_event_categories() === TRUE ) { // Load script required when editing categories $script_to_load[] = self::EVENT_CATEGORY_PAGE; } if ( $this->_are_we_editing_less_variables() === TRUE ) { // Load script required when editing categories $script_to_load[] = self::LESS_VARIBALES_PAGE; } // Load the js needed when you edit an event / add a new event if ( true === $this->_are_we_creating_a_new_event() || true === $this->_are_we_editing_an_event() ) { // Load script for adding / modifying events $script_to_load[] = self::ADD_NEW_EVENT_PAGE; } if ( $this->_are_we_accessing_the_calendar_settings_page() === TRUE ) { $script_to_load[] = self::SETTINGS_PAGE; } if ( true === $this->_are_we_creating_widgets() ) { $script_to_load[] = self::WIDGET_CREATOR; } if ( ( $this->_registry->get( 'helper.api-settings' )->ai1ec_api_enabled() ) && ( true === $this->_are_we_managing_tickets() || true === $this->_are_we_managing_events_list() ) ) { $script_to_load[] = self::TICKETING; } if ( false === $script_to_load ) { $script_to_load[] = apply_filters( 'ai1ec_backend_js', self::LOAD_ONLY_BACKEND_SCRIPTS ); } foreach ($script_to_load as $value) { $this->add_link_to_render_js( $value, true ); } } /** * Loads version 1.9 or 2.0 of jQuery based on user agent. * If $user_agent is null (due to lack of HTTP header) we always serve * jQuery 2.0. * * @param string $user_agent * * @return string */ public function get_jquery_version_based_on_browser( $user_agent ) { $js_path = AI1EC_ADMIN_THEME_JS_PATH . DIRECTORY_SEPARATOR; $jquery = 'jquery_timely20.js'; preg_match( '/MSIE (.*?);/', $user_agent, $matches ); if ( count( $matches ) > 1 ) { //Then we're using IE $version = (int) $matches[1]; if ( $version <= 8 ) { //IE 8 or under! $jquery = 'jquery_timely19.js'; } } return file_get_contents( $js_path . $jquery ); } /** * Creates a requirejs module that can be used for translations * * @param string $object_name * @param array $data * * @return string */ public function create_require_js_module( $object_name, array $data ) { foreach ( (array) $data as $key => $value ) { if ( ! is_scalar( $value ) ) continue; $data[$key] = html_entity_decode( (string) $value, ENT_QUOTES, 'UTF-8'); } $json_data = json_encode( $data ); $prefix = self::REQUIRE_NAMESPACE; $script = "$prefix.define( '$object_name', $json_data );"; return $script; } /** * Create the array needed for translation and passing other settings to JS. * * @return $data array the dynamic data array */ public function get_translation_data() { $force_ssl_admin = force_ssl_admin(); if ( $force_ssl_admin && ! is_ssl() ) { force_ssl_admin( false ); } $ajax_url = ai1ec_admin_url( 'admin-ajax.php' ); force_ssl_admin( $force_ssl_admin ); $settings = $this->_registry->get( 'model.settings' ); $locale = $this->_registry->get( 'p28n.wpml' ); $blog_timezone = $this->_registry->get( 'model.option' ) ->get( 'gmt_offset' ); $application = $this->_registry->get( 'bootstrap.registry.application' ); $data = array( 'calendar_feeds_nonce' => wp_create_nonce( 'ai1ec_ics_feed_nonce'), // ICS feed error messages 'duplicate_feed_message' => esc_html( Ai1ec_I18n::__( 'This feed is already being imported.' ) ), 'invalid_url_message' => esc_html( Ai1ec_I18n::__( 'Please enter a valid iCalendar URL.' ) ), 'invalid_email_message' => esc_html( Ai1ec_I18n::__( 'Please enter a valid email address.' ) ), 'choose_image_message' => Ai1ec_I18n::__( 'Choose Image' ), 'now' => $this->_registry->get( 'date.system' ) ->current_time(), 'size_less_variable_not_ok' => Ai1ec_I18n::__( 'The value you have entered is not a valid CSS length.' ), 'confirm_reset_theme' => Ai1ec_I18n::__( 'Are you sure you want to reset your theme options to their default values?' ), 'error_message_not_valid_lat' => Ai1ec_I18n::__( 'Please enter a valid latitude. A valid latitude is comprised between +90 and -90.' ), 'error_message_not_valid_long' => Ai1ec_I18n::__( 'Please enter a valid longitude. A valid longitude is comprised between +180 and -180.' ), 'error_message_not_entered_lat' => Ai1ec_I18n::__( 'When the "Input coordinates" checkbox is checked, "Latitude" is a required field.' ), 'error_message_not_entered_long' => Ai1ec_I18n::__( 'When the "Input coordinates" checkbox is checked, "Longitude" is a required field.' ), 'ai1ec_contact_url_not_valid' => Ai1ec_I18n::__( 'The URL you have entered in the Organizer Contact Info > Website URL seems to be invalid.' ), 'ai1ec_ticket_url_not_valid' => Ai1ec_I18n::__( 'The URL you have entered in the Event Cost and Tickets > Buy Tickets URL seems to be invalid.' ), 'general_url_not_valid' => Ai1ec_I18n::__( 'Please remember that URLs must start with either "http://" or "https://".' ), 'calendar_loading' => Ai1ec_I18n::__( 'Loading…' ), 'ticketing_required_fields' => Ai1ec_I18n::__( '
Some fields required for Ticketing are missing.
Missing or incorrect fields are outlined red.