/** * The Queue_Realtime constructor method. * * @param Tribe__Events__Aggregator__Record__Queue|null $queue An optional Queue instance. * @param Tribe__Events__Ajax__Operations|null $ajax_operations An optional Ajax Operations instance. * @param Tribe__Events__Aggregator__Record__Queue_Processor|null $queue_processor An optional Queue_Processor instance. */ public function __construct(Tribe__Events__Aggregator__Record__Queue $queue = null, Tribe__Events__Ajax__Operations $ajax_operations = null, Tribe__Events__Aggregator__Record__Queue_Processor $queue_processor = null) { tribe_notice('aggregator-update-msg', array($this, 'render_update_message'), 'type=warning&dismiss=0'); add_action('wp_ajax_tribe_aggregator_realtime_update', array($this, 'ajax')); $this->queue = $queue; $this->ajax_operations = $ajax_operations ? $ajax_operations : new Tribe__Events__Ajax__Operations(); $this->queue_processor = $queue_processor ? $queue_processor : Tribe__Events__Aggregator::instance()->queue_processor; }
/** * Setup all the hooks and filters * * @return void */ private function __construct() { $plugin = Tribe__Events__Main::instance(); // Hook the AJAX methods add_action('wp_ajax_tribe_convert_legacy_facebook_settings', array($this, 'ajax_convert_facebook_settings')); add_action('wp_ajax_tribe_convert_legacy_ical_settings', array($this, 'ajax_convert_ical_settings')); // Hook the Notice for the Migration tribe_notice('tribe-aggregator-migrate-legacy-settings', array($this, 'notice'), 'type=warning'); // Register Assets tribe_asset($plugin, 'tribe-migrate-legacy-settings', 'aggregator-admin-legacy-settings.js', array('jquery'), 'admin_enqueue_scripts'); }
/** * A private method to prevent it to be created twice. * It will add the methods and setup any dependencies */ private function __construct() { $plugin = Tribe__Events__Main::instance(); add_action('admin_menu', array($this, 'register_menu_item')); add_action('current_screen', array($this, 'action_request')); add_action('init', array($this, 'init')); // filter the plupload default settings to remove mime type restrictions add_filter('plupload_default_settings', array($this, 'filter_plupload_default_settings')); // Setup Tabs Instance $this->tabs = Tribe__Events__Aggregator__Tabs::instance(); tribe_notice('tribe-aggregator-legacy-import-plugins-active', array($this, 'notice_legacy_plugins'), 'type=warning'); }
public function get_result_messages($queue) { $messages = array(); if (is_wp_error($queue)) { $messages['error'][] = $queue->get_error_message(); tribe_notice('tribe-aggregator-import-failed', array($this, 'render_notice_import_failed'), 'type=error'); return $messages; } $is_queued = $queue->count(); $content_post_type = empty($queue->record->meta['content_type']) ? Tribe__Events__Main::POSTTYPE : $queue->record->meta['content_type']; $content_type = tribe_get_event_label_singular_lowercase(); $content_type_plural = tribe_get_event_label_plural_lowercase(); if ('csv' === $queue->record->meta['origin'] && 'tribe_events' !== $queue->record->meta['content_type']) { $content_type_object = get_post_type_object($queue->record->meta['content_type']); $content_type = empty($content_type_object->labels->singular_name_lowercase) ? $content_type_object->labels->singular_name : $content_type_object->labels->singular_name_lowercase; $content_type_plural = empty($content_type_object->labels->plural_name_lowercase) ? $content_type_object->labels->name : $content_type_object->labels->plural_name_lowercase; $content_post_type = $content_type_object->name; } if (!$is_queued) { $item_created = $queue->activity->get($content_post_type, 'created'); if (!empty($item_created)) { $content_label = 1 === $queue->activity->count($content_post_type, 'created') ? $content_type : $content_type_plural; $messages['success'][] = sprintf(_n('%1$d new %2$s was imported.', '%1$d new %2$s were imported.', $queue->activity->count($content_post_type, 'created'), 'the-events-calendar'), $queue->activity->count($content_post_type, 'created'), $content_label); } $item_updated = $queue->activity->get($content_post_type, 'updated'); if (!empty($item_updated)) { $content_label = 1 === $queue->activity->count($content_post_type, 'updated') ? $content_type : $content_type_plural; // @todo: include a part of sentence like: ", including %1$d %2$signored event%3$s.", <a href="/wp-admin/edit.php?post_status=tribe-ignored&post_type=tribe_events">, </a> $messages['success'][] = sprintf(_n('%1$d existing %2$s was updated.', '%1$d existing %2$s were updated.', $queue->activity->count($content_post_type, 'updated'), 'the-events-calendar'), $queue->activity->count($content_post_type, 'updated'), $content_label); } $item_skipped = $queue->activity->get($content_post_type, 'skipped'); if (!empty($item_skipped)) { $content_label = 1 === $queue->activity->count($content_post_type, 'skipped') ? $content_type : $content_type_plural; $messages['success'][] = sprintf(_n('%1$d already-imported %2$s was skipped.', '%1$d already-imported %2$s were skipped.', $queue->activity->count($content_post_type, 'skipped'), 'the-events-calendar'), $queue->activity->count($content_post_type, 'skipped'), $content_label); } $images_created = $queue->activity->get('images', 'created'); if (!empty($images_created)) { $messages['success'][] = sprintf(_n('%1$d new image was imported.', '%1$d new images were imported.', $queue->activity->count('images', 'created'), 'the-events-calendar'), $queue->activity->count('images', 'created')); } if ($queue && !$messages) { $messages['success'][] = sprintf(__('No %1$s were imported or updated.', 'the-events-calendar'), $content_type_plural); } if (!empty($messages['success']) && !empty($content_type_object->show_ui)) { // append a URL to view all records for the given post type $url = admin_url('edit.php?post_type=' . $content_post_type); $link_text = sprintf(__('View all %s', 'the-events-calendar'), $content_type_plural); $messages['success'][count($messages['success']) - 1] .= ' <a href="' . esc_url($url) . '" >' . esc_html($link_text) . '</a>'; } // if not CSV, pull counts for venues and organizers that were auto-created if ('csv' !== $queue->record->meta['origin']) { $venue_created = $queue->activity->get('venue', 'created'); if (!empty($venue_created)) { $messages['success'][] = '<br/>' . sprintf(_n('%1$d new venue was imported.', '%1$d new venues were imported.', $queue->activity->count('venue', 'created'), 'the-events-calendar'), $queue->activity->count('venue', 'created')) . ' <a href="' . admin_url('edit.php?post_type=tribe_venue') . '">' . __('View your event venues', 'the-events-calendar') . '</a>'; } $organizer_created = $queue->activity->get('organizer', 'created'); if (!empty($organizer_created)) { $messages['success'][] = '<br/>' . sprintf(_n('%1$d new organizer was imported.', '%1$d new organizers were imported.', $queue->activity->count('organizer', 'created'), 'the-events-calendar'), $queue->activity->count('organizer', 'created')) . ' <a href="' . admin_url('edit.php?post_type=tribe_organizer') . '">' . __('View your event organizers', 'the-events-calendar') . '</a>'; } } $category_created = $queue->activity->get('category', 'created'); if (!empty($category_created)) { $messages['success'][] = '<br/>' . sprintf(_n('%1$d new event category was created.', '%1$d new event categories were created.', $queue->activity->count('category', 'created'), 'the-events-calendar'), $queue->activity->count('category', 'created')) . ' <a href="' . admin_url('edit-tags.php?taxonomy=tribe_events_cat&post_type=tribe_events') . '">' . __('View your event categories', 'the-events-calendar') . '</a>'; } } if (!empty($messages['error']) || !empty($messages['success']) || !empty($messages['warning'])) { if ('manual' == $queue->record->type) { array_unshift($messages['success'], __('Import complete!', 'the-events-calendar') . '<br/>'); } else { array_unshift($messages['success'], __('Your scheduled import was saved and the first import is complete!', 'the-events-calendar') . '<br/>'); $scheduled_time = strtotime($queue->record->post->post_modified) + $queue->record->frequency->interval; $scheduled_time_string = date(get_option('date_format'), $scheduled_time) . _x(' at ', 'separator between date and time', 'the-events-calendar') . date(get_option('time_format'), $scheduled_time); $messages['success'][] = '<br/>' . sprintf(__('The next import is scheduled for %1$s.', 'the-events-calendar'), esc_html($scheduled_time_string)) . ' <a href="' . admin_url('edit.php?page=aggregator&post_type=tribe_events&tab=scheduled') . '">' . __('View your scheduled imports.', 'the-events-calendar') . '</a>'; } } return $messages; }
/** * Set up any necessary notices */ public function setup_notices() { if (!$this->api('origins')->is_oauth_enabled('facebook')) { return; } tribe_notice('tribe-aggregator-facebook-token-expired', array($this, 'notice_facebook_token_expired'), 'type=error'); tribe_notice('tribe-aggregator-facebook-oauth-feedback', array($this, 'notice_facebook_oauth_feedback'), 'type=success'); }
/** * Add filters and actions */ protected function addHooks() { // Since TEC is active, change the base page for the Event Settings page Tribe__Settings::$parent_page = 'edit.php'; // Load Rewrite add_action('plugins_loaded', array(Tribe__Events__Rewrite::instance(), 'hooks')); add_action('init', array($this, 'init'), 10); add_action('admin_init', array($this, 'admin_init')); // Frontend Javascript add_action('wp_enqueue_scripts', array($this, 'loadStyle')); add_filter('tribe_events_before_html', array($this, 'before_html_data_wrapper')); add_filter('tribe_events_after_html', array($this, 'after_html_data_wrapper')); // Styling add_filter('post_class', array($this, 'post_class')); add_filter('body_class', array($this, 'body_class')); add_filter('admin_body_class', array($this, 'admin_body_class')); add_filter('post_type_archive_link', array($this, 'event_archive_link'), 10, 2); add_filter('query_vars', array($this, 'eventQueryVars')); add_filter('bloginfo_rss', array($this, 'add_space_to_rss')); add_filter('post_updated_messages', array($this, 'updatePostMessage')); /* Add nav menu item - thanks to http://wordpress.org/extend/plugins/cpt-archives-in-nav-menus/ */ add_filter('nav_menu_items_' . self::POSTTYPE, array($this, 'add_events_checkbox_to_menu'), null, 3); add_filter('wp_nav_menu_objects', array($this, 'add_current_menu_item_class_to_events'), null, 2); add_filter('template_redirect', array($this, 'redirect_past_upcoming_view_urls'), 11); /* Setup Tribe Events Bar */ add_filter('tribe-events-bar-views', array($this, 'setup_listview_in_bar'), 1, 1); add_filter('tribe-events-bar-views', array($this, 'setup_gridview_in_bar'), 5, 1); add_filter('tribe-events-bar-views', array($this, 'setup_dayview_in_bar'), 15, 1); add_filter('tribe-events-bar-filters', array($this, 'setup_date_search_in_bar'), 1, 1); add_filter('tribe-events-bar-filters', array($this, 'setup_keyword_search_in_bar'), 1, 1); add_filter('tribe-events-bar-views', array($this, 'remove_hidden_views'), 9999, 2); /* End Setup Tribe Events Bar */ add_action('admin_menu', array($this, 'addEventBox')); add_action('wp_insert_post', array($this, 'addPostOrigin'), 10, 2); add_action('save_post', array($this, 'addEventMeta'), 15, 2); add_action('post_updated', array($this, 'track_event_post_field_changes'), 10, 3); /* Registers the list widget */ add_action('widgets_init', array($this, 'register_list_widget'), 90); add_action('save_post_' . self::VENUE_POST_TYPE, array($this, 'save_venue_data'), 16, 2); add_action('save_post_' . self::ORGANIZER_POST_TYPE, array($this, 'save_organizer_data'), 16, 2); add_action('save_post_' . self::POSTTYPE, array(Tribe__Events__Dates__Known_Range::instance(), 'maybe_update_known_range')); add_action('tribe_events_csv_import_complete', array(Tribe__Events__Dates__Known_Range::instance(), 'rebuild_known_range')); add_action('publish_' . self::POSTTYPE, array($this, 'publishAssociatedTypes'), 25, 2); add_action('delete_post', array(Tribe__Events__Dates__Known_Range::instance(), 'maybe_rebuild_known_range')); add_action('parse_query', array($this, 'setDisplay'), 51, 0); add_action('tribe_events_post_errors', array('Tribe__Events__Post_Exception', 'displayMessage')); add_action('tribe_settings_top', array('Tribe__Events__Options_Exception', 'displayMessage')); add_action('admin_enqueue_scripts', array($this, 'add_admin_assets')); add_filter('tribe_events_register_event_type_args', array($this, 'setDashicon')); add_action('trash_' . self::VENUE_POST_TYPE, array($this, 'cleanupPostVenues')); add_action('trash_' . self::ORGANIZER_POST_TYPE, array($this, 'cleanupPostOrganizers')); add_action('wp_ajax_tribe_event_validation', array($this, 'ajax_form_validate')); add_action('plugins_loaded', array('Tribe__Cache_Listener', 'instance')); add_action('plugins_loaded', array('Tribe__Cache', 'setup')); add_action('plugins_loaded', array('Tribe__Support', 'getInstance')); if (!Tribe__Main::instance()->doing_ajax()) { add_action('current_screen', array($this, 'init_admin_list_screen')); } else { add_action('admin_init', array($this, 'init_admin_list_screen')); } // Load organizer and venue editors add_action('admin_menu', array($this, 'addVenueAndOrganizerEditor')); add_action('tribe_venue_table_top', array($this, 'displayEventVenueDropdown')); add_action('tribe_venue_table_top', array($this, 'display_rich_snippets_helper'), 5); add_action('template_redirect', array($this, 'template_redirect')); add_action('wp', array($this, 'issue_noindex')); add_action('plugin_row_meta', array($this, 'addMetaLinks'), 10, 2); // organizer and venue if (!defined('TRIBE_HIDE_UPSELL') || !TRIBE_HIDE_UPSELL) { add_action('wp_dashboard_setup', array($this, 'dashboardWidget')); add_action('tribe_events_cost_table', array($this, 'maybeShowMetaUpsell')); } add_action('load-tribe_events_page_' . Tribe__Settings::$parent_slug, array('Tribe__Events__Amalgamator', 'listen_for_migration_button'), 10, 0); add_action('tribe_settings_after_save', array($this, 'flushRewriteRules')); add_action('update_option_' . Tribe__Main::OPTIONNAME, array($this, 'fix_all_day_events'), 10, 2); // add-on compatibility if (is_multisite()) { add_action('network_admin_notices', array($this, 'checkAddOnCompatibility')); } else { add_action('admin_notices', array($this, 'checkAddOnCompatibility')); } add_action('wp_before_admin_bar_render', array($this, 'add_toolbar_items'), 10); add_action('all_admin_notices', array($this, 'addViewCalendar')); add_action('admin_head', array($this, 'setInitialMenuMetaBoxes'), 500); add_action('plugin_action_links_' . trailingslashit($this->plugin_dir) . 'the-events-calendar.php', array($this, 'addLinksToPluginActions')); // override default wp_terms_checklist arguments to prevent checked items from bubbling to the top. Instead, retain hierarchy. add_filter('wp_terms_checklist_args', array($this, 'prevent_checked_on_top_terms'), 10, 2); add_action('tribe_events_pre_get_posts', array($this, 'set_tribe_paged')); // Upgrade material. add_action('init', array($this, 'run_updates'), 0, 0); if (defined('WP_LOAD_IMPORTERS') && WP_LOAD_IMPORTERS) { add_filter('wp_import_post_data_raw', array($this, 'filter_wp_import_data_before'), 10, 1); add_filter('wp_import_post_data_processed', array($this, 'filter_wp_import_data_after'), 10, 1); } add_action('plugins_loaded', array($this, 'init_ical'), 2, 0); add_action('plugins_loaded', array($this, 'init_day_view'), 2); add_action('plugins_loaded', array('Tribe__Events__Bar', 'instance')); add_action('plugins_loaded', array('Tribe__Events__Templates', 'init')); add_action('init', array($this, 'filter_cron_schedules')); add_action('plugins_loaded', array('Tribe__Events__Event_Tickets__Main', 'instance')); // Add support for tickets plugin add_action('tribe_tickets_ticket_added', array('Tribe__Events__API', 'update_event_cost')); add_action('tribe_tickets_ticket_deleted', array('Tribe__Events__API', 'update_event_cost')); add_filter('tribe_tickets_default_end_date', array($this, 'default_end_date_for_tickets'), 10, 2); add_filter('tribe_post_types', array($this, 'filter_post_types')); add_filter('tribe_is_post_type_screen_post_types', array($this, 'is_post_type_screen_post_types')); add_filter('tribe_currency_symbol', array($this, 'maybe_set_currency_symbol_with_post'), 10, 2); add_filter('tribe_reverse_currency_position', array($this, 'maybe_set_currency_position_with_post'), 10, 2); // Settings page hooks add_action('tribe_settings_do_tabs', array($this, 'do_addons_api_settings_tab')); add_filter('tribe_general_settings_tab_fields', array($this, 'general_settings_tab_fields')); add_filter('tribe_display_settings_tab_fields', array($this, 'display_settings_tab_fields')); add_filter('tribe_settings_url', array($this, 'tribe_settings_url')); // Setup Help Tab texting add_action('tribe_help_pre_get_sections', array($this, 'add_help_section_feature_box_content')); add_action('tribe_help_pre_get_sections', array($this, 'add_help_section_support_content')); add_action('tribe_help_pre_get_sections', array($this, 'add_help_section_extra_content')); add_action('plugins_loaded', array('Tribe__Events__Aggregator', 'instance')); // Setup Shortcodes add_action('plugins_loaded', array('Tribe__Events__Shortcode__Event_Details', 'hook')); // Load Ignored Events add_action('plugins_loaded', array('Tribe__Events__Ignored_Events', 'instance')); // Google Maps API key setting $google_maps_api_key = Tribe__Events__Google__Maps_API_Key::instance(); add_filter('tribe_addons_tab_fields', array($google_maps_api_key, 'filter_tribe_addons_tab_fields')); add_filter('tribe_events_google_maps_api', array($google_maps_api_key, 'filter_tribe_events_google_maps_api')); add_filter('tribe_events_pro_google_maps_api', array($google_maps_api_key, 'filter_tribe_events_google_maps_api')); // Preview handling add_action('template_redirect', array(Tribe__Events__Revisions__Preview::instance(), 'hook')); // Register slug conflict notices (but test to see if tribe_notice() is indeed available, in case another plugin // is hosting an earlier version of tribe-common which is already active) // // @todo remove this safety check when we're confident the risk has diminished if (function_exists('tribe_notice')) { tribe_notice('archive-slug-conflict', array($this, 'render_notice_archive_slug_conflict'), 'dismiss=1&type=error'); } /** * Expire notices */ add_action('transition_post_status', array($this, 'action_expire_archive_slug_conflict_notice'), 10, 3); }
/** * Tests to see if there are any extant notifications and renders them if so. * * This must run prior to Tribe__Admin__Notices::hook() (which currently runs during * "current_screen" priority 20). */ public function setup_notices() { // Don't allow this to run multiple times remove_action('current_screen', array($this, 'setup_notices')); // No need to display license key notices to users without appropriate capabilities if (!current_user_can('install_plugins')) { return; } foreach ($this->notices as $notice_type => $plugin_names) { if (empty($plugin_names)) { continue; } $callback = array($this, 'render_' . $notice_type); if (is_callable($callback)) { tribe_notice('pue_key-' . $notice_type, $callback, 'dismiss=1&type=warning'); } } }
/** * Error and success messages for delete * * @param string $action saved, deleted * @param array $statuses Which status occurred * @return string */ private function action_notice($action, $ids = array(), $error = null) { if ($ids && !is_array($ids)) { $ids = explode(',', $ids); } $errors = array(); if (is_string($error)) { $transient = $this->get_errors_transient_name($error); $errors = get_transient($transient); // After getting delete delete_transient($transient); } $success = count($ids); $message = (object) array('success' => array(), 'error' => array()); if (!empty($errors)) { if ('run-import' === $_GET['action']) { foreach ($errors as $post_id => $error) { $message->error[] = $error->get_error_message(); } } else { $message->error[] = sprintf(esc_html__('Error: %d scheduled import was not %s.', 'the-events-calendar'), $action, count($errors)); foreach ($errors as $post_id => $error) { $message->error[] = implode('<br/>', sprintf('%d: %s', $post_id, $error->get_error_message())); } } tribe_notice('tribe-aggregator-action-records-error', '<p>' . implode('<br/>', $message->error) . '</p>', 'type=error'); } if (0 < $success) { $message->success[] = sprintf(esc_html__('Successfully %s %d scheduled import', 'the-events-calendar'), $action, $success); tribe_notice('tribe-aggregator-action-records-success', '<p>' . implode("\r\n", $message->success) . '</p>', 'type=success'); } }
/** * Finalizes the saving of a scheduled import * * @param Tribe__Events__Aggregator__Record__Abstract $record Record object * @param array $post_data Massaged POSTed data * @param array $meta Meta to be saved to the schedule */ public function finalize_schedule_edit($record, $post_data, $meta) { $this->messages = array('error' => array(), 'success' => array(), 'warning' => array()); $meta['post_status'] = empty($post_data['post_status']) ? 'draft' : $post_data['post_status']; $meta['category'] = empty($post_data['category']) ? null : $post_data['category']; $result = $record->save($post_data['post_id'], array(), $meta); if (is_wp_error($result)) { $this->messages['error'][] = $result->get_error_message(); ob_start(); ?> <p> <?php echo implode(' ', $this->messages['error']); ?> </p> <?php $html = ob_get_clean(); tribe_notice('tribe-aggregator-schedule-edit-failed', $html, 'type=error'); return $result; } $this->messages['success'][] = esc_html__('Scheduled import was successfully updated.'); ob_start(); ?> <p> <?php echo implode(' ', $this->messages['success']); ?> <a href="<?php echo esc_url(admin_url('edit.php?post_type=' . Tribe__Events__Main::POSTTYPE . '&page=aggregator&tab=scheduled')); ?> " ><?php esc_html_e('View All Scheduled Imports', 'the-events-calendar'); ?> </a> </p> <?php $html = ob_get_clean(); $this->messages['success'][] = __('Your Scheduled Import has been updated!', 'the-events-calendar'); tribe_notice('tribe-aggregator-schedule-edit-complete', $html, 'type=success'); return $result; }
/** * @param string $plugin_path Path to the plugin file we're showing a notice for */ public function __construct($plugin_path) { $this->plugin_path = $plugin_path; tribe_notice(plugin_basename($plugin_path), array($this, 'show_inactive_plugins_alert')); }
/** * Allows Bulk Actions to Work it's magic (more Complex than it needs to be) * * @return void|false */ public function action_restore_ignored() { if (!Tribe__Admin__Helpers::instance()->is_post_type_screen(Tribe__Events__Main::POSTTYPE)) { return false; } if (!isset($_GET['ids'])) { return false; } if (!isset($_GET['tribe-action']) || 'tribe-restore' !== $_GET['tribe-action']) { return false; } if (!isset($_GET['_wpnonce']) || !wp_verify_nonce($_GET['_wpnonce'], 'tribe-restore')) { return false; } $ids = (array) explode(',', $_GET['ids']); $restored = array(); foreach ($ids as $id) { if (!current_user_can('delete_post', $id)) { wp_die(esc_html__('You do not have permission to restore this post.', 'the-events-calendar')); } $restore = $this->restore_event($id); if (!$restore) { wp_die(esc_html__('Error restoring from Ignored Events.', 'the-events-calendar')); } $restored[] = $restore; } $count_restored = count($restored); $message = '<p>' . sprintf(_n('%s post restored.', '%s posts restored.', $count_restored, 'the-events-calendar'), $count_restored) . '</p>'; if (!empty($_SERVER['REQUEST_URI'])) { $_SERVER['REQUEST_URI'] = remove_query_arg(array('tribe-action', '_wpnonce'), $_SERVER['REQUEST_URI']); } elseif (!empty($_REQUEST['_wp_http_referer'])) { $_REQUEST['_wp_http_referer'] = remove_query_arg(array('tribe-action', '_wpnonce'), $_REQUEST['_wp_http_referer']); } elseif (!empty($_SERVER['HTTP_REFERER'])) { $_SERVER['HTTP_REFERER'] = remove_query_arg(array('tribe-action', '_wpnonce'), $_SERVER['HTTP_REFERER']); } return tribe_notice('restored-events', $message, 'dismiss=1&type=success'); }
/** * Gets the name of the class the method is called in; typically will be a child class * * This uses some hackery if the server is on PHP 5.2, and it can fail in rare * circumstances causing a null value to be returned. * * @return string|null Class name */ protected static final function get_called_class() { $class_name = null; if (function_exists('get_called_class')) { // For PHP 5.3+ we can use the late static binding class name. $class_name = get_called_class(); } else { // For PHP 5.2 and under we hack around the lack of late static bindings. try { $backtraces = debug_backtrace(); // Grab each class from the backtrace. foreach ($backtraces as $i) { $class = null; if (array_key_exists('class', $i)) { // Direct call to a class. $class = $i['class']; } elseif (array_key_exists('function', $i) && strpos($i['function'], 'call_user_func') === 0 && array_key_exists('args', $i) && is_array($i['args']) && is_array($i['args'][0]) && isset($i['args'][0][0])) { // Found a call from call_user_func... and $i['args'][0][0] is present // indicating a static call to a method. $class = $i['args'][0][0]; } else { // Slight performance boost from skipping ahead. continue; } // Check to see if the parent is the current class. // The first backtrace with a matching parent is our class. if (get_parent_class($class) === __CLASS__) { $class_name = $class; break; } } } catch (Exception $e) { // Host has disabled or misconfigured debug_backtrace(). $exception = new Tribe__Exception($e); $exception->handle(); } } // Class name was not set by debug_backtrace() hackery. if (null === $class_name) { tribe_notice('tribe_debug_backtrace_disabled', array(__CLASS__, 'notice_debug_backtrace')); } return $class_name; }