/**
  * If it is detected that current theme is in legacy format, generate a
  * dashboard notice.
  */
 public function generate_notice_if_legacy_theme_installed($display_now = false)
 {
     $theme = Ai1ec_Meta::get_option('ai1ec_template', AI1EC_DEFAULT_THEME_NAME);
     // Save directory separator to more concise variable name.
     $slash = DIRECTORY_SEPARATOR;
     $errors = array();
     // ==========================
     // = Wrong style.css format =
     // ==========================
     // Check if a theme has a style.css file containing something besides a CSS
     // comment.
     try {
         $style = Ai1ec_Less_Factory::create_less_file_instance('..' . $slash . 'style');
         $css = file_get_contents($style->locate_exact_file_to_load_in_theme_folders());
     } catch (Ai1ec_File_Not_Found $e) {
         // File not found; no legacy theme code available to detect, so return.
         return;
     }
     $css = $this->remove_comments_and_space($css);
     if ($css) {
         $errors[] = sprintf(__('In your theme folder, <code>%s</code>, the file <code>%sstyle.css</code> should now be used only for metadata information (name, author, etc.).', AI1EC_PLUGIN_NAME) . ' ' . __('We detected custom CSS rules in that file. Those should be removed from <code>%sstyle.css</code> and placed in the file <code>%scss%soverride.css</code>.', AI1EC_PLUGIN_NAME), $theme, $slash, $slash, $slash, $slash);
     }
     // ==========================
     // = Required files missing =
     // ==========================
     // Check if the theme is missing any of the files that are in Gamma (which
     // includes the minimum files).
     $gamma_files = $this->_get_file_listing(AI1EC_THEMES_ROOT . $slash . 'gamma', '#' . $slash . '\\.|^' . $slash . 'functions\\.php$#i');
     $theme_files = $this->_get_file_listing($this->active_template_path());
     $diff = array_diff($gamma_files, $theme_files);
     if ($diff) {
         $errors[] = sprintf(__('Your theme folder <code>%s</code> is missing one or more required files: <code>%s</code>. Please copy these files from the skeleton theme folder, <code>gamma</code>, into the same relative location under <code>%s</code>.', AI1EC_PLUGIN_NAME), $theme, implode('</code>, <code>', $diff), $theme);
     }
     if ($errors) {
         // ===============================================================
         // = Additional checks for modified page templates and other CSS =
         // ===============================================================
         // Now that we've established that the theme is outdated, make certain
         // recommendations to the user based on the below checks.
         // If they also have overridden page templates. These *must* be updated.
         $vortex_php = $this->_get_file_listing(AI1EC_THEMES_ROOT . '/' . AI1EC_DEFAULT_THEME_NAME, '#^' . $slash . '(functions|index)\\.php$#i', '#\\.php$#i');
         $theme_php = $this->_get_file_listing($this->active_template_path(), '#^' . $slash . '(functions|index)\\.php$#i', '#\\.php$#i');
         $php_in_common = array_intersect($vortex_php, $theme_php);
         if ($php_in_common) {
             $errors[] = sprintf(__('We detected one or more custom templates files in your theme folder, <code>%s</code>:', AI1EC_PLUGIN_NAME) . ' ' . '<blockquote><code>' . implode('</code>, <code>', $php_in_common) . '</code></blockquote>' . __('These templates’ originals have changed significantly since these were copied from <code>%s</code>, and the new versions include numerous enhancements. <strong>Your theme’s outdated templates will likely cause your calendar to malfunction.</strong>', AI1EC_PLUGIN_NAME) . ' ' . __('We recommend you back up your templates and remove them from <code>%s</code>. Try using your calendar, and if changes are needed, copy the latest version of the template from <code>%s</code> to <code>%s</code> and then make your revisions.', AI1EC_PLUGIN_NAME), $theme, AI1EC_DEFAULT_THEME_NAME, $theme, AI1EC_DEFAULT_THEME_NAME, $theme);
         }
         // Check for overridden CSS. These must also be updated.
         $vortex_css = array($slash . 'less' . $slash . 'style.less', $slash . 'less' . $slash . 'calendar.less', $slash . 'less' . $slash . 'event.less', $slash . 'css' . $slash . 'style.css', $slash . 'css' . $slash . 'calendar.css', $slash . 'css' . $slash . 'event.css');
         $theme_css = $this->_get_file_listing($this->active_template_path(), '#^' . $slash . 'style\\.css$#i', '#\\.(css|less)$#i');
         $css_in_common = array_intersect($vortex_css, $theme_css);
         if ($css_in_common) {
             $errors[] = sprintf(__('We detected one or more custom CSS or LESS files in your theme folder, <code>%s</code>, that will override the corresponding original in %s:', AI1EC_PLUGIN_NAME) . '<blockquote><code>' . implode('</code>, <code>', $css_in_common) . '</code></blockquote>' . __('The originals have changed significantly since these were copied from <code>%s</code>, and the new versions include numerous enhancements. <strong>Your theme’s outdated CSS/LESS files will likely cause your calendar to be displayed incorrectly.</strong>', AI1EC_PLUGIN_NAME) . ' ' . __('We recommend you back up the affected CSS/LESS files and remove them from <code>%s</code>. Try using your calendar and if changes are needed, place your custom CSS rules in <code>%scss%soverride.css</code> (or custom LESS rules in <code>%sless%soverride.less</code>).', AI1EC_PLUGIN_NAME), $theme, AI1EC_DEFAULT_THEME_NAME, AI1EC_DEFAULT_THEME_NAME, $theme, $slash, $slash, $slash, $slash);
         }
         // Display final report.
         $message = Ai1ec_Helper_Factory::create_admin_message_instance('<p>' . __("You are using a calendar theme that should be updated to the new conventions:", AI1EC_PLUGIN_NAME) . '</p><ol><li>' . implode('</li><li>', $errors) . '</li></ol><p>' . sprintf(__('<strong>Note:</strong> After modifying any of your theme’s CSS or LESS files, you <em>must</em> click <strong>Events</strong> &gt; <strong>Theme Options</strong> &gt; <strong>Save Options</strong> to refresh the compiled CSS used in the front-end.', AI1EC_PLUGIN_NAME) . '</p><p>' . __('You can learn more from our <a href="%s" target="_blank">Help Desk article</a>.', AI1EC_PLUGIN_NAME), 'http://help.time.ly/customer/portal/articles/803082') . '</p>', __("All-in-One Event Calendar Warning: Calendar theme is in legacy format", AI1EC_PLUGIN_NAME));
         if (true === $display_now) {
             $message->render();
         } else {
             $aie1c_admin_notices_helper = Ai1ec_Admin_Notices_Helper::get_instance();
             $aie1c_admin_notices_helper->add_renderable_children($message);
         }
     }
 }
 /**
  * a static method to get variables
  *
  * @param Ai1ec_Db_Adapter $db_adapter
  * @return array
  */
 public static function get_saved_variables(Ai1ec_Db_Adapter $db_adapter)
 {
     $variables = $db_adapter->get_data_from_config(self::DB_KEY_FOR_LESS_VARIABLES);
     $variables_with_description = self::get_less_variable_data_from_config_file(Ai1ec_Less_Factory::create_less_file_instance(Ai1ec_Less_File::USER_VARIABLES_FILE));
     // Add the description at runtime so that it can get the translation
     foreach ($variables as $name => $attrs) {
         if (isset($variables_with_description[$name]['description'])) {
             $variables[$name]['description'] = $variables_with_description[$name]['description'];
         }
     }
     return $variables;
 }
 /**
  * Constructor
  *
  * Default constructor - application initialization
  **/
 private function __construct($preview_mode)
 {
     global $wpdb, $wp_locale, $wp_scripts, $ai1ec_app_helper, $ai1ec_view_helper, $ai1ec_events_controller, $ai1ec_events_helper, $ai1ec_importer_controller, $ai1ec_exporter_controller, $ai1ec_settings_controller, $ai1ec_settings, $ai1ec_themes_controller, $ai1ec_calendar_controller, $ai1ec_calendar_helper, $ai1ec_importer_plugin_helper, $ai1ec_requirejs_controller, $ai1ec_rss_feed, $ai1ec_duplicate_controller;
     $aie1c_admin_notices_helper = Ai1ec_Admin_Notices_Helper::get_instance();
     $ai1ec_duplicate_controller->set_admin_notice_helper($aie1c_admin_notices_helper);
     $css_controller = Ai1ec_Less_Factory::create_css_controller_instance();
     // register_activation_hook
     register_activation_hook(AI1EC_PLUGIN_NAME . '/' . AI1EC_PLUGIN_NAME . '.php', array(&$this, 'activation_hook'));
     // Configure MySQL to operate in GMT time
     $wpdb->query("SET time_zone = '+0:00'");
     // Load plugin text domain
     $this->load_textdomain();
     // Install/update database schema as necessary
     $this->install_schema();
     // Enable stats collection
     $this->install_n_cron();
     // Enable plugins for importing events from external sources
     $this->install_plugins();
     $lessphp_controller = Ai1ec_Less_Factory::create_lessphp_controller();
     // Update less variables in the db
     if (isset($_POST[Ai1ec_Less_Variables_Editing_Page::FORM_SUBMIT_NAME]) || isset($_POST[Ai1ec_Less_Variables_Editing_Page::FORM_SUBMIT_RESET_THEME])) {
         $css_controller->handle_less_variables_page_form_post();
     }
     // Adds the image field only if we are on event categories page
     $this->add_image_field_to_event_categories();
     // Enable checking for cron updates
     $this->install_u_cron();
     // Continue loading hooks only if themes are installed. Otherwise display a
     // notification on the backend with instructions how to install themes.
     if (!$ai1ec_themes_controller->are_themes_available()) {
         // Enables the hidden themes installer page
         add_action('admin_menu', array(&$ai1ec_themes_controller, 'register_theme_installer'), 10);
         // Redirects the user to install theme page
         add_action('admin_menu', array(&$this, 'check_themes'), 2);
         return;
     }
     if (false === $preview_mode && !$ai1ec_themes_controller->are_themes_outdated()) {
         // Create the less variables if they are not set, but only if we are not in preview mode.
         // this is because there is an edge case when you activate a theme and then you preview another
         // the variables of the other theme are set.
         $lessphp_controller->initialize_less_variables_if_not_set(Ai1ec_Less_Factory::create_less_file_instance(Ai1ec_Less_File::USER_VARIABLES_FILE));
     }
     // Check for legacy format themes when viewing WP dashboard; do not perform
     // the check when switching themes or if current theme files are outdated.
     if (is_admin() && !isset($_GET['ai1ec_template']) && !$ai1ec_themes_controller->are_themes_outdated()) {
         $ai1ec_themes_controller->generate_notice_if_legacy_theme_installed();
     }
     // ===========
     // = ACTIONS =
     // ===========
     // Very early on in WP bootstrap, prepare to do any requested theme preview.
     add_action('setup_theme', array(&$ai1ec_themes_controller, 'preview_theme'));
     // Calendar theme initialization
     add_action('after_setup_theme', array(&$ai1ec_themes_controller, 'setup_theme'));
     // Create custom post type
     add_action('init', array(&$ai1ec_app_helper, 'create_post_type'));
     // Handle ICS export requests
     add_action('init', array(&$this, 'parse_standalone_request'));
     // RSS Feed
     add_action('init', array($ai1ec_rss_feed, 'add_feed'));
     // Add the link for CSS generation
     if (!is_admin()) {
         add_action('init', array($css_controller, 'add_link_to_html_for_frontend'), 1);
     }
     // Load plugin text domain
     add_action('init', array(&$this, 'load_textdomain'));
     // Load back-end javascript files
     add_action('init', array($ai1ec_requirejs_controller, 'load_admin_js'));
     // Load the scripts for the backend for wordpress version < 3.3
     add_action('admin_footer', array($ai1ec_requirejs_controller, 'print_admin_script_footer_for_wordpress_32'));
     // Load the scripts for the frontend for wordpress version < 3.3
     add_action('wp_footer', array($ai1ec_requirejs_controller, 'print_frontend_script_footer_for_wordpress_32'));
     // Set an action to load front-end javascript
     add_action('ai1ec_load_frontend_js', array($ai1ec_requirejs_controller, 'load_frontend_js'), 10, 1);
     // Check if themes are installed
     add_action('init', array(&$ai1ec_themes_controller, 'check_themes'));
     // Register The Event Calendar importer
     add_action('admin_init', array(&$ai1ec_importer_controller, 'register_importer'));
     // Install admin menu items.
     add_action('admin_menu', array(&$this, 'admin_menu'), 9);
     // Enable theme updater page if last version of core themes is older than
     // current version.
     if ($ai1ec_themes_controller->are_themes_outdated()) {
         add_action('admin_menu', array(&$ai1ec_themes_controller, 'register_theme_updater'), 10);
     }
     // Add Event counts to dashboard.
     add_action('right_now_content_table_end', array(&$ai1ec_app_helper, 'right_now_content_table_end'));
     // add content for our custom columns
     add_action('manage_ai1ec_event_posts_custom_column', array(&$ai1ec_app_helper, 'custom_columns'), 10, 2);
     // Add filtering dropdowns for event categories and tags
     add_action('restrict_manage_posts', array(&$ai1ec_app_helper, 'taxonomy_filter_restrict_manage_posts'));
     // Trigger display of page in front-end depending on request
     add_action('template_redirect', array(&$this, 'route_request'));
     // Add meta boxes to event creation/edit form.
     add_action('add_meta_boxes', array(&$ai1ec_app_helper, 'add_meta_boxes'));
     add_action('show_user_profile', array(&$ai1ec_app_helper, 'add_profile_boxes'));
     add_action('personal_options_update', array(&$ai1ec_app_helper, 'save_user_profile'), 10, 1);
     // Save event data when post is saved
     add_action('save_post', array(&$ai1ec_events_controller, 'save_post'), 10, 2);
     // Delete event data when post is deleted
     add_action('delete_post', array(&$ai1ec_events_controller, 'delete_post'));
     add_action('delete_term', array($ai1ec_settings, 'term_deletion'), 10, 3);
     // Notification cron job hook
     add_action('ai1ec_n_cron', array(&$ai1ec_exporter_controller, 'n_cron'));
     // Updates cron job hook
     add_action('ai1ec_u_cron', array(&$ai1ec_settings_controller, 'u_cron'));
     // Category colors
     add_action('events_categories_add_form_fields', array(&$ai1ec_events_controller, 'events_categories_add_form_fields'));
     add_action('events_categories_edit_form_fields', array(&$ai1ec_events_controller, 'events_categories_edit_form_fields'));
     add_action('created_events_categories', array(&$ai1ec_events_controller, 'created_events_categories'));
     add_action('edited_events_categories', array(&$ai1ec_events_controller, 'edited_events_categories'));
     add_action('admin_notices', array(&$ai1ec_app_helper, 'admin_notices'));
     // The new object that handles notices.
     add_action('admin_notices', array(&$aie1c_admin_notices_helper, 'render'));
     // Scripts/styles for settings and widget admin screens.
     add_action('admin_enqueue_scripts', array(&$ai1ec_app_helper, 'admin_enqueue_scripts'));
     // Widgets
     add_action('widgets_init', create_function('', "return register_widget( 'Ai1ec_Agenda_Widget' );"));
     // Modify WP admin bar
     add_action('admin_bar_menu', array(&$ai1ec_app_helper, 'modify_admin_bar'));
     // ===========
     // = FILTERS =
     // ===========
     if (is_admin() && 'admin-ajax.php' !== basename($_SERVER['SCRIPT_NAME'])) {
         add_filter('the_title', array(&$ai1ec_view_helper, 'the_title_admin'), 1, 2);
     }
     add_filter('posts_orderby', array(&$ai1ec_app_helper, 'orderby'), 10, 2);
     // add custom column names and change existing columns
     add_filter('manage_ai1ec_event_posts_columns', array(&$ai1ec_app_helper, 'change_columns'));
     // filter the post lists by custom filters
     add_filter('parse_query', array(&$ai1ec_app_helper, 'taxonomy_filter_post_type_request'));
     // Override excerpt filters for proper event display in excerpt form
     add_filter('get_the_excerpt', array(&$ai1ec_events_controller, 'event_excerpt'), 11);
     add_filter('the_excerpt', array(&$ai1ec_events_controller, 'event_excerpt_noautop'), 11);
     remove_filter('the_excerpt', 'wpautop', 10);
     // Update event post update messages
     add_filter('post_updated_messages', array(&$ai1ec_events_controller, 'post_updated_messages'));
     // Sort the custom columns
     add_filter('manage_edit-ai1ec_event_sortable_columns', array(&$ai1ec_app_helper, 'sortable_columns'));
     add_filter('map_meta_cap', array(&$ai1ec_app_helper, 'map_meta_cap'), 10, 4);
     // Inject event categories, only in front-end, depending on setting
     if ($ai1ec_settings->inject_categories && !is_admin()) {
         add_filter('get_terms', array(&$ai1ec_app_helper, 'inject_categories'), 10, 3);
         add_filter('wp_list_categories', array(&$ai1ec_app_helper, 'selected_category_link'), 10, 2);
     }
     // Rewrite event category URLs to point to calendar page.
     add_filter('term_link', array(&$ai1ec_app_helper, 'calendar_term_link'), 10, 3);
     // Add a link to settings page on the plugin list page.
     add_filter('plugin_action_links_' . AI1EC_PLUGIN_BASENAME, array(&$ai1ec_settings_controller, 'plugin_action_links'));
     // Add a link to donate page on plugin list page.
     add_filter('plugin_row_meta', array(&$ai1ec_settings_controller, 'plugin_row_meta'), 10, 2);
     add_filter('post_type_link', array(&$ai1ec_events_helper, 'post_type_link'), 10, 3);
     add_filter('ai1ec_template_root_path', array(&$ai1ec_themes_controller, 'template_root_path'));
     add_filter('ai1ec_template_root_url', array(&$ai1ec_themes_controller, 'template_root_url'));
     // ========
     // = AJAX =
     // ========
     // RRule to Text
     add_action('wp_ajax_ai1ec_rrule_to_text', array(&$ai1ec_events_helper, 'convert_rrule_to_text'));
     // Display Repeat Box
     add_action('wp_ajax_ai1ec_get_repeat_box', array(&$ai1ec_events_helper, 'get_repeat_box'));
     add_action('wp_ajax_ai1ec_get_date_picker_box', array(&$ai1ec_events_helper, 'get_date_picker_box'));
     // Disable notifications
     add_action('wp_ajax_ai1ec_disable_notification', array(&$ai1ec_settings_controller, 'disable_notification'));
     add_action('wp_ajax_ai1ec_disable_intro_video', array(&$ai1ec_settings_controller, 'disable_intro_video'));
     // Front-end event creation
     add_action('wp_ajax_ai1ec_front_end_create_event_form', array(&$ai1ec_events_helper, 'get_front_end_create_event_form'));
     add_action('wp_ajax_ai1ec_front_end_submit_event', array(&$ai1ec_events_helper, 'submit_front_end_create_event_form'));
     if ($ai1ec_settings->allow_anonymous_submissions) {
         add_action('wp_ajax_nopriv_ai1ec_front_end_create_event_form', array(&$ai1ec_events_helper, 'get_front_end_create_event_form'));
         add_action('wp_ajax_nopriv_ai1ec_front_end_submit_event', array(&$ai1ec_events_helper, 'submit_front_end_create_event_form'));
     }
     // Invalid license status warning.
     add_action('wp_ajax_ai1ec_set_license_warning', array(&$ai1ec_settings_controller, 'set_license_warning'));
     // ==============
     // = Shortcodes =
     // ==============
     add_shortcode('ai1ec', array(&$ai1ec_events_helper, 'shortcode'));
 }
 /**
  * Try to get the CSS from cache.
  * If it's not there re-generate it and save it to cache
  * If we are in preview mode, recompile the css using the theme present in the url.
  *
  */
 private function get_compiled_css()
 {
     try {
         // If we want to force a recompile, we throw an exception.
         if ($this->preview_mode === true || self::PARSE_LESS_FILES_AT_EVERY_REQUEST === true) {
             throw new Ai1ec_Cache_Not_Set_Exception();
         } else {
             // This throws an exception if the key is not set
             $css = $this->persistance_context->get_data_from_persistence();
             return $css;
         }
     } catch (Ai1ec_Cache_Not_Set_Exception $e) {
         // If we are in preview mode we force a recompile and we pass the variables.
         if ($this->preview_mode) {
             return $this->lessphp_controller->parse_less_files($this->lessphp_controller->get_less_variable_data_from_config_file(Ai1ec_Less_Factory::create_less_file_instance(Ai1ec_Less_File::USER_VARIABLES_FILE)));
         } else {
             $css = $this->lessphp_controller->parse_less_files();
         }
         try {
             $this->update_persistence_layer($css);
             return $css;
         } catch (Ai1ec_Cache_Write_Exception $e) {
             // If something is really broken, still return the css.
             // This means we parse it every time. This should never happen.
             return $css;
         }
     }
 }