src/DataProvider/Analytics.php line 102
<?php
// api/src/DataProvider/BlogPostCollectionDataProvider.php
namespace App\DataProvider;
use App\Common\Functions\AggregateFuns;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use App\Common\Functions\Helpers;
use App\Functions\Common\Variables;
use Doctrine\ODM\MongoDB\DocumentManager as MongoDBDocumentManager;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class Analytics extends AbstractController
{
protected $headers = array('Content-Type', 'application/json');
public $propertyAccessor;
private $groups_functions;
private $options = Variables::SERIALIZER_OPTIONS;
public function __construct(public string $rootPath, public MongoDBDocumentManager $dm, public SerializerInterface $serializer, public ValidatorInterface $validator)
{
$this->groups_functions = ["date"=>fn($x)=>(['$dateToString'=>['format'=>$x->format, 'date'=>'$'.$x->field]]), 'main'=>fn($x)=>('$'.$x)];
$this->propertyAccessor = PropertyAccess::createPropertyAccessor();
$this->options[AbstractNormalizer::CIRCULAR_REFERENCE_LIMIT] = 3;
$this->options[AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER] = function($object){
if(method_exists($object, 'getId')){
return $object->getId();
}
return $object;
};
}
private function grouping($main_query, $query, $groups){
$gr_exp = $main_query->expr();
foreach($groups as $kg=>$group){
$val = $group['date']??$group;
if(is_array($val)){
$val = (object) $val;
}
$fun = $this->groups_functions[$group['fun'] ?? 'main'];
$gr_exp = $gr_exp->field($group['key'] ?? $kg)->expression($fun($val));
}
return $query->group()
->field('id')
->expression(
$gr_exp
);
}
private function applyField($model, $query, $type='main'){
$file = str_replace('App\\Document\\', 'Reports\\', $model).'.json';
$file = str_replace('\\', '/', $file);
$data = file_get_contents($this->rootPath.'/'.$file);
$var = json_decode($data, true);
$fields = $var[$type] ?? [];
foreach ($fields as $key=>$field){
$fun = $field['fun'] ?? $field;
$fi = $field['field'] ?? '$'.$key;
$query = $query->field($key)->{$fun}($fi);
}
return $query;
}
private function applyAnalysis($model, $filters, $groups, $params=[])
{
$main_query = $this->dm->createAggregationBuilder($model);
$cs = Helpers::get_model_config($model);
$query = $main_query;
if(count($filters)){
$query = $query->match()->addAnd($filters);
}
$out = Helpers::getModelFilter($cs->filters ?? []);
if(count($out)>0){
if(!count($filters)){
$query = $query->match();
}
$query = $query->addAnd($out);
}
$m_aggs = [...$cs->aggregation['analysis'] ?? [], ...($params['aggs'] ?? [])];
foreach ($m_aggs as $agg => $val) {
$query = AggregateFuns::{$val['agg'] ?? $agg}($query, array_diff_key($val, ['agg' => null]));
}
$query = $this->grouping($main_query, $query, $groups);
$query = $query->field('counts')
->sum(1);
$query = $this->applyField($model, $query, $params['analysis'] ?? 'main');
return $query->execute();
}
private function applyListAnalysis($model, $filters, $groups, $include_data=false)
{
$main_query = $this->dm->createAggregationBuilder($model);
$query = $main_query;
if(count($filters)){
$query = $query->match()->addAnd($filters);
}
$query = $this->grouping($main_query, $query, $groups);
$query = $query->field('count')->sum(1)->field('ids')->push('$_id');
if($include_data){
return $query->field('data')->push('$$ROOT')->execute();
}
return $query->execute();
}
public function analysis(Request $request)
{
$data = $request->request->all();
$this->dm->clear(); // to fix fetching from proxy
$out = [];
foreach($data as $key=>$val){
$model = Helpers::get_module($val['model'] ?? $key);
$filters = $val['filter'] ?? [];
$groups = $val['group'] ?? [];
$out[$key] =$this->applyAnalysis($model, $filters, $groups, $val);
}
$res = $this->serializer->serialize($out, 'json');
return new Response($res, Response::HTTP_OK, ['Content-Type' => 'application/json']);
}
public function listAnalysis(Request $request)
{
$data = $request->request->all();
$this->dm->clear(); // to fix fetching from proxy
$out = [];
foreach($data as $key=>$val){
$model = Helpers::get_module($val['model'] ?? $key);
$filters = $val['filter'] ?? [];
$groups = $val['group'] ?? [];
$out[$key] =$this->applyListAnalysis($model, $filters, $groups, $val['include'] ?? false);
}
$res = $this->serializer->serialize($out, 'json');
return new Response($res, Response::HTTP_OK, ['Content-Type' => 'application/json']);
}
}