<?php
/**
* Clarkson Core Objects.
*/
namespace Clarkson_Core;
use Clarkson_Core\WordPress_Object\Clarkson_Object;
use Clarkson_Core\WordPress_Object\Clarkson_Post_Type;
use Clarkson_Core\WordPress_Object\Clarkson_Role;
use Clarkson_Core\WordPress_Object\Clarkson_Taxonomy;
use Clarkson_Core\WordPress_Object\Clarkson_Template;
use Clarkson_Core\WordPress_Object\Clarkson_Term;
use Clarkson_Core\WordPress_Object\Clarkson_User;
use DomainException;
/**
* This class is used to convert WordPress posts, terms and users into Clarkson
* Objects.
*/
class Objects {
const OBJECT_CLASS_NAMESPACE = '\\Clarkson_Core\\WordPress_Object\\';
/**
* Convert WP_Term object to a Clarkson Object.
*
* @param \WP_Term[] $terms array of \WP_Term objects.
*
* @return Clarkson_Term[]
*/
public function get_terms( array $terms ): array {
$term_objects = array();
foreach ( $terms as $term ) {
$term_objects[] = $this->get_term( $term );
}
return $term_objects;
}
/**
* Get term data.
*
* @param \WP_Term $term The term.
*
* @return Clarkson_Term
*/
public function get_term( \WP_Term $term ): Clarkson_Term {
$cc = Clarkson_Core::get_instance();
$types = array(
self::OBJECT_CLASS_NAMESPACE . $cc->autoloader->sanitize_object_name( $term->taxonomy ),
self::OBJECT_CLASS_NAMESPACE . 'base_term',
);
/**
* Allows the theme to overwrite classes to look for when creating an object.
*
* @hook clarkson_term_types
* @since 1.0.0
* @param {array} $typse Sanitized class names to load.
* @param {WP_Term} $term Term which we are trying to convert into an object.
* @return {array} Class names to search for.
*
* @example
* // load a different class instead of what Clarkson Core calculates.
* add_filter( 'clarkson_term_types', function( $types, $term ) {
* if ( $term->taxonomy === 'gm_category' ){
* array_unshift($types, self::OBJECT_CLASS_NAMESPACE . 'custom_taxonomy_class';
* }
* return $types;
* }, 10, 2 );
*/
$types = apply_filters( 'clarkson_term_types', $types, $term );
foreach ( $types as $type ) {
if ( class_exists( $type ) ) {
$term_object = new $type( $term );
if ( $term_object instanceof Clarkson_Term ) {
return $term_object;
}
}
}
return new Clarkson_Term( $term );
}
/**
* Convert WP_User object to a Clarkson Object.
*
* @param \WP_User[] $users array of \WP_User objects.
*
* @return Clarkson_User[]
*/
public function get_users( array $users ): array {
$user_objects = array();
foreach ( $users as $user ) {
$user_objects[] = $this->get_user( $user );
}
return $user_objects;
}
/**
* Get user by user id.
*
* @param \WP_User $user WP_User object.
*
* @return Clarkson_User
*/
public function get_user( \WP_User $user ): Clarkson_User {
/**
* @psalm-var string
*/
$type = self::OBJECT_CLASS_NAMESPACE . 'user';
/**
* Allows the theme to overwrite class that is going to be used to create a user.
*
* @hook clarkson_user_type
* @since 1.0.0
* @param {null|string} $type Sanitized class name.
* @param {WP_User} $user Sanitized class name.
* @return {null|string} Class name of user to be created.
*
* @example
* // load a different class instead of what Clarkson Core calculates.
* add_filter( 'clarkson_user_type', function( $type, $user ) {
* if ( user_can( $user, 'read' ) ){
* $type = self::OBJECT_CLASS_NAMESPACE . 'custom_user_class';
* }
* return $type;
* }, 10, 2 );
*/
$type = apply_filters( 'clarkson_user_type', $type, $user );
if ( class_exists( $type ) ) {
$user_object = new $type( $user );
if ( $user_object instanceof Clarkson_User ) {
return $user_object;
}
}
return new Clarkson_User( $user );
}
/**
* Get an array of posts converted to their corresponding WordPress object class.
*
* @param \WP_Post[] $posts Posts.
*
* @return Clarkson_Object[] $objects Array of post objects.
*/
public function get_objects( array $posts ): array {
$objects = array();
foreach ( $posts as $post ) {
$objects[] = $this->get_object( $post );
}
return $objects;
}
/**
* Get post that's converted to their corresponding WordPress object class.
*
* @param \WP_Post $post Post.
*
* @return Clarkson_Object Clarkson Post object.
*/
public function get_object( \WP_Post $post ): Clarkson_Object {
$cc = Clarkson_Core::get_instance();
$types = array(
self::OBJECT_CLASS_NAMESPACE . 'base_object',
Clarkson_Object::class,
);
$type = get_post_type( $post );
if ( ! empty( $type ) ) {
$type = $cc->autoloader->sanitize_object_name( $type );
array_unshift( $types, self::OBJECT_CLASS_NAMESPACE . $type );
}
$class_to_load = null;
foreach ( $types as $type ) {
if ( class_exists( $type ) ) {
$class_to_load = $type;
break;
}
}
/**
* Allows the theme to overwrite class that is going to be used to create an object.
*
* @hook clarkson_object_type
* @since 0.1.1
* @param {null|string} $type Sanitized class name.
* @param {WP_Post} $post Sanitized class name.
* @return {null|string} Class name of object to be created.
*
* @example
* // load a different class instead of what Clarkson Core calculates.
* add_filter( 'clarkson_object_type', function( $type, $post ) {
* if ( get_post_type( $post ) === 'gm_event' ){
* $type = self::OBJECT_CLASS_NAMESPACE . 'custom_event_class';
* }
* return $type;
* }, 10, 2 );
*/
$class_to_load = apply_filters( 'clarkson_object_type', $class_to_load, $post );
if ( null === $class_to_load ) {
throw new DomainException( sprintf( 'No valid Clarkson Object was loaded. Tried: %s.', implode( ', ', $types ) ) );
}
/**
* Allows to control object creation before Clarkson Core determines the correct class to use. For example by calling "wc_get_product".
*
* @hook clarkson_core_create_object_callback
* @since 0.3.1
* @param {callable|bool} false Callable that determines how the class should be instantiated.
* False means no custom object creation will be used.
* @param $type {string} Sanitized class name of what Clarkson Core would load as an object.
* @param $post_id {int|string} Post ID that an object is being created for.
* @return {string} Class name of object to be created.
* @see https://github.com/level-level/Clarkson-Core/issues/131
*
* @example
* // Use a different object factory then the default one provided by Clarkson Core.
* add_filter( 'clarkson_core_create_object_callback', function( $callback, $type, $post_id ) {
* if ( $type === '\Clarkson_Core\Object\shop_order' ){
* $callback = 'wc_get_order'; // wc_get_order is a callable function when Woocommerce is enabled.
* }
* return $type;
* } );
*/
$object_creation_callback = apply_filters( 'clarkson_core_create_object_callback', false, $class_to_load, $post->ID );
if ( is_callable( $object_creation_callback ) ) {
$clarkson_object = call_user_func_array( $object_creation_callback, array( $post->ID ) );
if ( $clarkson_object instanceof Clarkson_Object ) {
return $clarkson_object;
}
}
$clarkson_object = new $class_to_load( $post );
if ( $clarkson_object instanceof Clarkson_Object ) {
return $clarkson_object;
}
throw new DomainException( sprintf( 'No valid Clarkson Object was loaded. Tried to find %s. Make sure it extends Clarkson_Object.', $class_to_load ) );
}
/**
* Get an array of roles converted from their corresponding WordPress role class.
*
* @param \WP_Role[] $roles Array of WordPress role objects.
*
* @return Clarkson_Role[] $objects Array of post objects.
*/
public function get_roles( array $roles ): array {
$clarkson_roles = array();
foreach ( $roles as $role ) {
$clarkson_roles[] = $this->get_role( $role );
}
return $clarkson_roles;
}
/**
* Get Clarkson role object by WordPress role object.
*/
public function get_role( \WP_Role $role ): Clarkson_Role {
$cc = Clarkson_Core::get_instance();
$class_name = 'role_' . $role->name;
$class_name = self::OBJECT_CLASS_NAMESPACE . $cc->autoloader->sanitize_object_name( $class_name );
/**
* Allows the theme to overwrite class that is going to be used to create a role object.
*
* @hook clarkson_role_class
* @since 1.0.0
* @param {null|string} $type Sanitized class name.
* @param {WP_Role} $role Sanitized class name.
* @return {null|string} Class name of role to be created.
*
* @example
* // load a different class instead of what Clarkson Core calculates.
* add_filter( 'clarkson_role_class', function( $type, $role ) {
* if ( $role->name === 'example' ){
* $type = self::OBJECT_CLASS_NAMESPACE . 'custom_role_class';
* }
* return $type;
* }, 10, 2 );
*/
$class_name = apply_filters( 'clarkson_role_class', $class_name, $role );
if ( class_exists( $class_name ) ) {
$object = new $class_name( $role );
if ( $object instanceof Clarkson_Role ) {
return $object;
}
}
/**
* @psalm-var string
*/
$class_name = self::OBJECT_CLASS_NAMESPACE . 'base_role';
if ( class_exists( $class_name ) ) {
$object = new $class_name( $role );
if ( $object instanceof Clarkson_Role ) {
return $object;
}
}
return new Clarkson_Role( $role );
}
public function get_template( \WP_Post $post ): Clarkson_Template {
$template = get_page_template_slug( $post );
$template = pathinfo( (string) $template, PATHINFO_FILENAME );
$template = Clarkson_Core::get_instance()->autoloader->sanitize_object_name( $template );
if ( empty( $template ) ) {
$template = 'template_default';
}
$class_name = self::OBJECT_CLASS_NAMESPACE . $template;
/**
* Allows the theme to overwrite class that is going to be used to create a template object.
*
* @hook clarkson_template_class
* @since 1.0.0
* @param {null|string} $type Sanitized class name.
* @param {WP_Post} $post The WordPress post to load a template for.
* @return {null|string} Class name of template to be created.
*
* @example
* // load a different class instead of what Clarkson Core calculates.
* add_filter( 'clarkson_template_class', function( $class, $post ) {
* if ( $post->ID === 15 ){
* $class = self::OBJECT_CLASS_NAMESPACE . 'custom_template_class';
* }
* return $class;
* }, 10, 2 );
*/
$class_name = apply_filters( 'clarkson_template_class', $class_name, $post );
if ( class_exists( $class_name ) ) {
$object = new $class_name( $post );
if ( $object instanceof Clarkson_Template ) {
return $object;
}
}
/**
* @psalm-var string
*/
$class_name = self::OBJECT_CLASS_NAMESPACE . 'base_template';
if ( class_exists( $class_name ) ) {
$object = new $class_name( $post );
if ( $object instanceof Clarkson_Template ) {
return $object;
}
}
return new Clarkson_Template( $post );
}
/**
* Get an array of posts converted to their corresponding WordPress template class.
*
* @param \WP_Post[] $posts Posts.
*
* @return Clarkson_Template[] $objects Array of post templates.
*/
public function get_templates( array $posts ): array {
$objects = array();
foreach ( $posts as $post ) {
$objects[] = $this->get_template( $post );
}
return $objects;
}
/**
* Get an array of post types converted from their corresponding WordPress post type class.
*
* @param \WP_Post_Type[] $post_types WordPress post type objects
*
* @return Clarkson_Post_Type[] $objects Array of Clarkson post type objects.
*/
public function get_post_types( array $post_types ): array {
$objects = array();
foreach ( $post_types as $post_type ) {
$objects[] = $this->get_post_type( $post_type );
}
return $objects;
}
/**
* Get post type object by post type.
*/
public function get_post_type( \WP_Post_Type $post_type ):Clarkson_Post_Type {
$cc = Clarkson_Core::get_instance();
$class_name = 'post_type_' . $post_type->name;
$class_name = self::OBJECT_CLASS_NAMESPACE . $cc->autoloader->sanitize_object_name( $class_name );
/**
* Allows the theme to overwrite class that is going to be used to create a post_type object.
*
* @hook clarkson_post_type_class
* @since 1.0.0
* @param {null|string} $type Sanitized class name.
* @param {WP_Post_Type} $post_type The original post type object.
* @return {null|string} Class name of post_type to be created.
*
* @example
* // load a different class instead of what Clarkson Core calculates.
* add_filter( 'clarkson_post_type_class', function( $type, $post_type ) {
* if ( $post_type->name === 'example' ){
* $type = self::OBJECT_CLASS_NAMESPACE . 'custom_post_type_class';
* }
* return $type;
* }, 10, 2 );
*/
$class_name = apply_filters( 'clarkson_post_type_class', $class_name, $post_type );
if ( class_exists( $class_name ) ) {
$object = new $class_name( $post_type );
if ( $object instanceof Clarkson_Post_Type ) {
return $object;
}
}
/**
* @psalm-var string
*/
$class_name = self::OBJECT_CLASS_NAMESPACE . 'base_post_type';
if ( class_exists( $class_name ) ) {
$object = new $class_name( $post_type );
if ( $object instanceof Clarkson_Post_Type ) {
return $object;
}
}
return new Clarkson_Post_Type( $post_type );
}
/**
* Get an array of taxonomies converted from their corresponding WordPress taxonomy class.
*
* @param \WP_Taxonomy[] $taxonomies WordPress taxonomy objects
*
* @return Clarkson_Taxonomy[] $objects Array of Clarkson taxonomy objects.
*/
public function get_taxonomies( array $taxonomies ): array {
$objects = array();
foreach ( $taxonomies as $taxonomy ) {
$objects[] = $this->get_taxonomy( $taxonomy );
}
return $objects;
}
/**
* Get taxonomy object by taxonomy.
*/
public function get_taxonomy( \WP_Taxonomy $taxonomy ):Clarkson_Taxonomy {
$cc = Clarkson_Core::get_instance();
$class_name = 'taxonomy_' . $taxonomy->name;
$class_name = self::OBJECT_CLASS_NAMESPACE . $cc->autoloader->sanitize_object_name( $class_name );
/**
* Allows the theme to overwrite class that is going to be used to create a taxonomy object.
*
* @hook clarkson_taxonomy_class
* @since 1.0.0
* @param {null|string} $type Sanitized class name.
* @param {WP_Taxonomy} $taxonomy The original taxonomy object.
* @return {null|string} Class name of taxonomy to be created.
*
* @example
* // load a different class instead of what Clarkson Core calculates.
* add_filter( 'clarkson_taxonomy_class', function( $type, $taxonomy ) {
* if ( $taxonomy->name === 'example' ){
* $type = self::OBJECT_CLASS_NAMESPACE . 'custom_taxonomy_class';
* }
* return $type;
* }, 10, 2 );
*/
$class_name = apply_filters( 'clarkson_taxonomy_class', $class_name, $taxonomy );
if ( class_exists( $class_name ) ) {
$object = new $class_name( $taxonomy );
if ( $object instanceof Clarkson_Taxonomy ) {
return $object;
}
}
/**
* @psalm-var string
*/
$class_name = self::OBJECT_CLASS_NAMESPACE . 'base_taxonomy';
if ( class_exists( $class_name ) ) {
$object = new $class_name( $taxonomy );
if ( $object instanceof Clarkson_Taxonomy ) {
return $object;
}
}
return new Clarkson_Taxonomy( $taxonomy );
}
/**
* Singleton.
*
* @var null|\Clarkson_Core\Objects $instance The Clarkson core objects.
*/
protected static $instance;
/**
* Get the instance.
*
* @return \Clarkson_Core\Objects
*/
public static function get_instance(): \Clarkson_Core\Objects {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Clone.
* @codeCoverageIgnore
*/
private function __clone() {
}
/**
* Wakeup.
* @codeCoverageIgnore
*/
public function __wakeup() {
}
}