Skip to content

Instantly share code, notes, and snippets.

@radynsade
Created January 11, 2023 13:05
Show Gist options
  • Save radynsade/91a4cd84705cfcfb99ac7de8722cfbe0 to your computer and use it in GitHub Desktop.
Save radynsade/91a4cd84705cfcfb99ac7de8722cfbe0 to your computer and use it in GitHub Desktop.
<?php
namespace Core\Models;
use Core\Services\Storage;
use Phalcon\Cache\Adapter\AdapterInterface as CacheAdapterInterface;
use Phalcon\Db\Adapter\AdapterInterface as DbAdapterInterface;
use Phalcon\Mvc\Model;
use ReflectionClass;
use ReflectionProperty;
use Utils\Text\Strings;
abstract class BaseModel extends Model {
/**
* @var string[]
*/
protected array $modelProperties;
/**
* @var integer|null
*/
protected ?int $id = null;
/**
* @return integer|null
*/
public function getId(): int|null {
return $this->id;
}
/**
* @param integer|null $id
* @return static
*/
public function setId($id): static {
$this->id = $id;
return $this;
}
/**
* @return string[]
*/
public function getModelProperties() {
if (!isset($this->modelProperties)) {
$this->modelProperties = $this->scanProperties();
}
return $this->modelProperties;
}
/**
* @return boolean
*/
public function isSaved(): bool {
return !empty($this->id);
}
/**
* @return boolean
*/
public function isNew(): bool {
return !$this->isSaved();
}
/**
* @return void
*/
public function initialize(): void {
$this->useDynamicUpdate(true);
$class = new \ReflectionClass($this);
$className = $class->getShortName();
$namespaceName = $class->getNamespaceName();
$moduleName = explode("\\", $namespaceName)[1];
$tableName = Strings::camelCaseToSnakeCase($className);
$this->setSchema(strtolower($moduleName));
$this->setSource($tableName);
$this->addBehavior(new ErrorLogBehavior([
'notSaved' => [],
'notDeleted' => []
]));
}
/**
* @return array
*/
public function columnMap(): array {
return $this->buildColumnMap();
}
/**
* @return string[]
*/
protected function scanProperties(): array {
$properties = [];
$class = new ReflectionClass($this);
$reflectProperties = $class->getProperties();
foreach ($reflectProperties as $reflectProperty) {
$name = $reflectProperty->getName();
if (
$reflectProperty->isStatic()
|| $this->isFrameworkProperty($name)
|| $name === 'modelProperties'
|| !$this->isAccessableProperty($class, $reflectProperty)
) {
continue;
}
$properties[] = $name;
}
return $properties;
}
/**
* @return Storage
*/
protected function getStorage(): Storage {
return $this->container->get('storage');
}
/**
* @return CacheAdapterInterface
*/
protected function getCache(): CacheAdapterInterface {
return $this->container->get('cache');
}
/**
* @return DbAdapterInterface
*/
protected function getDatabase(): DbAdapterInterface {
return $this->container->get('db');
}
/**
* @param string $propertyName
* @return boolean
*/
private function isFrameworkProperty(string $propertyName): bool {
return in_array($propertyName, [
'dirtyState',
'dirtyRelated',
'errorMessages',
'modelsManager',
'modelsMetaData',
'related',
'operationMade',
'oldSnapshot',
'skipped',
'snapshot',
'transaction',
'uniqueKey',
'uniqueParams',
'uniqueTypes',
'container',
'belongsTo'
]);
}
/**
* @param ReflectionProperty $property
* @return boolean
*/
private function isAccessableProperty(
ReflectionClass $class,
ReflectionProperty $property
): bool {
if ($property->isPublic()) {
return true;
}
$name = $property->getName();
$getterName = Strings::getterName($name);
return $class->hasMethod($getterName)
&& $class->getMethod($getterName)->isPublic();
}
/**
* @return array
*/
private function buildColumnMap(): array {
$properties = $this->getModelProperties();
$map = [];
foreach ($properties as $property) {
$map[Strings::camelCaseToSnakeCase($property)] = $property;
}
return $map;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment