public function test_register() { //make sure nobody else interfers with this test $this->_stop_pretending_addon_hook_time(); remove_all_filters('FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders'); $pretend_addon_name = 'More_Core'; $args = array('dms_paths' => array(EE_TESTS_DIR . 'mocks/core/data_migration_scripts')); //try registering at wrong time try { EE_Register_Data_Migration_Scripts::register($pretend_addon_name, $args); $this->fail('We should have had a warning saying that we are setting up the ee addon at the wrong time'); } catch (PHPUnit_Framework_Error_Notice $e) { $this->assertTrue(True); } //and check we didn't actually register the DMSs (because we attempted to do so at teh wrong time) $DMSs_available = EE_Data_Migration_Manager::reset()->get_all_data_migration_scripts_available(); $this->assertArrayNotHasKey('EE_DMS_Core_1_0_0', $DMSs_available); //ok now pretend we're registering the DMS at the right time $this->_pretend_addon_hook_time(); EE_Register_Data_Migration_Scripts::register($pretend_addon_name, $args); $DMSs_available = EE_Data_Migration_Manager::reset()->get_all_data_migration_scripts_available(); $this->assertArrayHasKey('EE_DMS_Core_1_0_0', $DMSs_available); //now deregister it EE_Register_Data_Migration_Scripts::deregister($pretend_addon_name); $DMSs_available = EE_Data_Migration_Manager::reset()->get_all_data_migration_scripts_available(); $this->assertArrayNotHasKey('EE_DMS_Core_1_0_0', $DMSs_available); $this->_stop_pretending_addon_hook_time(); }
/** * Method for registering new EE_Addons. * Should be called AFTER AHEE__EE_System__load_espresso_addons but BEFORE AHEE__EE_System___detect_if_activation_or_upgrade__begin in order to register all its components. * However, it may also be called after the 'activate_plugin' action (when an addon is activated), * because an activating addon won't be loaded by WP until after AHEE__EE_System__load_espresso_addons has fired. * If its called after 'activate_plugin', it registers the addon still, but its components are not registered * (they shouldn't be needed anyways, because it's just an activation request and they won't have a chance to do anything anyways). Instead, it just sets the newly-activated addon's activation indicator wp option and returns * (so that we can detect that the addon has activated on the subsequent request) * * @since 4.3.0 * @param string $addon_name the EE_Addon's name. Required. * @param array $setup_args { An array of arguments provided for registering the message type. * @type string $class_name the addon's main file name. If left blank, generated from the addon name, changes something like "calendar" to "EE_Calendar" * @type string $min_core_version the minimum version of EE Core that the addon will work with. eg "4.8.1.rc.084" * @type string $version the "software" version for the addon. eg "1.0.0.p" for a first stable release, or "1.0.0.rc.043" for a version in progress * @type string $main_file_path the full server path to the main file loaded directly by WP * @type string $admin_path full server path to the folder where the addon\'s admin files reside * @type string $admin_callback a method to be called when the EE Admin is first invoked, can be used for hooking into any admin page * @type string $config_section the section name for this addon's configuration settings section (defaults to "addons") * @type string $config_class the class name for this addon's configuration settings object * @type string $config_name the class name for this addon's configuration settings object * @type string $autoloader_paths an array of class names and the full server paths to those files. Required. * @type string $autoloader_folders an array of "full server paths" for any folders containing classes that might be invoked by the addon * @type string $dms_paths an array of full server paths to folders that contain data migration scripts. Required. * @type string $module_paths an array of full server paths to any EED_Modules used by the addon * @type string $shortcode_paths an array of full server paths to folders that contain EES_Shortcodes * @type string $widget_paths an array of full server paths to folders that contain WP_Widgets * @type string $pue_options * @type array $capabilities { * an array indexed by role name (i.e. administrator,author ) and the values are an array of caps to add to the role. * 'administrator' => array('read_addon', 'edit_addon' etc.). * } * @type EE_Meta_Capability_Map[] $capability_maps an array of EE_Meta_Capability_Map object for any addons that need to register any special meta mapped capabilities. Should be indexed where the key is the EE_Meta_Capability_Map class name and the values are the arguments sent to the class. * @type array $model_paths array of folders containing DB models @see EE_Register_Model * @type array $class_paths array of folders containing DB classes @see EE_Register_Model * @type array $model_extension_paths array of folders containing DB model extensions @see EE_Register_Model_Extension * @type array $class_extension_paths array of folders containing DB class extensions @see EE_Register_Model_Extension * @type array message_types { * An array of message types with the key as the message type name and the values as below: * @type string $mtfilename The filename of the message type being registered. This will be the main * EE_{Messagetype_Name}_message_type class. (eg. EE_Declined_Registration_message_type.class.php). Required. * @type array $autoloadpaths An array of paths to add to the messages autoloader for the new message type. Required. * @type array $messengers_to_activate_with An array of messengers that this message * type should activate with. Each value in the array should match the name property of a EE_messenger. Optional. * @type array $messengers_to_validate_with An array of messengers that this message * type should validate with. Each value in the array should match the name property of an EE_messenger. Optional. * } * @type array $custom_post_types * @type array $custom_taxonomies * @type array $payment_method_paths each element is the folder containing the EE_PMT_Base child class * (eg, 'public_html/wp-content/plugins/my_plugin/Payomatic/' which contains the files * EE_PMT_Payomatic.pm.php) * @type array $default_terms * } * * @throws EE_Error * @return void */ public static function register($addon_name = '', $setup_args = array()) { // required fields MUST be present, so let's make sure they are. if (empty($addon_name) || !is_array($setup_args)) { throw new EE_Error(__('In order to register an EE_Addon with EE_Register_Addon::register(), you must include the "addon_name" (the name of the addon), and an array of arguments.', 'event_espresso')); } if (!isset($setup_args['main_file_path']) || empty($setup_args['main_file_path'])) { throw new EE_Error(sprintf(__('When registering an addon, you didn\'t provide the "main_file_path", which is the full path to the main file loaded directly by Wordpress. You only provided %s', 'event_espresso'), implode(",", array_keys($setup_args)))); } // check that addon has not already been registered with that name if (isset(self::$_settings[$addon_name]) && !did_action('activate_plugin')) { throw new EE_Error(sprintf(__('An EE_Addon with the name "%s" has already been registered and each EE_Addon requires a unique name.', 'event_espresso'), $addon_name)); } // no class name for addon? if (empty($setup_args['class_name'])) { // generate one by first separating name with spaces $class_name = str_replace(array('-', '_'), ' ', trim($addon_name)); //capitalize, then replace spaces with underscores $class_name = str_replace(' ', '_', ucwords($class_name)); } else { $class_name = $setup_args['class_name']; } $class_name = strpos($class_name, 'EE_') === 0 ? $class_name : 'EE_' . $class_name; //setup $_settings array from incoming values. $addon_settings = array('class_name' => $class_name, 'plugin_slug' => isset($setup_args['plugin_slug']) ? (string) $setup_args['plugin_slug'] : '', 'plugin_action_slug' => isset($setup_args['plugin_action_slug']) ? (string) $setup_args['plugin_action_slug'] : '', 'version' => isset($setup_args['version']) ? (string) $setup_args['version'] : '', 'min_core_version' => isset($setup_args['min_core_version']) ? (string) $setup_args['min_core_version'] : '', 'main_file_path' => isset($setup_args['main_file_path']) ? (string) $setup_args['main_file_path'] : '', 'admin_path' => isset($setup_args['admin_path']) ? (string) $setup_args['admin_path'] : '', 'admin_callback' => isset($setup_args['admin_callback']) ? (string) $setup_args['admin_callback'] : '', 'config_section' => isset($setup_args['config_section']) ? (string) $setup_args['config_section'] : 'addons', 'config_class' => isset($setup_args['config_class']) ? (string) $setup_args['config_class'] : '', 'config_name' => isset($setup_args['config_name']) ? (string) $setup_args['config_name'] : '', 'autoloader_paths' => isset($setup_args['autoloader_paths']) ? (array) $setup_args['autoloader_paths'] : array(), 'autoloader_folders' => isset($setup_args['autoloader_folders']) ? (array) $setup_args['autoloader_folders'] : array(), 'dms_paths' => isset($setup_args['dms_paths']) ? (array) $setup_args['dms_paths'] : array(), 'module_paths' => isset($setup_args['module_paths']) ? (array) $setup_args['module_paths'] : array(), 'shortcode_paths' => isset($setup_args['shortcode_paths']) ? (array) $setup_args['shortcode_paths'] : array(), 'widget_paths' => isset($setup_args['widget_paths']) ? (array) $setup_args['widget_paths'] : array(), 'pue_options' => isset($setup_args['pue_options']) ? (array) $setup_args['pue_options'] : array(), 'message_types' => isset($setup_args['message_types']) ? (array) $setup_args['message_types'] : array(), 'capabilities' => isset($setup_args['capabilities']) ? (array) $setup_args['capabilities'] : array(), 'capability_maps' => isset($setup_args['capability_maps']) ? (array) $setup_args['capability_maps'] : array(), 'model_paths' => isset($setup_args['model_paths']) ? (array) $setup_args['model_paths'] : array(), 'class_paths' => isset($setup_args['class_paths']) ? (array) $setup_args['class_paths'] : array(), 'model_extension_paths' => isset($setup_args['model_extension_paths']) ? (array) $setup_args['model_extension_paths'] : array(), 'class_extension_paths' => isset($setup_args['class_extension_paths']) ? (array) $setup_args['class_extension_paths'] : array(), 'custom_post_types' => isset($setup_args['custom_post_types']) ? (array) $setup_args['custom_post_types'] : array(), 'custom_taxonomies' => isset($setup_args['custom_taxonomies']) ? (array) $setup_args['custom_taxonomies'] : array(), 'payment_method_paths' => isset($setup_args['payment_method_paths']) ? (array) $setup_args['payment_method_paths'] : array(), 'default_terms' => isset($setup_args['default_terms']) ? (array) $setup_args['default_terms'] : array(), 'plugins_page_row' => isset($setup_args['plugins_page_row']) ? $setup_args['plugins_page_row'] : ''); // if plugin_action_slug is NOT set, but an admin page path IS set, then let's just use the plugin_slug since that will be used for linking to the admin page $addon_settings['plugin_action_slug'] = empty($addon_settings['plugin_action_slug']) && !empty($addon_settings['admin_path']) ? $addon_settings['plugin_slug'] : $addon_settings['plugin_action_slug']; // full server path to main file (file loaded directly by WP) $addon_settings['plugin_basename'] = plugin_basename($addon_settings['main_file_path']); //check whether this addon version is compatible with EE core if (isset(EE_Register_Addon::$_incompatible_addons[$addon_name]) && !self::_meets_min_core_version_requirement(EE_Register_Addon::$_incompatible_addons[$addon_name], $addon_settings['version'])) { $incompatibility_message = sprintf(__('The Event Espresso "%1$s" addon was deactivated because it is incompatible with this version of core.%2$s Only version %3$s or higher of "%1$s" can run with this version of core. This can happen when attempting to run beta versions or release candidates with older versions of core, or running old versions of addons with a newer version of core.%2$sPlease upgrade Event Espresso Core and the "%1$s" addon, then re-attempt activating it.', 'event_espresso'), $addon_name, '<br />', EE_Register_Addon::$_incompatible_addons[$addon_name]); } else { if (!self::_meets_min_core_version_requirement($setup_args['min_core_version'], espresso_version())) { $incompatibility_message = sprintf(__('The Event Espresso "%1$s" addon could not be activated because it requires Event Espresso Core version "%2$s" or higher in order to run.%4$sYour version of Event Espresso Core is currently at "%3$s". Please upgrade Event Espresso Core first and then re-attempt activating "%1$s".', 'event_espresso'), $addon_name, self::_effective_version($setup_args['min_core_version']), self::_effective_version(espresso_version()), '<br />'); } else { $incompatibility_message = ''; } } if (!empty($incompatibility_message)) { //remove 'activate' from the REQUEST so WP doesn't erroneously tell the user the //plugin activated fine when it didn't if (isset($_GET['activate'])) { unset($_GET['activate']); } if (isset($_REQUEST['activate'])) { unset($_REQUEST['activate']); } //and show an error message indicating the plugin didn't activate properly EE_Error::add_error($incompatibility_message, __FILE__, __FUNCTION__, __LINE__); if (current_user_can('activate_plugins')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; deactivate_plugins(plugin_basename($addon_settings['main_file_path']), TRUE); } return; } //this is an activation request if (did_action('activate_plugin')) { //to find if THIS is the addon that was activated, //just check if we have already registered it or not //(as the newly-activated addon wasn't around the first time addons were registered) if (!isset(self::$_settings[$addon_name])) { self::$_settings[$addon_name] = $addon_settings; $addon = self::_load_and_init_addon_class($addon_name); $addon->set_activation_indicator_option(); //dont bother setting up the rest of the addon. //we know it was just activated and the request will end soon } return; } else { // make sure this was called in the right place! if (!did_action('AHEE__EE_System__load_espresso_addons') || did_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin')) { EE_Error::doing_it_wrong(__METHOD__, sprintf(__('An attempt to register an EE_Addon named "%s" has failed because it was not registered at the correct time. Please use the "AHEE__EE_System__load_espresso_addons" hook to register addons.', 'event_espresso'), $addon_name), '4.3.0'); } self::$_settings[$addon_name] = $addon_settings; } // we need cars if (!empty(self::$_settings[$addon_name]['autoloader_paths'])) { // setup autoloader for single file EEH_Autoloader::instance()->register_autoloader(self::$_settings[$addon_name]['autoloader_paths']); } // setup autoloaders for folders if (!empty(self::$_settings[$addon_name]['autoloader_folders'])) { foreach (self::$_settings[$addon_name]['autoloader_folders'] as $autoloader_folder) { EEH_Autoloader::register_autoloaders_for_each_file_in_folder($autoloader_folder); } } // register new models if (!empty(self::$_settings[$addon_name]['model_paths']) || !empty(self::$_settings[$addon_name]['class_paths'])) { EE_Register_Model::register($addon_name, array('model_paths' => self::$_settings[$addon_name]['model_paths'], 'class_paths' => self::$_settings[$addon_name]['class_paths'])); } // register model extensions if (!empty(self::$_settings[$addon_name]['model_extension_paths']) || !empty(self::$_settings[$addon_name]['class_extension_paths'])) { EE_Register_Model_Extensions::register($addon_name, array('model_extension_paths' => self::$_settings[$addon_name]['model_extension_paths'], 'class_extension_paths' => self::$_settings[$addon_name]['class_extension_paths'])); } // setup DMS if (!empty(self::$_settings[$addon_name]['dms_paths'])) { EE_Register_Data_Migration_Scripts::register($addon_name, array('dms_paths' => self::$_settings[$addon_name]['dms_paths'])); } // if config_class is present let's register config. if (!empty(self::$_settings[$addon_name]['config_class'])) { EE_Register_Config::register(self::$_settings[$addon_name]['config_class'], array('config_section' => self::$_settings[$addon_name]['config_section'], 'config_name' => self::$_settings[$addon_name]['config_name'])); } // register admin page if (!empty(self::$_settings[$addon_name]['admin_path'])) { EE_Register_Admin_Page::register($addon_name, array('page_path' => self::$_settings[$addon_name]['admin_path'])); } // add to list of modules to be registered if (!empty(self::$_settings[$addon_name]['module_paths'])) { EE_Register_Module::register($addon_name, array('module_paths' => self::$_settings[$addon_name]['module_paths'])); } // add to list of shortcodes to be registered if (!empty(self::$_settings[$addon_name]['shortcode_paths'])) { EE_Register_Shortcode::register($addon_name, array('shortcode_paths' => self::$_settings[$addon_name]['shortcode_paths'])); } // add to list of widgets to be registered if (!empty(self::$_settings[$addon_name]['widget_paths'])) { EE_Register_Widget::register($addon_name, array('widget_paths' => self::$_settings[$addon_name]['widget_paths'])); } //register capability related stuff. if (!empty(self::$_settings[$addon_name]['capabilities'])) { EE_Register_Capabilities::register($addon_name, array('capabilities' => self::$_settings[$addon_name]['capabilities'], 'capability_maps' => self::$_settings[$addon_name]['capability_maps'])); } //any message type to register? if (!empty(self::$_settings[$addon_name]['message_types'])) { add_action('EE_Brewing_Regular___messages_caf', array('EE_Register_Addon', 'register_message_types')); } // if plugin update engine is being used for auto-updates (not needed if PUE is not being used) if (!empty($setup_args['pue_options'])) { self::$_settings[$addon_name]['pue_options'] = array('pue_plugin_slug' => isset($setup_args['pue_options']['pue_plugin_slug']) ? (string) $setup_args['pue_options']['pue_plugin_slug'] : 'espresso_' . strtolower($class_name), 'plugin_basename' => isset($setup_args['pue_options']['plugin_basename']) ? (string) $setup_args['pue_options']['plugin_basename'] : plugin_basename(self::$_settings[$addon_name]['main_file_path']), 'checkPeriod' => isset($setup_args['pue_options']['checkPeriod']) ? (string) $setup_args['pue_options']['checkPeriod'] : '24', 'use_wp_update' => isset($setup_args['pue_options']['use_wp_update']) ? (string) $setup_args['pue_options']['use_wp_update'] : FALSE); add_action('AHEE__EE_System__brew_espresso__after_pue_init', array('EE_Register_Addon', 'load_pue_update')); } //any custom post type/ custom capabilities or default terms to register if (!empty(self::$_settings[$addon_name]['custom_post_types']) || !empty(self::$_settings[$addon_name]['custom_taxonomies'])) { EE_Register_CPT::register($addon_name, array('cpts' => self::$_settings[$addon_name]['custom_post_types'], 'cts' => self::$_settings[$addon_name]['custom_taxonomies'], 'default_terms' => self::$_settings[$addon_name]['default_terms'])); } if (!empty(self::$_settings[$addon_name]['payment_method_paths'])) { EE_Register_Payment_Method::register($addon_name, array('payment_method_paths' => self::$_settings[$addon_name]['payment_method_paths'])); } // load and instantiate main addon class $addon = self::_load_and_init_addon_class($addon_name); // call any additional admin_callback functions during load_admin_controller hook if (!empty(self::$_settings[$addon_name]['admin_callback'])) { add_action('AHEE__EE_System__load_controllers__load_admin_controllers', array($addon, self::$_settings[$addon_name]['admin_callback'])); } }