<?php
namespace IRI\Bundle\WikiTagBundle\Entity;
use Doctrine\ORM\EntityRepository;
use IRI\Bundle\WikiTagBundle\Entity\Document;
use Doctrine\ORM\Query\ResultSetMapping;
use \ReflectionClass;
use Doctrine\ORM\AbstractQuery;
/**
* DocumentRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class DocumentRepository extends EntityRepository
{
/**
*
* TODO : Enter description here ...
* @var ReflectionClass
*/
private $reflection_class;
private $reflection_doc_class;
private $set_methods = array();
private $get_methods = array();
function findOneByExternalId($external_id)
{
return $this->findOneBy(array("externalId" => $external_id));
}
private function reflectionSetField($object, $method_name, $value)
{
if(isset($this->set_methods[$method_name]))
{
$set_method = $this->set_methods[$method_name];
}
if(!isset($set_method) || is_null($set_method))
{
if(is_null($this->reflection_doc_class))
{
$this->reflection_doc_class = new ReflectionClass(get_class($object));
}
$set_method = NULL;
if($this->reflection_doc_class->hasMethod($method_name))
{
$set_method = $this->reflection_doc_class->getMethod($method_name);
}
if(!is_null($set_method))
{
$this->set_methods[$method_name]=$set_method;
}
}
if(!isset($set_method) || is_null($set_method) || !$set_method->isPublic())
{
throw new \Exception("setter method unknown $method_name");
}
//set value
$set_method->invoke($object, $value);
}
private function reflectionGetField($document, $accessor)
{
if(!isset($this->get_methods[$accessor]) || is_null($this->get_methods[$accessor]))
{
if(is_null($this->reflection_class))
{
$this->reflection_class = new \ReflectionClass(get_class($document));
}
//look at properties
if($this->reflection_class->hasProperty($accessor))
{
$get_object = $this->reflection_class->getProperty($accessor);
if(!$get_object->isPublic())
{
$get_object = NULL;
}
}
if((!isset($get_object) || is_null($get_object)) && $this->reflection_class->hasMethod($accessor))
{
$get_object = $this->reflection_class->getMethod($accessor);
if(!$get_object->isPublic())
{
$get_object = NULL;
}
}
if((!isset($get_object) || is_null($get_object)) && $this->reflection_class->hasMethod("get".ucfirst($accessor)))
{
$get_object = $this->reflection_class->getMethod("get".ucfirst($accessor));
if(!$get_object->isPublic())
{
$get_object = NULL;
}
}
if(isset($get_object) && !is_null($get_object))
{
$this->get_methods[$accessor] = $get_object;
}
}
if(isset($this->get_methods[$accessor]))
{
$get_object = $this->get_methods[$accessor];
if(!is_null($get_object))
{
if(is_a($get_object,"\ReflectionMethod"))
{
return $get_object->invoke($document);
}
elseif(is_a($get_object,"\ReflectionProperty"))
{
return $get_object->getValue($document);
}
else
{
//TODO : custom exception
throw new \Exception("Bad reflection object type");
}
}
}
//TODO: replace by custom exception
throw new \Exception("Unknown accessor $accessor");
}
function writeDocument($document, $document_id_column, $fields)
{
// get document from id
$docid = $this->reflectionGetField($document, $document_id_column);
$baseDocument = $this->findOneByExternalId($docid);
if(is_null($baseDocument))
{
$baseDocument = new Document();
$baseDocument->setExternalId($document);
}
foreach ($fields as $name => $field_def) {
if(isset($field_def['accessor']))
{
$accessor = $field_def['accessor'];
}
else
{
$accessor = NULL;
}
if(is_null($accessor))
{
$accessor = $name;
}
$value = strval($this->reflectionGetField($document,$accessor));
$method_name = "set".ucfirst($name);
$this->reflectionSetField($baseDocument, $method_name, $value);
}
$this->getEntityManager()->persist($baseDocument);
$this->getEntityManager()->flush();
return $baseDocument;
}
function removeDocument($document, $document_id_column)
{
$docid = $this->reflectionGetField($document, $document_id_column);
$baseDocument = $this->findOneByExternalId($docid);
if(!is_null($baseDocument))
{
$this->getEntityManager()->remove($baseDocument);
}
}
function getTagsStr($document)
{
$em = $this->getEntityManager();
$query = $em->createQuery("SELECT t.label FROM WikiTagBundle:DocumentTag dt JOIN dt.tag t WHERE dt.document = :docid");
$query = $query->setParameter("docid", $document);
$result = $query->getScalarResult();
$tagstr = array();
foreach ($result as $res) {
$tagstr[] = $res['label'];
}
return $tagstr;
}
function updateTagsStr($document)
{
$tagstr = $this->getTagsStr($document);
$document->setTagsStr(implode(",",$tagstr));
$this->getEntityManager()->persist($document);
}
/**
*
* Enter description here ...
* @param array $values : key: the fields to search into, value : array('value'=>value, 'weight'=>weight)
* @param array $conditions : array : key : field name, value : simple value (operator is "=") or array(valuea, value2,...) (operatr is IN) or array("operator"=>"", "value"=>value)
* @return Ambigous <multitype:, \Doctrine\ORM\mixed, \Doctrine\DBAL\Driver\Statement, \Doctrine\ORM\Internal\Hydration\mixed>
*/
function search(array $values, array $conditions=NULL)
{
$em = $this->getEntityManager();
$rsm = new ResultSetMapping();
$rsm->addEntityResult("IRI\Bundle\WikiTagBundle\Entity\Document", "d");
$rsm->addFieldResult("d", "id", "id");
$rsm->addScalarResult("score", "score");
$rsm->addMetaResult("d", "external_id", "externalId");
$score = array();
$i = 0;
foreach ($values as $fielddef) {
$i++;
$columns = $fielddef["columns"];
$value = $fielddef["value"];
$weight = isset($fielddef["weight"])?$fielddef["weight"]:1.0;
$score[] = "(MATCH($columns) AGAINST (:value_$i))*:weight_$i";
$parameters["value_$i"] = $value;
$parameters["weight_$i"] = $weight;
}
$score_def = "(".implode("+", $score).")";
$conditions_str = "";
if(!is_null($conditions))
{
$conditions_array = array();
$i = 0;
foreach ($conditions as $field => $conddef)
{
$i++;
if(is_array($conddef) && isset($conddef['operator']))
{
$operator = $conddef["operator"];
$values = $conddef["value"];
}
elseif(is_array($conddef))
{
$operator = "IN";
$values = $conddef;
}
else
{
$operator = "=";
$values = $conddef;
}
if($operator === "IN")
{
$in_parameters = array();
for ($j = 0; $j < count($values); $j++) {
$parameters["cond_val_$i_$j"] = $values[$j];
$in_parameters[] = ":cond_val_$i_$j";
}
$cond = "($field IN (".implode(",",$in_parameters)."))";
}
else
{
$cond = "($field $operator :cond_val_$i)";
$parameters["cond_val_$i"] = $values;
}
$conditions_array[] = $cond;
}
if(count($conditions_array) > 0)
{
$conditions_str = " AND ".implode(" AND ", $conditions_array);
}
}
$query = $em->createNativeQuery("SELECT d.id, d.external_id, $score_def AS score FROM wikitag_document d WHERE $score_def > 0 $conditions_str ORDER BY score DESC", $rsm);
$query->setParameters($parameters);
$res = $query->getResult();
return $res;
}
}