/**
  * Constructor.
  *
  * @param object|array $instance Required at all times.
  *    A parent object instance, which contains the parent's `$instance`,
  *    or a new `$instance` array.
  *
  * @throws \exception If there is a missing and/or invalid `$instance`.
  */
 public function __construct($instance)
 {
     if ($instance instanceof framework) {
         $plugin_root_ns = $instance->instance->plugin_root_ns;
     } else {
         if (is_array($instance) && !empty($instance['plugin_root_ns'])) {
             $plugin_root_ns = (string) $instance['plugin_root_ns'];
         }
     }
     if (empty($plugin_root_ns) || !isset($GLOBALS[$plugin_root_ns]) || !$GLOBALS[$plugin_root_ns] instanceof framework) {
         throw new \exception(sprintf(stub::__('Invalid `$instance` to constructor: `%1$s`'), print_r($instance, TRUE)));
     }
     $this->plugin = $GLOBALS[$plugin_root_ns];
 }
Example #2
0
 /**
  * Core class constructor.
  *
  * @param framework|array $instance Required at all times.
  *    A framework class object instance containing a parent's `$instance`.
  *    Or, a new `$instance` array with the elements listed below.
  *
  *    An array MUST contain the following elements:
  *       • `(string)$instance['plugin_name']` — Name of current plugin.
  *       • `(string)$instance['plugin_var_ns']` — Plugin variable namespace.
  *       • `(string)$instance['plugin_cap']` — Capability required to manage the plugin.
  *       • `(string)$instance['plugin_root_ns']` — Root namespace of current plugin.
  *       • `(string)$instance['plugin_version']` — Version of current plugin.
  *       • `(string)$instance['plugin_dir']` — Current plugin directory.
  *       • `(string)$instance['plugin_site']` — Plugin site URL (http://).
  *
  * @throws \exception If there is a missing and/or invalid `$instance`.
  * @throws \exception If there are NOT 7 configuration elements in an `$instance` array.
  *
  * @throws \exception If the plugin's root namespace does NOT match this regex validation pattern.
  *    See: {@link stub::$regex_valid_plugin_root_ns}
  *
  * @throws \exception If the plugin's variable namespace does NOT match this regex validation pattern.
  *    See: {@link stub::$regex_valid_plugin_var_ns}
  *
  * @throws \exception If the plugin's capability does NOT match this regex validation pattern.
  *    See: {@link stub::$regex_valid_plugin_cap}
  *
  * @throws \exception If the plugin's version does NOT match this regex validation pattern.
  *    See: {@link stub::$regex_valid_plugin_version}
  *
  * @throws \exception If the plugin's directory is missing (e.g. the plugin's directory MUST actually exist).
  *    In addition, the plugin's directory MUST contain a main `classes` directory with the name `classes`.
  *    In addition, the plugin's directory MUST contain a main plugin file with the name `plugin.php`.
  *
  * @throws \exception If the plugin's site URL is NOT valid (MUST start with `http://.+`).
  *
  * @throws \exception If the namespace\class path does NOT match this regex validation pattern.
  *    See: {@link stub::$regex_valid_plugin_ns_class}
  *
  * @throws \exception If the core namespace does NOT match this regex validation pattern.
  *    See: {@link stub::$regex_valid_core_ns_version}
  *
  * @public A magic/overload constructor MUST always remain public.
  *
  * @extenders If a class extender creates its own constructor,
  *    it MUST collect an `$instance`, and it MUST call upon this core constructor using:
  *    `parent::__construct($instance)`.
  *
  * @note This should NOT rely directly or indirectly on any other core class objects.
  *    Any static properties/methods in the XDaRk Core stub will be fine to use though.
  *    In addition — once the object if fully constructed; we can use anything :-)
  */
 public function __construct($instance)
 {
     $this->hooks =& static::___hooks();
     $this->static =& static::___static();
     if ($instance instanceof framework) {
         $parent_instance = $instance->instance;
     } else {
         $parent_instance = null;
     }
     // No parent config.
     $ns_class = get_class($this);
     // Always NEED `$this` for cache entry.
     if ($parent_instance) {
         $cache_entry = $parent_instance->plugin_root_ns . $ns_class;
         if (isset(static::$___instance_cache[$cache_entry])) {
             $this->instance = static::$___instance_cache[$cache_entry];
             return;
             // Using cache. Nothing more to do here.
         }
         $this->instance = clone $parent_instance;
     } else {
         if (is_array($instance) && count($instance) === 7 && !empty($instance['plugin_name']) && is_string($instance['plugin_name']) && !empty($instance['plugin_root_ns']) && is_string($instance['plugin_root_ns']) && preg_match(stub::$regex_valid_plugin_root_ns, $instance['plugin_root_ns']) && !empty($instance['plugin_var_ns']) && is_string($instance['plugin_var_ns']) && preg_match(stub::$regex_valid_plugin_var_ns, $instance['plugin_var_ns']) && !empty($instance['plugin_version']) && is_string($instance['plugin_version']) && preg_match(stub::$regex_valid_plugin_version, $instance['plugin_version']) && !empty($instance['plugin_cap']) && is_string($instance['plugin_cap']) && preg_match(stub::$regex_valid_plugin_cap, $instance['plugin_cap']) && !empty($instance['plugin_dir']) && is_string($instance['plugin_dir']) && is_dir($instance['plugin_dir'] = stub::n_dir_seps($instance['plugin_dir'])) && is_file($instance['plugin_dir'] . '/plugin.php') && is_dir($instance['plugin_dir'] . '/classes') && !empty($instance['plugin_site']) && is_string($instance['plugin_site']) && ($instance['plugin_site'] = rtrim($instance['plugin_site'], '/')) && preg_match('/^http\\:\\/\\/.+/i', $instance['plugin_site'])) {
             $cache_entry = $instance['plugin_root_ns'] . $ns_class;
             if (isset(static::$___instance_cache[$cache_entry])) {
                 $this->instance = static::$___instance_cache[$cache_entry];
                 return;
                 // Using cache (nothing more to do here).
             }
             $this->instance = new instance($instance);
         } else {
             throw new \exception(sprintf(stub::__('Invalid `$instance` to constructor: `%1$s`'), print_r($instance, true)));
         }
     }
     // Mostly from core stub. These properties will NOT change from one class instance to another.
     if (!$parent_instance) {
         // Core name & core site; begins with `http://`.
         $this->instance->core_name = stub::$core_name;
         $this->instance->core_site = stub::$core_site;
         // Core directories; mostly from stub.
         $this->instance->local_wp_dev_dir = stub::$local_wp_dev_dir;
         $this->instance->local_core_repo_dir = stub::$local_core_repo_dir;
         $this->instance->core_dir = stub::n_dir_seps_up(__FILE__, 3);
         $this->instance->core_classes_dir = $this->instance->core_dir . '/classes';
         // Based on `stub::$core_prefix`.
         $this->instance->core_prefix = stub::$core_prefix;
         $this->instance->core_prefix_with_dashes = stub::$core_prefix_with_dashes;
         // Based on `stub::$core_ns`.
         $this->instance->core_ns = stub::$core_ns;
         $this->instance->core_ns_prefix = stub::$core_ns_prefix;
         $this->instance->core_ns_with_dashes = stub::$core_ns_with_dashes;
         // Based on `stub::$core_ns_stub`.
         $this->instance->{stub::$core_ns_stub} = stub::$core_ns_stub;
         $this->instance->core_ns_stub = stub::$core_ns_stub;
         $this->instance->core_ns_stub_with_dashes = stub::$core_ns_stub_with_dashes;
         // Based on `stub::$core_ns_stub_v`.
         $this->instance->core_ns_stub_v = stub::$core_ns_stub_v;
         $this->instance->core_ns_stub_v_with_dashes = stub::$core_ns_stub_v_with_dashes;
         // Based on `stub::$core_version`.
         $this->instance->core_version = stub::$core_version;
         $this->instance->core_version_with_underscores = stub::$core_version_with_underscores;
         $this->instance->core_version_with_dashes = stub::$core_version_with_dashes;
         // Check core `namespace` for validation issues.
         if (!preg_match(stub::$regex_valid_core_ns_version, $this->instance->core_ns)) {
             throw new \exception(sprintf(stub::__('Invalid core namespace: `%1$s`.'), $this->instance->core_ns));
         }
     }
     // Check `namespace\sub_namespace\class` for validation issues.
     if (!preg_match(stub::$regex_valid_plugin_ns_class, $this->instance->ns_class = $ns_class)) {
         throw new \exception(sprintf(stub::__('Namespace\\class contains invalid chars: `%1$s`.'), $this->instance->ns_class));
     }
     // The `namespace\sub_namespace` for `$this` class.
     $this->instance->ns = substr($this->instance->ns_class, 0, strrpos($this->instance->ns_class, '\\'));
     // The `sub_namespace\class` for `$this` class.
     $this->instance->sub_ns_class = ltrim(strstr($this->instance->ns_class, '\\'), '\\');
     $this->instance->sub_ns_class_with_underscores = stub::with_underscores($this->instance->sub_ns_class);
     $this->instance->sub_ns_class_with_dashes = stub::with_dashes($this->instance->sub_ns_class);
     // The `namespace\sub_namespace\class` for `$this` class.
     $this->instance->ns_class_prefix = '\\' . $this->instance->ns_class;
     $this->instance->ns_class_with_underscores = stub::with_underscores($this->instance->ns_class);
     $this->instance->ns_class_with_dashes = stub::with_dashes($this->instance->ns_class);
     $this->instance->ns_class_basename = basename(str_replace('\\', '/', $this->instance->ns_class));
     // Only if we're NOT in the same namespace as the `$parent_instance`.
     if (!$parent_instance || $parent_instance->ns !== $this->instance->ns) {
         // The `namespace\sub_namespace` for `$this` class.
         $this->instance->ns_prefix = '\\' . $this->instance->ns;
         $this->instance->ns_with_underscores = stub::with_underscores($this->instance->ns);
         $this->instance->ns_with_dashes = stub::with_dashes($this->instance->ns);
         // The `namespace` for `$this` class.
         $this->instance->root_ns = strstr($this->instance->ns_class, '\\', true);
         $this->instance->root_ns_prefix = '\\' . $this->instance->root_ns;
         $this->instance->root_ns_with_dashes = stub::with_dashes($this->instance->root_ns);
     }
     // Based entirely on current plugin. These properties will NOT change from one class instance to another.
     if (!$parent_instance) {
         // Plugin name & plugin site; begins with `http://`.
         $this->instance->plugin_name = $this->instance->plugin_name;
         $this->instance->plugin_site = $this->instance->plugin_site;
         // Based on `plugin_version`.
         $this->instance->plugin_version = $this->instance->plugin_version;
         $this->instance->plugin_version_with_underscores = stub::with_underscores($this->instance->plugin_version);
         $this->instance->plugin_version_with_dashes = stub::with_dashes($this->instance->plugin_version);
         // Based on `plugin_var_ns` (which serves a few different purposes).
         $this->instance->plugin_var_ns = $this->instance->plugin_var_ns;
         $this->instance->plugin_var_ns_with_dashes = stub::with_dashes($this->instance->plugin_var_ns);
         // Based on `plugin_var_ns` (which serves a few different purposes).
         $this->instance->plugin_prefix = $this->instance->plugin_var_ns . '_';
         $this->instance->plugin_prefix_with_dashes = stub::with_dashes($this->instance->plugin_prefix);
         if ($this->instance->plugin_root_ns === $this->instance->core_ns) {
             $this->instance->plugin_prefix = $this->instance->core_prefix;
             $this->instance->plugin_prefix_with_dashes = $this->instance->core_prefix_with_dashes;
         }
         // Based on `plugin_cap` (used for a default set of access controls).
         $this->instance->plugin_cap = $this->instance->plugin_cap;
         $this->instance->plugin_cap_with_dashes = stub::with_dashes($this->instance->plugin_cap);
         // Based on plugin's root `namespace` (via `plugin_root_ns`).
         $this->instance->plugin_root_ns = $this->instance->plugin_root_ns;
         $this->instance->plugin_root_ns_prefix = '\\' . $this->instance->plugin_root_ns;
         $this->instance->plugin_root_ns_with_dashes = stub::with_dashes($this->instance->plugin_root_ns);
         // Based on plugin's root `namespace` (via `plugin_root_ns`).
         $this->instance->plugin_root_ns_stub = $this->instance->plugin_root_ns;
         $this->instance->plugin_root_ns_stub_with_dashes = $this->instance->plugin_root_ns_with_dashes;
         if ($this->instance->plugin_root_ns === $this->instance->core_ns) {
             $this->instance->plugin_root_ns_stub = $this->instance->core_ns_stub;
             $this->instance->plugin_root_ns_stub_with_dashes = $this->instance->core_ns_stub_with_dashes;
         }
         // Based on the plugin's directory (i.e. `plugin_dir`).
         $this->instance->plugin_dir = $this->instance->plugin_dir;
         $this->instance->plugin_dir_basename = basename($this->instance->plugin_dir);
         $this->instance->plugin_dir_file_basename = $this->instance->plugin_dir_basename . '/plugin.php';
         // Based on the plugin's directory (i.e. `plugin_dir`).
         if ($this->instance->plugin_root_ns === $this->instance->core_ns) {
             $this->instance->plugin_data_dir = stub::get_temp_dir() . '/' . $this->instance->core_ns_stub_with_dashes . '-data';
         } else {
             $this->instance->plugin_data_dir = stub::n_dir_seps(WP_CONTENT_DIR) . '/data/' . $this->instance->plugin_dir_basename;
         }
         // Based on the plugin's directory (i.e. `plugin_dir`).
         $this->instance->plugin_data_dir = apply_filters($this->instance->plugin_root_ns_stub . '__data_dir', $this->instance->plugin_data_dir);
         // Based on the plugin's directory (i.e. `plugin_dir`).
         $this->instance->plugin_file = $this->instance->plugin_dir . '/plugin.php';
         $this->instance->plugin_classes_dir = $this->instance->plugin_dir . '/classes';
         $this->instance->plugin_api_class_file = $this->instance->plugin_classes_dir . '/' . $this->instance->plugin_root_ns_with_dashes . '.php';
         // Based on the current plugin; we establish properties for a pro add-on (optional).
         $this->instance->plugin_pro_var = $this->instance->plugin_root_ns . '_pro';
         $this->instance->plugin_pro_dir = $this->instance->plugin_dir . '-pro';
         if (stripos($this->instance->plugin_pro_dir, 'phar://') === 0) {
             // In case of core.
             $this->instance->plugin_pro_dir = substr($this->instance->plugin_pro_dir, 7);
         }
         $this->instance->plugin_pro_dir_basename = basename($this->instance->plugin_pro_dir);
         $this->instance->plugin_pro_dir_file_basename = $this->instance->plugin_pro_dir_basename . '/plugin.php';
         $this->instance->plugin_pro_file = $this->instance->plugin_pro_dir . '/plugin.php';
         $this->instance->plugin_pro_classes_dir = $this->instance->plugin_pro_dir . '/classes';
         $this->instance->plugin_pro_class_file = $this->instance->plugin_pro_classes_dir . '/' . $this->instance->plugin_root_ns_with_dashes . '/pro.php';
     }
     // Based on `plugin_root_ns_stub`.
     // Also on `namespace\sub_namespace\class` for `$this` class.
     // Here we swap out the real root namespace, in favor of the plugin's root namespace.
     // This is helpful when we need to build strings for hooks, filters, contextual slugs, and the like.
     $this->instance->plugin_stub_as_root_ns_class = $this->instance->plugin_root_ns_stub . substr(preg_replace('/_x$/', '', $this->instance->ns_class), $root_ns_length = strlen($this->instance->root_ns));
     $this->instance->plugin_stub_as_root_ns_class_with_underscores = stub::with_underscores($this->instance->plugin_stub_as_root_ns_class);
     $this->instance->plugin_stub_as_root_ns_class_with_dashes = stub::with_dashes($this->instance->plugin_stub_as_root_ns_class);
     // Based on `plugin_root_ns_stub`.
     // Also on `namespace\sub_namespace` for `$this` class.
     // Here we swap out the real root namespace, in favor of the plugin's root namespace.
     // This is helpful when we need to build strings for hooks, filters, contextual slugs, and the like.
     $this->instance->plugin_stub_as_root_ns = $this->instance->plugin_root_ns_stub . substr($this->instance->ns, $root_ns_length);
     $this->instance->plugin_stub_as_root_ns_with_underscores = stub::with_underscores($this->instance->plugin_stub_as_root_ns);
     $this->instance->plugin_stub_as_root_ns_with_dashes = stub::with_dashes($this->instance->plugin_stub_as_root_ns);
     // Now let's cache `$this->instance` for easy re-use.
     static::$___instance_cache[$cache_entry] = $this->instance;
     // Check global reference & load plugin (if applicable).
     if (!isset($GLOBALS[$this->instance->plugin_root_ns]) || !$GLOBALS[$this->instance->plugin_root_ns] instanceof framework) {
         $GLOBALS[$this->instance->plugin_root_ns] = $this;
         if ($this->instance->plugin_root_ns !== stub::$core_ns) {
             $this->©plugin->load();
         }
         // Not the core (only load plugins).
     }
 }
 /**
  * Adds a new core class alias.
  *
  * @param string $ns_or_ns_class A class path (including namespace); or ONLY the namespace.
  *    If this is ONLY the namespace; `$class_file` MUST be passed in also.
  *
  * @param string $class_file Optional. If passed, `$ns_or_ns_class` is assumed to be the namespace only.
  *
  * @throws \exception If invalid types are passed through arguments list.
  * @throws \exception If the parsed `$ns_class` is empty, or is NOT a valid core class name.
  * @throws \exception If the parsed `$ns_class` is NOT from this version of the core.
  * @throws \exception If the parsed `$ns_class` is NOT already defined.
  */
 public static function add_core_ns_class_alias($ns_or_ns_class, $class_file = '')
 {
     if (!is_string($ns_or_ns_class) || !($ns_or_ns_class = trim($ns_or_ns_class, '\\')) || !is_string($class_file)) {
         throw new \exception(sprintf(stub::__('Invalid arguments: `%1$s`'), print_r(func_get_args(), TRUE)));
     }
     if ($class_file) {
         // Interpret `$ns_or_ns_class` as a namespace only.
         $ns_class = $ns_or_ns_class . '\\' . stub::with_underscores(basename($class_file, '.php'));
     } else {
         $ns_class = $ns_or_ns_class;
     }
     // Presume full class path.
     if (!preg_match(stub::$regex_valid_plugin_ns_class, $ns_class)) {
         throw new \exception(sprintf(stub::__('Namespace\\class contains invalid chars: `%1$s`.'), $ns_class));
     }
     if (strpos($ns_class, stub::$core_ns . '\\') !== 0) {
         throw new \exception(sprintf(stub::__('Namespace\\class is NOT from this core: `%1$s`.'), $ns_class));
     }
     if (!class_exists('\\' . $ns_class, FALSE) && !interface_exists('\\' . $ns_class, FALSE) && (!function_exists('trait_exists') || !trait_exists('\\' . $ns_class, FALSE))) {
         throw new \exception(sprintf(stub::__('Namespace\\class does NOT exist yet: `%1$s`.'), $ns_class));
     }
     $alias = str_replace(array(stub::$core_ns . '\\', '\\'), array(stub::$core_ns_stub . '\\', '__'), $ns_class);
     if (!class_exists('\\' . $alias, FALSE) && !interface_exists('\\' . $alias, FALSE) && (!function_exists('trait_exists') || !trait_exists('\\' . $alias, FALSE))) {
         class_alias('\\' . $ns_class, $alias);
     }
 }
 /**
  * Handles all PHP exceptions.
  *
  * @param exception|\exception $exception An exception.
  *
  * @note Exceptions handled successfully by this routine will NOT be logged by PHP as errors.
  *    As the exception handler, we will need to log and/or display anything that needs to be recorded here.
  *    The PHP interpreter simply terminates script execution whenever an exception occurs (nothing more).
  *
  * @note If an exception is thrown while handling an exception; PHP will revert to it's default exception handler.
  *    This will result in a fatal error that may get logged by PHP itself (depending on `error_reporting` and `error_log`).
  *
  * @throws exception|\exception If we are unable to handle the exception (i.e. the XDaRk Core is not even available yet),
  *    this handler will simply re-throw the exception (forcing a fatal error); as just described in the previous note.
  *
  * @note The display of exception messages is NOT dependent upon `display_errors`; nor do we consider that setting here.
  *    However, we do tighten security within the `exception.php` template file; hiding most details by default; and displaying all details
  *    only if the current user is a Super Administrator in WordPress; or if `WP_DEBUG_DISPLAY` mode has been enabled on this site.
  *
  * @note If there was another exception handler active on the site; and this exception is NOT for
  *    a plugin under this version of the XDaRk Core; we simply hand the exception back to the previous handler.
  *    In the case of multiple versions of the XDaRk Core across various plugins; this allows us to work up the chain
  *    of previous handlers until we find the right version of the XDaRk Core; assuming each version
  *    of the XDaRk Core handles things this way too (which is to be expected).
  *
  * @see http://php.net/manual/en/function.set-exception-handler.php
  */
 public static function handle(\exception $exception)
 {
     try {
         static::$exception = $exception;
         // Reference.
         if (static::$exception instanceof exception) {
             static::$plugin = static::$exception->plugin;
             static::handle_plugin_exception();
             return;
             // We're done here.
         }
         // Else this is some other type of exception.
         if (static::$previous_handler && is_callable(static::$previous_handler)) {
             call_user_func(static::$previous_handler, static::$exception);
             return;
             // We're done here.
         }
         // There is NO other handler available (deal w/ it here; if possible).
         if (is_callable('\\' . stub::$core_ns . '\\core')) {
             static::$plugin = core();
             static::handle_plugin_exception();
             return;
             // We're done here.
         }
         throw static::$exception;
         // Re-throw (forcing a fatal error).
     } catch (\exception $_exception) {
         throw new \exception(sprintf(stub::__('Failed to handle exception code: `%1$s` with message: `%2$s`.'), $exception->getCode(), $exception->getMessage()) . ' ' . sprintf(stub::__('Failure caused by exception code: `%1$s` with message: `%2$s`.'), $_exception->getCode(), $_exception->getMessage()), 20, $_exception);
     }
 }
