<?php
namespace gnomephp\crud;
class DoctrineEntity{
const IDENT_SEPARATOR = '-_-_-';
/**
* @var Doctrine\ORM\EntityManager
*/
protected $em;
/**
* Holds the namespaced class name.
* This is including the application namespace.
* @var string
*/
protected $ns;
/**
* Holds the object of the entity.
* @var \Object
*/
protected $obj;
/**
* Holds the metadata of the entity.
* @var Doctrine\ORM\Mapping\ClassMetadata
*/
public $meta;
public function __construct($em, $ns){
$this->em = $em;
$this->ns = $ns;
$this->meta = $this->em->getMetadataFactory()->getMetadataFor($ns);
$this->obj = $this->createObject();
}
public function createObject(){
$obj = $this->ns;
$refClass = new \ReflectionClass( $obj );
$constructor = $refClass->getConstructor();
$params = $constructor->getParameters();
// Build parameters.
$paramArray = array();
for($i = 0; $i <= count($params); $i++){
$paramArray[] = null;
}
return $refClass->newInstanceArgs($paramArray);
}
public function getFields(){
$refObject = new \ReflectionObject( $this->obj );
if ($refObject->implementsInterface('gnomephp\crud\FieldAccess')){
$ar = $this->meta->fieldMappings;
foreach($ar as $k => $v){
if (!in_array($k, $this->obj->crudFields()))unset($ar[$k]);
}
return $ar;
}
return $this->meta->fieldMappings;
}
public function translateField($field){
$obj = $this->createObject();
$ar = $obj->getFieldNames();
return isset($ar[$field]) ? $ar[$field] : $field;
}
public function getEntries(){
$query = $this->em->createQuery("SELECT fieldGnomePHP FROM {$this->ns} fieldGnomePHP");
$entries = $query->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
return $entries;
}
public function getEntryWhereId($id, $hydrate = true){
// Create query.
$query = $this->em->createQuery("SELECT fieldGnomePHP FROM {$this->ns} fieldGnomePHP {$this->generateWhere($id)}");
// Fetch result.
$entry = $query->getResult($hydrate ? \Doctrine\ORM\Query::HYDRATE_ARRAY : null);
return $entry[0];
}
public function updateEntry($id, $vars){
$query = $this->em->createQuery("UPDATE {$this->ns} fieldGnomePHP ".$this->varsToDQL($vars)." {$this->generateWhere($id)}");
$query->execute();
// Create query.
$query = $this->em->createQuery("SELECT fieldGnomePHP FROM {$this->ns} fieldGnomePHP {$this->generateWhere($id)}");
// Fetch result.
$entry = $query->getOneOrNullResult();
if ($entry !== null){
$refObject = new \ReflectionObject( $entry );
if ($refObject->implementsInterface('gnomephp\crud\OnUpdateListener')){
$entry->onUpdate();
}
$this->em->persist($entry);
$this->em->flush();
}
return false;
}
public function deleteEntry($id){
// Create query.
$query = $this->em->createQuery("SELECT fieldGnomePHP FROM {$this->ns} fieldGnomePHP {$this->generateWhere($id)}");
// Fetch result.
$entry = $query->getOneOrNullResult();
if ($entry !== null){
$refObject = new \ReflectionObject( $entry );
if ($refObject->implementsInterface('gnomephp\crud\OnDeleteListener')){
$entry->onDelete();
}
$this->em->persist($entry);
$this->em->flush();
}
// Create query.
$query = $this->em->createQuery("DELETE FROM {$this->ns} fieldGnomePHP {$this->generateWhere($id)}");
return $query->execute();
}
public function createEntry($data){
$this->validateFields($this->meta->fieldMappings, $data);
$entity = $this->ns;
$obj = new $entity;
$refObject = new \ReflectionObject( $obj );
foreach($data as $key => $val){
if (!$val)$val = null;
$refProperty = $refObject->getProperty( $key );
$refProperty->setAccessible( true );
$refProperty->setValue($obj, $val);
}
if ($refObject->implementsInterface('gnomephp\crud\OnCreateListener')){
$obj->onCreate();
}
$this->em->persist($obj);
$this->em->flush();
}
public function getIdentifier($entry){
$uid = '';
foreach($this->meta->identifier as $ident){
$uid .= $entry[$ident] . DoctrineEntity::IDENT_SEPARATOR;
}
return $uid;
}
public function generateWhere($id){
$idents = $this->meta->identifier;
$bits = explode(DoctrineEntity::IDENT_SEPARATOR, $id);
$where = 'WHERE ';
foreach($idents as $k => $ident){
$where .= ($k != 0 ? ' AND ' : '').'fieldGnomePHP.'.$ident . ' = ' . "'".$bits[$k]."'";
}
return $where;
}
public function getRelations($id=false){
$ret = array();
$rels = $this->meta->associationMappings;
if ($id){
$entry = $this->getEntryWhereId($id, false);
$refObject = new \ReflectionObject( $entry );
}else{
$entry = null;
}
foreach($rels as $key => $info){
$rel = new DoctrineEntity($this->em, $info['targetEntity']);
if ($entry !== null){
$value = null;
}else{
$value = null;
}
$ret[$key] = array(
'value' => $value,
'key' => $key,
'list' => $rel->getEntries(),
'idkey' => $rel->meta->identifier[0],
'fields' => $rel->getFields(),
'worker' => $rel
);
}
return $ret;
}
protected function varsToDQL($array){
$dql = 'SET ';
foreach($array as $k => $v){
$dql .= 'fieldGnomePHP.' . $k . '=' . ($v != '' ? "'".$v."'" : 'NULL'). ",";
}
$dql = substr($dql, 0, -1).' ';
return $dql;
}
public function validateFields($fields, $posts){
foreach($posts as $name => $val){
$info = $fields[$name];
$f = $val;
if ($info['length'])$f->maxLength($info['length']);
if ($info['type']){
switch($info['type']){
case 'integer':
$f->numeric();
break;
case 'date':
case 'datetime':
case 'time':
if (!strtotime($val)){
throw new \gnomephp\input\DataFieldValidException(array("$name is not a valid date. Please define a valid date."));
}
break;
case 'float':
$f->float();
break;
case 'boolean':
if ($val != 0 && $val != 1){
throw new \gnomephp\input\DataFieldValidException(array("$name is not a valid boolean type."));
}
break;
}
}
$f->validate();
}
}
}