diff --git a/admin_pages/messages/Messages_Admin_Page.core.php b/admin_pages/messages/Messages_Admin_Page.core.php index 8c03283c028..e2760ab3620 100644 --- a/admin_pages/messages/Messages_Admin_Page.core.php +++ b/admin_pages/messages/Messages_Admin_Page.core.php @@ -990,7 +990,7 @@ public function load_scripts_styles_settings() [], EVENT_ESPRESSO_VERSION ); - wp_enqueue_style('ee-text-links'); + wp_enqueue_style('ee-text-links-css'); wp_enqueue_style('ee-message-settings'); wp_enqueue_script('ee-messages-settings'); } diff --git a/admin_pages/payments/Payments_Admin_Page.core.php b/admin_pages/payments/Payments_Admin_Page.core.php index 93d267172da..26e11a2117a 100644 --- a/admin_pages/payments/Payments_Admin_Page.core.php +++ b/admin_pages/payments/Payments_Admin_Page.core.php @@ -242,6 +242,7 @@ public function load_scripts_styles() { // styles wp_enqueue_style('espresso-ui-theme'); + wp_enqueue_style('ee-text-links-css'); wp_register_style( 'espresso_payments', EE_PAYMENTS_ASSETS_URL . 'ee-payments.css', @@ -250,7 +251,7 @@ public function load_scripts_styles() ); // scripts wp_enqueue_script('ee_admin_js'); - wp_enqueue_script('ee-text-links'); + wp_enqueue_script('ee-text-links-js'); wp_enqueue_script( 'espresso_payments', EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js', @@ -264,7 +265,7 @@ public function load_scripts_styles() public function load_scripts_styles_default() { wp_enqueue_style('espresso_payments'); - wp_enqueue_style('ee-text-links'); + wp_enqueue_style('ee-text-links-css'); } diff --git a/core/EE_Dependency_Map.core.php b/core/EE_Dependency_Map.core.php index 257795f4281..d5b32d30562 100644 --- a/core/EE_Dependency_Map.core.php +++ b/core/EE_Dependency_Map.core.php @@ -485,6 +485,9 @@ protected function _register_core_dependencies() 'EventEspresso\core\services\session\SessionStartHandler' => EE_Dependency_Map::load_from_cache, 'EE_Encryption' => EE_Dependency_Map::load_from_cache, ], + 'EventEspresso\core\services\session\SessionStartHandler' => [ + 'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache, + ], 'EE_Cart' => [ 'EE_Session' => EE_Dependency_Map::load_from_cache, ], diff --git a/core/EE_Registry.core.php b/core/EE_Registry.core.php index b2280358c51..20c1a9601a3 100644 --- a/core/EE_Registry.core.php +++ b/core/EE_Registry.core.php @@ -1020,12 +1020,12 @@ public function clear_cached_class( ): bool { $class_abbreviation = $this->get_class_abbreviation($class_name); // check if class has already been loaded, and return it if it has been - if (isset($this->{$class_abbreviation})) { + if (isset($this->{$class_abbreviation}) && ! $this->{$class_abbreviation} instanceof InterminableInterface) { $this->{$class_abbreviation} = null; return true; } $class_name = str_replace('\\', '_', $class_name); - if (isset($this->{$class_name})) { + if (isset($this->{$class_name}) && ! $this->{$class_name} instanceof InterminableInterface) { $this->{$class_name} = null; return true; } @@ -1033,9 +1033,12 @@ public function clear_cached_class( $this->addons->remove($class_name); return true; } - $class_name = $this->object_identifier->getIdentifier($class_name, $arguments); - if ($this->LIB->has($class_name)) { - $this->LIB->remove($class_name); + $object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments); + if ( + $this->LIB->has($object_identifier) + && ! $this->LIB->get($object_identifier) instanceof InterminableInterface + ) { + $this->LIB->remove($object_identifier); return true; } return false; @@ -1382,9 +1385,7 @@ protected function _resolve_dependencies( $param_class = str_replace(' ', '_', $param_class); } // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime) - $param_class = $this->class_cache->isAlias($param_class, $class_name) - ? $this->class_cache->getFqnForAlias($param_class, $class_name) - : $param_class; + $param_class = $this->class_cache->getFqnForAlias($param_class, $class_name); if ( // param is not even a class ($param_class === null || $this->parameterIsPrimitive($param_class)) @@ -1498,7 +1499,7 @@ protected function _resolve_dependency(string $class_name, string $param_class, * in the EE_Dependency_Map::$_class_loaders array, * including the class prefix, ie: "EE_", "EEM_", "EEH_", etc * @param array $arguments - * @return object + * @return mixed */ public static function factory(string $classname, array $arguments = []) { @@ -1522,6 +1523,10 @@ public static function factory(string $classname, array $arguments = []) public function getAddon(string $class_name): ?EE_Addon { $class_name = str_replace('\\', '_', $class_name); + $addon = $this->_get_cached_class($class_name); + if ($addon) { + return $addon; + } return $this->addons->{$class_name} ?? null; } @@ -1648,28 +1653,59 @@ public function reset_model(string $model_name): ?EEM_Base * @return EE_Registry * @throws EE_Error * @throws ReflectionException + * @throws InvalidArgumentException */ public static function reset(bool $hard = false, bool $reinstantiate = true, bool $reset_models = true): EE_Registry { - $instance = self::instance(); - $instance->_cache_on = true; - // reset some "special" classes - EEH_Activation::reset(); - $hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard); - $instance->CFG = EE_Config::reset($hard, $reinstantiate); - $instance->CART = null; - $instance->MRM = null; - // messages reset - EED_Messages::reset(); - // handle of objects cached on LIB - foreach (['LIB', 'modules'] as $cache) { - foreach ($instance->{$cache} as $class_name => $class) { - if (self::_reset_and_unset_object($class, $reset_models)) { - unset($instance->{$cache}->{$class_name}); + $hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard); + $cached_properties = [ + 'BUS', + 'CART', + 'CFG', + 'LIB', + 'MRM', + 'REQ', + 'SSN', + 'AssetsRegistry', + // 'addons', + // 'models', + 'modules', + 'shortcodes', + 'widgets', + ]; + foreach ($cached_properties as $cached_property) { + // if (EE_UnitTestCase::$debug) { + // echo "\n\n" . __LINE__ . ') ' . strtoupper($cached_property); + // } + if ( + ! property_exists(self::$_instance, $cached_property) + || ! isset(self::$_instance->{$cached_property}) + ) { + continue; + } + $cached = self::$_instance->{$cached_property}; + if (is_array($cached) || $cached instanceof RegistryContainer) { + foreach ($cached as $class_name => $class) { + if (self::_reset_object($class_name, $class, $reset_models, $hard, $reinstantiate)) { + // because unset() doesn't guarantee object destruction + self::$_instance->{$cached_property}->{$class_name} = null; + unset(self::$_instance->{$cached_property}->{$class_name}); + } + } + continue; + } + if (is_object($cached)) { + if (self::_reset_object(get_class($cached), $cached, $reset_models, $hard, $reinstantiate)) { + // because unset() doesn't guarantee object destruction + self::$_instance->{$cached_property} = null; + unset(self::$_instance->{$cached_property}); } } } - return $instance; + // if (EE_UnitTestCase::$debug) { + // echo "\n\n"; + // } + return self::$_instance; } @@ -1678,37 +1714,82 @@ public static function reset(bool $hard = false, bool $reinstantiate = true, boo * if passed object implements InterminableInterface, then return false, * to indicate that it should NOT be cleared from the Registry cache * - * @param $object - * @param bool $reset_models + * @param string $class_name + * @param $object + * @param bool $reset_models + * @param bool $hard + * @param bool $reinstantiate * @return bool returns true if cached object should be unset * @throws EE_Error * @throws ReflectionException */ - private static function _reset_and_unset_object($object, bool $reset_models): bool - { + private static function _reset_object( + string $class_name, + $object, + bool $reset_models, + bool $hard, + bool $reinstantiate + ): bool { + // if (EE_UnitTestCase::$debug) { + // echo "\n\n - reset $class_name"; + // } if (! is_object($object)) { + // if (EE_UnitTestCase::$debug) { + // echo "\n --> not an object"; + // } // don't unset anything that's not an object return false; } + if ($object instanceof InterminableInterface) { + // if (EE_UnitTestCase::$debug) { + // echo "\n --> NO (interminable)"; + // } + // don't unset anything that's not terminable + return false; + } if ($object instanceof EED_Module) { $object::reset(); + // if (EE_UnitTestCase::$debug) { + // echo "\n --> NO (module)"; + // } // don't unset modules return false; } if ($object instanceof ResettableInterface) { + // reset some "special" classes + if ($object instanceof EE_Config) { + EE_Config::reset($hard, $reinstantiate); + // if (EE_UnitTestCase::$debug) { + // echo "\n --> NO (config)"; + // } + return false; + } + if ($object instanceof EEH_Activation) { + EEH_Activation::reset(); + // if (EE_UnitTestCase::$debug) { + // echo "\n --> NO (activation)"; + // } + return false; + } if ($object instanceof EEM_Base) { if ($reset_models) { - $object->reset(); - return true; + self::$_instance->reset_model($class_name); } return false; } - $object->reset(); - return true; - } - if (! $object instanceof InterminableInterface) { - return true; + if (method_exists($object, 'reset') && is_callable([$object, 'reset'])) { + // if (EE_UnitTestCase::$debug) { + // echo "\n --> NO (has reset)"; + // } + $object->reset(); + return false; + } } + // if (EE_UnitTestCase::$debug) { + // echo "\n --> YES ??? " . get_class($object); + // } + // at least clear object from cache + self::$_instance->clear_cached_class(get_class($object)); return false; } diff --git a/core/EE_Session.core.php b/core/EE_Session.core.php index 74b7919eb10..8f51842ef15 100644 --- a/core/EE_Session.core.php +++ b/core/EE_Session.core.php @@ -23,18 +23,19 @@ */ class EE_Session implements SessionIdentifierInterface { - const session_id_prefix = 'ee_ssn_'; + const session_id_prefix = 'ee_ssn_'; - const hash_check_prefix = 'ee_shc_'; + const hash_check_prefix = 'ee_shc_'; const OPTION_NAME_SETTINGS = 'ee_session_settings'; - const STATUS_CLOSED = 0; + const STATUS_CLOSED = 0; - const STATUS_OPEN = 1; + const STATUS_OPEN = 1; - const SAVE_STATE_CLEAN = 'clean'; - const SAVE_STATE_DIRTY = 'dirty'; + const SAVE_STATE_CLEAN = 'clean'; + + const SAVE_STATE_DIRTY = 'dirty'; /** @@ -78,7 +79,7 @@ class EE_Session implements SessionIdentifierInterface * * @var array */ - private $_session_data = array(); + private $_session_data = []; /** * how long an EE session lasts @@ -142,7 +143,7 @@ class EE_Session implements SessionIdentifierInterface * * @var array */ - private $_default_session_vars = array( + private $_default_session_vars = [ 'id' => null, 'user_id' => null, 'ip_address' => null, @@ -150,8 +151,8 @@ class EE_Session implements SessionIdentifierInterface 'init_access' => null, 'last_access' => null, 'expiration' => null, - 'pages_visited' => array(), - ); + 'pages_visited' => [], + ]; /** * timestamp for when last garbage collection cycle was performed @@ -182,15 +183,12 @@ class EE_Session implements SessionIdentifierInterface /** * @singleton method used to instantiate class object - * @param CacheStorageInterface $cache_storage - * @param SessionLifespan|null $lifespan - * @param RequestInterface $request - * @param SessionStartHandler $session_start_handler - * @param EE_Encryption $encryption - * @return EE_Session - * @throws InvalidArgumentException - * @throws InvalidDataTypeException - * @throws InvalidInterfaceException + * @param CacheStorageInterface|null $cache_storage + * @param SessionLifespan|null $lifespan + * @param RequestInterface|null $request + * @param SessionStartHandler|null $session_start_handler + * @param EE_Encryption|null $encryption + * @return EE_Session|null */ public static function instance( CacheStorageInterface $cache_storage = null, @@ -198,7 +196,7 @@ public static function instance( RequestInterface $request = null, SessionStartHandler $session_start_handler = null, EE_Encryption $encryption = null - ) { + ): ?EE_Session { // check if class object is instantiated // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: // add_filter( 'FHEE_load_EE_Session', '__return_false' ); @@ -229,10 +227,7 @@ public static function instance( * @param SessionLifespan $lifespan * @param RequestInterface $request * @param SessionStartHandler $session_start_handler - * @param EE_Encryption $encryption - * @throws InvalidArgumentException - * @throws InvalidDataTypeException - * @throws InvalidInterfaceException + * @param EE_Encryption|null $encryption */ protected function __construct( CacheStorageInterface $cache_storage, @@ -249,18 +244,18 @@ protected function __construct( return; } $this->session_start_handler = $session_start_handler; - $this->session_lifespan = $lifespan; - $this->request = $request; + $this->session_lifespan = $lifespan; + $this->request = $request; if (! defined('ESPRESSO_SESSION')) { define('ESPRESSO_SESSION', true); } // retrieve session options from db - $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array()); + $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, []); if (! empty($session_settings)) { // cycle though existing session options foreach ($session_settings as $var_name => $session_setting) { // set values for class properties - $var_name = '_' . $var_name; + $var_name = '_' . $var_name; $this->{$var_name} = $session_setting; } } @@ -271,16 +266,15 @@ protected function __construct( // encrypt data via: $this->encryption->encrypt(); $this->encryption = $encryption; // filter hook allows outside functions/classes/plugins to change default empty cart - $extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array()); - array_merge($this->_default_session_vars, $extra_default_session_vars); + $this->_default_session_vars += apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', []); // apply default session vars $this->_set_defaults(); - add_action('AHEE__EE_System__initialize', array($this, 'open_session')); + add_action('AHEE__EE_System__initialize', [$this, 'open_session']); // check request for 'clear_session' param - add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded')); + add_action('AHEE__EE_Request_Handler__construct__complete', [$this, 'wp_loaded']); // once everything is all said and done, - add_action('shutdown', array($this, 'update'), 100); - add_action('shutdown', array($this, 'garbageCollection'), 1000); + add_action('shutdown', [$this, 'update'], 100); + add_action('shutdown', [$this, 'garbageCollection'], 1000); $this->configure_garbage_collection_filters(); } @@ -291,7 +285,7 @@ protected function __construct( * @throws InvalidDataTypeException * @throws InvalidInterfaceException */ - public static function isLoadedAndActive() + public static function isLoadedAndActive(): bool { return did_action('AHEE__EE_System__core_loaded_and_ready') && EE_Session::instance() instanceof EE_Session @@ -302,7 +296,7 @@ public static function isLoadedAndActive() /** * @return bool */ - public function isActive() + public function isActive(): bool { return $this->status === EE_Session::STATUS_OPEN; } @@ -331,7 +325,7 @@ public function open_session() /** * @return bool */ - public function expired() + public function expired(): bool { return $this->_expired; } @@ -349,7 +343,7 @@ public function reset_expired() /** * @return int */ - public function expiration() + public function expiration(): int { return $this->_expiration; } @@ -358,7 +352,7 @@ public function expiration() /** * @return int */ - public function extension() + public function extension(): int { return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS); } @@ -367,9 +361,9 @@ public function extension() /** * @param int $time number of seconds to add to session expiration */ - public function extend_expiration($time = 0) + public function extend_expiration(int $time = 0) { - $time = $time ? $time : $this->extension(); + $time = $time ?: $this->extension(); $this->_expiration += absint($time); } @@ -377,7 +371,7 @@ public function extend_expiration($time = 0) /** * @return int */ - public function lifespan() + public function lifespan(): int { return $this->session_lifespan->inSeconds(); } @@ -392,7 +386,7 @@ public function lifespan() * * @param string $save_state */ - public function setSaveState($save_state = EE_Session::SAVE_STATE_DIRTY) + public function setSaveState(string $save_state = EE_Session::SAVE_STATE_DIRTY) { $valid_save_states = [ EE_Session::SAVE_STATE_CLEAN, @@ -405,7 +399,6 @@ public function setSaveState($save_state = EE_Session::SAVE_STATE_DIRTY) } - /** * This just sets some defaults for the _session data property * @@ -416,7 +409,7 @@ private function _set_defaults() // set some defaults foreach ($this->_default_session_vars as $key => $default_var) { if (is_array($default_var)) { - $this->_session_data[ $key ] = array(); + $this->_session_data[ $key ] = []; } else { $this->_session_data[ $key ] = ''; } @@ -428,17 +421,17 @@ private function _set_defaults() * @retrieve session data * @return string */ - public function id() + public function id(): string { return $this->_sid; } /** - * @param \EE_Cart $cart + * @param EE_Cart $cart * @return bool */ - public function set_cart(EE_Cart $cart) + public function set_cart(EE_Cart $cart): bool { $this->_session_data['cart'] = $cart; $this->setSaveState(); @@ -458,9 +451,9 @@ public function reset_cart() /** - * @return \EE_Cart + * @return EE_Cart */ - public function cart() + public function cart(): ?EE_Cart { return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart ? $this->_session_data['cart'] @@ -469,10 +462,10 @@ public function cart() /** - * @param \EE_Checkout $checkout + * @param EE_Checkout $checkout * @return bool */ - public function set_checkout(EE_Checkout $checkout) + public function set_checkout(EE_Checkout $checkout): bool { $this->_session_data['checkout'] = $checkout; $this->setSaveState(); @@ -492,9 +485,9 @@ public function reset_checkout() /** - * @return \EE_Checkout + * @return EE_Checkout */ - public function checkout() + public function checkout(): ?EE_Checkout { return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout ? $this->_session_data['checkout'] @@ -503,11 +496,12 @@ public function checkout() /** - * @param \EE_Transaction $transaction + * @param EE_Transaction $transaction * @return bool * @throws EE_Error + * @throws ReflectionException */ - public function set_transaction(EE_Transaction $transaction) + public function set_transaction(EE_Transaction $transaction): bool { // first remove the session from the transaction before we save the transaction in the session $transaction->set_txn_session_data(null); @@ -529,9 +523,9 @@ public function reset_transaction() /** - * @return \EE_Transaction + * @return EE_Transaction */ - public function transaction() + public function transaction(): ?EE_Transaction { return isset($this->_session_data['transaction']) && $this->_session_data['transaction'] instanceof EE_Transaction @@ -545,9 +539,9 @@ public function transaction() * * @param null $key * @param bool $reset_cache - * @return array + * @return mixed */ - public function get_session_data($key = null, $reset_cache = false) + public function get_session_data($key = null, bool $reset_cache = false) { if ($reset_cache) { $this->reset_cart(); @@ -555,7 +549,7 @@ public function get_session_data($key = null, $reset_cache = false) $this->reset_transaction(); } if (! empty($key)) { - return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null; + return $this->_session_data[ $key ] ?? null; } return $this->_session_data; } @@ -564,10 +558,10 @@ public function get_session_data($key = null, $reset_cache = false) /** * Returns TRUE on success, FALSE on fail * - * @param array $data + * @param array|null $data * @return bool */ - public function set_session_data($data) + public function set_session_data(?array $data): bool { // nothing ??? bad data ??? go home! if (empty($data) || ! is_array($data)) { @@ -616,7 +610,7 @@ public function set_session_data($data) * @throws RuntimeException * @throws ReflectionException */ - private function _espresso_session() + private function _espresso_session(): bool { do_action('AHEE_log', __FILE__, __FUNCTION__, ''); $this->session_start_handler->startSession(); @@ -633,9 +627,7 @@ private function _espresso_session() // get the current time in UTC $this->_time = $this->_time !== null ? $this->_time : time(); // and reset the session expiration - $this->_expiration = isset($session_data['expiration']) - ? $session_data['expiration'] - : $this->_time + $this->session_lifespan->inSeconds(); + $this->_expiration = $session_data['expiration'] ?? $this->_time + $this->session_lifespan->inSeconds(); } else { // set initial site access time and the session expiration $this->_set_init_access_and_expiration(); @@ -675,15 +667,16 @@ private function _espresso_session() * @throws InvalidDataTypeException * @throws InvalidInterfaceException * @throws RuntimeException + * @throws ReflectionException */ - protected function _retrieve_session_data() + protected function _retrieve_session_data(): array { $ssn_key = EE_Session::session_id_prefix . $this->_sid; try { // we're using WP's Transient API to store session data using the PHP session ID as the option name $session_data = $this->cache_storage->get($ssn_key, false); if (empty($session_data)) { - return array(); + return []; } if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { $hash_check = $this->cache_storage->get( @@ -708,7 +701,7 @@ protected function _retrieve_session_data() } catch (Exception $e) { // let's just eat that error for now and attempt to correct any corrupted data global $wpdb; - $row = $wpdb->get_row( + $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", '_transient_' . $ssn_key @@ -781,7 +774,7 @@ function ($match) { * * @return string */ - protected function _generate_session_id() + protected function _generate_session_id(): string { // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length $session_id = $this->request->requestParamIsSet('EESID') @@ -792,11 +785,9 @@ protected function _generate_session_id() /** - * _get_sid_salt - * * @return string */ - protected function _get_sid_salt() + protected function _get_sid_salt(): string { // was session id salt already saved to db ? if (empty($this->_sid_salt)) { @@ -810,20 +801,18 @@ protected function _get_sid_salt() $this->_sid_salt = wp_generate_password(64); } // and save it as a permanent session setting - $this->updateSessionSettings(array('sid_salt' => $this->_sid_salt)); + $this->updateSessionSettings(['sid_salt' => $this->_sid_salt]); } return $this->_sid_salt; } /** - * _set_init_access_and_expiration - * * @return void */ protected function _set_init_access_and_expiration() { - $this->_time = time(); + $this->_time = time(); $this->_expiration = $this->_time + $this->session_lifespan->inSeconds(); // set initial site access time $this->_session_data['init_access'] = $this->_time; @@ -842,15 +831,15 @@ protected function _set_init_access_and_expiration() * @throws InvalidInterfaceException * @throws ReflectionException */ - public function update($new_session = false) + public function update(bool $new_session = false): bool { $this->_session_data = is_array($this->_session_data) && isset($this->_session_data['id']) ? $this->_session_data - : array(); + : []; if (empty($this->_session_data)) { $this->_set_defaults(); } - $session_data = array(); + $session_data = []; foreach ($this->_session_data as $key => $value) { switch ($key) { case 'id': @@ -925,13 +914,15 @@ private function _create_espresso_session() $this->update(true); } + /** * Detects if there is anything worth saving in the session (eg the cart is a good one, notices are pretty good * too). This is used when determining if we want to save the session or not. - * @since 4.9.67.p + * * @return bool + * @since 4.9.67.p */ - private function sessionHasStuffWorthSaving() + private function sessionHasStuffWorthSaving(): bool { return $this->save_state === EE_Session::SAVE_STATE_DIRTY // we may want to eventually remove the following @@ -959,7 +950,7 @@ private function sessionHasStuffWorthSaving() * @throws InvalidInterfaceException * @throws ReflectionException */ - private function _save_session_to_db($clear_session = false) + private function _save_session_to_db(bool $clear_session = false): bool { // don't save sessions for crawlers // and unless we're deleting the session data, don't save anything if there isn't a cart @@ -1009,17 +1000,17 @@ private function _save_session_to_db($clear_session = false) * @get the full page request the visitor is accessing * @return string */ - public function _get_page_visit() + public function _get_page_visit(): string { $page_visit = home_url('/') . 'wp-admin/admin-ajax.php'; // check for request url if ($this->request->serverParamIsSet('REQUEST_URI')) { - $page_id = '?'; - $e_reg = ''; + $page_id = '?'; + $e_reg = ''; $request_uri = $this->request->getServerParam('REQUEST_URI'); - $ru_bits = explode('?', $request_uri); + $ru_bits = explode('?', $request_uri); $request_uri = $ru_bits[0]; - $http_host = $this->request->getServerParam('HTTP_HOST'); + $http_host = $this->request->getServerParam('HTTP_HOST'); // check for page_id in SERVER REQUEST if ($this->request->requestParamIsSet('page_id')) { // rebuild $e_reg without any of the extra parameters @@ -1040,7 +1031,7 @@ public function _get_page_visit() * @the current wp user id * @return int */ - public function _wp_user_id() + public function _wp_user_id(): ?int { // if I need to explain the following lines of code, then you shouldn't be looking at this! $this->_wp_user_id = get_current_user_id(); @@ -1060,13 +1051,13 @@ public function _wp_user_id() * @throws InvalidInterfaceException * @throws ReflectionException */ - public function clear_session($class = '', $function = '') + public function clear_session(string $class = '', string $function = '') { -// echo ' -//
'; $data2 = preg_replace_callback( @@ -1246,39 +1237,39 @@ function ($match) { }, $data1 ); - $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2); + $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2); $error .= $data1 . PHP_EOL; $error .= $data2 . PHP_EOL; for ($i = 0; $i < $max; $i++) { if (@$data1[ $i ] !== @$data2[ $i ]) { - $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL; - $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL; - $error .= "\t-> Line Number = $i" . PHP_EOL; - $start = ($i - 20); - $start = ($start < 0) ? 0 : $start; + $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL; + $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL; + $error .= "\t-> Line Number = $i" . PHP_EOL; + $start = ($i - 20); + $start = ($start < 0) ? 0 : $start; $length = 40; - $point = $max - $i; + $point = $max - $i; if ($point < 20) { - $rlength = 1; - $rpoint = -$point; + $rLength = 1; + $rPoint = -$point; } else { - $rpoint = $length - 20; - $rlength = 1; + $rPoint = $length - 20; + $rLength = 1; } $error .= "\t-> Section Data1 = "; $error .= substr_replace( substr($data1, $start, $length), "{$data1[ $i ]}", - $rpoint, - $rlength + $rPoint, + $rLength ); $error .= PHP_EOL; $error .= "\t-> Section Data2 = "; $error .= substr_replace( substr($data2, $start, $length), "{$data2[ $i ]}", - $rpoint, - $rlength + $rPoint, + $rLength ); $error .= PHP_EOL; } @@ -1293,10 +1284,10 @@ function ($match) { * * @param array $updated_settings */ - private function updateSessionSettings(array $updated_settings = array()) + private function updateSessionSettings(array $updated_settings = []) { // add existing settings, but only if not included in incoming $updated_settings array - $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array()); + $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, []); update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings); } @@ -1309,7 +1300,7 @@ public function garbageCollection() // only perform during regular requests if last garbage collection was over an hour ago if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { $this->_last_gc = time(); - $this->updateSessionSettings(array('last_gc' => $this->_last_gc)); + $this->updateSessionSettings(['last_gc' => $this->_last_gc]); /** @type WPDB $wpdb */ global $wpdb; // filter the query limit. Set to 0 to turn off garbage collection @@ -1321,12 +1312,12 @@ public function garbageCollection() ); // non-zero LIMIT means take out the trash if ($expired_session_transient_delete_query_limit) { - $session_key = str_replace('_', '\_', EE_Session::session_id_prefix); + $session_key = str_replace('_', '\_', EE_Session::session_id_prefix); $hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix); // since transient expiration timestamps are set in the future, we can compare against NOW // but we only want to pick up any trash that's been around for more than a day $expiration = time() - DAY_IN_SECONDS; - $SQL = " + $SQL = " SELECT option_name FROM {$wpdb->options} WHERE @@ -1342,7 +1333,7 @@ public function garbageCollection() // AND option_value < 1508368198 LIMIT 50 $expired_sessions = $wpdb->get_col($SQL); // valid results? - if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { + if (! empty($expired_sessions)) { $this->cache_storage->deleteMany($expired_sessions, true); } } diff --git a/core/db_classes/EE_Base_Class.class.php b/core/db_classes/EE_Base_Class.class.php index 8e313c0b010..87acd886c3c 100644 --- a/core/db_classes/EE_Base_Class.class.php +++ b/core/db_classes/EE_Base_Class.class.php @@ -1848,9 +1848,8 @@ public function save($set_cols_n_values = array()) // if the object already has an ID, update it. Otherwise, insert it // also: change the assumption about values passed to the model NOT being prepare dby the model object. // They have been - $old_assumption_concerning_value_preparation = $model - ->get_assumption_concerning_values_already_prepared_by_model_object(); - $model->assume_values_already_prepared_by_model_object(true); + $old_assumption_concerning_value_preparation = $model->get_assumption_concerning_values_already_prepared_by_model_object(); + $model->assume_values_already_prepared_by_model_object(EEM_Base::prepared_by_model_object); // does this model have an autoincrement PK? if ($model->has_primary_key_field()) { if ($model->get_primary_key_field()->is_auto_increment()) { diff --git a/core/db_models/EEM_Base.model.php b/core/db_models/EEM_Base.model.php index 6e33d961471..2db1361d005 100644 --- a/core/db_models/EEM_Base.model.php +++ b/core/db_models/EEM_Base.model.php @@ -45,7 +45,7 @@ abstract class EEM_Base extends EE_Base implements ResettableInterface * * @var boolean */ - private $_values_already_prepared_by_model_object = 0; + private $_values_already_prepared_by_model_object = EEM_Base::not_prepared_by_model_object; /** * when $_values_already_prepared_by_model_object equals this, we assume @@ -581,6 +581,7 @@ protected function __construct($timezone = null) if (empty(EEM_Base::$_model_query_blog_id)) { EEM_Base::set_model_query_blog_id(); } + $this->_values_already_prepared_by_model_object = EEM_Base::not_prepared_by_model_object; /** * Filters the list of tables on a model. It is best to NOT use this directly and instead * just use EE_Register_Model_Extension @@ -1552,9 +1553,10 @@ public function get_formats_for($field_name, $pretty = false) * formatted string matching the set format for the field in the set timezone will * be returned. * @param string $what Whether to return the string in just the time format, the date format, or both. - * @return int|string If the given field_name is not of the EE_Datetime_Field type, then an EE_Error + * @return string If the given field_name is not of the EE_Datetime_Field type, then an EE_Error * exception is triggered. - * @throws EE_Error If the given field_name is not of the EE_Datetime_Field type. + * @throws Exception + * @throws EE_Error If the given field_name is not of the EE_Datetime_Field type.* * @since 4.6.x */ public function current_time_for_query($field_name, $timestamp = false, $what = 'both') @@ -1568,13 +1570,10 @@ public function current_time_for_query($field_name, $timestamp = false, $what = switch ($what) { case 'time': return $DateTime->format($formats[1]); - break; case 'date': return $DateTime->format($formats[0]); - break; default: return $DateTime->format(implode(' ', $formats)); - break; } } @@ -1835,9 +1834,9 @@ public function get_col($query_params = [], $field_to_select = null) } elseif ($this->has_primary_key_field()) { $field = $this->get_primary_key_field(); } else { - // no primary key, just grab the first column $field_settings = $this->field_settings(); - $field = reset($field_settings); + // no primary key, just grab the first column + $field = reset($field_settings); } $model_query_info = $this->_create_model_query_info_carrier($query_params); $select_expressions = $field->get_qualified_column(); @@ -2459,7 +2458,6 @@ private function _process_wpdb_query($wpdb_method, $arguments_to_provide) case EEM_Base::db_verified_addons: // ummmm... you in trouble return $result; - break; } if (! empty($error_message)) { EE_Log::instance()->log(__FILE__, __FUNCTION__, $error_message, 'error'); @@ -2478,6 +2476,7 @@ private function _process_wpdb_query($wpdb_method, $arguments_to_provide) * @param string $wpdb_method * @param array $arguments_to_provide * @return string + * @throws EE_Error */ private function _verify_core_db($wpdb_method, $arguments_to_provide) { @@ -5830,7 +5829,7 @@ public function ensure_is_ID($base_class_obj_or_id) * @return void */ public function assume_values_already_prepared_by_model_object( - $values_already_prepared = self::not_prepared_by_model_object + int $values_already_prepared = self::not_prepared_by_model_object ) { $this->_values_already_prepared_by_model_object = $values_already_prepared; } diff --git a/core/db_models/EEM_Event.model.php b/core/db_models/EEM_Event.model.php index 189f4e3005b..0e17ed27c11 100644 --- a/core/db_models/EEM_Event.model.php +++ b/core/db_models/EEM_Event.model.php @@ -87,9 +87,10 @@ protected function __construct($timezone = null) ), ) ); - self::$_default_reg_status = empty(self::$_default_reg_status) + self::$_default_reg_status = empty(EE_Registry::instance()->CFG->registration->default_STS_ID) ? EEM_Registration::status_id_pending_payment - : self::$_default_reg_status; + : EE_Registry::instance()->CFG->registration->default_STS_ID; + $this->_tables = array( 'Event_CPT' => new EE_Primary_Table('posts', 'ID'), 'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'), diff --git a/core/db_models/EEM_Payment.model.php b/core/db_models/EEM_Payment.model.php index be2de1d2212..06cb4ad3e9d 100644 --- a/core/db_models/EEM_Payment.model.php +++ b/core/db_models/EEM_Payment.model.php @@ -1,49 +1,39 @@ singular_item = esc_html__('Payment', 'event_espresso'); - $this->plural_item = esc_html__('Payments', 'event_espresso'); - - $this->_tables = array( - 'Payment' => new EE_Primary_Table('esp_payment', 'PAY_ID') - ); - $this->_fields = array( - 'Payment' => array( - 'PAY_ID' => new EE_Primary_Key_Int_Field('PAY_ID', esc_html__('Payment ID', 'event_espresso')), - 'TXN_ID' => new EE_Foreign_Key_Int_Field('TXN_ID', esc_html__('Transaction ID', 'event_espresso'), false, 0, 'Transaction'), - 'STS_ID' => new EE_Foreign_Key_String_Field('STS_ID', esc_html__('Status ID', 'event_espresso'), false, EEM_Payment::status_id_failed, 'Status'), - 'PAY_timestamp' => new EE_Datetime_Field('PAY_timestamp', esc_html__('Timestamp of when payment was attempted', 'event_espresso'), false, EE_Datetime_Field::now, $timezone), - 'PAY_source' => new EE_All_Caps_Text_Field('PAY_source', esc_html__('User-friendly description of payment', 'event_espresso'), false, 'CART'), - 'PAY_amount' => new EE_Money_Field('PAY_amount', esc_html__('Amount Payment should be for', 'event_espresso'), false, 0), - 'PMD_ID' => new EE_Foreign_Key_Int_Field('PMD_ID', esc_html__("Payment Method ID", 'event_espresso'), false, null, 'Payment_Method'), - 'PAY_gateway_response' => new EE_Plain_Text_Field('PAY_gateway_response', esc_html__('Response from Gateway about the payment', 'event_espresso'), false, ''), - 'PAY_txn_id_chq_nmbr' => new EE_Plain_Text_Field('PAY_txn_id_chq_nmbr', esc_html__('Gateway Transaction ID or Cheque Number', 'event_espresso'), true, ''), - 'PAY_po_number' => new EE_Plain_Text_Field('PAY_po_number', esc_html__('Purchase or Sales Number', 'event_espresso'), true, ''), - 'PAY_extra_accntng' => new EE_Simple_HTML_Field('PAY_extra_accntng', esc_html__('Extra Account Info', 'event_espresso'), true, ''), - 'PAY_details' => new EE_Serialized_Text_Field('PAY_details', esc_html__('Full Gateway response about payment', 'event_espresso'), true, ''), - 'PAY_redirect_url' => new EE_Plain_Text_Field('PAY_redirect_url', esc_html__("Redirect URL", 'event_espresso'), true), - 'PAY_redirect_args' => new EE_Serialized_Text_Field('PAY_redirect_args', esc_html__("Key-Value POST vars to send along with redirect", 'event_espresso'), true) - ) - ); - $this->_model_relations = array( - 'Transaction' => new EE_Belongs_To_Relation(), - 'Status' => new EE_Belongs_To_Relation(), - 'Payment_Method' => new EE_Belongs_To_Relation(), + $this->plural_item = esc_html__('Payments', 'event_espresso'); + + $this->_tables = [ + 'Payment' => new EE_Primary_Table('esp_payment', 'PAY_ID'), + ]; + $this->_fields = [ + 'Payment' => [ + 'PAY_ID' => new EE_Primary_Key_Int_Field( + 'PAY_ID', + esc_html__('Payment ID', 'event_espresso') + ), + 'TXN_ID' => new EE_Foreign_Key_Int_Field( + 'TXN_ID', + esc_html__('Transaction ID', 'event_espresso'), + false, + 0, + 'Transaction' + ), + 'STS_ID' => new EE_Foreign_Key_String_Field( + 'STS_ID', + esc_html__('Status ID', 'event_espresso'), + false, + EEM_Payment::status_id_failed, + 'Status' + ), + 'PAY_timestamp' => new EE_Datetime_Field( + 'PAY_timestamp', + esc_html__( + 'Timestamp of when payment was attempted', + 'event_espresso' + ), + false, + EE_Datetime_Field::now, + $timezone + ), + 'PAY_source' => new EE_All_Caps_Text_Field( + 'PAY_source', + esc_html__( + 'User-friendly description of payment', + 'event_espresso' + ), + false, + 'CART' + ), + 'PAY_amount' => new EE_Money_Field( + 'PAY_amount', + esc_html__('Amount Payment should be for', 'event_espresso'), + false + ), + 'PMD_ID' => new EE_Foreign_Key_Int_Field( + 'PMD_ID', + esc_html__("Payment Method ID", 'event_espresso'), + false, + null, + 'Payment_Method' + ), + 'PAY_gateway_response' => new EE_Plain_Text_Field( + 'PAY_gateway_response', + esc_html__( + 'Response from Gateway about the payment', + 'event_espresso' + ), + false, + '' + ), + 'PAY_txn_id_chq_nmbr' => new EE_Plain_Text_Field( + 'PAY_txn_id_chq_nmbr', + esc_html__( + 'Gateway Transaction ID or Cheque Number', + 'event_espresso' + ), + true, + '' + ), + 'PAY_po_number' => new EE_Plain_Text_Field( + 'PAY_po_number', + esc_html__( + 'Purchase or Sales Number', + 'event_espresso' + ), + true, + '' + ), + 'PAY_extra_accntng' => new EE_Simple_HTML_Field( + 'PAY_extra_accntng', + esc_html__('Extra Account Info', 'event_espresso'), + true, + '' + ), + 'PAY_details' => new EE_Serialized_Text_Field( + 'PAY_details', + esc_html__( + 'Full Gateway response about payment', + 'event_espresso' + ), + true, + '' + ), + 'PAY_redirect_url' => new EE_Plain_Text_Field( + 'PAY_redirect_url', + esc_html__("Redirect URL", 'event_espresso'), + true + ), + 'PAY_redirect_args' => new EE_Serialized_Text_Field( + 'PAY_redirect_args', + esc_html__( + "Key-Value POST vars to send along with redirect", + 'event_espresso' + ), + true + ), + ], + ]; + + $this->_model_relations = [ + 'Transaction' => new EE_Belongs_To_Relation(), + 'Status' => new EE_Belongs_To_Relation(), + 'Payment_Method' => new EE_Belongs_To_Relation(), 'Registration_Payment' => new EE_Has_Many_Relation(), - 'Registration' => new EE_HABTM_Relation('Registration_Payment'), - ); + 'Registration' => new EE_HABTM_Relation('Registration_Payment'), + ]; $this->_model_chain_to_wp_user = 'Payment_Method'; - $this->_caps_slug = 'transactions'; + $this->_caps_slug = 'transactions'; parent::__construct($timezone); } - - /** * Gets the payment by the gateway server's unique ID. Eg, the unique ID PayPal assigned * to the payment. This is handy for verifying an IPN hasn't already been processed. + * * @param string $PAY_txn_id_chq_nmbr - * @return EE_Payment + * @return EE_Payment|null + * @throws EE_Error */ - public function get_payment_by_txn_id_chq_nmbr($PAY_txn_id_chq_nmbr) + public function get_payment_by_txn_id_chq_nmbr($PAY_txn_id_chq_nmbr): ?EE_Payment { - return $this->get_one(array(array('PAY_txn_id_chq_nmbr' => $PAY_txn_id_chq_nmbr))); + return $this->get_one([['PAY_txn_id_chq_nmbr' => $PAY_txn_id_chq_nmbr]]); } - - /** - * retrieve all payments from db for a particular transaction, optionally with - * a particular status - * - * @access public - * @param $TXN_ID - * @param string $status_of_payment one of EEM_Payment::status_id_*, like 'PAP','PCN',etc. If none is provided, gets payments with any status - * @return EE_Payment[] - */ - public function get_payments_for_transaction($TXN_ID = false, $status_of_payment = null) + * retrieve all payments from db for a particular transaction, optionally with a particular status + * + * @param int $TXN_ID + * @param string|null $status_of_payment one of EEM_Payment::status_id_*, like 'PAP','PCN',etc. If none is provided, + * gets + * payments with any status + * @return EE_Payment[] + * @throws EE_Error + */ + public function get_payments_for_transaction(int $TXN_ID = 0, ?string $status_of_payment = null): array { // all payments for a TXN ordered chronologically - $query_params = array( array( 'TXN_ID' => $TXN_ID ), 'order_by' => array( 'PAY_timestamp' => 'ASC' )); + $query_params = [['TXN_ID' => $TXN_ID], 'order_by' => ['PAY_timestamp' => 'ASC']]; // if provided with a status, search specifically for that status. Otherwise get them all if ($status_of_payment) { $query_params[0]['STS_ID'] = $status_of_payment; @@ -135,44 +222,51 @@ public function get_payments_for_transaction($TXN_ID = false, $status_of_payment } - /** * Only gets payments which have been approved + * * @param int $TXN_ID * @return EE_Payment[] + * @throws EE_Error */ - public function get_approved_payments_for_transaction($TXN_ID = 0) + public function get_approved_payments_for_transaction(int $TXN_ID = 0): array { return $this->get_payments_for_transaction($TXN_ID, EEM_Payment::status_id_approved); } - - - /** * retrieve all payments from db between two dates, * - * @param string $start_date incoming start date. If empty the beginning of today is used. - * @param string $end_date incoming end date. If empty the end of today is used. - * @param string $format If you include $start_date or $end_date then you must include the format string - * for the format your date is in. - * @param string $timezone If your range is in a different timezone then the current setting on this + * @param string $start_date incoming start date. If empty the beginning of today is used. + * @param string $end_date incoming end date. If empty the end of today is used. + * @param string $format If you include $start_date or $end_date then you must include the format string + * for the format your date is in. + * @param string $timezone If your range is in a different timezone then the current setting on this * WordPress install, then include it here. + * @return EE_Payment[] * @throws EE_Error * - * @return EE_Payment[] */ - public function get_payments_made_between_dates($start_date = '', $end_date = '', $format = '', $timezone = '') - { + public function get_payments_made_between_dates( + string $start_date = '', + string $end_date = '', + string $format = '', + string $timezone = '' + ): array { $timezone = empty($timezone) ? EEH_DTT_Helper::get_timezone() : $timezone; // if $start_date or $end date, verify $format is included. - if (( ! empty($start_date) || ! empty($end_date) ) && empty($format)) { - throw new EE_Error(esc_html__('You included a start date and/or a end date for this method but did not include a format string. The format string is needed for setting up the query', 'event_espresso')); + if ((! empty($start_date) || ! empty($end_date)) && empty($format)) { + throw new EE_Error( + esc_html__( + 'You included a start date and/or a end date for this method but did not include a format string. The format string is needed for setting up the query', + 'event_espresso' + ) + ); } $now = new DateTime('now'); // setup timezone objects once - $modelDateTimeZone = new DateTimeZone($this->_timezone); + $modelDateTimeZone = new DateTimeZone($this->_timezone); $passedDateTimeZone = new DateTimeZone($timezone); // setup start date $start_date = ! empty($start_date) ? date_create_from_format($format, $start_date, $passedDateTimeZone) : $now; @@ -187,55 +281,77 @@ public function get_payments_made_between_dates($start_date = '', $end_date = '' // make sure our start date is the lowest value and vice versa $start = min($start_date, $end_date); - $end = max($start_date, $end_date); - - // yes we generated the date and time string in utc but we WANT this start date and time used in the set timezone on the model. - $start_date = $this->convert_datetime_for_query('PAY_timestamp', date('Y-m-d', $start) . ' 00:00:00', 'Y-m-d H:i:s', $this->get_timezone()); - $end_date = $this->convert_datetime_for_query('PAY_timestamp', date('Y-m-d', $end) . ' 23:59:59', 'Y-m-d H:i:s', $this->get_timezone()); + $end = max($start_date, $end_date); + + // yes we generated the date and time string in utc + // but we WANT this start date and time used in the set timezone on the model. + $start_date = $this->convert_datetime_for_query( + 'PAY_timestamp', + date('Y-m-d', $start) . ' 00:00:00', + 'Y-m-d H:i:s', + $this->get_timezone() + ); + $end_date = $this->convert_datetime_for_query( + 'PAY_timestamp', + date('Y-m-d', $end) . ' 23:59:59', + 'Y-m-d H:i:s', + $this->get_timezone() + ); - return $this->get_all(array(array('PAY_timestamp' => array('>=',$start_date),'PAY_timestamp*' => array('<=',$end_date)))); + return $this->get_all([['PAY_timestamp' => ['>=', $start_date], 'PAY_timestamp*' => ['<=', $end_date]]]); } - /** - * methods for EEMI_Payment - */ + /** * returns a string for the approved status - * @return string + * + * @return string */ - public function approved_status() + public function approved_status(): string { return self::status_id_approved; } + + /** * returns a string for the pending status - * @return string + * + * @return string */ - public function pending_status() + public function pending_status(): string { return self::status_id_pending; } + + /** * returns a string for the cancelled status - * @return string + * + * @return string */ - public function cancelled_status() + public function cancelled_status(): string { return self::status_id_cancelled; } + + /** * returns a string for the failed status - * @return string + * + * @return string */ - public function failed_status() + public function failed_status(): string { return self::status_id_failed; } + + /** * returns a string for the declined status - * @return string + * + * @return string */ - public function declined_status() + public function declined_status(): string { return self::status_id_declined; } diff --git a/core/db_models/EEM_WP_User.model.php b/core/db_models/EEM_WP_User.model.php index 59c7c0f3590..114549a04ac 100644 --- a/core/db_models/EEM_WP_User.model.php +++ b/core/db_models/EEM_WP_User.model.php @@ -65,7 +65,8 @@ protected function __construct($timezone, ModelFieldFactory $model_field_factory 'user_registered' => $model_field_factory->createDatetimeField( 'user_registered', esc_html__('Date User Registered', 'event_espresso'), - $timezone + $timezone, + false ), 'user_activation_key' => $model_field_factory->createPlainTextField( 'user_activation_key', @@ -125,7 +126,7 @@ protected function __construct($timezone, ModelFieldFactory $model_field_factory * @return string * @throws EE_Error */ - public function wp_user_field_name() + public function wp_user_field_name(): string { return $this->primary_key_name(); } @@ -136,7 +137,7 @@ public function wp_user_field_name() * * @return boolean */ - public function is_owned() + public function is_owned(): bool { return true; } diff --git a/core/domain/entities/custom_post_types/CustomTaxonomyDefinitions.php b/core/domain/entities/custom_post_types/CustomTaxonomyDefinitions.php index f82fc2f5db1..7c4b25d192a 100644 --- a/core/domain/entities/custom_post_types/CustomTaxonomyDefinitions.php +++ b/core/domain/entities/custom_post_types/CustomTaxonomyDefinitions.php @@ -3,6 +3,7 @@ namespace EventEspresso\core\domain\entities\custom_post_types; use EEH_URL; +use EventEspresso\core\interfaces\InterminableInterface; /** * Class CustomTaxonomyDefinitions @@ -12,7 +13,7 @@ * @author Darren Ethier / Brent Christensen * @since 4.9.62.p */ -class CustomTaxonomyDefinitions +class CustomTaxonomyDefinitions implements InterminableInterface { /** * @var array $taxonomies @@ -104,7 +105,7 @@ private function setTaxonomies() /** * @return array */ - public function getCustomTaxonomyDefinitions() + public function getCustomTaxonomyDefinitions(): array { return (array) apply_filters( 'FHEE__EventEspresso_core_domain_entities_custom_post_types_TaxonomyDefinitions__getTaxonomies', @@ -121,7 +122,7 @@ public function getCustomTaxonomyDefinitions() /** * @return array */ - public function getCustomTaxonomySlugs() + public function getCustomTaxonomySlugs(): array { return array_keys($this->getCustomTaxonomyDefinitions()); } @@ -142,7 +143,7 @@ public function getCustomTaxonomySlugs() * @param string $taxonomy The taxonomy name for the taxonomy being filtered. * @return string */ - public function filterCustomTermDescription($description, $taxonomy) + public function filterCustomTermDescription(string $description, string $taxonomy): string { // get a list of EE taxonomies $custom_taxonomies = $this->getCustomTaxonomySlugs(); diff --git a/core/domain/entities/routing/specifications/RouteMatchSpecificationInterface.php b/core/domain/entities/routing/specifications/RouteMatchSpecificationInterface.php index 615a25be96e..6e79b1efddf 100644 --- a/core/domain/entities/routing/specifications/RouteMatchSpecificationInterface.php +++ b/core/domain/entities/routing/specifications/RouteMatchSpecificationInterface.php @@ -2,6 +2,8 @@ namespace EventEspresso\core\domain\entities\routing\specifications; +use EventEspresso\core\interfaces\InterminableInterface; + /** * Class RouteMatchSpecificationInterface * Variation of the Specification design pattern for matching current request to specific routes @@ -10,7 +12,7 @@ * @author Brent Christensen * @since 4.9.71.p */ -interface RouteMatchSpecificationInterface +interface RouteMatchSpecificationInterface extends InterminableInterface { /** * returns true if current request matches specification diff --git a/core/domain/services/assets/CoreAssetManager.php b/core/domain/services/assets/CoreAssetManager.php index 8c39bf23b22..0bad03bb679 100644 --- a/core/domain/services/assets/CoreAssetManager.php +++ b/core/domain/services/assets/CoreAssetManager.php @@ -30,15 +30,17 @@ class CoreAssetManager extends AssetManager { // WordPress core / Third party JS asset handles - const JS_HANDLE_JS_CORE = 'eejs-core'; - const JS_HANDLE_CORE = 'espresso_core'; + const JS_HANDLE_JS_CORE = 'eejs-core'; + const JS_HANDLE_I18N = 'eei18n'; + const JS_HANDLE_RAMDA = 'ramda'; + const JS_HANDLE_VENDOR = 'eventespresso-vendor'; - const JS_HANDLE_RAMDA = 'ramda'; + const JS_HANDLE_WP_PLUGINS_PAGE = 'eventespresso-wp-plugins-page-js'; const RAMDA_VERSION = '0.27.1'; @@ -47,6 +49,8 @@ class CoreAssetManager extends AssetManager const CSS_HANDLE_CUSTOM = 'espresso_custom_css'; + const CSS_HANDLE_WP_PLUGINS_PAGE = 'eventespresso-wp-plugins-page-css'; + /** * @var EE_Currency_Config $currency_config */ diff --git a/core/domain/services/assets/EspressoLegacyAdminAssetManager.php b/core/domain/services/assets/EspressoLegacyAdminAssetManager.php index 30cf4d2ce8c..1016ffc7efa 100644 --- a/core/domain/services/assets/EspressoLegacyAdminAssetManager.php +++ b/core/domain/services/assets/EspressoLegacyAdminAssetManager.php @@ -35,7 +35,7 @@ class EspressoLegacyAdminAssetManager extends AssetManager const JS_HANDLE_PARSE_URI = 'ee-parse-uri'; - const JS_HANDLE_EE_TEXT_LINKS = 'ee-text-links'; + const JS_HANDLE_EE_TEXT_LINKS = 'ee-text-links-js'; const JS_HANDLE_EE_SERIALIZE_FULL_ARRAY = 'ee-serialize-full-array'; @@ -47,7 +47,7 @@ class EspressoLegacyAdminAssetManager extends AssetManager const CSS_HANDLE_EE_JOYRIDE = 'ee-joyride-css'; - const CSS_HANDLE_EE_TEXT_LINKS = 'ee-text-links'; + const CSS_HANDLE_EE_TEXT_LINKS = 'ee-text-links-css'; const CSS_HANDLE_EE_UI_THEME = 'espresso-ui-theme'; diff --git a/core/domain/services/contexts/RequestTypeContextCheckerInterface.php b/core/domain/services/contexts/RequestTypeContextCheckerInterface.php index 7dc1438e606..5764d861540 100644 --- a/core/domain/services/contexts/RequestTypeContextCheckerInterface.php +++ b/core/domain/services/contexts/RequestTypeContextCheckerInterface.php @@ -2,6 +2,8 @@ namespace EventEspresso\core\domain\services\contexts; +use EventEspresso\core\interfaces\InterminableInterface; + /** * RequestTypeContextCheckerInterface * Service class that provides useful methods for evaluating the current request type @@ -10,7 +12,7 @@ * @author Brent Christensen * @since 4.9.53 */ -interface RequestTypeContextCheckerInterface +interface RequestTypeContextCheckerInterface extends InterminableInterface { /** * true if the current request involves some form of activation diff --git a/core/domain/services/contexts/RequestTypeContextDetector.php b/core/domain/services/contexts/RequestTypeContextDetector.php index 0d134f3fbf7..f97aeab708e 100644 --- a/core/domain/services/contexts/RequestTypeContextDetector.php +++ b/core/domain/services/contexts/RequestTypeContextDetector.php @@ -3,6 +3,7 @@ namespace EventEspresso\core\domain\services\contexts; use EventEspresso\core\domain\Domain; +use EventEspresso\core\interfaces\InterminableInterface; use EventEspresso\core\services\graphql\GraphQLEndpoint; use EventEspresso\core\services\request\RequestInterface; use EventEspresso\core\domain\entities\contexts\RequestTypeContext; @@ -16,7 +17,7 @@ * @author Brent Christensen * @since 4.9.51 */ -class RequestTypeContextDetector +class RequestTypeContextDetector implements InterminableInterface { /** * @var GraphQLEndpoint $gql_endpoint diff --git a/core/domain/services/contexts/RequestTypeContextFactory.php b/core/domain/services/contexts/RequestTypeContextFactory.php index 9fbe8d2cf5e..c6fb7f5d825 100644 --- a/core/domain/services/contexts/RequestTypeContextFactory.php +++ b/core/domain/services/contexts/RequestTypeContextFactory.php @@ -37,7 +37,7 @@ public function __construct(LoaderInterface $loader) * @param string $slug * @return RequestTypeContext */ - public function create($slug) + public function create($slug): RequestTypeContext { switch ($slug) { case RequestTypeContext::ACTIVATION: diff --git a/core/domain/services/contexts/RequestTypeContextFactoryInterface.php b/core/domain/services/contexts/RequestTypeContextFactoryInterface.php index de6b3932f1c..d1cf6eab3d7 100644 --- a/core/domain/services/contexts/RequestTypeContextFactoryInterface.php +++ b/core/domain/services/contexts/RequestTypeContextFactoryInterface.php @@ -3,6 +3,7 @@ namespace EventEspresso\core\domain\services\contexts; use EventEspresso\core\domain\entities\contexts\RequestTypeContext; +use EventEspresso\core\interfaces\InterminableInterface; /** * RequestTypeContextFactoryInterface @@ -12,7 +13,7 @@ * @author Brent Christensen * @since 4.9.51 */ -interface RequestTypeContextFactoryInterface +interface RequestTypeContextFactoryInterface extends InterminableInterface { /** * @param string $slug diff --git a/core/domain/services/custom_post_types/RewriteRules.php b/core/domain/services/custom_post_types/RewriteRules.php index e7cc4f1c3a1..388a9fc7b71 100644 --- a/core/domain/services/custom_post_types/RewriteRules.php +++ b/core/domain/services/custom_post_types/RewriteRules.php @@ -2,6 +2,8 @@ namespace EventEspresso\core\domain\services\custom_post_types; +use EventEspresso\core\interfaces\InterminableInterface; + /** * Class RewriteRules * Manages the flushing of rewrite rules @@ -10,7 +12,7 @@ * @author Brent Christensen * @since 4.9.62.p */ -class RewriteRules +class RewriteRules implements InterminableInterface { const OPTION_KEY_FLUSH_REWRITE_RULES = 'ee_flush_rewrite_rules'; diff --git a/core/domain/services/factories/CartFactory.php b/core/domain/services/factories/CartFactory.php index 8e57fd8deea..def51a5adc1 100644 --- a/core/domain/services/factories/CartFactory.php +++ b/core/domain/services/factories/CartFactory.php @@ -3,10 +3,7 @@ namespace EventEspresso\core\domain\services\factories; use EE_Cart; -use EventEspresso\core\exceptions\InvalidDataTypeException; -use EventEspresso\core\exceptions\InvalidInterfaceException; use EventEspresso\core\services\loaders\LoaderFactory; -use InvalidArgumentException; /** * Class CartFactory @@ -16,16 +13,13 @@ * @author Brent Christensen * @since 4.9.59.p */ -class CartFactory +class CartFactory extends LoaderFactory { /** * @return EE_Cart - * @throws InvalidArgumentException - * @throws InvalidInterfaceException - * @throws InvalidDataTypeException */ - public static function getCart() + public static function getCart(): EE_Cart { - return LoaderFactory::getLoader()->getShared('EE_Cart'); + return CartFactory::getShared('EE_Cart'); } } diff --git a/core/domain/services/factories/EmailAddressFactory.php b/core/domain/services/factories/EmailAddressFactory.php index 08dea80d1a3..532d5d993b3 100644 --- a/core/domain/services/factories/EmailAddressFactory.php +++ b/core/domain/services/factories/EmailAddressFactory.php @@ -3,11 +3,9 @@ namespace EventEspresso\core\domain\services\factories; use EventEspresso\core\domain\services\validation\email\EmailValidationException; +use EventEspresso\core\domain\services\validation\email\EmailValidationService; use EventEspresso\core\domain\values\EmailAddress; -use EventEspresso\core\exceptions\InvalidDataTypeException; -use EventEspresso\core\exceptions\InvalidInterfaceException; use EventEspresso\core\services\loaders\LoaderFactory; -use InvalidArgumentException; /** * Class EmailAddressFactory @@ -16,21 +14,49 @@ * @package EventEspresso\core\domain\services\factories * @author Brent Christensen */ -class EmailAddressFactory implements FactoryInterface +class EmailAddressFactory extends LoaderFactory implements FactoryInterface { + /** + * @var EmailValidationService + * @since $VID:$ + */ + private static $validator; + + + /** + * @return EmailValidationService + */ + public static function getValidator(): EmailValidationService + { + if (! EmailAddressFactory::$validator instanceof EmailValidationService) { + EmailAddressFactory::setValidator(EmailAddressFactory::getShared(EmailValidationService::class)); + } + return EmailAddressFactory::$validator; + } + + + /** + * @param EmailValidationService $validator + */ + public static function setValidator(EmailValidationService $validator): void + { + EmailAddressFactory::$validator = $validator; + } + + /** * @param string $email_address * @return EmailAddress * @throws EmailValidationException - * @throws InvalidDataTypeException - * @throws InvalidInterfaceException - * @throws InvalidArgumentException */ - public static function create($email_address) + public static function create($email_address): EmailAddress { - return LoaderFactory::getLoader()->getNew( - 'EventEspresso\core\domain\values\EmailAddress', - array($email_address) + return EmailAddressFactory::getNew( + EmailAddress::class, + [ + $email_address, + EmailAddressFactory::getValidator() + ] ); } } diff --git a/core/domain/services/factories/ModelFactory.php b/core/domain/services/factories/ModelFactory.php index 0dbbd4d01a1..ea39ebb9a12 100644 --- a/core/domain/services/factories/ModelFactory.php +++ b/core/domain/services/factories/ModelFactory.php @@ -2,13 +2,8 @@ namespace EventEspresso\core\domain\services\factories; -use EE_Error; -use EE_Registry; use EEM_Base; -use EventEspresso\core\exceptions\InvalidDataTypeException; -use EventEspresso\core\exceptions\InvalidInterfaceException; -use InvalidArgumentException; -use ReflectionException; +use EventEspresso\core\services\loaders\LoaderFactory; /** * Class ModelFactory @@ -18,19 +13,14 @@ * @author Brent Christensen * @since 4.9.59.p */ -class ModelFactory +class ModelFactory extends LoaderFactory { /** * @param string $model_name * @return bool|EEM_Base - * @throws EE_Error - * @throws InvalidDataTypeException - * @throws InvalidInterfaceException - * @throws InvalidArgumentException - * @throws ReflectionException */ - public static function getModel($model_name) + public static function getModel(string $model_name) { - return EE_Registry::instance()->load_model($model_name); + return ModelFactory::getShared($model_name); } } diff --git a/core/domain/services/validation/email/EmailValidationService.php b/core/domain/services/validation/email/EmailValidationService.php index a6c532761d7..98ce65355f2 100644 --- a/core/domain/services/validation/email/EmailValidationService.php +++ b/core/domain/services/validation/email/EmailValidationService.php @@ -3,6 +3,10 @@ namespace EventEspresso\core\domain\services\validation\email; use EE_Registration_Config; +use EventEspresso\core\domain\services\validation\email\strategies\Basic; +use EventEspresso\core\domain\services\validation\email\strategies\International; +use EventEspresso\core\domain\services\validation\email\strategies\InternationalDNS; +use EventEspresso\core\domain\services\validation\email\strategies\WordPress; use EventEspresso\core\services\loaders\Loader; /** @@ -15,16 +19,46 @@ */ class EmailValidationService implements EmailValidatorInterface { + public const VALIDATION_LEVEL_BASIC = 'basic'; + + public const VALIDATION_LEVEL_I18N = 'i18n'; + + public const VALIDATION_LEVEL_I18N_DNS = 'i18n_dns'; + + public const VALIDATION_LEVEL_WP_DEFAULT = 'wp_default'; + + /** - * @var EE_Registration_Config $registration_config + * @var EE_Registration_Config */ protected $registration_config; /** - * @var Loader $loader + * @var Loader */ protected $loader; + /** + * @var Basic + */ + private $validator_basic; + + /** + * @var International + */ + private $validator_i18n; + + /** + * @var InternationalDNS + */ + private $validator_i18n_dns; + + /** + * @var WordPress + */ + private $validator_wordpress; + + /** * EmailValidationService constructor. @@ -44,36 +78,78 @@ public function __construct(EE_Registration_Config $config, Loader $loader) * Validates the email address. If it's invalid, an EmailValidationException * is thrown that describes why its invalid. * - * @param string $email_address + * @param string|null $email_address * @return boolean - * @throws EmailValidationException */ - public function validate($email_address) + public function validate(?string $email_address): bool { // pick the correct validator according to the config switch ($this->registration_config->email_validation_level) { - case 'basic': - $validator = $this->loader->getShared( - 'EventEspresso\core\domain\services\validation\email\strategies\Basic' - ); - break; - case 'i18n': - $validator = $this->loader->getShared( - 'EventEspresso\core\domain\services\validation\email\strategies\International' - ); - break; - case 'i18n_dns': - $validator = $this->loader->getShared( - 'EventEspresso\core\domain\services\validation\email\strategies\InternationalDNS' - ); - break; - case 'wp_default': + case EmailValidationService::VALIDATION_LEVEL_BASIC: + return $this->basicValidator()->validate($email_address); + case EmailValidationService::VALIDATION_LEVEL_I18N: + return $this->i18nValidator()->validate($email_address); + case EmailValidationService::VALIDATION_LEVEL_I18N_DNS: + return $this->i18nDnsValidator()->validate($email_address); + case EmailValidationService::VALIDATION_LEVEL_WP_DEFAULT: default: - $validator = $this->loader->getShared( - 'EventEspresso\core\domain\services\validation\email\strategies\WordPress' - ); - break; + return $this->wordpressValidator()->validate($email_address); + } + } + + + /** + * @return Basic + */ + public function basicValidator(): Basic + { + if (! $this->validator_basic instanceof Basic) { + $this->validator_basic = $this->loader->getShared( + 'EventEspresso\core\domain\services\validation\email\strategies\Basic' + ); + } + return $this->validator_basic; + } + + + /** + * @return International + */ + public function i18nValidator(): International + { + if (! $this->validator_i18n instanceof Basic) { + $this->validator_i18n = $this->loader->getShared( + 'EventEspresso\core\domain\services\validation\email\strategies\International' + ); + } + return $this->validator_i18n; + } + + + /** + * @return InternationalDNS + */ + public function i18nDnsValidator(): InternationalDNS + { + if (! $this->validator_i18n_dns instanceof Basic) { + $this->validator_i18n_dns = $this->loader->getShared( + 'EventEspresso\core\domain\services\validation\email\strategies\InternationalDNS' + ); + } + return $this->validator_i18n_dns; + } + + + /** + * @return WordPress + */ + public function wordpressValidator(): WordPress + { + if (! $this->validator_wordpress instanceof Basic) { + $this->validator_wordpress = $this->loader->getShared( + 'EventEspresso\core\domain\services\validation\email\strategies\WordPress' + ); } - return $validator->validate($email_address); + return $this->validator_wordpress; } } diff --git a/core/domain/services/validation/email/EmailValidatorInterface.php b/core/domain/services/validation/email/EmailValidatorInterface.php index 78220f691ba..ec7d4e11296 100644 --- a/core/domain/services/validation/email/EmailValidatorInterface.php +++ b/core/domain/services/validation/email/EmailValidatorInterface.php @@ -16,9 +16,9 @@ interface EmailValidatorInterface /** * Validates the supplied email address. If it is invalid, throws EmailValidationException * - * @param string $email_address + * @param string|null $email_address * @return boolean * @throws EmailValidationException */ - public function validate($email_address); + public function validate(?string $email_address): bool; } diff --git a/core/domain/services/validation/email/strategies/Basic.php b/core/domain/services/validation/email/strategies/Basic.php index 52e5a949a0d..3f6a2d16b38 100644 --- a/core/domain/services/validation/email/strategies/Basic.php +++ b/core/domain/services/validation/email/strategies/Basic.php @@ -15,11 +15,11 @@ class Basic implements EmailValidatorInterface { /** - * @param string $email_address + * @param string|null $email_address * @return bool * @throws EmailValidationException */ - public function validate($email_address) + public function validate(?string $email_address): bool { if (! preg_match('/^.+\@\S+$/', (string) $email_address)) { // email not in correct {string}@{string} format diff --git a/core/domain/services/validation/email/strategies/International.php b/core/domain/services/validation/email/strategies/International.php index 33b0bc80266..eaff1282805 100644 --- a/core/domain/services/validation/email/strategies/International.php +++ b/core/domain/services/validation/email/strategies/International.php @@ -15,11 +15,11 @@ class International extends Basic { /** - * @param string $email_address + * @param string|null $email_address * @return bool * @throws \EventEspresso\core\domain\services\validation\email\EmailValidationException */ - public function validate($email_address) + public function validate(?string $email_address): bool { parent::validate($email_address); if ( diff --git a/core/domain/services/validation/email/strategies/InternationalDNS.php b/core/domain/services/validation/email/strategies/InternationalDNS.php index c30cf15b811..db5bb98fa4a 100644 --- a/core/domain/services/validation/email/strategies/InternationalDNS.php +++ b/core/domain/services/validation/email/strategies/InternationalDNS.php @@ -18,11 +18,11 @@ class InternationalDNS extends International * Validates the email in teh same way as the parent, but also * verifies the domain exists. * - * @param string $email_address + * @param string|null $email_address * @return bool * @throws EmailValidationException */ - public function validate($email_address) + public function validate(?string $email_address): bool { parent::validate($email_address); $domain = $this->getDomainPartOfEmail( diff --git a/core/domain/services/validation/email/strategies/WordPress.php b/core/domain/services/validation/email/strategies/WordPress.php index afee5b3a89e..63adf51cfdf 100644 --- a/core/domain/services/validation/email/strategies/WordPress.php +++ b/core/domain/services/validation/email/strategies/WordPress.php @@ -15,11 +15,11 @@ class WordPress extends Basic { /** - * @param string $email_address + * @param string|null $email_address * @return boolean * @throws EmailValidationException */ - public function validate($email_address) + public function validate(?string $email_address): bool { parent::validate($email_address); if (! is_email($email_address)) { diff --git a/core/domain/values/session/SessionLifespan.php b/core/domain/values/session/SessionLifespan.php index b3d9fad22b0..747740eca7f 100644 --- a/core/domain/values/session/SessionLifespan.php +++ b/core/domain/values/session/SessionLifespan.php @@ -34,7 +34,7 @@ class SessionLifespan * @param int $lifespan * @throws DomainException */ - public function __construct($lifespan = 0) + public function __construct(int $lifespan = 0) { $lifespan = absint($lifespan); $lifespan = $lifespan > 0 ? $lifespan : (int) HOUR_IN_SECONDS; @@ -46,7 +46,7 @@ public function __construct($lifespan = 0) * @param int $lifespan * @throws DomainException */ - protected function setLifespan($lifespan) + protected function setLifespan(int $lifespan) { if ($lifespan < 60) { throw new DomainException( @@ -70,7 +70,7 @@ protected function setLifespan($lifespan) /** * @return int */ - public function inSeconds() + public function inSeconds(): int { return $this->lifespan; } @@ -80,7 +80,7 @@ public function inSeconds() * @param string $separator * @return string */ - public function inHoursMinutesSeconds($separator = ':') + public function inHoursMinutesSeconds(string $separator = ':'): string { return sprintf( '%02d%s%02d%s%02d', @@ -100,7 +100,7 @@ public function inHoursMinutesSeconds($separator = ':') * If false, displays expiration in local time * @return int */ - public function expiration($utc = true) + public function expiration(bool $utc = true): int { return (int) current_time('timestamp', $utc) - $this->lifespan; } @@ -109,7 +109,7 @@ public function expiration($utc = true) /** * @return string */ - public function __toString() + public function __toString(): string { return (string) $this->inSeconds(); } diff --git a/core/helpers/EEH_Activation.helper.php b/core/helpers/EEH_Activation.helper.php index 4d14ac66e72..72fcdf1b348 100644 --- a/core/helpers/EEH_Activation.helper.php +++ b/core/helpers/EEH_Activation.helper.php @@ -587,7 +587,12 @@ public static function get_default_creator_id() } $capabilities_key = EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities'); $query = $wpdb->prepare( - "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1", + "SELECT user_id + FROM $wpdb->usermeta + WHERE meta_key = '$capabilities_key' + AND meta_value LIKE %s + ORDER BY user_id ASC + LIMIT 0,1", '%' . $role_to_check . '%' ); $user_id = $wpdb->get_var($query); @@ -595,9 +600,8 @@ public static function get_default_creator_id() if ($user_id && (int) $user_id) { self::$_default_creator_id = (int) $user_id; return self::$_default_creator_id; - } else { - return null; } + return null; } diff --git a/core/helpers/EEH_DTT_Helper.helper.php b/core/helpers/EEH_DTT_Helper.helper.php index a477ff8197e..b7b85769bbd 100644 --- a/core/helpers/EEH_DTT_Helper.helper.php +++ b/core/helpers/EEH_DTT_Helper.helper.php @@ -3,7 +3,7 @@ use EventEspresso\core\services\helpers\datetime\HelperInterface; use EventEspresso\core\exceptions\InvalidDataTypeException; use EventEspresso\core\exceptions\InvalidInterfaceException; -use EventEspresso\core\services\loaders\LoaderFactory; +use EventEspresso\core\services\helpers\datetime\PhpCompatGreaterFiveSixHelper; /** * EEH_DTT_Helper @@ -1035,10 +1035,11 @@ public static function get_user_locale($user_id = 0) */ private static function getHelperAdapter() { - $dtt_helper_fqcn = PHP_VERSION_ID < 50600 - ? 'EventEspresso\core\services\helpers\datetime\PhpCompatLessFiveSixHelper' - : 'EventEspresso\core\services\helpers\datetime\PhpCompatGreaterFiveSixHelper'; - return LoaderFactory::getLoader()->getShared($dtt_helper_fqcn); + static $dtt_helper_fqcn; + if (! $dtt_helper_fqcn instanceof PhpCompatGreaterFiveSixHelper) { + $dtt_helper_fqcn = new PhpCompatGreaterFiveSixHelper(); + } + return $dtt_helper_fqcn; } diff --git a/core/interfaces/EEI_Address_Formatter.interface.php b/core/interfaces/EEI_Address_Formatter.interface.php index cd5f1bd2ff7..41d7c0cdeca 100644 --- a/core/interfaces/EEI_Address_Formatter.interface.php +++ b/core/interfaces/EEI_Address_Formatter.interface.php @@ -14,5 +14,13 @@ interface EEI_Address_Formatter * @param string $country * @param string $CNT_ISO */ - public function format($address, $address2, $city, $state, $zip, $country, $CNT_ISO); + public function format( + string $address, + string $address2, + string $city, + string $state, + string $zip, + string $country, + string $CNT_ISO + ): ?string; } diff --git a/core/libraries/messages/data_class/EE_Messages_Preview_incoming_data.class.php b/core/libraries/messages/data_class/EE_Messages_Preview_incoming_data.class.php index 4214e7ba0ed..a92fba958b2 100644 --- a/core/libraries/messages/data_class/EE_Messages_Preview_incoming_data.class.php +++ b/core/libraries/messages/data_class/EE_Messages_Preview_incoming_data.class.php @@ -432,13 +432,11 @@ private function _get_some_events(array $event_ids = []) */ protected function _setup_data() { - // need to figure out the running total for test purposes so... we're going to create a temp cart and add the tickets to it! - if (EE_Registry::instance()->SSN instanceof EE_Session) { - EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__); - $session = EE_Registry::instance()->SSN; - } else { - $session = EE_Registry::instance()->load_core('Session'); - } + /** @var EE_Session $session */ + $session = LoaderFactory::getLoader()->getNew(EE_Session::class); + $session->clear_session(__CLASS__, __FUNCTION__); + // need to figure out the running total for test purposes so... + // we're going to create a temp cart and add the tickets to it! $cart = EE_Cart::instance(null, $session); // add tickets to cart diff --git a/core/libraries/payment_methods/EE_Payment_Method_Manager.lib.php b/core/libraries/payment_methods/EE_Payment_Method_Manager.lib.php index da56e059838..afecfe167dd 100644 --- a/core/libraries/payment_methods/EE_Payment_Method_Manager.lib.php +++ b/core/libraries/payment_methods/EE_Payment_Method_Manager.lib.php @@ -34,12 +34,12 @@ class EE_Payment_Method_Manager implements ResettableInterface /** * @var array keys are class names without 'EE_PMT_', values are their filepaths */ - protected $_payment_method_types = array(); + protected $_payment_method_types = []; /** * @var EE_PMT_Base[] */ - protected $payment_method_objects = array(); + protected $payment_method_objects = []; /** @@ -48,7 +48,7 @@ class EE_Payment_Method_Manager implements ResettableInterface * @throws EE_Error * @throws DomainException */ - public function __construct() + protected function __construct() { // if in admin lets ensure caps are set. if (is_admin()) { @@ -58,7 +58,7 @@ public function __construct() // plus any time they get reset add_filter( 'FHEE__EE_Capabilities__addCaps__capabilities_to_add', - array($this, 'addPaymentMethodCapsDuringReset') + [$this, 'addPaymentMethodCapsDuringReset'] ); } } @@ -69,8 +69,9 @@ public function __construct() * @return EE_Payment_Method_Manager instance * @throws DomainException * @throws EE_Error + * @throws ReflectionException */ - public static function instance() + public static function instance(): EE_Payment_Method_Manager { // check if class object is instantiated, and instantiated properly if (! self::$_instance instanceof EE_Payment_Method_Manager) { @@ -87,10 +88,14 @@ public static function instance() * @return EE_Payment_Method_Manager * @throws DomainException * @throws EE_Error + * @throws ReflectionException */ - public static function reset() + public static function reset(): EE_Payment_Method_Manager { - self::$_instance = null; + self::$_instance->payment_method_caps_initialized = false; + self::$_instance->_payment_method_types = []; + self::$_instance->payment_method_objects = []; + self::$_instance = null; return self::instance(); } @@ -98,11 +103,11 @@ public static function reset() /** * If necessary, re-register payment methods * - * @param boolean $force_recheck whether to recheck for payment method types, + * @param bool $force_recheck whether to recheck for payment method types, * or just re-use the PMTs we found last time we checked during this request (if * we have not yet checked during this request, then we need to check anyways) */ - public function maybe_register_payment_methods($force_recheck = false) + public function maybe_register_payment_methods(bool $force_recheck = false) { if (! $this->_payment_method_types || $force_recheck) { $this->_register_payment_methods(); @@ -115,7 +120,7 @@ public function maybe_register_payment_methods($force_recheck = false) * * @return array */ - protected function _register_payment_methods() + protected function _register_payment_methods(): array { // grab list of installed modules $pm_to_register = glob(EE_PAYMENT_METHODS . '*', GLOB_ONLYDIR); @@ -147,7 +152,7 @@ protected function _register_payment_methods() * @param string $payment_method_path - full path up to and including payment method folder * @return boolean */ - public function register_payment_method($payment_method_path = '') + public function register_payment_method(string $payment_method_path = ''): bool { do_action('AHEE__EE_Payment_Method_Manager__register_payment_method__begin', $payment_method_path); $module_ext = '.pm.php'; @@ -156,7 +161,7 @@ public function register_payment_method($payment_method_path = '') // grab and sanitize module name $module_dir = basename($payment_method_path); // create class name from module directory name - $module = str_replace(array('_', ' '), array(' ', '_'), $module_dir); + $module = str_replace(['_', ' '], [' ', '_'], $module_dir); // add class prefix $module_class = 'EE_PMT_' . $module; // does the module exist ? @@ -196,7 +201,7 @@ public function register_payment_method($payment_method_path = '') * @param boolean $force_recheck whether to force re-checking for new payment method types * @return boolean */ - public function payment_method_type_exists($payment_method_name, $force_recheck = false) + public function payment_method_type_exists(string $payment_method_name, bool $force_recheck = false): bool { if ( $force_recheck @@ -221,12 +226,12 @@ public function payment_method_type_exists($payment_method_name, $force_recheck * @param boolean $force_recheck whether to force re-checking for new payment method types * @return array */ - public function payment_method_type_names($with_prefixes = false, $force_recheck = false) + public function payment_method_type_names(bool $with_prefixes = false, bool $force_recheck = false): array { $this->maybe_register_payment_methods($force_recheck); if ($with_prefixes) { - $classnames = array_keys($this->_payment_method_types); - $payment_methods = array(); + $classnames = array_keys($this->_payment_method_types); + $payment_methods = []; foreach ($classnames as $classname) { $payment_methods[] = $this->payment_method_class_from_type($classname); } @@ -243,7 +248,7 @@ public function payment_method_type_names($with_prefixes = false, $force_recheck * @param boolean $force_recheck whether to force re-checking for new payment method types * @return EE_PMT_Base[] */ - public function payment_method_types($force_recheck = false) + public function payment_method_types(bool $force_recheck = false): array { if ($force_recheck || empty($this->payment_method_objects)) { $this->maybe_register_payment_methods($force_recheck); @@ -264,7 +269,7 @@ public function payment_method_types($force_recheck = false) * @param string $classname * @return string */ - public function payment_method_type_sans_class_prefix($classname) + public function payment_method_type_sans_class_prefix(string $classname): string { return str_replace('EE_PMT_', '', $classname); } @@ -276,7 +281,7 @@ public function payment_method_type_sans_class_prefix($classname) * @param string $type * @return string */ - public function payment_method_class_from_type($type) + public function payment_method_class_from_type(string $type): string { return 'EE_PMT_' . $type; } @@ -289,8 +294,9 @@ public function payment_method_class_from_type($type) * @return EE_Payment_Method * @throws InvalidDataTypeException * @throws EE_Error + * @throws ReflectionException */ - public function activate_a_payment_method_of_type($payment_method_type) + public function activate_a_payment_method_of_type(string $payment_method_type): EE_Payment_Method { $this->maybe_register_payment_methods(); $payment_method = EEM_Payment_Method::instance()->get_one_of_type($payment_method_type); @@ -298,7 +304,7 @@ public function activate_a_payment_method_of_type($payment_method_type) $pm_type_class = $this->payment_method_class_from_type($payment_method_type); if (class_exists($pm_type_class)) { /** @var $pm_type_obj EE_PMT_Base */ - $pm_type_obj = new $pm_type_class(); + $pm_type_obj = new $pm_type_class(); $payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_type_obj->system_name()); if (! $payment_method) { $payment_method = $this->create_payment_method_of_type($pm_type_obj); @@ -350,27 +356,27 @@ public function activate_a_payment_method_of_type($payment_method_type) /** * Creates a payment method of the specified type. Does not save it. * - * @global WP_User $current_user * @param EE_PMT_Base $pm_type_obj * @return EE_Payment_Method - * @throws EE_Error + * @throws EE_Error*@throws ReflectionException + * @throws ReflectionException + * @global WP_User $current_user */ - public function create_payment_method_of_type($pm_type_obj) + public function create_payment_method_of_type(EE_PMT_Base $pm_type_obj): EE_Payment_Method { global $current_user; - $payment_method = EE_Payment_Method::new_instance( - array( + return EE_Payment_Method::new_instance( + [ 'PMD_type' => $pm_type_obj->system_name(), 'PMD_name' => $pm_type_obj->defaultFrontendName(), 'PMD_admin_name' => $pm_type_obj->pretty_name(), 'PMD_slug' => $pm_type_obj->system_name(),// automatically converted to slug 'PMD_wp_user' => $current_user->ID, 'PMD_order' => EEM_Payment_Method::instance()->count( - array(array('PMD_type' => array('!=', 'Admin_Only'))) + [['PMD_type' => ['!=', 'Admin_Only']]] ) * 10, - ) + ] ); - return $payment_method; } @@ -380,8 +386,9 @@ public function create_payment_method_of_type($pm_type_obj) * @param EE_Payment_Method $payment_method * @return EE_Payment_Method * @throws EE_Error + * @throws ReflectionException */ - public function initialize_payment_method($payment_method) + public function initialize_payment_method(EE_Payment_Method $payment_method): EE_Payment_Method { $pm_type_obj = $payment_method->type_obj(); $payment_method->set_description($pm_type_obj->default_description()); @@ -406,12 +413,11 @@ public function initialize_payment_method($payment_method) /** * Makes sure the payment method is related to the specified payment method * - * @deprecated in 4.9.40 because the currency payment method table is being deprecated * @param EE_Payment_Method $payment_method * @return EE_Payment_Method - * @throws EE_Error + * @deprecated in 4.9.40 because the currency payment method table is being deprecated */ - public function set_usable_currencies_on_payment_method($payment_method) + public function set_usable_currencies_on_payment_method(EE_Payment_Method $payment_method): EE_Payment_Method { EE_Error::doing_it_wrong( 'EE_Payment_Method_Manager::set_usable_currencies_on_payment_method', @@ -431,8 +437,9 @@ public function set_usable_currencies_on_payment_method($payment_method) * @param string $payment_method_slug The slug for the payment method to deactivate. * @return int count of rows updated. * @throws EE_Error + * @throws ReflectionException */ - public function deactivate_payment_method($payment_method_slug) + public function deactivate_payment_method(string $payment_method_slug): int { EE_Log::instance()->log( __FILE__, @@ -447,8 +454,8 @@ public function deactivate_payment_method($payment_method_slug) 'payment_method_change' ); $count_updated = EEM_Payment_Method::instance()->update( - array('PMD_scope' => array()), - array(array('PMD_slug' => $payment_method_slug)) + ['PMD_scope' => []], + [['PMD_slug' => $payment_method_slug]] ); do_action( 'AHEE__EE_Payment_Method_Manager__deactivate_payment_method__after_deactivating_payment_method', @@ -497,9 +504,9 @@ protected function initializePaymentMethodCaps() * @return array * @throws DomainException */ - protected function getPaymentMethodCaps() + protected function getPaymentMethodCaps(): array { - $caps = array(); + $caps = []; foreach ($this->payment_method_type_names() as $payment_method_name) { $caps = $this->addPaymentMethodCap($payment_method_name, $caps); } @@ -514,8 +521,11 @@ protected function getPaymentMethodCaps() * @return array * @throws DomainException */ - public function addPaymentMethodCap($payment_method_name, array $payment_method_caps, $role = 'administrator') - { + public function addPaymentMethodCap( + string $payment_method_name, + array $payment_method_caps, + string $role = 'administrator' + ): array { if (empty($payment_method_name)) { throw new DomainException( esc_html__( @@ -536,7 +546,7 @@ public function addPaymentMethodCap($payment_method_name, array $payment_method_ ); } if (! isset($payment_method_caps[ $role ])) { - $payment_method_caps[ $role ] = array(); + $payment_method_caps[ $role ] = []; } $payment_method_caps[ $role ][] = EE_Payment_Method_Manager::CAPABILITIES_PREFIX . strtolower($payment_method_name); @@ -554,20 +564,20 @@ public function addPaymentMethodCap($payment_method_name, array $payment_method_ * @return array * @throws DomainException */ - public function addPaymentMethodCapsDuringReset(array $caps, $reset = false) + public function addPaymentMethodCapsDuringReset(array $caps, bool $reset = false): array { if ($reset || ! $this->payment_method_caps_initialized) { $this->payment_method_caps_initialized = true; - $caps = array_merge_recursive($caps, $this->getPaymentMethodCaps()); + $caps = array_merge_recursive($caps, $this->getPaymentMethodCaps()); } return $caps; } /** - * @deprecated 4.9.42 * @param $caps * @return mixed + * @deprecated 4.9.42 */ public function add_payment_method_caps($caps) { diff --git a/core/services/address/CountrySubRegionDao.php b/core/services/address/CountrySubRegionDao.php index c3373766f68..85e3d1ed61a 100644 --- a/core/services/address/CountrySubRegionDao.php +++ b/core/services/address/CountrySubRegionDao.php @@ -5,7 +5,6 @@ use EE_Country; use EE_Error; use EE_State; -use EEM_Country; use EEM_State; use EventEspresso\core\exceptions\InvalidDataTypeException; use EventEspresso\core\exceptions\InvalidInterfaceException; @@ -72,11 +71,11 @@ public function __construct(EEM_State $state_model, JsonValidator $json_validato * @throws InvalidInterfaceException * @throws ReflectionException */ - public function saveCountrySubRegions(EE_Country $country_object) + public function saveCountrySubRegions(EE_Country $country_object): bool { $CNT_ISO = $country_object->ID(); $has_sub_regions = $this->state_model->count(array(array('Country.CNT_ISO' => $CNT_ISO))); - $data = []; + $data = new stdClass(); if (empty($this->countries)) { $this->data_version = $this->getCountrySubRegionDataVersion(); $data = $this->retrieveJsonData(self::REPO_URL . 'countries.json'); @@ -110,7 +109,7 @@ public function saveCountrySubRegions(EE_Country $country_object) * @since 4.9.70.p * @return string */ - private function getCountrySubRegionDataVersion() + private function getCountrySubRegionDataVersion(): string { return get_option(self::OPTION_NAME_COUNTRY_DATA_VERSION, null); } @@ -119,7 +118,7 @@ private function getCountrySubRegionDataVersion() /** * @param string $version */ - private function updateCountrySubRegionDataVersion($version = '') + private function updateCountrySubRegionDataVersion(string $version = '') { // add version option if it has never been added before, or update existing if ($this->data_version === null) { @@ -135,16 +134,12 @@ private function updateCountrySubRegionDataVersion($version = '') * @param array $countries * @return int * @throws EE_Error - * @throws InvalidArgumentException - * @throws InvalidDataTypeException - * @throws InvalidInterfaceException - * @throws ReflectionException * @since 4.9.70.p */ - private function processCountryData($CNT_ISO, $countries = array()) + private function processCountryData(string $CNT_ISO, array $countries = array()): int { if (! empty($countries)) { - foreach ($countries as $key => $country) { + foreach ($countries as $country) { if ( $country instanceof stdClass && $country->code === $CNT_ISO @@ -166,7 +161,7 @@ private function processCountryData($CNT_ISO, $countries = array()) * @param string $url * @return array */ - private function retrieveJsonData($url) + private function retrieveJsonData(string $url): array { if (empty($url)) { EE_Error::add_error( @@ -204,9 +199,8 @@ private function retrieveJsonData($url) * @throws InvalidArgumentException * @throws InvalidDataTypeException * @throws InvalidInterfaceException - * @throws ReflectionException */ - private function saveSubRegionData(stdClass $country, $sub_regions = array()) + private function saveSubRegionData(stdClass $country, array $sub_regions = array()): int { $results = 0; if (is_array($sub_regions)) { @@ -244,15 +238,14 @@ private function saveSubRegionData(stdClass $country, $sub_regions = array()) /** * @param string $CNT_ISO - * @since 4.9.76.p * @return array * @throws EE_Error * @throws InvalidArgumentException * @throws InvalidDataTypeException * @throws InvalidInterfaceException - * @throws ReflectionException + *@since 4.9.76.p */ - private function getExistingStateAbbreviations($CNT_ISO) + private function getExistingStateAbbreviations(string $CNT_ISO): array { $existing_sub_region_IDs = []; $existing_sub_regions = $this->state_model->get_all(array( diff --git a/core/services/address/formatters/AddressFormatter.php b/core/services/address/formatters/AddressFormatter.php index f4d1bfec6d2..0790c7b791a 100644 --- a/core/services/address/formatters/AddressFormatter.php +++ b/core/services/address/formatters/AddressFormatter.php @@ -22,18 +22,18 @@ class AddressFormatter * @param string $country * @param string $formatted_address * @param string $sub - * @return mixed + * @return string */ protected function parse_formatted_address( - $address, - $address2, - $city, - $state, - $zip, - $country, - $formatted_address, - $sub - ) { + string $address, + string $address2, + string $city, + string $state, + string $zip, + string $country, + string $formatted_address, + string $sub + ): string { // swap address part placeholders for the real text $formatted_address = str_replace( // find diff --git a/core/services/address/formatters/InlineAddressFormatter.php b/core/services/address/formatters/InlineAddressFormatter.php index 82ce790ee0f..d3c8c0eeba8 100644 --- a/core/services/address/formatters/InlineAddressFormatter.php +++ b/core/services/address/formatters/InlineAddressFormatter.php @@ -2,6 +2,8 @@ namespace EventEspresso\core\services\address\formatters; +use EEI_Address_Formatter; + /** * Class InlineAddressFormatter * This class will format an address and add commas in appropriate places @@ -11,7 +13,7 @@ * @author Brent Christensen * @since 4.8 */ -class InlineAddressFormatter extends AddressFormatter implements \EEI_Address_Formatter +class InlineAddressFormatter extends AddressFormatter implements EEI_Address_Formatter { /** * @param string $address @@ -23,8 +25,15 @@ class InlineAddressFormatter extends AddressFormatter implements \EEI_Address_Fo * @param string $CNT_ISO * @return string */ - public function format($address, $address2, $city, $state, $zip, $country, $CNT_ISO) - { + public function format( + string $address, + string $address2, + string $city, + string $state, + string $zip, + string $country, + string $CNT_ISO + ): string { $address_formats = apply_filters( 'FHEE__EE_Inline_Address_Formatter__address_formats', array( @@ -35,8 +44,7 @@ public function format($address, $address2, $city, $state, $zip, $country, $CNT_ ) ); // if the incoming country has a set format, use that, else use the default - $formatted_address = isset($address_formats[ $CNT_ISO ]) ? $address_formats[ $CNT_ISO ] - : $address_formats['ZZZ']; + $formatted_address = $address_formats[ $CNT_ISO ] ?? $address_formats['ZZZ']; return $this->parse_formatted_address( $address, $address2, diff --git a/core/services/address/formatters/MultiLineAddressFormatter.php b/core/services/address/formatters/MultiLineAddressFormatter.php index 50e8f7f1546..c20ed6f7831 100644 --- a/core/services/address/formatters/MultiLineAddressFormatter.php +++ b/core/services/address/formatters/MultiLineAddressFormatter.php @@ -2,6 +2,8 @@ namespace EventEspresso\core\services\address\formatters; +use EEI_Address_Formatter; + /** * Class MultiLineAddressFormatter * This class will format an address and add line breaks in appropriate places @@ -11,7 +13,7 @@ * @author Brent Christensen * @since 4.8 */ -class MultiLineAddressFormatter extends AddressFormatter implements \EEI_Address_Formatter +class MultiLineAddressFormatter extends AddressFormatter implements EEI_Address_Formatter { /** * @param string $address @@ -23,8 +25,15 @@ class MultiLineAddressFormatter extends AddressFormatter implements \EEI_Address * @param string $CNT_ISO * @return string */ - public function format($address, $address2, $city, $state, $zip, $country, $CNT_ISO) - { + public function format( + string $address, + string $address2, + string $city, + string $state, + string $zip, + string $country, + string $CNT_ISO + ): string { $address_formats = apply_filters( 'FHEE__EE_MultiLine_Address_Formatter__address_formats', array( @@ -35,8 +44,7 @@ public function format($address, $address2, $city, $state, $zip, $country, $CNT_ ) ); // if the incoming country has a set format, use that, else use the default - $formatted_address = isset($address_formats[ $CNT_ISO ]) ? $address_formats[ $CNT_ISO ] - : $address_formats['ZZ']; + $formatted_address = $address_formats[ $CNT_ISO ] ?? $address_formats['ZZ']; return $this->parse_formatted_address( $address, $address2, diff --git a/core/services/address/formatters/NullAddressFormatter.php b/core/services/address/formatters/NullAddressFormatter.php index 15120e94f25..2f0c50d5df1 100644 --- a/core/services/address/formatters/NullAddressFormatter.php +++ b/core/services/address/formatters/NullAddressFormatter.php @@ -20,10 +20,17 @@ class NullAddressFormatter implements \EEI_Address_Formatter * @param string $zip * @param string $country * @param string $CNT_ISO - * @return string + * @return null */ - public function format($address, $address2, $city, $state, $zip, $country, $CNT_ISO) - { + public function format( + string $address, + string $address2, + string $city, + string $state, + string $zip, + string $country, + string $CNT_ISO + ): ?string { return null; } } diff --git a/core/services/bootstrap/BootstrapCore.php b/core/services/bootstrap/BootstrapCore.php index ba0e7c2fd8e..18d74967c0e 100644 --- a/core/services/bootstrap/BootstrapCore.php +++ b/core/services/bootstrap/BootstrapCore.php @@ -10,6 +10,7 @@ use EventEspresso\core\exceptions\InvalidDataTypeException; use EventEspresso\core\exceptions\InvalidFilePathException; use EventEspresso\core\exceptions\InvalidInterfaceException; +use EventEspresso\core\interfaces\InterminableInterface; use EventEspresso\core\services\loaders\LoaderInterface; use EventEspresso\core\services\request\InvalidRequestStackMiddlewareException; use EventEspresso\core\services\request\RequestInterface; @@ -44,7 +45,7 @@ * @author Brent Christensen * @since 4.9.59.p */ -class BootstrapCore +class BootstrapCore implements InterminableInterface { /** * @type LoaderInterface $loader diff --git a/core/services/bootstrap/BootstrapDependencyInjectionContainer.php b/core/services/bootstrap/BootstrapDependencyInjectionContainer.php index 0a8bdc71a3b..0e6c6d2d373 100644 --- a/core/services/bootstrap/BootstrapDependencyInjectionContainer.php +++ b/core/services/bootstrap/BootstrapDependencyInjectionContainer.php @@ -7,6 +7,7 @@ use EE_Registry; use EventEspresso\core\exceptions\InvalidDataTypeException; use EventEspresso\core\exceptions\InvalidInterfaceException; +use EventEspresso\core\interfaces\InterminableInterface; use EventEspresso\core\services\container\Mirror; use EventEspresso\core\services\loaders\ClassInterfaceCache; use EventEspresso\core\services\loaders\LoaderFactory; @@ -22,7 +23,7 @@ * @author Brent Christensen * @since 4.9.59.p */ -class BootstrapDependencyInjectionContainer +class BootstrapDependencyInjectionContainer implements InterminableInterface { /** * @var EE_Dependency_Map $dependency_map diff --git a/core/services/bootstrap/BootstrapRequestResponseObjects.php b/core/services/bootstrap/BootstrapRequestResponseObjects.php index ac1628dfcfd..fb8ca0e6480 100644 --- a/core/services/bootstrap/BootstrapRequestResponseObjects.php +++ b/core/services/bootstrap/BootstrapRequestResponseObjects.php @@ -5,6 +5,7 @@ use EE_Dependency_Map; use EE_Error; use EE_Request; +use EventEspresso\core\interfaces\InterminableInterface; use EventEspresso\core\services\loaders\LoaderInterface; use EventEspresso\core\services\request\LegacyRequestInterface; use EventEspresso\core\services\request\Request; @@ -26,7 +27,7 @@ * @author Brent Christensen * @since 4.9.53 */ -class BootstrapRequestResponseObjects +class BootstrapRequestResponseObjects implements InterminableInterface { /** * @type LegacyRequestInterface $legacy_request diff --git a/core/services/collections/Collection.php b/core/services/collections/Collection.php index 5d2c23d4f8a..0746f5d05af 100644 --- a/core/services/collections/Collection.php +++ b/core/services/collections/Collection.php @@ -4,6 +4,7 @@ use EventEspresso\core\exceptions\InvalidEntityException; use EventEspresso\core\exceptions\InvalidInterfaceException; +use EventEspresso\core\interfaces\InterminableInterface; use LimitIterator; use SplObjectStorage; @@ -51,7 +52,7 @@ class Collection extends SplObjectStorage implements CollectionInterface * @param string $collection_name * @throws InvalidInterfaceException */ - public function __construct($collection_interface, $collection_name = '') + public function __construct(string $collection_interface, string $collection_name = '') { $this->setCollectionInterface($collection_interface); $this->setCollectionName($collection_name); @@ -75,7 +76,7 @@ public function collectionInterface(): string * @param string $collection_interface * @throws InvalidInterfaceException */ - protected function setCollectionInterface($collection_interface) + protected function setCollectionInterface(string $collection_interface) { if (! (interface_exists($collection_interface) || class_exists($collection_interface))) { throw new InvalidInterfaceException($collection_interface); @@ -87,7 +88,7 @@ protected function setCollectionInterface($collection_interface) /** * @return string */ - public function collectionName() + public function collectionName(): string { return $this->collection_name; } @@ -96,7 +97,7 @@ public function collectionName() /** * @param string $collection_name */ - protected function setCollectionName($collection_name) + protected function setCollectionName(string $collection_name) { $this->collection_name = ! empty($collection_name) ? sanitize_key($collection_name) @@ -107,7 +108,7 @@ protected function setCollectionName($collection_name) /** * @return string */ - public function collectionIdentifier() + public function collectionIdentifier(): string { return $this->collection_identifier; } @@ -138,22 +139,22 @@ protected function setCollectionIdentifier() * and sets any supplied data associated with the current iterator entry * by calling EE_Object_Collection::set_identifier() * - * @param $object - * @param mixed $identifier + * @param mixed $object + * @param mixed $identifier * @return bool * @throws InvalidEntityException * @throws DuplicateCollectionIdentifierException */ - public function add($object, $identifier = null) + public function add($object, $identifier = null): bool { if (! $object instanceof $this->collection_interface) { throw new InvalidEntityException($object, $this->collection_interface); } - if ($this->contains($object)) { + $identifier = $this->getIdentifier($object, $identifier); + if ($this->contains($object) || $this->has($identifier)) { throw new DuplicateCollectionIdentifierException($identifier); } - $this->attach($object); - $this->setIdentifier($object, $identifier); + parent::attach($object, $identifier); return $this->contains($object); } @@ -164,13 +165,11 @@ public function add($object, $identifier = null) * * @param $object * @param mixed $identifier - * @return bool + * @return string */ - public function getIdentifier($object, $identifier = null) + public function getIdentifier($object, $identifier = null): string { - return ! empty($identifier) - ? $identifier - : spl_object_hash($object); + return ! empty($identifier) ? $identifier : spl_object_hash($object); } @@ -183,7 +182,7 @@ public function getIdentifier($object, $identifier = null) * @param mixed $identifier * @return bool */ - public function setIdentifier($object, $identifier = null) + public function setIdentifier($object, $identifier = null): bool { $identifier = $this->getIdentifier($object, $identifier); $this->rewind(); @@ -231,7 +230,7 @@ public function get($identifier) * @param mixed $identifier * @return bool */ - public function has($identifier) + public function has($identifier): bool { $this->rewind(); while ($this->valid()) { @@ -252,7 +251,7 @@ public function has($identifier) * @param $object * @return bool */ - public function hasObject($object) + public function hasObject($object): bool { return $this->contains($object); } @@ -264,7 +263,7 @@ public function hasObject($object) * * @return bool */ - public function hasObjects() + public function hasObjects(): bool { return $this->count() !== 0; } @@ -276,7 +275,7 @@ public function hasObjects() * * @return bool */ - public function isEmpty() + public function isEmpty(): bool { return $this->count() === 0; } @@ -289,13 +288,35 @@ public function isEmpty() * @param $object * @return bool */ - public function remove($object) + public function remove($object): bool { $this->detach($object); return true; } + /** + * detaches the object matching the supplied identifier from the Collection + * + * @param mixed $identifier + * @return bool + */ + public function removeByIdentifier($identifier): bool + { + $this->rewind(); + while ($this->valid()) { + $object = $this->current(); + $this->next(); + if ($identifier === $this->getInfo()) { + $this->detach($object); + unset($object); + return true; + } + } + return false; + } + + /** * setCurrent * advances pointer to the object whose identifier matches that which was provided @@ -303,7 +324,7 @@ public function remove($object) * @param mixed $identifier * @return boolean */ - public function setCurrent($identifier) + public function setCurrent($identifier): bool { $this->rewind(); while ($this->valid()) { @@ -323,7 +344,7 @@ public function setCurrent($identifier) * @param $object * @return boolean */ - public function setCurrentUsingObject($object) + public function setCurrentUsingObject($object): bool { $this->rewind(); while ($this->valid()) { @@ -358,7 +379,7 @@ public function previous() * * @see http://stackoverflow.com/a/8736013 * @param $object - * @return boolean|int|string + * @return boolean|int */ public function indexOf($object) { @@ -397,7 +418,7 @@ public function objectAtIndex($index) * @param int $length * @return array */ - public function slice($offset, $length) + public function slice($offset, $length): array { $slice = array(); $iterator = new LimitIterator($this, $offset, $length); @@ -419,7 +440,7 @@ public function slice($offset, $length) * @throws DuplicateCollectionIdentifierException * @throws InvalidEntityException */ - public function insertObjectAt($object, $index, $identifier = null) + public function insertObjectAt($object, int $index, $identifier = null): bool { // check to ensure that objects don't already exist in the collection if ($this->has($identifier)) { @@ -480,11 +501,11 @@ public function insertAt($objects, $index) } // add the new objects we're splicing in foreach ($objects as $object) { - $this->attach($object); + $this->add($object); } // attach the objects we previously detached foreach ($remaining as $object) { - $this->attach($object); + $this->add($object); } } @@ -524,8 +545,10 @@ public function trashAndDetachAll() while ($this->valid()) { $object = $this->current(); $this->next(); - $this->detach($object); - unset($object); + if (! $object instanceof InterminableInterface) { + $this->detach($object); + unset($object); + } } } } diff --git a/core/services/collections/CollectionDetails.php b/core/services/collections/CollectionDetails.php index e77049bc474..75cdde51e95 100644 --- a/core/services/collections/CollectionDetails.php +++ b/core/services/collections/CollectionDetails.php @@ -2,7 +2,7 @@ namespace EventEspresso\core\services\collections; -use EventEspresso\core\exceptions\InvalidDataTypeException; +use EventEspresso\core\exceptions\InvalidClassException; use EventEspresso\core\exceptions\InvalidFilePathException; use EventEspresso\core\exceptions\InvalidIdentifierException; use EventEspresso\core\exceptions\InvalidInterfaceException; @@ -139,7 +139,6 @@ class CollectionDetails implements CollectionDetailsInterface /** * CollectionDetails constructor. * - * @access public * @param string $collection_name * @param string $collection_interface * @param array $collection_FQCNs @@ -147,17 +146,17 @@ class CollectionDetails implements CollectionDetailsInterface * @param string $file_mask * @param string $identifier_type * @param string $identifier_callback - * @param LocatorInterface $file_locator + * @param LocatorInterface|null $file_locator * @throws CollectionDetailsException */ public function __construct( - $collection_name, - $collection_interface, + string $collection_name, + string $collection_interface, array $collection_FQCNs = array(), array $collection_paths = array(), - $file_mask = '', - $identifier_type = CollectionDetails::ID_OBJECT_HASH, - $identifier_callback = '', + string $file_mask = '', + string $identifier_type = CollectionDetails::ID_OBJECT_HASH, + string $identifier_callback = '', LocatorInterface $file_locator = null ) { try { @@ -176,21 +175,19 @@ public function __construct( /** - * @access public - * @return mixed + * @return string */ - public function getCollectionInterface() + public function getCollectionInterface(): string { return $this->collection_interface; } /** - * @access protected * @param string $collection_interface - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException + * @throws InvalidInterfaceException */ - protected function setCollectionInterface($collection_interface) + protected function setCollectionInterface(string $collection_interface) { if (! (interface_exists($collection_interface) || class_exists($collection_interface))) { throw new InvalidInterfaceException($collection_interface); @@ -202,10 +199,9 @@ protected function setCollectionInterface($collection_interface) /** * the collection name will be used for creating dynamic filters * - * @access public * @return string */ - public function collectionName() + public function collectionName(): string { return $this->collection_name; } @@ -214,15 +210,10 @@ public function collectionName() /** * sanitizes collection name and converts spaces and dashes to underscores * - * @access protected * @param string $collection_name - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException */ - protected function setCollectionName($collection_name) + protected function setCollectionName(string $collection_name) { - if (! is_string($collection_name)) { - throw new InvalidDataTypeException('$collection_name', $collection_name, 'string'); - } $this->collection_name = str_replace( '-', '_', @@ -232,26 +223,25 @@ protected function setCollectionName($collection_name) /** - * @access public * @return string */ - public function identifierType() + public function identifierType(): string { return $this->identifier_type; } /** - * @access protected * @param string $identifier_type * @throws InvalidIdentifierException */ - protected function setIdentifierType($identifier_type) + protected function setIdentifierType(string $identifier_type) { if ( - ! ($identifier_type === CollectionDetails::ID_CLASS_NAME - || $identifier_type === CollectionDetails::ID_OBJECT_HASH - || $identifier_type === CollectionDetails::ID_CALLBACK_METHOD + ! ( + $identifier_type === CollectionDetails::ID_CLASS_NAME + || $identifier_type === CollectionDetails::ID_OBJECT_HASH + || $identifier_type === CollectionDetails::ID_CALLBACK_METHOD ) ) { throw new InvalidIdentifierException( @@ -264,34 +254,27 @@ protected function setIdentifierType($identifier_type) /** - * @access public * @return string */ - public function identifierCallback() + public function identifierCallback(): string { return $this->identifier_callback; } /** - * @access protected * @param string $identifier_callback - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException */ - protected function setIdentifierCallback($identifier_callback = 'identifier') + protected function setIdentifierCallback(string $identifier_callback = 'identifier') { - if (! is_string($identifier_callback)) { - throw new InvalidDataTypeException('$identifier_callback', $identifier_callback, 'string'); - } $this->identifier_callback = $identifier_callback; } /** - * @access public * @return string */ - public function getFileMask() + public function getFileMask(): string { return $this->file_mask; } @@ -301,36 +284,26 @@ public function getFileMask() * sets the file mask which is then used to filter what files get loaded * when searching for classes to add to the collection. Defaults to '*.php' * - * @access protected * @param string $file_mask - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException */ - protected function setFileMasks($file_mask) + protected function setFileMasks(string $file_mask) { $this->file_mask = ! empty($file_mask) ? $file_mask : '*.php'; - // we know our default is a string, so if it's not a string now, - // then that means the incoming parameter was something else - if (! is_string($this->file_mask)) { - throw new InvalidDataTypeException('$file_mask', $this->file_mask, 'string'); - } } /** - * @access public * @return array */ - public function getCollectionFQCNs() + public function getCollectionFQCNs(): array { return $this->collection_FQCNs; } /** - * @access public * @param string|array $collection_FQCNs - * @throws \EventEspresso\core\exceptions\InvalidClassException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException + * @throws InvalidClassException */ public function setCollectionFQCNs($collection_FQCNs) { @@ -339,7 +312,8 @@ public function setCollectionFQCNs($collection_FQCNs) if (class_exists($collection_FQCN)) { $this->collection_FQCNs[] = $collection_FQCN; } else { - foreach ($this->getFQCNsFromPartialNamespace($collection_FQCN) as $FQCN) { + $FQCNs = $this->getFQCNsFromPartialNamespace($collection_FQCN); + foreach ($FQCNs as $FQCN) { $this->collection_FQCNs[] = $FQCN; } } @@ -349,13 +323,11 @@ public function setCollectionFQCNs($collection_FQCNs) /** - * @access protected - * @param string $partial_FQCN + * @param string $partial_FQCN * @return array - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\exceptions\InvalidClassException + * @throws InvalidClassException */ - protected function getFQCNsFromPartialNamespace($partial_FQCN) + protected function getFQCNsFromPartialNamespace(string $partial_FQCN): array { if (! $this->file_locator instanceof FqcnLocator) { $this->file_locator = new FqcnLocator(); @@ -366,19 +338,17 @@ protected function getFQCNsFromPartialNamespace($partial_FQCN) /** - * @access public * @return array */ - public function getCollectionPaths() + public function getCollectionPaths(): array { return $this->collection_paths; } /** - * @access public * @param string|array $collection_paths - * @throws \EventEspresso\core\exceptions\InvalidFilePathException + * @throws InvalidFilePathException */ public function setCollectionPaths($collection_paths) { diff --git a/core/services/collections/CollectionLoader.php b/core/services/collections/CollectionLoader.php index 0ca1a605376..fe566f86138 100644 --- a/core/services/collections/CollectionLoader.php +++ b/core/services/collections/CollectionLoader.php @@ -73,8 +73,8 @@ class CollectionLoader * CollectionLoader constructor. * * @param CollectionDetailsInterface $collection_details - * @param CollectionInterface $collection - * @param LocatorInterface $file_locator + * @param CollectionInterface|null $collection + * @param LocatorInterface|null $file_locator * @param FactoryInterface|null $entity_factory * @throws CollectionLoaderException */ @@ -141,7 +141,7 @@ protected function loadAllFromFilepaths() /** - * @param string $filepath + * @param string|null $filepath * @return string * @throws InvalidEntityException * @throws InvalidDataTypeException @@ -149,7 +149,7 @@ protected function loadAllFromFilepaths() * @throws InvalidClassException * @throws DuplicateCollectionIdentifierException */ - protected function loadClassFromFilepath($filepath) + protected function loadClassFromFilepath(?string $filepath): string { if (! is_string($filepath)) { throw new InvalidDataTypeException('$filepath', $filepath, 'string'); @@ -179,7 +179,7 @@ protected function loadClassFromFilepath($filepath) * @throws InvalidEntityException * @throws DuplicateCollectionIdentifierException */ - protected function addEntityToCollection($entity, $identifier) + protected function addEntityToCollection($entity, $identifier): string { do_action( 'FHEE__CollectionLoader__addEntityToCollection__entity', @@ -188,7 +188,7 @@ protected function addEntityToCollection($entity, $identifier) $this->collection_details ); $identifier = $this->setIdentifier($entity, $identifier); - if ($this->collection->has($identifier)) { + if ($this->collection->contains($entity) || $this->collection->has($identifier)) { do_action( 'FHEE__CollectionLoader__addEntityToCollection__entity_already_added', $this, @@ -222,7 +222,7 @@ protected function addEntityToCollection($entity, $identifier) * @return string * @throws InvalidEntityException */ - protected function setIdentifier($entity, $identifier) + protected function setIdentifier($entity, $identifier): string { switch ($this->collection_details->identifierType()) { // every unique object gets added to the collection, but not duplicates of the exact same object @@ -289,7 +289,7 @@ protected function loadFromFQCNs() /** - * @param string $FQCN Fully Qualified Class Name + * @param string|null $FQCN Fully Qualified Class Name * @return string * @throws InvalidArgumentException * @throws InvalidInterfaceException @@ -300,7 +300,7 @@ protected function loadFromFQCNs() * @throws InvalidClassException * @throws DuplicateCollectionIdentifierException */ - protected function loadClassFromFQCN($FQCN) + protected function loadClassFromFQCN(?string $FQCN): string { if (! is_string($FQCN)) { throw new InvalidDataTypeException('$FQCN', $FQCN, 'string'); diff --git a/core/services/collections/LooseCollection.php b/core/services/collections/LooseCollection.php index 605a1f5a5e5..8a1273cce31 100644 --- a/core/services/collections/LooseCollection.php +++ b/core/services/collections/LooseCollection.php @@ -20,7 +20,7 @@ class LooseCollection extends Collection * @access protected * @param string $collection_interface */ - protected function setCollectionInterface($collection_interface) + protected function setCollectionInterface(string $collection_interface) { $this->collection_interface = ''; } @@ -38,13 +38,13 @@ protected function setCollectionInterface($collection_interface) * @return bool * @throws InvalidEntityException */ - public function add($object, $identifier = null) + public function add($object, $identifier = null): bool { if (! is_object($object)) { throw new InvalidEntityException($object, 'object'); } - $this->attach($object); - $this->setIdentifier($object, $identifier); + $identifier = $this->getIdentifier($object, $identifier); + parent::attach($object, $identifier); return $this->contains($object); } } diff --git a/core/services/commands/CommandBusInterface.php b/core/services/commands/CommandBusInterface.php index f149eaca3b7..45e8e4002c2 100644 --- a/core/services/commands/CommandBusInterface.php +++ b/core/services/commands/CommandBusInterface.php @@ -2,12 +2,14 @@ namespace EventEspresso\core\services\commands; +use EventEspresso\core\interfaces\InterminableInterface; + /** * Interface CommandBusInterface * * @package EventEspresso\core\services\commands */ -interface CommandBusInterface +interface CommandBusInterface extends InterminableInterface { /** * @return CommandHandlerManagerInterface diff --git a/core/services/commands/CommandFactoryInterface.php b/core/services/commands/CommandFactoryInterface.php index 5c37e2372f8..77e0a25d848 100644 --- a/core/services/commands/CommandFactoryInterface.php +++ b/core/services/commands/CommandFactoryInterface.php @@ -2,11 +2,12 @@ namespace EventEspresso\core\services\commands; +use EventEspresso\core\interfaces\InterminableInterface; use InvalidArgumentException; use EventEspresso\core\exceptions\InvalidDataTypeException; use EventEspresso\core\exceptions\InvalidInterfaceException; -interface CommandFactoryInterface +interface CommandFactoryInterface extends InterminableInterface { /** * @param string $command_fqcn diff --git a/core/services/commands/CommandHandlerInterface.php b/core/services/commands/CommandHandlerInterface.php index e323dd4f16a..436189bafb0 100644 --- a/core/services/commands/CommandHandlerInterface.php +++ b/core/services/commands/CommandHandlerInterface.php @@ -2,12 +2,14 @@ namespace EventEspresso\core\services\commands; +use EventEspresso\core\interfaces\InterminableInterface; + /** * Interface CommandHandlerInterface * * @package EventEspresso\core\services\commands */ -interface CommandHandlerInterface +interface CommandHandlerInterface extends InterminableInterface { /** * verifies that the supplied command is the correct class for the handler. diff --git a/core/services/commands/CommandHandlerManagerInterface.php b/core/services/commands/CommandHandlerManagerInterface.php index 4df0013b2b0..cf1e5b20c86 100644 --- a/core/services/commands/CommandHandlerManagerInterface.php +++ b/core/services/commands/CommandHandlerManagerInterface.php @@ -2,12 +2,14 @@ namespace EventEspresso\core\services\commands; +use EventEspresso\core\interfaces\InterminableInterface; + /** * Interface CommandHandlerManagerInterface * * @package EventEspresso\core\services\commands */ -interface CommandHandlerManagerInterface +interface CommandHandlerManagerInterface extends InterminableInterface { /** * !!! IMPORTANT !!! diff --git a/core/services/commands/middleware/CommandBusMiddlewareInterface.php b/core/services/commands/middleware/CommandBusMiddlewareInterface.php index 9b76477e141..c868ec934f9 100644 --- a/core/services/commands/middleware/CommandBusMiddlewareInterface.php +++ b/core/services/commands/middleware/CommandBusMiddlewareInterface.php @@ -3,6 +3,7 @@ namespace EventEspresso\core\services\commands\middleware; use Closure; +use EventEspresso\core\interfaces\InterminableInterface; use EventEspresso\core\services\commands\CommandInterface; /** @@ -10,7 +11,7 @@ * * @package EventEspresso\core\services\commands */ -interface CommandBusMiddlewareInterface +interface CommandBusMiddlewareInterface extends InterminableInterface { /** * @param CommandInterface $command diff --git a/core/services/database/TableAnalysis.php b/core/services/database/TableAnalysis.php index 84485f81cd8..bef86ec94c8 100644 --- a/core/services/database/TableAnalysis.php +++ b/core/services/database/TableAnalysis.php @@ -2,6 +2,11 @@ namespace EventEspresso\core\services\database; +use EE_Base; +use EEH_Activation; +use EventEspresso\core\interfaces\InterminableInterface; +use wpdb; + /** * Class TableAnalysis * For analyzing database tables; should not perform any manipulation, or have @@ -11,7 +16,7 @@ * @subpackage * @author Mike Nelson */ -class TableAnalysis extends \EE_Base +class TableAnalysis extends EE_Base implements InterminableInterface { /** * The maximum number of characters that can be indexed on a column using utf8mb4 collation, @@ -19,16 +24,17 @@ class TableAnalysis extends \EE_Base */ const INDEX_COLUMN_SIZE = 191; + /** * Returns the table name which will definitely have the wpdb prefix on the front, * except if it currently has the wpdb->base_prefix on the front, in which case * it will have the wpdb->base_prefix on it * - * @global \wpdb $wpdb * @param string $table_name * @return string $tableName, having ensured it has the wpdb prefix on the front + * @global wpdb $wpdb */ - public function ensureTableNameHasPrefix($table_name) + public function ensureTableNameHasPrefix(string $table_name): string { global $wpdb; return strpos($table_name, $wpdb->base_prefix) === 0 ? $table_name : $wpdb->prefix . $table_name; @@ -39,17 +45,17 @@ public function ensureTableNameHasPrefix($table_name) * Indicates whether or not the table has any entries. $table_name can * optionally start with $wpdb->prefix or not * - * @global \wpdb $wpdb * @param string $table_name * @return bool + * @global wpdb $wpdb */ - public function tableIsEmpty($table_name) + public function tableIsEmpty(string $table_name): bool { global $wpdb; $table_name = $this->ensureTableNameHasPrefix($table_name); if ($this->tableExists($table_name)) { $count = $wpdb->get_var("SELECT COUNT(*) FROM $table_name"); - return absint($count) === 0 ? true : false; + return absint($count) === 0; } return false; } @@ -59,39 +65,37 @@ public function tableIsEmpty($table_name) * Indicates whether or not the table exists. $table_name can optionally * have the $wpdb->prefix on the beginning, or not. * - * @global \wpdb $wpdb - * @global array EZSQL_Error - * @param $table_name + * @param string $table_name * @return bool + * @global wpdb $wpdb */ - public function tableExists($table_name) + public function tableExists(string $table_name): bool { global $wpdb, $EZSQL_ERROR; $table_name = $this->ensureTableNameHasPrefix($table_name); // ignore if this causes an sql error - $old_error = $wpdb->last_error; - $old_suppress_errors = $wpdb->suppress_errors(); + $old_error = $wpdb->last_error; + $old_suppress_errors = $wpdb->suppress_errors(); $old_show_errors_value = $wpdb->show_errors(false); - $ezsql_error_cache = $EZSQL_ERROR; + $ezsql_error_cache = $EZSQL_ERROR; $wpdb->get_results("SELECT * from $table_name LIMIT 1"); $wpdb->show_errors($old_show_errors_value); $wpdb->suppress_errors($old_suppress_errors); - $new_error = $wpdb->last_error; + $new_error = $wpdb->last_error; $wpdb->last_error = $old_error; - $EZSQL_ERROR = $ezsql_error_cache; + $EZSQL_ERROR = $ezsql_error_cache; // if there was a table doesn't exist error if (! empty($new_error)) { if ( in_array( - \EEH_Activation::last_wpdb_error_code(), - array( - 1051, // bad table - 1109, // unknown table - 117, // no such table - ) + EEH_Activation::last_wpdb_error_code(), + [ + 1051, // bad table + 1109, // unknown table + 117, // no such table + ] ) - || - preg_match( + || preg_match( '~^Table .* doesn\'t exist~', $new_error ) // in case not using mysql and error codes aren't reliable, just check for this error string @@ -115,8 +119,8 @@ public function tableExists($table_name) /** - * @param $table_name - * @param $index_name + * @param string $table_name + * @param string $index_name * @return array of columns used on that index, Each entry is an object with the following properties { * @type string Table * @type string Non_unique "0" or "1" @@ -132,12 +136,12 @@ public function tableExists($table_name) * @type string Index_type * @type string Comment * @type string Index_comment - * } + * } */ - public function showIndexes($table_name, $index_name) + public function showIndexes(string $table_name, string $index_name): array { global $wpdb; - $table_name = $this->ensureTableNameHasPrefix($table_name); + $table_name = $this->ensureTableNameHasPrefix($table_name); $index_exists_query = "SHOW INDEX FROM {$table_name} WHERE Key_name = '{$index_name}'"; return $wpdb->get_results($index_exists_query); } diff --git a/core/services/graphql/connections/ConnectionCollection.php b/core/services/graphql/connections/ConnectionCollection.php index 01571b8fedc..060d5d3c78e 100644 --- a/core/services/graphql/connections/ConnectionCollection.php +++ b/core/services/graphql/connections/ConnectionCollection.php @@ -94,9 +94,9 @@ public function loadConnections() * * @param $object * @param mixed $identifier - * @return bool + * @return string */ - public function getIdentifier($object, $identifier = null) + public function getIdentifier($object, $identifier = null): string { return ! empty($identifier) ? $identifier diff --git a/core/services/graphql/enums/EnumCollection.php b/core/services/graphql/enums/EnumCollection.php index a55aad78f88..49bbd807757 100644 --- a/core/services/graphql/enums/EnumCollection.php +++ b/core/services/graphql/enums/EnumCollection.php @@ -94,9 +94,9 @@ public function loadEnums() * * @param $object * @param mixed $identifier - * @return bool + * @return string */ - public function getIdentifier($object, $identifier = null) + public function getIdentifier($object, $identifier = null): string { return ! empty($identifier) ? $identifier diff --git a/core/services/graphql/inputs/InputCollection.php b/core/services/graphql/inputs/InputCollection.php index 55ad792f1e5..a976cf7a6fb 100644 --- a/core/services/graphql/inputs/InputCollection.php +++ b/core/services/graphql/inputs/InputCollection.php @@ -94,9 +94,9 @@ public function loadInputs() * * @param $object * @param mixed $identifier - * @return bool + * @return string */ - public function getIdentifier($object, $identifier = null) + public function getIdentifier($object, $identifier = null): string { return ! empty($identifier) ? $identifier diff --git a/core/services/graphql/resolvers/ResolverCollection.php b/core/services/graphql/resolvers/ResolverCollection.php index 82e3f46fffa..8cc59cba6d2 100644 --- a/core/services/graphql/resolvers/ResolverCollection.php +++ b/core/services/graphql/resolvers/ResolverCollection.php @@ -94,9 +94,9 @@ public function loadResolvers() * * @param $object * @param mixed $identifier - * @return bool + * @return string */ - public function getIdentifier($object, $identifier = null) + public function getIdentifier($object, $identifier = null): string { return ! empty($identifier) ? $identifier diff --git a/core/services/graphql/types/TypeCollection.php b/core/services/graphql/types/TypeCollection.php index e69d3c71a3a..fd1f22c9d47 100644 --- a/core/services/graphql/types/TypeCollection.php +++ b/core/services/graphql/types/TypeCollection.php @@ -97,9 +97,9 @@ public function loadTypes() * * @param $object * @param mixed $identifier - * @return bool + * @return string */ - public function getIdentifier($object, $identifier = null) + public function getIdentifier($object, $identifier = null): string { return ! empty($identifier) ? $identifier diff --git a/core/services/loaders/ClassInterfaceCache.php b/core/services/loaders/ClassInterfaceCache.php index 0bbabb69cad..7912968856c 100644 --- a/core/services/loaders/ClassInterfaceCache.php +++ b/core/services/loaders/ClassInterfaceCache.php @@ -4,6 +4,7 @@ use EventEspresso\core\domain\values\FullyQualifiedName; use EventEspresso\core\exceptions\InvalidAliasException; +use EventEspresso\core\interfaces\InterminableInterface; /** * Class ClassInterfaceCache @@ -14,7 +15,7 @@ * @author Brent Christensen * @since 4.9.62.p */ -class ClassInterfaceCache +class ClassInterfaceCache implements InterminableInterface { /** * array of interfaces indexed by FQCNs where values are arrays of interface FQNs @@ -38,10 +39,10 @@ public function getAliases() } /** - * @param string $fqn + * @param string|FullyQualifiedName $fqn * @return string */ - public function getFqn($fqn) + public function getFqn($fqn): string { $fqn = $fqn instanceof FullyQualifiedName ? $fqn->string() : $fqn; return ltrim((string) $fqn, '\\'); @@ -49,10 +50,10 @@ public function getFqn($fqn) /** - * @param string $fqn + * @param string|FullyQualifiedName $fqn * @return array */ - public function getInterfaces($fqn) + public function getInterfaces($fqn): array { $fqn = $this->getFqn($fqn); // have we already seen this FQCN ? @@ -70,11 +71,11 @@ public function getInterfaces($fqn) /** - * @param string $fqn - * @param string $interface + * @param string|FullyQualifiedName $fqn + * @param string|FullyQualifiedName $interface * @return bool */ - public function hasInterface($fqn, $interface) + public function hasInterface($fqn, $interface): bool { $fqn = $this->getFqn($fqn); $interfaces = $this->getInterfaces($fqn); @@ -85,12 +86,12 @@ public function hasInterface($fqn, $interface) /** * adds an alias for a classname * - * @param string $fqn the class name that should be used (concrete class to replace interface) - * @param string $alias the class name that would be type hinted for (abstract parent or interface) - * @param string $for_class the class that has the dependency (is type hinting for the interface) + * @param string|FullyQualifiedName $fqn the class name that should be used (concrete class to replace interface) + * @param string|FullyQualifiedName $alias the class name that would be type hinted for (abstract parent or interface) + * @param string $for_class the class that has the dependency (is type hinting for the interface) * @throws InvalidAliasException */ - public function addAlias($fqn, $alias, $for_class = '') + public function addAlias($fqn, $alias, string $for_class = '') { $fqn = $this->getFqn($fqn); $alias = $this->getFqn($alias); @@ -113,11 +114,11 @@ public function addAlias($fqn, $alias, $for_class = '') /** * returns TRUE if the provided FQN is an alias * - * @param string $fqn - * @param string $for_class + * @param string|FullyQualifiedName $fqn + * @param string $for_class * @return bool */ - public function isAlias($fqn = '', $for_class = '') + public function isAlias($fqn = '', string $for_class = ''): bool { $fqn = $this->getFqn($fqn); if ($this->isAliasForClass($fqn, $for_class)) { @@ -136,9 +137,9 @@ public function isAlias($fqn = '', $for_class = '') * @param string $fqn * @return bool */ - protected function isDirectAlias($fqn = '') + protected function isDirectAlias(string $fqn = ''): bool { - return isset($this->aliases[ (string) $fqn ]) && ! is_array($this->aliases[ (string) $fqn ]); + return isset($this->aliases[ $fqn ]) && ! is_array($this->aliases[ $fqn ]); } @@ -149,12 +150,9 @@ protected function isDirectAlias($fqn = '') * @param string $for_class * @return bool */ - protected function isAliasForClass($fqn = '', $for_class = '') + protected function isAliasForClass(string $fqn = '', string $for_class = ''): bool { - return ( - $for_class !== '' - && isset($this->aliases[ (string) $for_class ][ (string) $fqn ]) - ); + return $for_class !== '' && isset($this->aliases[ $for_class ][ $fqn ]); } @@ -170,19 +168,19 @@ protected function isAliasForClass($fqn = '', $for_class = '') * then one could use Loader::getNew( 'interface_alias' ) * to load an instance of 'some\namespace\classname' * - * @param string $alias - * @param string $for_class + * @param string|FullyQualifiedName $alias + * @param string $for_class * @return string */ - public function getFqnForAlias($alias = '', $for_class = '') + public function getFqnForAlias($alias = '', string $for_class = ''): string { $alias = $this->getFqn($alias); if ($this->isAliasForClass($alias, $for_class)) { - return $this->getFqnForAlias($this->aliases[ (string) $for_class ][ (string) $alias ], $for_class); + return $this->getFqnForAlias($this->aliases[ $for_class ][ $alias ], $for_class); } if ($this->isDirectAlias($alias)) { // note: changed '' to $for_class - return $this->getFqnForAlias($this->aliases[ (string) $alias ], $for_class); + return $this->getFqnForAlias($this->aliases[ $alias ], $for_class); } return $alias; } diff --git a/core/services/loaders/ObjectIdentifier.php b/core/services/loaders/ObjectIdentifier.php index 20944e93b3b..4de2d4c00c8 100644 --- a/core/services/loaders/ObjectIdentifier.php +++ b/core/services/loaders/ObjectIdentifier.php @@ -44,7 +44,7 @@ public function __construct(ClassInterfaceCache $class_cache) * @param string $object_identifier * @return bool */ - public function hasArguments($object_identifier) + public function hasArguments(string $object_identifier): bool { // type casting to bool instead of using strpos() !== false // because an object identifier should never begin with the delimiter @@ -65,7 +65,7 @@ public function hasArguments($object_identifier) * @param string $object_identifier * @return bool */ - public function fqcnMatchesObjectIdentifier($fqcn, $object_identifier) + public function fqcnMatchesObjectIdentifier(string $fqcn, string $object_identifier): bool { $fqcn = str_replace('\\', '_', $fqcn); return $fqcn === $object_identifier @@ -80,7 +80,7 @@ public function fqcnMatchesObjectIdentifier($fqcn, $object_identifier) * @param array $arguments * @return string */ - public function getIdentifier($fqcn, array $arguments = array()) + public function getIdentifier(string $fqcn, array $arguments = array()): string { // only build identifier from arguments if class is not ReservedInstanceInterface $identifier = ! $this->class_cache->hasInterface( @@ -104,7 +104,7 @@ public function getIdentifier($fqcn, array $arguments = array()) * @param array $arguments * @return string */ - protected function getIdentifierForArguments(array $arguments) + protected function getIdentifierForArguments(array $arguments): string { if (empty($arguments)) { return ''; diff --git a/core/services/locators/FqcnLocator.php b/core/services/locators/FqcnLocator.php index 838af503069..26cb8306259 100644 --- a/core/services/locators/FqcnLocator.php +++ b/core/services/locators/FqcnLocator.php @@ -80,6 +80,7 @@ public function locate($namespaces): array $this->FQCNs[ $key ] = $file; } } + $this->FQCNs = array_unique($this->FQCNs, SORT_STRING); return $this->FQCNs; } @@ -104,22 +105,23 @@ protected function findFQCNsByNamespace(string $partial_namespace): array if (iterator_count($iterator) === 0) { return []; } + $FQCNs = []; foreach ($iterator as $file) { if ($file->isFile() && $file->getExtension() === 'php') { - $file = $file->getPath() . '/' . $file->getBasename('.php'); + $file_name = $file->getPath() . '/' . $file->getBasename('.php'); foreach ($this->namespaces as $namespace => $base_dir) { $namespace .= Psr4Autoloader::NS; - if (strpos($file, $base_dir) === 0) { - $this->FQCNs[] = Psr4Autoloader::NS . str_replace( + if (strpos($file_name, $base_dir) === 0) { + $FQCNs[] = Psr4Autoloader::NS . str_replace( [$base_dir, '/'], [$namespace, Psr4Autoloader::NS], - $file + $file_name ); } } } } - return $this->FQCNs; + return array_unique($FQCNs, SORT_STRING); } diff --git a/core/services/orm/ModelFieldFactory.php b/core/services/orm/ModelFieldFactory.php index 0ac9db3e04d..c511cc2f00d 100644 --- a/core/services/orm/ModelFieldFactory.php +++ b/core/services/orm/ModelFieldFactory.php @@ -32,6 +32,7 @@ use EE_WP_Post_Status_Field; use EE_WP_Post_Type_Field; use EE_WP_User_Field; +use EventEspresso\core\interfaces\InterminableInterface; use EventEspresso\core\services\loaders\LoaderInterface; // phpcs:disable PEAR.Functions.ValidDefaultValue.NotAtEnd @@ -44,7 +45,7 @@ * @author Brent Christensen * @since 4.9.45 */ -class ModelFieldFactory +class ModelFieldFactory implements InterminableInterface { /** * @var LoaderInterface $loader @@ -64,10 +65,10 @@ public function __construct(LoaderInterface $loader) /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_All_Caps_Text_Field */ public function createAllCapsTextField( @@ -84,11 +85,11 @@ public function createAllCapsTextField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value - * @param string $model_name + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value + * @param string $model_name * @return EE_Any_Foreign_Model_Name_Field */ public function createAnyForeignModelNameField( @@ -106,10 +107,10 @@ public function createAnyForeignModelNameField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_Boolean_Field */ public function createBooleanField( @@ -126,27 +127,35 @@ public function createBooleanField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param string $default_value + * @param string $table_column + * @param string $nice_name + * @param bool|null $nullable + * @param string|null $default_value * @return EE_Datetime_Field */ public function createDatetimeField( string $table_column, string $nice_name, - bool $nullable = false, - string $default_value = EE_Datetime_Field::now + ?bool $nullable = false, + ?string $default_value = EE_Datetime_Field::now ): EE_Datetime_Field { - return $this->loader->getNew('EE_Datetime_Field', [$table_column, $nice_name, $nullable, $default_value,]); + return $this->loader->getNew( + 'EE_Datetime_Field', + [ + $table_column, + $nice_name, + $nullable, + $default_value, + ] + ); } /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_DB_Only_Float_Field */ public function createDbOnlyFloatField( @@ -163,10 +172,10 @@ public function createDbOnlyFloatField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_DB_Only_Int_Field */ public function createDbOnlyIntField( @@ -183,10 +192,10 @@ public function createDbOnlyIntField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_DB_Only_Text_Field */ public function createDbOnlyTextField( @@ -223,12 +232,12 @@ public function createEmailField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value - * @param array $allowed_enum_values keys are values to be used in the DB, - * values are how they should be displayed + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value + * @param array $allowed_enum_values keys are values to be used in the DB, + * values are how they should be displayed * @return EE_Enum_Integer_Field */ public function createEnumIntegerField( @@ -246,12 +255,12 @@ public function createEnumIntegerField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value - * @param array $allowed_enum_values keys are values to be used in the DB, - * values are how they should be displayed + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value + * @param array $allowed_enum_values keys are values to be used in the DB, + * values are how they should be displayed * @return EE_Enum_Text_Field */ public function createEnumTextField( @@ -269,10 +278,10 @@ public function createEnumTextField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_Float_Field */ public function createFloatField( @@ -289,11 +298,11 @@ public function createFloatField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value - * @param string $model_name + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value + * @param string $model_name * @return EE_Foreign_Key_Int_Field */ public function createForeignKeyIntField( @@ -311,11 +320,11 @@ public function createForeignKeyIntField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value - * @param string $model_name + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value + * @param string $model_name * @return EE_Foreign_Key_String_Field */ public function createForeignKeyStringField( @@ -333,10 +342,10 @@ public function createForeignKeyStringField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_Full_HTML_Field */ public function createFullHtmlField( @@ -353,10 +362,10 @@ public function createFullHtmlField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_Infinite_Integer_Field */ public function createInfiniteIntegerField( @@ -373,10 +382,10 @@ public function createInfiniteIntegerField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param integer $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param int $default_value * @return EE_Integer_Field */ public function createIntegerField( @@ -393,10 +402,10 @@ public function createIntegerField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_Maybe_Serialized_Simple_HTML_Field */ public function createMaybeSerializedSimpleHtmlField( @@ -413,10 +422,10 @@ public function createMaybeSerializedSimpleHtmlField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_Maybe_Serialized_Text_Field */ public function createMaybeSerializedTextField( @@ -433,10 +442,10 @@ public function createMaybeSerializedTextField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_Money_Field */ public function createMoneyField( @@ -473,10 +482,10 @@ public function createPlainTextField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_Post_Content_Field */ public function createPostContentField( @@ -515,10 +524,10 @@ public function createPrimaryKeyStringField(string $table_column, string $nice_n /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_Serialized_Text_Field */ public function createSerializedTextField( @@ -535,10 +544,10 @@ public function createSerializedTextField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_Simple_HTML_Field */ public function createSimpleHtmlField( @@ -555,10 +564,10 @@ public function createSimpleHtmlField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_Slug_Field */ public function createSlugField( @@ -575,10 +584,10 @@ public function createSlugField( /** - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param null $default_value + * @param string $table_column + * @param string $nice_name + * @param bool $nullable + * @param mixed|null $default_value * @return EE_Trashed_Flag_Field */ public function createTrashedFlagField( diff --git a/core/services/request/Response.php b/core/services/request/Response.php index 63b50b9a9fb..25894fd5cd1 100644 --- a/core/services/request/Response.php +++ b/core/services/request/Response.php @@ -2,6 +2,7 @@ namespace EventEspresso\core\services\request; +use EventEspresso\core\interfaces\InterminableInterface; use EventEspresso\core\interfaces\ReservedInstanceInterface; /** @@ -12,7 +13,7 @@ * @subpackage /core/ * @author Brent Christensen */ -class Response implements ResponseInterface, ReservedInstanceInterface +class Response implements InterminableInterface, ResponseInterface, ReservedInstanceInterface { /** * @var array $notice @@ -63,14 +64,14 @@ public function setNotice($key, $value) */ public function getNotice($key) { - return isset($this->notice[ $key ]) ? $this->notice[ $key ] : null; + return $this->notice[ $key ] ?? null; } /** * @return array */ - public function getNotices() + public function getNotices(): array { return $this->notice; } @@ -102,16 +103,16 @@ public function getOutput($as_string = true, $separator = PHP_EOL) /** - * @return boolean + * @return bool */ - public function requestTerminated() + public function requestTerminated(): bool { return $this->request_terminated; } /** - * @param boolean $request_terminated + * @param bool $request_terminated */ public function terminateRequest($request_terminated = true) { @@ -120,9 +121,9 @@ public function terminateRequest($request_terminated = true) /** - * @return boolean + * @return bool */ - public function pluginDeactivated() + public function pluginDeactivated(): bool { return $this->deactivate_plugin; } diff --git a/core/services/request/middleware/Middleware.php b/core/services/request/middleware/Middleware.php index dfa1fb0955f..9fb5cb3644c 100644 --- a/core/services/request/middleware/Middleware.php +++ b/core/services/request/middleware/Middleware.php @@ -2,6 +2,7 @@ namespace EventEspresso\core\services\request\middleware; +use EventEspresso\core\interfaces\InterminableInterface; use EventEspresso\core\services\loaders\LoaderInterface; use EventEspresso\core\services\request\RequestDecoratorInterface; use EventEspresso\core\services\request\RequestInterface; @@ -22,7 +23,7 @@ * @author Brent Christensen * @since 4.9.52 */ -abstract class Middleware implements RequestDecoratorInterface +abstract class Middleware implements InterminableInterface, RequestDecoratorInterface { /** * @var RequestDecoratorInterface $request_stack_app diff --git a/core/services/request/sanitizers/AllowedTags.php b/core/services/request/sanitizers/AllowedTags.php index c0248eeca03..80085a298c0 100644 --- a/core/services/request/sanitizers/AllowedTags.php +++ b/core/services/request/sanitizers/AllowedTags.php @@ -2,6 +2,8 @@ namespace EventEspresso\core\services\request\sanitizers; +use EventEspresso\core\interfaces\InterminableInterface; + /** * Class AllowedTags * expanded list of tags and attributes for use with wp_kses() @@ -10,7 +12,7 @@ * @package EventEspresso\core\services\request\sanitizers * @since 4.10.29.p */ -class AllowedTags +class AllowedTags implements InterminableInterface { /** * @var array[] diff --git a/core/services/request/sanitizers/AttributesSanitizer.php b/core/services/request/sanitizers/AttributesSanitizer.php index 22c9009c4ca..4299bb1584c 100644 --- a/core/services/request/sanitizers/AttributesSanitizer.php +++ b/core/services/request/sanitizers/AttributesSanitizer.php @@ -2,6 +2,8 @@ namespace EventEspresso\core\services\request\sanitizers; +use EventEspresso\core\interfaces\InterminableInterface; + /** * Class MultipleAttributes * @@ -9,7 +11,7 @@ * @package EventEspresso\core\services\request\sanitizers * @since 4.10.31.p */ -class AttributesSanitizer +class AttributesSanitizer implements InterminableInterface { /** * @param string $attributes diff --git a/core/services/request/sanitizers/RequestSanitizer.php b/core/services/request/sanitizers/RequestSanitizer.php index 0220af1d767..a6e54c24fe9 100644 --- a/core/services/request/sanitizers/RequestSanitizer.php +++ b/core/services/request/sanitizers/RequestSanitizer.php @@ -2,9 +2,10 @@ namespace EventEspresso\core\services\request\sanitizers; +use EventEspresso\core\interfaces\InterminableInterface; use EventEspresso\core\services\request\DataType; -class RequestSanitizer +class RequestSanitizer implements InterminableInterface { /** * Will sanitize the supplied request parameter based on the specified data type diff --git a/core/services/request/sanitizers/ServerSanitizer.php b/core/services/request/sanitizers/ServerSanitizer.php index 88d035136fe..aab89f88494 100644 --- a/core/services/request/sanitizers/ServerSanitizer.php +++ b/core/services/request/sanitizers/ServerSanitizer.php @@ -2,6 +2,8 @@ namespace EventEspresso\core\services\request\sanitizers; +use EventEspresso\core\interfaces\InterminableInterface; + /** * Class ServerSanitizer * @@ -9,7 +11,7 @@ * @package EventEspresso\core\services\request\sanitizers * @since 4.10.14.p */ -class ServerSanitizer +class ServerSanitizer implements InterminableInterface { /** * @param string $key diff --git a/core/services/routing/RouteCollection.php b/core/services/routing/RouteCollection.php index a30fd54e356..8a5e0c91df2 100644 --- a/core/services/routing/RouteCollection.php +++ b/core/services/routing/RouteCollection.php @@ -2,7 +2,6 @@ namespace EventEspresso\core\services\routing; -use EventEspresso\core\services\routing\RouteInterface; use EventEspresso\core\exceptions\InvalidInterfaceException; use EventEspresso\core\services\collections\Collection; @@ -40,9 +39,9 @@ public function __construct() * * @param $object * @param mixed $identifier - * @return bool + * @return string */ - public function getIdentifier($object, $identifier = null) + public function getIdentifier($object, $identifier = null): string { return ! empty($identifier) ? $identifier @@ -55,7 +54,7 @@ public function getIdentifier($object, $identifier = null) * * @return RouteInterface[] */ - public function getRoutesForCurrentRequest() + public function getRoutesForCurrentRequest(): array { $routes = []; $this->rewind(); diff --git a/core/services/routing/RouteMatchSpecificationCollection.php b/core/services/routing/RouteMatchSpecificationCollection.php index 65b4ba8e56c..b555bbf27a7 100644 --- a/core/services/routing/RouteMatchSpecificationCollection.php +++ b/core/services/routing/RouteMatchSpecificationCollection.php @@ -39,9 +39,9 @@ public function __construct() * * @param $object * @param mixed $identifier - * @return bool + * @return string */ - public function getIdentifier($object, $identifier = null) + public function getIdentifier($object, $identifier = null): string { return ! empty($identifier) ? $identifier diff --git a/core/services/routing/RouteMatchSpecificationFactory.php b/core/services/routing/RouteMatchSpecificationFactory.php index ad7875af45e..72102e665fa 100644 --- a/core/services/routing/RouteMatchSpecificationFactory.php +++ b/core/services/routing/RouteMatchSpecificationFactory.php @@ -5,6 +5,7 @@ use EventEspresso\core\domain\entities\routing\specifications\RouteMatchSpecification; use EventEspresso\core\exceptions\InvalidDataTypeException; use EventEspresso\core\exceptions\InvalidInterfaceException; +use EventEspresso\core\interfaces\InterminableInterface; use EventEspresso\core\services\factory\FactoryWithDependencyResolver; use EventEspresso\core\services\loaders\LoaderFactory; use EventEspresso\core\services\loaders\LoaderInterface; @@ -20,7 +21,7 @@ * @author Brent Christensen * @since 4.9.71.p */ -class RouteMatchSpecificationFactory extends FactoryWithDependencyResolver +class RouteMatchSpecificationFactory extends FactoryWithDependencyResolver implements InterminableInterface { /** * RouteMatchSpecificationFactory constructor @@ -34,12 +35,12 @@ public function __construct(RouteMatchSpecificationDependencyResolver $dependenc } /** - * @param $fqcn + * @param string $fqcn * @return RouteMatchSpecification * @throws InvalidDataTypeException * @since 4.9.71.p */ - public function createNewRouteMatchSpecification($fqcn) + public function createNewRouteMatchSpecification(string $fqcn): RouteMatchSpecification { $this->dependencyResolver()->resolveDependenciesForClass($fqcn); return $this->loader()->getShared($fqcn); @@ -47,14 +48,14 @@ public function createNewRouteMatchSpecification($fqcn) /** - * @param $fqcn + * @param string $fqcn * @return RouteMatchSpecification * @throws InvalidArgumentException * @throws InvalidDataTypeException * @throws InvalidInterfaceException * @since 4.9.71.p */ - public static function create($fqcn) + public static function create($fqcn): RouteMatchSpecification { /** @var RouteMatchSpecificationFactory $specification_factory */ $specification_factory = LoaderFactory::getLoader()->getShared( diff --git a/core/services/routing/RouteMatchSpecificationManager.php b/core/services/routing/RouteMatchSpecificationManager.php index aae2e9384eb..6ec3a6b8590 100644 --- a/core/services/routing/RouteMatchSpecificationManager.php +++ b/core/services/routing/RouteMatchSpecificationManager.php @@ -4,6 +4,7 @@ use EventEspresso\core\domain\entities\routing\specifications\RouteMatchSpecificationInterface; use EventEspresso\core\exceptions\InvalidClassException; +use EventEspresso\core\interfaces\InterminableInterface; use EventEspresso\core\services\collections\CollectionDetails; use EventEspresso\core\services\collections\CollectionDetailsException; use EventEspresso\core\services\collections\CollectionInterface; @@ -16,14 +17,14 @@ * and compares specifications in it via the currentRequestMatches() method. * Folders containing RouteMatchSpecification classes can be added to the collection using the * FHEE__EventEspresso_core_services_route_match_RouteMatchSpecificationManager__populateSpecificationCollection__collection_FQCNs - * filter prior to the AHEE__EE_System__initialize hookpoint + * filter prior to the AHEE__EE_System__initialize hook point * * * @package EventEspresso\core\services\routing * @author Brent Christensen * @since 4.9.71.p */ -class RouteMatchSpecificationManager +class RouteMatchSpecificationManager implements InterminableInterface { /** * @var CollectionInterface[]|RouteMatchSpecificationInterface[] $specifications @@ -61,19 +62,23 @@ public function __construct( */ public function initialize() { - $this->populateSpecificationCollection(); + // static $initialized = false; + // if (! $initialized) { + $this->populateSpecificationCollection(); + // $initialized = true; + // } } /** - * @return CollectionInterface|RouteMatchSpecificationInterface[] + * @return void * @throws CollectionLoaderException * @throws CollectionDetailsException * @since 4.9.71.p */ private function populateSpecificationCollection() { - $loader = new CollectionLoader( + new CollectionLoader( new CollectionDetails( // collection name RouteMatchSpecificationCollection::COLLECTION_NAME, @@ -99,7 +104,6 @@ private function populateSpecificationCollection() null, $this->specifications_factory ); - return $loader->getCollection(); } @@ -111,7 +115,7 @@ private function populateSpecificationCollection() * @throws InvalidClassException * @since 4.9.71.p */ - public function routeMatchesCurrentRequest($routeMatchSpecificationFqcn) + public function routeMatchesCurrentRequest(string $routeMatchSpecificationFqcn): bool { /** @var RouteMatchSpecificationInterface $specification */ $specification = $this->specifications->get($routeMatchSpecificationFqcn); @@ -132,7 +136,7 @@ public function routeMatchesCurrentRequest($routeMatchSpecificationFqcn) * @return array * @since 4.9.71.p */ - public function findRouteMatchSpecificationsMatchingCurrentRequest() + public function findRouteMatchSpecificationsMatchingCurrentRequest(): array { $matches = array(); foreach ($this->specifications as $specification) { diff --git a/core/services/session/SessionStartHandler.php b/core/services/session/SessionStartHandler.php index 40dd77e0335..f4e67245880 100644 --- a/core/services/session/SessionStartHandler.php +++ b/core/services/session/SessionStartHandler.php @@ -28,16 +28,21 @@ class SessionStartHandler { const OPTION_NAME_SESSION_SAVE_HANDLER_STATUS = 'ee_session_save_handler_status'; - const REQUEST_PARAM_RETRY_SESSION = 'ee_retry_session'; - const SESSION_SAVE_HANDLER_STATUS_FAILED = 'session_save_handler_failed'; - const SESSION_SAVE_HANDLER_STATUS_SUCCESS = 'session_save_handler_success'; - const SESSION_SAVE_HANDLER_STATUS_UNKNOWN = 'session_save_handler_untested'; + + const REQUEST_PARAM_RETRY_SESSION = 'ee_retry_session'; + + const SESSION_SAVE_HANDLER_STATUS_FAILED = 'session_save_handler_failed'; + + const SESSION_SAVE_HANDLER_STATUS_SUCCESS = 'session_save_handler_success'; + + const SESSION_SAVE_HANDLER_STATUS_UNKNOWN = 'session_save_handler_untested'; /** * @var RequestInterface $request */ protected $request; + /** * StartSession constructor. * @@ -48,6 +53,7 @@ public function __construct(RequestInterface $request) $this->request = $request; } + /** * Check if a custom session save handler is in play * and attempt to start the PHP session @@ -68,23 +74,19 @@ public function startSession() } } + /** * Returns `true` if the 'session.save_handler' ini setting matches a known custom handler * - * @since 4.9.68.p * @return bool + * @since 4.9.68.p */ - private function hasKnownCustomSessionSaveHandler() + private function hasKnownCustomSessionSaveHandler(): bool { - return in_array( - ini_get('session.save_handler'), - array( - 'user', - ), - true - ); + return ini_get('session.save_handler') === 'user'; } + /** * Attempt to start the PHP session when a custom Session Save Handler is known to be set. * @@ -119,10 +121,10 @@ private function checkCustomSessionSaveHandler() * retrieves the value for the 'ee_session_save_handler_status' WP option. * default value = 'session_save_handler_untested' * - * @since 4.9.68.p * @return string + * @since 4.9.68.p */ - private function getSessionSaveHandlerStatus() + private function getSessionSaveHandlerStatus(): string { return get_option( SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, @@ -130,83 +132,89 @@ private function getSessionSaveHandlerStatus() ); } + /** * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_failed' * which can then be upgraded is everything works correctly * + * @return void * @since 4.9.68.p - * @return bool */ - private function initializeSessionSaveHandlerStatus() + private function initializeSessionSaveHandlerStatus(): void { - return update_option( + update_option( SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_FAILED ); } + /** * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_success' * + * @return void * @since 4.9.68.p - * @return bool */ - private function setSessionSaveHandlerStatusToValid() + private function setSessionSaveHandlerStatusToValid(): void { - return update_option( + update_option( SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_SUCCESS ); } + /** * Sets the 'ee_session_save_handler_status' WP option value to 'session_save_handler_untested' * + * @return void * @since 4.9.68.p - * @return bool */ - private function resetSessionSaveHandlerStatus() + private function resetSessionSaveHandlerStatus(): void { - return update_option( + update_option( SessionStartHandler::OPTION_NAME_SESSION_SAVE_HANDLER_STATUS, SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_UNKNOWN ); } + /** * Returns `true` if the 'ee_session_save_handler_status' WP option value * is equal to 'session_save_handler_success' * - * @since 4.9.68.p * @return bool + * @since 4.9.68.p */ - private function sessionSaveHandlerIsValid() + private function sessionSaveHandlerIsValid(): bool { return $this->getSessionSaveHandlerStatus() === SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_SUCCESS; } + /** * Returns `true` if the 'ee_session_save_handler_status' WP option value * is equal to 'session_save_handler_failed' * - * @since 4.9.68.p * @return bool + * @since 4.9.68.p */ - private function sessionSaveHandlerFailed() + private function sessionSaveHandlerFailed(): bool { return $this->getSessionSaveHandlerStatus() === SessionStartHandler::SESSION_SAVE_HANDLER_STATUS_FAILED; } + /** * Returns `true` if no errors were detected with the session save handler, * otherwise attempts to work notify the appropriate authorities * with a suggestion for how to fix the issue, and returns `false`. * * - * @since 4.9.68.p * @return bool + * @since 4.9.68.p */ - private function handleSessionSaveHandlerErrors() + private function handleSessionSaveHandlerErrors(): bool { // Check if we had a fatal error last time while trying to start the session if ($this->sessionSaveHandlerFailed()) { @@ -218,7 +226,7 @@ private function handleSessionSaveHandlerErrors() // Better to remove it and redirect, and try on the next request EEH_URL::safeRedirectAndExit( remove_query_arg( - array(SessionStartHandler::REQUEST_PARAM_RETRY_SESSION), + [SessionStartHandler::REQUEST_PARAM_RETRY_SESSION], EEH_URL::current_url() ) ); @@ -231,6 +239,7 @@ private function handleSessionSaveHandlerErrors() return true; } + /** * Generates an EE_Error notice regarding the current session woes * but only if the current user is an admin with permission to 'install_plugins'. @@ -241,7 +250,7 @@ private function displaySessionSaveHandlerErrorNotice() { if (current_user_can('install_plugins')) { $retry_session_url = add_query_arg( - array(SessionStartHandler::REQUEST_PARAM_RETRY_SESSION => true), + [SessionStartHandler::REQUEST_PARAM_RETRY_SESSION => true], EEH_URL::current_url() ); EE_Error::add_error( diff --git a/tests/mocks/admin/events/Events_Admin_Page_Mock.php b/tests/mocks/admin/events/Events_Admin_Page_Mock.php index 34310d35696..ba1e171ba48 100644 --- a/tests/mocks/admin/events/Events_Admin_Page_Mock.php +++ b/tests/mocks/admin/events/Events_Admin_Page_Mock.php @@ -1,51 +1,61 @@ _default_tickets_update( $evtobj, $data ); - } - - - - - /** - * Mock for the _delete_event method that will handle setting up things for testing event deletes via the admin page. - * @param $EVT_ID_to_delete - */ - public function delete_event( $EVT_ID_to_delete ) { - //set request data for event +class Events_Admin_Page_Mock extends Events_Admin_Page +{ + /** + * @var EE_Admin_Config + */ + public $admin_config; + + + public function __construct($routing = true) + { + //define any constants that might not be defined yet when using this mock. + if (! defined('EVENTS_PG_SLUG')) { + define('EVENTS_PG_SLUG', 'espresso_events'); + define('EVENTS_LABEL', esc_html__('Events', 'event_espresso')); + define('EVENTS_ADMIN', EE_ADMIN_PAGES . 'events/'); + define('EVENTS_ADMIN_URL', admin_url('admin.php?page=' . EVENTS_PG_SLUG)); + define('EVENTS_TEMPLATE_PATH', EVENTS_ADMIN . 'templates/'); + define('EVENTS_ASSETS_URL', EE_PLUGIN_DIR_URL . 'admin_pages/events/assets/'); + } + + parent::__construct(false); + } + + + public function default_tickets_update($evtobj, $data) + { + return $this->_default_tickets_update($evtobj, $data); + } + + + /** + * Mock for the _delete_event method that will handle setting up things for testing event deletes via the admin + * page. + * + * @param $EVT_ID_to_delete + */ + public function delete_event($EVT_ID_to_delete) + { + //set request data for event $this->request->setRequestParam('EVT_IDs', $EVT_ID_to_delete); - $this->_delete_event( false ); - } - -} //end class Events_Admin_Page_Mock + $this->_delete_event(false); + } +} +//end class Events_Admin_Page_Mock diff --git a/tests/mocks/core/EE_Session_Mock.core.php b/tests/mocks/core/EE_Session_Mock.core.php index 84c88882c1f..6a9e611c22a 100644 --- a/tests/mocks/core/EE_Session_Mock.core.php +++ b/tests/mocks/core/EE_Session_Mock.core.php @@ -1,72 +1,70 @@ cache_storage = $cache_storage; - $this->request = $request; - $this->encryption = $encryption; + $this->request = $request; + $this->encryption = $encryption; } - public function lifespan() { - return 60 * MINUTE_IN_SECONDS; - } - + public function lifespan(): int + { + return 60 * MINUTE_IN_SECONDS; + } - /** - * @return EE_Encryption - */ - public function encryption() { - return $this->encryption; - } + /** + * @return EE_Encryption + */ + public function encryption(): ?EE_Encryption + { + return $this->encryption; + } /** * @param null $key * @param bool $reset_cache - * @return array + * @return mixed + * @throws EE_Error + * @throws ReflectionException */ - public function get_session_data($key = null, $reset_cache = false) + public function get_session_data($key = null, bool $reset_cache = false) { if ($reset_cache) { $this->clear_session(); } if (! empty($key)) { - return isset($this->session_data[ $key ]) ? $this->session_data[ $key ] : null; + return $this->session_data[ $key ] ?? null; } return $this->session_data; } @@ -137,11 +135,10 @@ public function get_session_data($key = null, $reset_cache = false) /** * set session data * - * @access public - * @param array $data + * @param array|null $data * @return TRUE on success, FALSE on fail */ - public function set_session_data($data) + public function set_session_data(?array $data): bool { foreach ($data as $key => $value) { $this->session_data[ $key ] = $value; @@ -150,17 +147,17 @@ public function set_session_data($data) } - public function clear_session($class = '', $function = '') + public function clear_session(string $class = '', string $function = '') { - $this->session_data = array(); + $this->session_data = []; } /** - * @param \EE_Cart $cart + * @param EE_Cart $cart * @return bool */ - public function set_cart(EE_Cart $cart) + public function set_cart(EE_Cart $cart): bool { $this->session_data['cart'] = $cart; return true; @@ -177,9 +174,9 @@ public function reset_cart() /** - * @return \EE_Cart + * @return EE_Cart */ - public function cart() + public function cart(): ?EE_Cart { return isset($this->session_data['cart']) && $this->session_data['cart'] instanceof EE_Cart ? $this->session_data['cart'] @@ -188,10 +185,10 @@ public function cart() /** - * @param \EE_Checkout $checkout + * @param EE_Checkout $checkout * @return bool */ - public function set_checkout(EE_Checkout $checkout) + public function set_checkout(EE_Checkout $checkout): bool { $this->session_data['checkout'] = $checkout; return true; @@ -208,9 +205,9 @@ public function reset_checkout() /** - * @return \EE_Checkout + * @return EE_Checkout */ - public function checkout() + public function checkout(): ?EE_Checkout { return isset($this->session_data['checkout']) && $this->session_data['checkout'] instanceof EE_Checkout ? $this->session_data['checkout'] @@ -219,11 +216,12 @@ public function checkout() /** - * @param \EE_Transaction $transaction + * @param EE_Transaction $transaction * @return bool * @throws EE_Error + * @throws ReflectionException */ - public function set_transaction(EE_Transaction $transaction) + public function set_transaction(EE_Transaction $transaction): bool { // first remove the session from the transaction before we save the transaction in the session $transaction->set_txn_session_data(null); @@ -242,9 +240,9 @@ public function reset_transaction() /** - * @return \EE_Transaction + * @return EE_Transaction */ - public function transaction() + public function transaction(): ?EE_Transaction { return isset($this->session_data['transaction']) && $this->session_data['transaction'] instanceof EE_Transaction diff --git a/tests/testcases/admin_pages/events_decaf/Events_Admin_Page_Decaf_Test.php b/tests/testcases/admin_pages/events_decaf/Events_Admin_Page_Decaf_Test.php index e6cae1a82ef..d4d6283e7e7 100644 --- a/tests/testcases/admin_pages/events_decaf/Events_Admin_Page_Decaf_Test.php +++ b/tests/testcases/admin_pages/events_decaf/Events_Admin_Page_Decaf_Test.php @@ -1,244 +1,326 @@ delayedAdminPageMocks( 'decaf_events' ); - $this->setupRequest(); - $this->useAdvancedEditor= EE_Registry::instance()->CFG->admin->useAdvancedEditor(); +class Events_Admin_Page_Decaf_Test extends EE_UnitTestCase +{ + /** + * This holds the Events_Admin_Page_Mock class + * + * @var Events_Admin_Page_Mock + */ + protected $_admin_page; + + + /** + * This holds the EE_Event object for testing with. + * + * @var EE_Event + */ + protected $_event; + + + /** + * @var boolean + */ + protected $useAdvancedEditor; + + + public function set_up() + { + parent::set_up(); + $this->useAdvancedEditor = EE_Registry::instance()->CFG->admin->useAdvancedEditor(); EE_Registry::instance()->CFG->admin->setUseAdvancedEditor(false); - } - - public function tear_down() - { - parent::tear_down(); - EE_Registry::instance()->CFG->admin->setUseAdvancedEditor($this->useAdvancedEditor); - } - - - /** - * loader for setting the $_admin_page_property - * - * @param string $timezone Timezone string to initialize the times in. - * @since 4.6 - */ - protected function _load_requirements( $timezone = 'America/Vancouver' ) - { - $this->_admin_page = new Events_Admin_Page_Mock(); - $this->_event = $this->factory->event->create(); - $this->_event->set_timezone( $timezone ); - $this->_event->save(); - $this->_set_default_dates( $timezone ); - } - - - - - /** - * tests the decaf datetime and tickets update method for Events Admin Page. - * - *@since 4.6 - */ - public function test_default_tickets_update() { - //first test is just with default data - $this->_load_requirements(); - $this->_testing_updates( "Tests with Default Data\n" ); - - //next test is with empty TKT_start and TKT_end dates. - $replacement['edit_tickets']['1']['TKT_start_date'] = null; - $replacement['edit_tickets']['1']['TKT_end_date'] = null; - - //override _default_dates because we expect something different. - $this->_default_dates = array(); - $this->_load_requirements(); - $this->_default_dates['TKT_start'] = new DateTime( 'now', new DateTimeZone( 'America/Vancouver' ) ); - - /** - * TKT_start is set in the decaf ticket saves without seconds, so we need to set the seconds to zero as well for comparison. - */ - $this->_default_dates['TKT_start']->setTime( $this->_default_dates['TKT_start']->format( 'H' ), $this->_default_dates['TKT_start']->format( 'i' ), 0 ); - /** - * tkt end date is the same as start date because here's the code execution in Events_Admin_page::default_tickets_update: - * 1. If no TKT_end_date, then set to DTT_EVT_start. - * 2. However, this means that DTT_EVT_start (because its static) will always be earlier than what the value for TKT_start_date is. - * 3. So later the code changes TKT_end_date to be the SAME as TKT_start_date and then sets it forward by a day. So that's what our expected value will be. - */ - $this->_default_dates['TKT_end'] = clone $this->_default_dates['TKT_start']; - $this->_default_dates['TKT_end'] = $this->_default_dates['TKT_end']->add( new DateInterval( 'P1D' ) ); - $this->_testing_updates( "Tests with unset tkt start and end date\n", $replacement ); - - } - - - - - /** - * This is a common looped to test saves of ticket and datetime data. - * - * @param string $context_for_error_messages Used this to add context to any failed tests so - * you can easily verify what triggered it. - * @param array $data_to_replace An array of replacements for the default data. - * Use null to indicate you want the key unset. - * @since 4.6 - */ - protected function _testing_updates( $context_for_error_messages, $data_to_replace = array() ) { - $formats_to_test = $this->date_formats_to_test(); - - $saved_dtts_for_tickets = $formats_for_compare = $saved_tkts = array(); - - /** - * Note: Keep in mind, decaf does NOT provide the ability to choose the format that the dates are - * displayed in for the event editor. So when we test comparing formats, it is important to set the - * format on the objects before retrieval. Also important is that only the 'Y-m-d h:i a' format is used - * on the decaf editor form. So we make sure the all the dates going in for the data are in the same format. - */ - - foreach( $formats_to_test['date'] as $date_format ) { - foreach( $formats_to_test['time'] as $time_format ) { - $full_format = $date_format . ' ' . $time_format; - $decaf_date_format = 'Y-m-d h:i a'; - $data = $this->_get_save_data( $decaf_date_format ); - - //is there any data to unset/replace? - if ( ! empty( $data_to_replace ) ) { - //any data to unset? - foreach( $data_to_replace as $top_level => $second_level ) { - if ( is_array( $second_level ) ) { - foreach ( $second_level as $third_level => $fourth_level ) - if ( is_array( $fourth_level ) ) { - foreach ( $fourth_level as $fifth_level => $sixth_level ) { - if ( is_null( $sixth_level ) ) { - unset( $data_to_replace[$top_level][$third_level][$fifth_level] ); - unset( $data[$top_level][$third_level][$fifth_level] ); - - } - } - } else if ( is_null( $fourth_level ) ) { - unset( $data_to_replace[$top_level][$third_level] ); - unset( $data[$top_level][$third_level] ); - } - } else { - if ( is_null( $second_level ) ) { - unset( $data_to_replace[$top_level] ); - unset( $data[$top_level] ); - } - } - } - //moige - $data = array_merge( $data, $data_to_replace ); - } - - - - $saved_data = $this->_admin_page->default_tickets_update( $this->_event, $data ); - $dtt = $saved_data[0]; - $tkts = $saved_data[1]; - - //verify datetime. - $this->assertInstanceof( 'EE_Datetime', $dtt ); - //verify start and date - $this->assertEquals( $dtt->start_date_and_time( $date_format, $time_format ), $this->_default_dates['DTT_start']->format( $full_format ), $context_for_error_messages . sprintf( 'Start Date Format Tested: %s', $full_format ) ); - $this->assertEquals( $dtt->end_date_and_time( $date_format, $time_format ), $this->_default_dates['DTT_end']->format( $full_format ), $context_for_error_messages . sprintf( 'End Date Format Tested: %s', $full_format ) ); - - $saved_dtts_for_tickets[$full_format] = $dtt; - $formats_for_compare[$dtt->ID()] = array( $date_format, $time_format ); - - //verify tkts - foreach ( $tkts as $tkt ) { - $this->assertInstanceof( 'EE_Ticket', $tkt, $context_for_error_messages . sprintf( 'Format: %s', $full_format ) ); - - //verify start and date - //Note: currently this test sometimes fails depending on the timing of when it happens and how fast - // the server is. Whenever I've seen this fail its been off by 1 minute and that's because when the - // default dates for testing were created, they likely happened at the second turnover. - $this->assertDateWithinOneMinute( $tkt->start_date( $date_format, $time_format ), $this->_default_dates['TKT_start']->format( $full_format ), $full_format, $context_for_error_messages . sprintf( 'Start Ticket DateFormat Tested: %s', $full_format ) ); - $this->assertDateWithinOneMinute( $tkt->end_date( $date_format, $time_format ), $this->_default_dates['TKT_end']->format( $full_format ), $full_format, $context_for_error_messages . sprintf( 'End Ticket Date Format Tested: %s', $full_format ) ); - - $saved_tkts[$full_format] = $tkt; - } - } - } - - - //now let's verify these items were saved corectly in the db. - /*$new_tkts = $new_dtts = array(); - foreach ( $tkt as $format => $tkt ) { - $new_tkts[$format] = EEM_Ticket::instance()->refresh_entity_map_from_db( $tkt->ID() ); - } - - foreach ( $saved_dtts_for_tickets[$full_format] as $format => $dtt ) { - $new_dtts[$format] = EEM_Datetime::instance()->refresh_entity_map_from_db( $dtt->ID() ); - }/**/ - - $new_event = EEM_Event::instance()->refresh_entity_map_from_db( $this->_event->ID() ); - $new_event->set_timezone( 'America/Vancouver' ); - - $evt_dtts = $new_event->datetimes_ordered(); - - //now let's do comparisons. - foreach( $evt_dtts as $edtt ) { - $formats = $formats_for_compare[$edtt->ID()]; - $format = $formats[0] . ' ' . $formats[1]; - $this->assertEquals( $edtt->start_date_and_time( $formats[0], $formats[1] ), $this->_default_dates['DTT_start']->format( $format), $context_for_error_messages . sprintf( 'DB DTT/Default DTT Start Date Format Checked: %s', $format ) ); - $this->assertEquals( $edtt->end_date_and_time( $formats[0], $formats[1] ), $this->_default_dates['DTT_end']->format( $format ), $context_for_error_messages . sprintf( 'DB DTT/Default DTT End Date Format Checked: %s', $format ) ); - $this->assertEquals( $edtt->start_date_and_time( $formats[0], $formats[1] ), $saved_dtts_for_tickets[$format]->start_date_and_time( $formats[0], $formats[1] ), $context_for_error_messages . sprintf( 'DB DTT/Orig DTT Start Date Format Checked: %s', $format ) ); - $this->assertEquals( $edtt->end_date_and_time( $formats[0], $formats[1] ), $saved_dtts_for_tickets[$format]->end_date_and_time( $formats[0], $formats[1] ), $context_for_error_messages . sprintf( 'DB DTT/Orig DTT End Date Format Checked: %s', $format ) ); - - //get related ticket on this $edtt - $evt_tkt = $edtt->get_first_related( 'Ticket' ); - $this->assertDateWithinOneMinute( $evt_tkt->start_date( $formats[0], $formats[1] ), $this->_default_dates['TKT_start']->format( $format ), $format, $context_for_error_messages . sprintf( 'DB TKT/Default TKT Start Date Format Checked: %s', $format ) ); - $this->assertDateWithinOneMinute( $evt_tkt->end_date( $formats[0], $formats[1] ), $this->_default_dates['TKT_end']->format( $format ), $format, $context_for_error_messages . sprintf( 'DB TKT/Default TKT End Date Format Checked: %s', $format ) ); - $this->assertDateWithinOneMinute( $evt_tkt->start_date( $formats[0], $formats[1] ), $saved_tkts[$format]->start_date( $formats[0], $formats[1] ), $format, $context_for_error_messages . sprintf( 'DB TKT/Orig TKT Start Date Format Checked: %s', $format ) ); - $this->assertDateWithinOneMinute( $evt_tkt->end_date( $formats[0], $formats[1] ), $saved_tkts[$format]->end_date( $formats[0], $formats[1] ), $format, $context_for_error_messages . sprintf( 'DB TKT/Orig TKT End Date Format Checked: %s', $format ) ); - } - } - - - + $this->delayedAdminPageMocks('decaf_events'); + $this->setupRequest(); + } + public function tear_down() + { + parent::tear_down(); + EE_Registry::instance()->CFG->admin->setUseAdvancedEditor($this->useAdvancedEditor); + } + + + /** + * loader for setting the $_admin_page_property + * + * @param string $timezone Timezone string to initialize the times in. + * @since 4.6 + */ + protected function _load_requirements($timezone = 'America/Vancouver') + { + $this->_admin_page = new Events_Admin_Page_Mock(); + $this->_admin_page->admin_config = EE_Registry::instance()->CFG->admin; + $this->_event = $this->factory->event->create(); + $this->_event->set_timezone($timezone); + $this->_event->save(); + $this->_set_default_dates($timezone); + } + + + /** + * tests the decaf datetime and tickets update method for Events Admin Page. + * + * @since 4.6 + */ + public function test_default_tickets_update() + { + //first test is just with default data + $this->_load_requirements(); + $this->_testing_updates("Tests with Default Data\n"); + + //next test is with empty TKT_start and TKT_end dates. + $replacement['edit_tickets']['1']['TKT_start_date'] = null; + $replacement['edit_tickets']['1']['TKT_end_date'] = null; + + //override _default_dates because we expect something different. + $this->_default_dates = []; + $this->_load_requirements(); + $this->_default_dates['TKT_start'] = new DateTime('now', new DateTimeZone('America/Vancouver')); + + /** + * TKT_start is set in the decaf ticket saves without seconds, so we need to set the seconds to zero as well for comparison. + */ + $this->_default_dates['TKT_start']->setTime( + $this->_default_dates['TKT_start']->format('H'), + $this->_default_dates['TKT_start']->format('i'), + 0 + ); + /** + * tkt end date is the same as start date because here's the code execution in Events_Admin_page::default_tickets_update: + * 1. If no TKT_end_date, then set to DTT_EVT_start. + * 2. However, this means that DTT_EVT_start (because its static) will always be earlier than what the value for TKT_start_date is. + * 3. So later the code changes TKT_end_date to be the SAME as TKT_start_date and then sets it forward by a day. So that's what our expected value will be. + */ + $this->_default_dates['TKT_end'] = clone $this->_default_dates['TKT_start']; + $this->_default_dates['TKT_end'] = $this->_default_dates['TKT_end']->add(new DateInterval('P1D')); + $this->_testing_updates("Tests with unset tkt start and end date\n", $replacement); + } + + + /** + * This is a common looped to test saves of ticket and datetime data. + * + * @param string $context_for_error_messages Used this to add context to any failed tests so + * you can easily verify what triggered it. + * @param array $data_to_replace An array of replacements for the default data. + * Use null to indicate you want the key unset. + * @since 4.6 + */ + protected function _testing_updates($context_for_error_messages, $data_to_replace = []) + { + $formats_to_test = $this->date_formats_to_test(); + + $saved_dtts_for_tickets = $formats_for_compare = $saved_tkts = []; + + /** + * Note: Keep in mind, decaf does NOT provide the ability to choose the format that the dates are + * displayed in for the event editor. So when we test comparing formats, it is important to set the + * format on the objects before retrieval. Also important is that only the 'Y-m-d h:i a' format is used + * on the decaf editor form. So we make sure the all the dates going in for the data are in the same format. + */ + + foreach ($formats_to_test['date'] as $date_format) { + foreach ($formats_to_test['time'] as $time_format) { + $full_format = $date_format . ' ' . $time_format; + $decaf_date_format = 'Y-m-d h:i a'; + $data = $this->_get_save_data($decaf_date_format); + + //is there any data to unset/replace? + if (! empty($data_to_replace)) { + //any data to unset? + foreach ($data_to_replace as $top_level => $second_level) { + if (is_array($second_level)) { + foreach ($second_level as $third_level => $fourth_level) { + if (is_array($fourth_level)) { + foreach ($fourth_level as $fifth_level => $sixth_level) { + if (is_null($sixth_level)) { + unset($data_to_replace[ $top_level ][ $third_level ][ $fifth_level ]); + unset($data[ $top_level ][ $third_level ][ $fifth_level ]); + } + } + } elseif (is_null($fourth_level)) { + unset($data_to_replace[ $top_level ][ $third_level ]); + unset($data[ $top_level ][ $third_level ]); + } + } + } else { + if (is_null($second_level)) { + unset($data_to_replace[ $top_level ]); + unset($data[ $top_level ]); + } + } + } + //moige + $data = array_merge($data, $data_to_replace); + } + + $saved_data = $this->_admin_page->default_tickets_update($this->_event, $data); + $dtt = $saved_data[0]; + $tkts = $saved_data[1]; + + //verify datetime. + $this->assertInstanceof('EE_Datetime', $dtt); + //verify start and date + $this->assertEquals( + $dtt->start_date_and_time($date_format, $time_format), + $this->_default_dates['DTT_start']->format($full_format), + $context_for_error_messages . sprintf('Start Date Format Tested: %s', $full_format) + ); + $this->assertEquals( + $dtt->end_date_and_time($date_format, $time_format), + $this->_default_dates['DTT_end']->format($full_format), + $context_for_error_messages . sprintf('End Date Format Tested: %s', $full_format) + ); + + $saved_dtts_for_tickets[ $full_format ] = $dtt; + $formats_for_compare[ $dtt->ID() ] = [$date_format, $time_format]; + + //verify tkts + foreach ($tkts as $tkt) { + $this->assertInstanceof( + 'EE_Ticket', + $tkt, + $context_for_error_messages . sprintf('Format: %s', $full_format) + ); + + //verify start and date + //Note: currently this test sometimes fails depending on the timing of when it happens and how fast + // the server is. Whenever I've seen this fail its been off by 1 minute and that's because when the + // default dates for testing were created, they likely happened at the second turnover. + $this->assertDateWithinOneMinute( + $tkt->start_date($date_format, $time_format), + $this->_default_dates['TKT_start']->format($full_format), + $full_format, + $context_for_error_messages . sprintf( + 'Start Ticket DateFormat Tested: %s', + $full_format + ) + ); + $this->assertDateWithinOneMinute( + $tkt->end_date($date_format, $time_format), + $this->_default_dates['TKT_end']->format($full_format), + $full_format, + $context_for_error_messages . sprintf( + 'End Ticket Date Format Tested: %s', + $full_format + ) + ); + + $saved_tkts[ $full_format ] = $tkt; + } + } + } + + + //now let's verify these items were saved corectly in the db. + /*$new_tkts = $new_dtts = array(); + foreach ( $tkt as $format => $tkt ) { + $new_tkts[$format] = EEM_Ticket::instance()->refresh_entity_map_from_db( $tkt->ID() ); + } + + foreach ( $saved_dtts_for_tickets[$full_format] as $format => $dtt ) { + $new_dtts[$format] = EEM_Datetime::instance()->refresh_entity_map_from_db( $dtt->ID() ); + }/**/ + + $new_event = EEM_Event::instance()->refresh_entity_map_from_db($this->_event->ID()); + $new_event->set_timezone('America/Vancouver'); + + $evt_dtts = $new_event->datetimes_ordered(); + + //now let's do comparisons. + foreach ($evt_dtts as $edtt) { + $formats = $formats_for_compare[ $edtt->ID() ]; + $format = $formats[0] . ' ' . $formats[1]; + $this->assertEquals( + $edtt->start_date_and_time($formats[0], $formats[1]), + $this->_default_dates['DTT_start']->format($format), + $context_for_error_messages . sprintf( + 'DB DTT/Default DTT Start Date Format Checked: %s', + $format + ) + ); + $this->assertEquals( + $edtt->end_date_and_time($formats[0], $formats[1]), + $this->_default_dates['DTT_end']->format($format), + $context_for_error_messages . sprintf( + 'DB DTT/Default DTT End Date Format Checked: %s', + $format + ) + ); + $this->assertEquals( + $edtt->start_date_and_time($formats[0], $formats[1]), + $saved_dtts_for_tickets[ $format ]->start_date_and_time($formats[0], $formats[1]), + $context_for_error_messages . sprintf( + 'DB DTT/Orig DTT Start Date Format Checked: %s', + $format + ) + ); + $this->assertEquals( + $edtt->end_date_and_time($formats[0], $formats[1]), + $saved_dtts_for_tickets[ $format ]->end_date_and_time($formats[0], $formats[1]), + $context_for_error_messages . sprintf( + 'DB DTT/Orig DTT End Date Format Checked: %s', + $format + ) + ); + + //get related ticket on this $edtt + $evt_tkt = $edtt->get_first_related('Ticket'); + $this->assertDateWithinOneMinute( + $evt_tkt->start_date($formats[0], $formats[1]), + $this->_default_dates['TKT_start']->format($format), + $format, + $context_for_error_messages . sprintf( + 'DB TKT/Default TKT Start Date Format Checked: %s', + $format + ) + ); + $this->assertDateWithinOneMinute( + $evt_tkt->end_date($formats[0], $formats[1]), + $this->_default_dates['TKT_end']->format($format), + $format, + $context_for_error_messages . sprintf( + 'DB TKT/Default TKT End Date Format Checked: %s', + $format + ) + ); + $this->assertDateWithinOneMinute( + $evt_tkt->start_date($formats[0], $formats[1]), + $saved_tkts[ $format ]->start_date($formats[0], $formats[1]), + $format, + $context_for_error_messages . sprintf( + 'DB TKT/Orig TKT Start Date Format Checked: %s', + $format + ) + ); + $this->assertDateWithinOneMinute( + $evt_tkt->end_date($formats[0], $formats[1]), + $saved_tkts[ $format ]->end_date($formats[0], $formats[1]), + $format, + $context_for_error_messages . sprintf( + 'DB TKT/Orig TKT End Date Format Checked: %s', + $format + ) + ); + } + } } // end class Events_Admin_Page_Decaf // Location: testcases/admin_pages/events_decaf/Events_Admin_Page_Decaf_Test.php diff --git a/tests/testcases/core/db_models/EEM_Event_Test.php b/tests/testcases/core/db_models/EEM_Event_Test.php index 84de2848252..7d55a7bff35 100644 --- a/tests/testcases/core/db_models/EEM_Event_Test.php +++ b/tests/testcases/core/db_models/EEM_Event_Test.php @@ -1,11 +1,4 @@ $this->factory->datetime->create( array( 'DTT_EVT_start' => $past_start_date->format( $full_format ), 'DTT_EVT_end' => $past_start_date->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'upcoming_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $upcoming_start_date->format( $full_format ), 'DTT_EVT_end' => $upcoming_start_date->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'active_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $current->sub( new DateInterval( "PT2H") )->format( $full_format ), 'DTT_EVT_end' => $current_end_date->add( new DateInterval( "PT2H" ) )->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'sold_out_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $upcoming_start_date->format( $full_format ), 'DTT_EVT_end' => $upcoming_start_date->format( $full_format), 'DTT_reg_limit' => 10, 'DTT_sold' => 10, 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'inactive_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $current->sub( new DateInterval( "PT2H") )->format( $full_format ), 'DTT_EVT_end' => $current_end_date->add( new DateInterval( "PT2H" ) )->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ) - ); - - //setup some events + /** + * This just sets up some events in the db for running certain tests that query getting events back. + * + * @since 4.6.x + */ + protected function _setup_events() + { + //setup some dates we'll use for testing with. + $timezone = new DateTimeZone('America/Toronto'); + $upcoming_start_date = new DateTime("now +2hours", $timezone); + $past_start_date = new DateTime("now -2days", $timezone); + $current_end_date = new DateTime("now +2days", $timezone); + $current = new DateTime("now", $timezone); + $formats = ['Y-d-m', 'h:i a']; + $full_format = implode(' ', $formats); + + //setup some datetimes to attach to events. + $datetimes = [ + 'expired_datetime' => $this->factory->datetime->create( + [ + 'DTT_EVT_start' => $past_start_date->format($full_format), + 'DTT_EVT_end' => $past_start_date->format($full_format), + 'timezone' => 'America/Toronto', + 'formats' => $formats, + ] + ), + 'upcoming_datetime' => $this->factory->datetime->create( + [ + 'DTT_EVT_start' => $upcoming_start_date->format($full_format), + 'DTT_EVT_end' => $upcoming_start_date->format($full_format), + 'timezone' => 'America/Toronto', + 'formats' => $formats, + ] + ), + 'active_datetime' => $this->factory->datetime->create( + [ + 'DTT_EVT_start' => $current->sub(new DateInterval("PT2H"))->format($full_format), + 'DTT_EVT_end' => $current_end_date->add(new DateInterval("PT2H"))->format($full_format), + 'timezone' => 'America/Toronto', + 'formats' => $formats, + ] + ), + 'sold_out_datetime' => $this->factory->datetime->create( + [ + 'DTT_EVT_start' => $upcoming_start_date->format($full_format), + 'DTT_EVT_end' => $upcoming_start_date->format($full_format), + 'DTT_reg_limit' => 10, + 'DTT_sold' => 10, + 'timezone' => 'America/Toronto', + 'formats' => $formats, + ] + ), + 'inactive_datetime' => $this->factory->datetime->create( + [ + 'DTT_EVT_start' => $current->sub(new DateInterval("PT2H"))->format($full_format), + 'DTT_EVT_end' => $current_end_date->add(new DateInterval("PT2H"))->format($full_format), + 'timezone' => 'America/Toronto', + 'formats' => $formats, + ] + ), + ]; + + //setup some events /** @var EE_Event[] $events */ - $events = $this->factory->event->create_many( '4' ); - - //add datetimes to the events. - $events[0]->_add_relation_to( $datetimes['expired_datetime'], 'Datetime' ); - $events[0]->save(); - $events[1]->_add_relation_to( $datetimes['upcoming_datetime'], 'Datetime' ); - $events[1]->save(); - $events[2]->_add_relation_to( $datetimes['active_datetime'], 'Datetime' ); - $events[2]->save(); - $events[3]->_add_relation_to( $datetimes['sold_out_datetime'], 'Datetime' ); - $events[3]->save(); - - foreach( $events as $event ) { - $event->set('status', 'publish'); - $event->save(); - } - - //one more event that is just going to be inactive + $events = $this->factory->event->create_many('4'); + + //add datetimes to the events. + $events[0]->_add_relation_to($datetimes['expired_datetime'], 'Datetime'); + $events[0]->save(); + $events[1]->_add_relation_to($datetimes['upcoming_datetime'], 'Datetime'); + $events[1]->save(); + $events[2]->_add_relation_to($datetimes['active_datetime'], 'Datetime'); + $events[2]->save(); + $events[3]->_add_relation_to($datetimes['sold_out_datetime'], 'Datetime'); + $events[3]->save(); + + foreach ($events as $event) { + $event->set('status', 'publish'); + $event->save(); + } + + //one more event that is just going to be inactive /** @var EE_Event $final_event */ $final_event = $this->factory->event->create(); - $final_event->_add_relation_to( $datetimes['inactive_datetime'], 'Datetime' ); - $final_event->save(); + $final_event->_add_relation_to($datetimes['inactive_datetime'], 'Datetime'); + $final_event->save(); + } - } + + /** + * This tests getting active events. + * + * @since 4.6.x + */ + public function test_get_active_events() + { + $this->_setup_events(); + //now do our tests + $this->assertEquals(1, EEM_Event::instance()->get_active_events([], true)); + } + public function test_get_upcoming_events() + { + $this->_setup_events(); + //now do our tests + $this->assertEquals(2, EEM_Event::instance()->get_upcoming_events([], true)); + } - /** - * This tests getting active events. - * @since 4.6.x - */ - public function test_get_active_events() { - $this->_setup_events(); - //now do our tests - $this->assertEquals( 1, EEM_Event::instance()->get_active_events( array(), true ) ); - } + public function test_get_expired_events() + { + $this->_setup_events(); + //now do our tests + $this->assertEquals(1, EEM_Event::instance()->get_expired_events([], true)); + } - public function test_get_upcoming_events() { - $this->_setup_events(); - //now do our tests - $this->assertEquals( 2, EEM_Event::instance()->get_upcoming_events( array(), true ) ); - } + public function test_get_inactive_events() + { + $this->_setup_events(); + //now do our tests + $this->assertEquals(1, EEM_Event::instance()->get_inactive_events([], true)); + } - public function test_get_expired_events() { - $this->_setup_events(); - //now do our tests - $this->assertEquals( 1, EEM_Event::instance()->get_expired_events( array(), true ) ); - } - public function test_get_inactive_events() { - $this->_setup_events(); - //now do our tests - $this->assertEquals( 1, EEM_Event::instance()->get_inactive_events( array(), true ) ); - } + public function test_get_active_and_upcoming_events() + { + $this->_setup_events(); + //now do our tests + $this->assertEquals(3, EEM_Event::instance()->get_active_and_upcoming_events([], true)); + } - public function test_get_active_and_upcoming_events() { - $this->_setup_events(); - //now do our tests - $this->assertEquals( 3, EEM_Event::instance()->get_active_and_upcoming_events( array(), true ) ); - } + /** + * @see https://events.codebasehq.com/projects/event-espresso/tickets/8799 + * @group 8799 + * @since 4.8.8.rc.019 + */ + public function test_default_reg_status() + { + //first verify the default reg status on config is pending payment + $this->assertEquals( + EEM_Registration::status_id_pending_payment, + EE_Registry::instance()->CFG->registration->default_STS_ID + ); - /** - * @see https://events.codebasehq.com/projects/event-espresso/tickets/8799 - * @group 8799 - * @since 4.8.8.rc.019 - */ - public function test_default_reg_status() { - //first verify the default reg status on config is pending payment - $this->assertEquals( EEM_Registration::status_id_pending_payment, EE_Registry::instance()->CFG->registration->default_STS_ID ); + //verify creating default event from the model has that default reg status + /** @type EE_Event $event */ + $event = EEM_Event::instance()->create_default_object(); + $this->assertEquals(EEM_Registration::status_id_pending_payment, $event->default_registration_status()); - //verify creating default event from the model has that default reg status - /** @type EE_Event $event */ - $event = EEM_Event::instance()->create_default_object(); - $this->assertEquals( EEM_Registration::status_id_pending_payment, $event->default_registration_status() ); + //let's update config in the db to have default reg status of approved + EE_Registry::instance()->CFG->registration->default_STS_ID = EEM_Registration::status_id_approved; + EE_Registry::instance()->CFG->update_espresso_config(); - //let's update config in the db to have default reg status of approved - EE_Registry::instance()->CFG->registration->default_STS_ID = EEM_Registration::status_id_approved; - EE_Registry::instance()->CFG->update_espresso_config(); + //let's reset for new test + EEM_Event::reset(); + EE_Registry::reset(); - //let's reset for new test - EEM_Event::reset(); - EE_Registry::reset(); + //k NOW the default reg status in config should be approved + $this->assertEquals( + EEM_Registration::status_id_approved, + EE_Registry::instance()->CFG->registration->default_STS_ID + ); - //k NOW the default reg status in config should be approved - $this->assertEquals( EEM_Registration::status_id_approved, EE_Registry::instance()->CFG->registration->default_STS_ID ); + //new default event should have approved as the default reg status + $event = EEM_Event::instance()->create_default_object(); + $this->assertEquals(EEM_Registration::status_id_approved, $event->default_registration_status()); + } - //new default event should have approved as the default reg status - $event = EEM_Event::instance()->create_default_object(); - $this->assertEquals( EEM_Registration::status_id_approved, $event->default_registration_status() ); - } /** - * @since 4.10.0.p * @throws EE_Error * @throws InvalidArgumentException * @throws ReflectionException * @throws InvalidDataTypeException * @throws InvalidInterfaceException + * @since 4.10.0.p */ - public function testGetQuestionGroupsForEvent() + public function testGetQuestionGroupsForEvent() { $r = $this->new_model_obj_with_dependencies( 'Registration', [ - 'REG_count' => 1 + 'REG_count' => 1, ] ); $r->event_obj()->add_question_group(EEM_Question_Group::system_personal, true); @@ -187,6 +233,5 @@ public function testGetQuestionGroupsForEvent() $qgs ); } - } // Location: testcases/core/db_models/EEM_Event_Test.php diff --git a/tests/testcases/core/helpers/EEH_Activation_Test.php b/tests/testcases/core/helpers/EEH_Activation_Test.php index 39938f17b16..fb1262009ec 100644 --- a/tests/testcases/core/helpers/EEH_Activation_Test.php +++ b/tests/testcases/core/helpers/EEH_Activation_Test.php @@ -1,263 +1,295 @@ load_lib( 'Message_Resource_Manager' ); - // messengers that have been activated and verified installed - $active_messengers = $message_resource_manager->active_messengers(); - // ALL installed messengers regardless of whether they are active or not - $installed_messengers = $message_resource_manager->installed_messengers(); - $should_be_installed = array(); - foreach( $active_messengers as $msgr ) { - $this->assertInstanceOf( 'EE_messenger', $msgr ); - if ( $msgr->activate_on_install ) { - $should_be_installed[] = $msgr->name; - } - } - //loop through $should_be_installed and verify that those that should be active ARE active. - foreach ( $should_be_installed as $msgr_name ) { - $this->assertTrue( - isset( $installed_messengers[ $msgr_name ] ), - sprintf( 'The messenger %s should be active on fresh install, but it is not.', $msgr_name ) - ); - } - - //now verify that the code doesn't run new message template generation etc. - $this->assertFalse( EEH_Activation::generate_default_message_templates() ); - - - // now we simulate someone who's deactivated a messenger - // and we simulate a migration that triggers generating default message templates again. - // The html messenger should STICK and NOT be activated. - $message_resource_manager->deactivate_messenger( 'html' ); - - //do the same for message type - $message_resource_manager->deactivate_message_type_for_messenger( 'not_approved', 'email' ); - - //Reset messages to test stickiness - EE_Registry::reset(); - - $activated_response = EEH_Activation::generate_default_message_templates(); - - //verify we got a response (html should not have templates generated) - $this->assertFalse( $activated_response ); - - // double check we still don't have html in the active messengers array - $active_messengers = $message_resource_manager->get_active_messengers_option( true ); - $this->assertFalse( isset( $active_messengers['html'] ) ); - $this->assertFalse( $message_resource_manager->is_message_type_active_for_messenger( 'email', 'not_approved' ) ); - } - - - - - - /** - * This tests the generate_default_message_templates method with using the - * FHEE__EE_messenger__get_default_message_types__default_types filter to add a - * bogus message_type string. No errors should be triggered, and the invalid default mt - * should NOT be added to the active array for the messenger. - * - * @since 4.6 - * @group 7595 - */ - public function test_filtered_default_message_types_on_activation() { - /** @type EE_Message_Resource_Manager $message_resource_manager */ - $message_resource_manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' ); - //let's clear out all active messengers to get an accurate test of initial generation of message templates. - global $wpdb; - // delete message_template_group templates - $message_template_group_table = $wpdb->prefix . 'esp_message_template_group'; - $query = "DELETE FROM $message_template_group_table WHERE 'GRP_ID' > 0"; - $wpdb->query( $query ); - // delete message_template templates - $message_template_table = $wpdb->prefix . 'esp_message_template'; - $query = "DELETE FROM $message_template_table WHERE 'MTP_ID' > 0"; - $wpdb->query($query); - // delete event_message_template templates - $event_message_template_table = $wpdb->prefix . 'esp_event_message_template'; - $query = "DELETE FROM $event_message_template_table WHERE 'EMT_ID' > 0"; - $wpdb->query( $query ); - - $message_resource_manager->update_active_messengers_option( array() ); - //set a filter for the invalid message type - add_filter( - 'FHEE__EE_messenger__get_default_message_types__default_types', - function( $default_types ) { - $default_types[] = 'bogus_message_type'; - return $default_types; - }, 10, 2 - ); - - try { - //activate messages... if there's any problems then errors will trigger a fail. - EEH_Activation::generate_default_message_templates(); - } catch( EE_Error $e ){ - $this->assertInstanceOf( 'EE_Error', $e ); - } - - //all went well so let's make sure the activated system does NOT have our invalid message type string. - $active_messengers = $message_resource_manager->get_active_messengers_option( true ); - foreach( $active_messengers as $messenger => $settings ) { - $this->assertFalse( - isset( $settings[ 'settings' ][ $messenger . '-message_types' ][ 'bogus_message_type' ] ), - sprintf( 'The %s messenger should not have "bogus_message_type" active on it but it does.', $messenger ) - ); - } - } - - - - - /** - * Ensure getting default creator works as expected - * @since 4.6.0 - */ - public function test_get_default_creator_id() { - //clear out any previous users that may be lurking in teh system - foreach( get_users() as $wp_user ){ - wp_delete_user( $wp_user->ID ); - } - //set some users; and just make it interesting by having the first user NOT be an admin - $this->factory->user->create_many( 2 ); - $users = $this->factory->user->create_many( 2 ); - //make users administrators. - foreach ( $users as $user_id ) { - $user = $this->factory->user->get_object_by_id( $user_id ); - //verify - $this->assertInstanceOf( 'WP_User', $user ); - //add role - $user->add_role( 'administrator' ); - } - - //get all users so we know who is the first one that we should be expecting. - $expected_id = reset( $users ); - $this->assertEquals( EEH_Activation::get_default_creator_id(), $expected_id ); - - /** - * ok now let's verify EEH_Activation::reset() properly clears the cache - * on EEH_Activation. This is important for subsequent unit tests (because - * EEH_Activation::reset() is called between unit tests), but also when an admin - * resets their EE database, or when anyone wants to reset that cache) - * clear out any previous users that may be lurking in teh system - */ - EEH_Activation::reset(); - foreach( get_users() as $wp_user ){ - wp_delete_user( $wp_user->ID ); - } - //set some users; and just make it interesting by having the first user NOT be an admin - $this->factory->user->create_many( 2 ); - $users_created_after_reset = $this->factory->user->create_many( 2 ); - //make users administrators. - foreach ( $users_created_after_reset as $user_id ) { - $user = $this->factory->user->get_object_by_id( $user_id ); - //verify - $this->assertInstanceOf( 'WP_User', $user ); - //add role - $user->add_role( 'administrator' ); - } - - //get all users so we know who is the first one that we should be expecting. - $new_expected_id = reset( $users_created_after_reset ); - $this->assertEquals( EEH_Activation::get_default_creator_id(), $new_expected_id ); - - } - - function test_get_cron_tasks__old() { - add_filter( 'FHEE__EEH_Activation__get_cron_tasks', array( $this, 'change_cron_tasks' ) ); - $old_cron_tasks = EEH_Activation::get_cron_tasks( 'old' ); - $this->assertArrayHasKey( self::expired_cron_task_name, $old_cron_tasks ); - $this->assertArrayNotHasKey( self::current_cron_task_name, $old_cron_tasks ); - } - function test_get_cron_tasks__all() { - add_filter( 'FHEE__EEH_Activation__get_cron_tasks', array( $this, 'change_cron_tasks' ) ); - $old_cron_tasks = EEH_Activation::get_cron_tasks( 'all' ); - $this->assertArrayHasKey( self::expired_cron_task_name, $old_cron_tasks ); - $this->assertArrayHasKey( self::current_cron_task_name, $old_cron_tasks ); - } - - - /** - * @see https://events.codebasehq.com/projects/event-espresso/tickets/9501 - * @since 4.8.36 - */ - function test_remove_cron_tasks_with_empty_timestamp_values() { - //first cache existing cron array - $old_cron_option = _get_cron_array(); - //merge in a bunch of empty timestamps - $empty_timestamps = array( - time() + 30 => array(), - time() + 600 => array(), - time() - 400 => array() - ); - _set_cron_array( - array_merge( $empty_timestamps, $old_cron_option ) - ); - - //now let's run the EEH_Activation::remove_cron_tasks - EEH_Activation::remove_cron_tasks(); - - //and verify that there are no empty timestamps - $updated_cron_option = _get_cron_array(); - $this->assertEquals( count( $old_cron_option ), count( $updated_cron_option ) ); - - //now restore - _set_cron_array( $old_cron_option ); - } - - - /** - * Makes it so this function can be independent on what the current cron tasks actually are - * (because they'll likely change, whereas some of these functions just want to check that - * we are retrieving cron tasks correctly) - * - * @param array $old_cron_tasks - * @return array - */ - function change_cron_tasks( $old_cron_tasks ) { - return array( - self::current_cron_task_name => 'hourly', - self::expired_cron_task_name => EEH_Activation::cron_task_no_longer_in_use - ); - } - - function test_table_exists__success() { - $this->assertTrue( EEH_Activation::table_exists( 'posts' ) ); - $this->assertTrue( EEH_Activation::table_exists( 'esp_attendee_meta' ) ); - } - - function test_table_exists__false() { - $this->assertFalse( EEH_Activation::table_exists( 'monkeys' ) ); - } - +class EEH_Activation_Test extends EE_UnitTestCase +{ + const current_cron_task_name = 'current_one'; + + const expired_cron_task_name = 'expired_one'; + + + public function set_up() + { + parent::set_up(); + EEH_Activation::reset(); + } + + + /** + * Makes it so this function can be independent on what the current cron tasks actually are + * (because they'll likely change, whereas some of these functions just want to check that + * we are retrieving cron tasks correctly) + * + * @return array + */ + public function change_cron_tasks(): array + { + return [ + self::current_cron_task_name => 'hourly', + self::expired_cron_task_name => EEH_Activation::cron_task_no_longer_in_use, + ]; + } + + + /** + * The purpose of this test is to ensure that generation of default templates works as expected. + * + * @throws EE_Error + * @throws ReflectionException + * @since 4.5.0 + */ + public function test_generate_default_message_templates() + { + /** + * Testing default messengers setup on activation (or introduction on migration) + */ + //first let's make sure all message templates got setup on new install as they should be. + /** @type EE_Message_Resource_Manager $message_resource_manager */ + $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager'); + // messengers that have been activated and verified installed + $active_messengers = $message_resource_manager->active_messengers(); + // ALL installed messengers regardless of whether they are active or not + $installed_messengers = $message_resource_manager->installed_messengers(); + $should_be_installed = []; + foreach ($active_messengers as $msgr) { + $this->assertInstanceOf('EE_messenger', $msgr); + if ($msgr->activate_on_install) { + $should_be_installed[] = $msgr->name; + } + } + //loop through $should_be_installed and verify that those that should be active ARE active. + foreach ($should_be_installed as $msgr_name) { + $this->assertTrue( + isset($installed_messengers[ $msgr_name ]), + sprintf('The messenger %s should be active on fresh install, but it is not.', $msgr_name) + ); + } + + //now verify that the code doesn't run new message template generation etc. + $this->assertFalse(EEH_Activation::generate_default_message_templates()); + + + // now we simulate someone who's deactivated a messenger + // and we simulate a migration that triggers generating default message templates again. + // The html messenger should STICK and NOT be activated. + $message_resource_manager->deactivate_messenger('html'); + + //do the same for message type + $message_resource_manager->deactivate_message_type_for_messenger('not_approved', 'email'); + + //Reset messages to test stickiness + EE_Registry::reset(); + + $activated_response = EEH_Activation::generate_default_message_templates(); + + //verify we got a response (html should not have templates generated) + $this->assertFalse($activated_response); + + // double check we still don't have html in the active messengers array + $active_messengers = $message_resource_manager->get_active_messengers_option(true); + $this->assertFalse(isset($active_messengers['html'])); + $this->assertFalse($message_resource_manager->is_message_type_active_for_messenger('email', 'not_approved')); + } + + + /** + * This tests the generate_default_message_templates method with using the + * FHEE__EE_messenger__get_default_message_types__default_types filter to add a + * bogus message_type string. No errors should be triggered, and the invalid default mt + * should NOT be added to the active array for the messenger. + * + * @throws EE_Error + * @throws ReflectionException + * @since 4.6 + * @group 7595 + */ + public function test_filtered_default_message_types_on_activation() + { + /** @type EE_Message_Resource_Manager $message_resource_manager */ + $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager'); + //let's clear out all active messengers to get an accurate test of initial generation of message templates. + global $wpdb; + // delete message_template_group templates + $message_template_group_table = $wpdb->prefix . 'esp_message_template_group'; + $query = "DELETE FROM $message_template_group_table WHERE 'GRP_ID' > 0"; + $wpdb->query($query); + // delete message_template templates + $message_template_table = $wpdb->prefix . 'esp_message_template'; + $query = "DELETE FROM $message_template_table WHERE 'MTP_ID' > 0"; + $wpdb->query($query); + // delete event_message_template templates + $event_message_template_table = $wpdb->prefix . 'esp_event_message_template'; + $query = "DELETE FROM $event_message_template_table WHERE 'EMT_ID' > 0"; + $wpdb->query($query); + + $message_resource_manager->update_active_messengers_option([]); + //set a filter for the invalid message type + add_filter( + 'FHEE__EE_messenger__get_default_message_types__default_types', + function ($default_types) { + $default_types[] = 'bogus_message_type'; + return $default_types; + }, + 10, + 2 + ); + + try { + //activate messages... if there's any problems then errors will trigger a fail. + EEH_Activation::generate_default_message_templates(); + } catch (EE_Error $e) { + $this->assertInstanceOf('EE_Error', $e); + } + + //all went well so let's make sure the activated system does NOT have our invalid message type string. + $active_messengers = $message_resource_manager->get_active_messengers_option(true); + foreach ($active_messengers as $messenger => $settings) { + $this->assertFalse( + isset($settings['settings'][ $messenger . '-message_types' ]['bogus_message_type']), + sprintf('The %s messenger should not have "bogus_message_type" active on it but it does.', $messenger) + ); + } + } + + + /** + * Ensure getting default creator works as expected + * + * @throws EE_Error + * @throws ReflectionException + * @since 4.6.0 + */ + public function test_get_default_creator_id() + { + //clear out any previous users that may be lurking in teh system + foreach (get_users() as $wp_user) { + wp_delete_user($wp_user->ID); + } + //set some users; and just make it interesting by having the first user NOT be an admin + $this->factory->user->create_many(2); + $users = $this->factory->user->create_many(2); + //make users administrators. + foreach ($users as $user_id) { + $user = $this->factory->user->get_object_by_id($user_id); + //verify + $this->assertInstanceOf('WP_User', $user); + //add role + $user->add_role('administrator'); + } + + //get all users so we know who is the first one that we should be expecting. + $expected_id = reset($users); + $this->assertEquals($expected_id, EEH_Activation::get_default_creator_id()); + + /** + * ok now let's verify EEH_Activation::reset() properly clears the cache + * on EEH_Activation. This is important for subsequent unit tests (because + * EEH_Activation::reset() is called between unit tests), but also when an admin + * resets their EE database, or when anyone wants to reset that cache) + * clear out any previous users that may be lurking in teh system + */ + EEH_Activation::reset(); + foreach (get_users() as $wp_user) { + wp_delete_user($wp_user->ID); + } + //set some users; and just make it interesting by having the first user NOT be an admin + $this->factory->user->create_many(2); + $users_created_after_reset = $this->factory->user->create_many(2); + //make users administrators. + foreach ($users_created_after_reset as $user_id) { + $user = $this->factory->user->get_object_by_id($user_id); + //verify + $this->assertInstanceOf('WP_User', $user); + //add role + $user->add_role('administrator'); + } + + //get all users so we know who is the first one that we should be expecting. + $new_expected_id = reset($users_created_after_reset); + $this->assertEquals(EEH_Activation::get_default_creator_id(), $new_expected_id); + } + + + /** + * @throws EE_Error + */ + public function test_get_cron_tasks__old() + { + add_filter('FHEE__EEH_Activation__get_cron_tasks', [$this, 'change_cron_tasks']); + $old_cron_tasks = EEH_Activation::get_cron_tasks('old'); + $this->assertArrayHasKey(self::expired_cron_task_name, $old_cron_tasks); + $this->assertArrayNotHasKey(self::current_cron_task_name, $old_cron_tasks); + } + + + /** + * @throws EE_Error + */ + public function test_get_cron_tasks__all() + { + add_filter('FHEE__EEH_Activation__get_cron_tasks', [$this, 'change_cron_tasks']); + $old_cron_tasks = EEH_Activation::get_cron_tasks('all'); + $this->assertArrayHasKey(self::expired_cron_task_name, $old_cron_tasks); + $this->assertArrayHasKey(self::current_cron_task_name, $old_cron_tasks); + } + + + /** + * @throws EE_Error + * @see https://events.codebasehq.com/projects/event-espresso/tickets/9501 + * @since 4.8.36 + */ + public function test_remove_cron_tasks_with_empty_timestamp_values() + { + //first cache existing cron array + $old_cron_option = _get_cron_array(); + //merge in a bunch of empty timestamps + $empty_timestamps = [ + time() + 30 => [], + time() + 600 => [], + time() - 400 => [], + ]; + _set_cron_array( + array_merge($empty_timestamps, $old_cron_option) + ); + + //now let's run the EEH_Activation::remove_cron_tasks + EEH_Activation::remove_cron_tasks(); + + //and verify that there are no empty timestamps + $updated_cron_option = _get_cron_array(); + $this->assertEquals(count($old_cron_option), count($updated_cron_option)); + + //now restore + _set_cron_array($old_cron_option); + } + + + /** + * @throws EE_Error + * @throws ReflectionException + */ + public function test_table_exists__success() + { + $this->assertTrue(EEH_Activation::table_exists('posts')); + $this->assertTrue(EEH_Activation::table_exists('esp_attendee_meta')); + } + + + /** + * @throws EE_Error + * @throws ReflectionException + */ + public function test_table_exists__false() + { + $this->assertFalse(EEH_Activation::table_exists('monkeys')); + } } //end class EEH_Activation_Test diff --git a/tests/testcases/core/helpers/EEH_Parse_Shortcodes_Test.php b/tests/testcases/core/helpers/EEH_Parse_Shortcodes_Test.php index 6acfd4554ad..e84ac67e169 100644 --- a/tests/testcases/core/helpers/EEH_Parse_Shortcodes_Test.php +++ b/tests/testcases/core/helpers/EEH_Parse_Shortcodes_Test.php @@ -278,6 +278,7 @@ protected function _get_parsed_content($messenger, $message_type, $field, $conte */ public function test_parsing_email_payment_received() { + tests_add_filter('FHEE_load_EE_Session', '__return_true'); $parsed = $this->_get_parsed_content('email', 'payment', 'content', 'primary_attendee'); //now that we have parsed let's test the results, note for the purpose of this test we are verifying transaction shortcodes and ticket shortcodes. @@ -319,7 +320,7 @@ public function test_parsing_email_payment_received() $parsed, '[TKT_QTY_PURCHASED] shortcode was not parsed correctly to the expected value which is 3' ); - + tests_add_filter('FHEE_load_EE_Session', '__return_true'); } diff --git a/tests/testcases/core/libraries/plugin_api/EE_Register_Payment_Method_Test.php b/tests/testcases/core/libraries/plugin_api/EE_Register_Payment_Method_Test.php index 4ed8a73aa9e..44a9349db61 100644 --- a/tests/testcases/core/libraries/plugin_api/EE_Register_Payment_Method_Test.php +++ b/tests/testcases/core/libraries/plugin_api/EE_Register_Payment_Method_Test.php @@ -30,7 +30,7 @@ public function set_up() ], ]; $this->_pmt_name = 'Mock_Onsite'; - $this->payment_method_manager = LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager'); + $this->payment_method_manager = EE_Payment_Method_Manager::reset(); } @@ -51,7 +51,7 @@ public function test_register__fail() $this->_stop_pretending_addon_hook_time(); remove_all_filters('FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register'); - //first verify it doesn't already exists + // first verify it doesn't already exists $pmt_exists = $this->payment_method_manager->payment_method_type_exists($this->_pmt_name); $this->assertFalse($pmt_exists); diff --git a/tests/testcases/core/services/loaders/CachingLoaderTest.php b/tests/testcases/core/services/loaders/CachingLoaderTest.php index 15c3c63a46f..a7ce54c07b5 100644 --- a/tests/testcases/core/services/loaders/CachingLoaderTest.php +++ b/tests/testcases/core/services/loaders/CachingLoaderTest.php @@ -43,7 +43,7 @@ public function set_up() //different persistence tests if (! CachingLoaderTest::$caching_loader instanceof LoaderDecorator) { CachingLoaderTest::$caching_loader = new CachingLoaderMock( - new CoreLoader(EE_Registry::instance()), + new CoreLoader(EE_Registry::reset()), new LooseCollection(''), new ObjectIdentifier(new ClassInterfaceCache()) ); diff --git a/tests/testcases/core/services/request/RequestStackBuilderTest.php b/tests/testcases/core/services/request/RequestStackBuilderTest.php index 47bc96480d9..1661daa99da 100644 --- a/tests/testcases/core/services/request/RequestStackBuilderTest.php +++ b/tests/testcases/core/services/request/RequestStackBuilderTest.php @@ -91,6 +91,11 @@ public function setMiddlewareFQCNs() */ public function addMiddleware(bool $legacy = false) { + // but first, clear out any existing middleware + while ($this->request_stack_builder->count() > 0) { + $this->request_stack_builder->pop(); + } + $this->assertCount(0, $this->request_stack_builder); $this->setMiddlewareFQCNs(); if ($legacy) { $this->request_stack_builder->push([0, $this->general_grievous]); @@ -215,14 +220,14 @@ public function TheBattleOfUtapau() $this->assertEquals(0, EE_Error::has_notices()); $request_stack->handleRequest($this->request, $this->getResponse()); $notices = $this->getNotices(); - $this->assertCount(1, $notices['success']); + $this->assertCount(1, $notices['success'], var_export($notices['success'], true)); $this->assertEquals('Hello There!', reset($notices['success'])); - $this->assertCount(1, $notices['attention']); + $this->assertCount(1, $notices['attention'], var_export($notices['attention'], true)); $this->assertEquals('General Kenobi!', reset($notices['attention'])); $this->assertCount(1, $notices['errors']); $this->assertEquals( 'Back away! I will deal with this Jedi slime myself!', - $notices['errors'][0], + reset($notices['errors']), 'notices array: ' . var_export($notices, true) ); $request_stack->handleResponse();