Example #5
0
 /**
  * Constructor.
  *
  * @param object|array    $instance Required at all times.
  *    A parent object instance, which contains the parent's `$instance`,
  *    or a new `$instance` array.
  *
  * @param string          $code Optional error code (string, NO integers please).
  *
  * @param null|mixed      $data Optional exception data (i.e. something to assist in reporting/logging).
  *    This argument can be bypassed using a NULL value (that's fine).
  *
  * @param string          $message Optional exception message (i.e. an error message).
  *
  * @param null|\exception $previous Optional previous exception (if re-thrown).
  *
  * @throws \exception If there is a missing and/or invalid `$instance`.
  * @throws \exception A standard exception class; if any additional issues occur during this type of exception.
  *    This prevents endless exceptions, which may occur when/if we make use of a plugin instance.
  */
 public function __construct($instance = NULL, $code = 'exception', $data = NULL, $message = '', \exception $previous = NULL)
 {
     try {
         if ($instance instanceof framework) {
             $plugin_root_ns = $instance->instance->plugin_root_ns;
         } else {
             if (is_array($instance) && !empty($instance['plugin_root_ns'])) {
                 $plugin_root_ns = (string) $instance['plugin_root_ns'];
             }
         }
         if (empty($plugin_root_ns) || !isset($GLOBALS[$plugin_root_ns]) || !$GLOBALS[$plugin_root_ns] instanceof framework) {
             throw new \exception(sprintf(stub::__('Invalid `$instance` to constructor: `%1$s`'), print_r($instance, TRUE)));
         }
         $this->plugin = $GLOBALS[$plugin_root_ns];
         $code = (string) $code ? (string) $code : 'exception';
         $message = (string) $message ? (string) $message : sprintf($this->plugin->__('Exception code: `%1$s`.'), $code);
         parent::__construct($message, 0, $previous);
         // Call parent constructor.
         $this->code = $code;
         // Set code for this instance. We always use string exception codes (no exceptions :-).
         $this->data = $data;
         // Optional diagnostic data associated with this exception (possibly a NULL value).
         $this->wp_debug_log();
         // Possible debug logging.
         $this->db_log();
         // Possible database logging routine.
     } catch (\exception $_exception) {
         throw new \exception(sprintf(stub::__('Could NOT instantiate exception code: `%1$s` with message: `%2$s`.'), $code, $message) . ' ' . sprintf(stub::__('Failure caused by exception code: `%1$s` with message: `%2$s`.'), $_exception->getCode(), $_exception->getMessage()), 20, $_exception);
     }
 }