class-model.php
<?php
namespace HivePress\Models;
use HivePress\Helpers as hp;
use HivePress\Traits;
defined( 'ABSPATH' ) || exit;
abstract class Model {
use Traits\Mutator {
set_property as _set_property;
}
use Traits\Meta {
get_meta as _get_meta;
set_meta as _set_meta;
}
protected $id;
protected $fields = [];
protected $values = [];
protected $errors = [];
public static function init( $meta = [] ) {
$meta = hp\merge_arrays(
[
'name' => hp\get_class_name( static::class ),
],
$meta
);
foreach ( hp\get_class_parents( static::class ) as $class ) {
$meta = apply_filters( 'hivepress/v1/models/' . hp\get_class_name( $class ) . '/meta', $meta );
}
static::_set_meta( $meta );
}
public function __construct( $args = [] ) {
foreach ( hp\get_class_parents( static::class ) as $class ) {
$args = apply_filters( 'hivepress/v1/models/' . hp\get_class_name( $class ), $args, $this );
}
foreach ( $args as $name => $value ) {
$this->_set_property( $name, $value, '_' );
}
$this->boot();
}
protected function boot() {}
final protected function _set_fields( $fields ) {
$this->fields = [];
foreach ( $fields as $name => $args ) {
if ( ! isset( $args['_alias'] ) ) {
if ( hp\get_array_value( $args, '_relation' ) === 'many_to_many' ) {
$args['_alias'] = hp\call_class_method( '\HivePress\Models\\' . hp\get_array_value( $args, '_model' ), '_get_meta', [ 'alias' ] );
} elseif ( hp\get_array_value( $args, '_external' ) ) {
$args['_alias'] = hp\prefix( $name );
}
}
$args['context']['model'] = static::_get_meta( 'name' );
$field = hp\create_class_instance( '\HivePress\Fields\\' . $args['type'], [ array_merge( $args, [ 'name' => $name ] ) ] );
if ( $field ) {
$this->fields[ $name ] = $field;
}
}
}
public function _get_fields() {
return $this->fields;
}
final public static function __callStatic( $name, $args ) {
if ( 'query' === $name ) {
return static::_get_query();
}
throw new \BadMethodCallException();
}
final public function __call( $name, $args ) {
if ( 'query' === $name ) {
return static::_get_query( $this );
}
$prefixes = [
'set',
'get',
'is',
'has',
'display',
'save',
];
foreach ( $prefixes as $prefix ) {
if ( strpos( $name, $prefix . '_' ) === 0 ) {
$action = ! in_array( $prefix, [ 'set', 'save' ], true ) ? 'get' : $prefix;
$field = substr( $name, strlen( $prefix . '_' ) );
if ( 'get' === $action ) {
$args = [ $args ];
if ( 'display' === $prefix ) {
$args[] = true;
}
}
array_unshift( $args, $field );
$value = call_user_func_array( [ $this, '_' . $action . '_value' ], $args );
if ( 'set' !== $action ) {
return $value;
}
return $this;
}
}
throw new \BadMethodCallException();
}
final protected static function _get_query( $model = null ) {
if ( empty( $model ) ) {
$model = new static();
}
foreach ( array_reverse( hp\get_class_parents( static::class ) ) as $class ) {
$query = hp\create_class_instance( '\HivePress\Queries\\' . hp\get_class_name( $class ), [ [ 'model' => $model ] ] );
if ( $query ) {
return $query;
}
}
}
final protected function _set_value( $name, $value ) {
if ( isset( $this->fields[ $name ] ) ) {
if ( $this->fields[ $name ]->get_arg( '_model' ) ) {
if ( is_array( $value ) ) {
$value = array_map(
function( $object ) {
return is_object( $object ) ? $object->get_id() : $object;
},
$value
);
} elseif ( is_object( $value ) ) {
$value = $value->get_id();
}
}
$this->fields[ $name ]->set_value( $value );
}
}
final protected function _get_value( $name, $args = [], $display = false ) {
$field = null;
if ( strpos( $name, '__' ) && ! isset( $this->fields[ $name ] ) ) {
list($name, $field) = explode( '__', $name );
}
if ( isset( $this->fields[ $name ] ) ) {
$value = null;
if ( $display && empty( $field ) ) {
$value = $this->fields[ $name ]->get_display_value();
} else {
$value = $this->fields[ $name ]->get_value();
$model = $this->fields[ $name ]->get_arg( '_model' );
if ( $model && 'id' !== $field ) {
if ( ! isset( $this->values[ $name ] ) ) {
if ( is_array( $value ) ) {
$value = array_filter(
array_map(
function( $id ) use ( $model ) {
return hivepress()->model->get_model_object( $model, $id );
},
$value
)
);
} else {
$value = hivepress()->model->get_model_object( $model, $value );
}
$this->values[ $name ] = is_null( $value ) ? false : $value;
} else {
$value = $this->values[ $name ];
if ( false === $value ) {
$value = null;
}
}
if ( $field ) {
$method = ( $display ? 'display' : 'get' ) . '_' . $field;
if ( is_array( $value ) ) {
$value = array_map(
function( $object ) use ( $method, $args ) {
return call_user_func_array( [ $object, $method ], $args );
},
$value
);
} elseif ( $value ) {
$value = call_user_func_array( [ $value, $method ], $args );
}
}
}
}
return $value;
}
}
final public function set_id( $id ) {
$this->id = absint( $id );
$fields = array_map(
function( $field ) {
return array_merge(
$field->get_args(),
[
'default' => $field->get_value(),
]
);
},
$this->fields
);
foreach ( hp\get_class_parents( static::class ) as $class ) {
$fields = apply_filters( 'hivepress/v1/models/' . hp\get_class_name( $class ) . '/fields', $fields, $this );
}
$this->_set_fields( $fields );
return $this;
}
final public function get_id() {
return $this->id;
}
final protected function _add_errors( $errors ) {
$this->errors = array_merge( $this->errors, (array) $errors );
}
final public function _get_errors() {
return $this->errors;
}
final protected function _save_value( $name ) {
return $this->save( [ $name ] );
}
final public function fill( $values ) {
unset( $values['id'] );
foreach ( $values as $name => $value ) {
call_user_func( [ $this, 'set_' . $name ], $value );
}
return $this;
}
final public function serialize() {
$values = [];
foreach ( $this->fields as $name => $field ) {
$field_name = $name;
if ( $field->get_arg( '_model' ) ) {
$field_name .= '__id';
}
$values[ $name ] = call_user_func( [ $this, 'get_' . $field_name ] );
}
return $values;
}
final public function validate( $names = [] ) {
$this->errors = [];
$fields = $this->fields;
if ( $names ) {
$fields = array_filter(
$fields,
function( $field ) use ( $names ) {
return in_array( $field->get_name(), $names, true );
}
);
}
foreach ( $fields as $field ) {
if ( ! $field->validate() ) {
$this->_add_errors( $field->get_errors() );
}
}
foreach ( hp\get_class_parents( static::class ) as $class ) {
$this->errors = apply_filters( 'hivepress/v1/models/' . hp\get_class_name( $class ) . '/errors', $this->errors, $this );
}
return empty( $this->errors );
}
abstract public function get( $id );
abstract public function save( $names = [] );
abstract public function delete( $id = null );
}