src/DataProvider/Analytics.php line 102

  1. <?php
  2. // api/src/DataProvider/BlogPostCollectionDataProvider.php
  3. namespace App\DataProvider;
  4. use App\Common\Functions\AggregateFuns;
  5. use Symfony\Component\HttpFoundation\Response;
  6. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  7. use App\Common\Functions\Helpers;
  8. use App\Functions\Common\Variables;
  9. use Doctrine\ODM\MongoDB\DocumentManager as MongoDBDocumentManager;
  10. use Symfony\Component\HttpFoundation\Request;
  11. use Symfony\Component\PropertyAccess\PropertyAccess;
  12. use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
  13. use Symfony\Component\Serializer\SerializerInterface;
  14. use Symfony\Component\Validator\Validator\ValidatorInterface;
  15. class Analytics extends AbstractController
  16. {
  17.   protected $headers = array('Content-Type''application/json');
  18.     public $propertyAccessor;
  19.     private $groups_functions;
  20.     private $options Variables::SERIALIZER_OPTIONS;
  21.     public function __construct(public string $rootPath, public MongoDBDocumentManager $dm, public SerializerInterface $serializer, public ValidatorInterface $validator)
  22.     {
  23.         $this->groups_functions = ["date"=>fn($x)=>(['$dateToString'=>['format'=>$x->format'date'=>'$'.$x->field]]), 'main'=>fn($x)=>('$'.$x)];
  24.         $this->propertyAccessor PropertyAccess::createPropertyAccessor();
  25.         $this->options[AbstractNormalizer::CIRCULAR_REFERENCE_LIMIT] = 3;
  26.         $this->options[AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER] = function($object){
  27.           if(method_exists($object'getId')){
  28.             return $object->getId();
  29.           }
  30.           return $object;
  31.         };
  32.     }
  33.     private function grouping($main_query$query$groups){
  34.         $gr_exp $main_query->expr();
  35.         foreach($groups as $kg=>$group){
  36.             $val $group['date']??$group;
  37.             if(is_array($val)){
  38.                 $val = (object) $val;
  39.             }
  40.             $fun $this->groups_functions[$group['fun'] ?? 'main'];
  41.             $gr_exp $gr_exp->field($group['key'] ?? $kg)->expression($fun($val));
  42.         }
  43.         return $query->group()
  44.             ->field('id')
  45.             ->expression(
  46.                 $gr_exp
  47.             );
  48.     }
  49.     private function applyField($model$query$type='main'){
  50.         $file str_replace('App\\Document\\''Reports\\'$model).'.json';
  51.         $file str_replace('\\''/'$file);
  52.         $data file_get_contents($this->rootPath.'/'.$file);
  53.         $var json_decode($datatrue);
  54.         $fields $var[$type] ?? [];
  55.         foreach ($fields as $key=>$field){
  56.             $fun $field['fun'] ?? $field;
  57.             $fi $field['field'] ?? '$'.$key;
  58.             $query $query->field($key)->{$fun}($fi);
  59.         }
  60.         return $query;
  61.     }
  62.     private function applyAnalysis($model$filters$groups$params=[])
  63.     {
  64.         $main_query $this->dm->createAggregationBuilder($model);
  65.         $cs Helpers::get_model_config($model);
  66.         $query $main_query;
  67.         if(count($filters)){
  68.             $query $query->match()->addAnd($filters);
  69.         }
  70.         $out Helpers::getModelFilter($cs->filters ?? []);
  71.           if(count($out)>0){
  72.           if(!count($filters)){
  73.             $query $query->match();
  74.           }
  75.           $query $query->addAnd($out);
  76.         }
  77.         $m_aggs = [...$cs->aggregation['analysis'] ?? [], ...($params['aggs'] ?? [])];
  78.         foreach ($m_aggs as $agg => $val) {
  79.           $query AggregateFuns::{$val['agg'] ?? $agg}($queryarray_diff_key($val, ['agg' => null]));
  80.         }
  81.         $query $this->grouping($main_query$query$groups);
  82.         $query $query->field('counts')
  83.                            ->sum(1);
  84.         $query $this->applyField($model$query$params['analysis'] ?? 'main');
  85.         return $query->execute();
  86.     }
  87.     private function applyListAnalysis($model$filters$groups$include_data=false)
  88.     {
  89.         $main_query $this->dm->createAggregationBuilder($model);
  90.         $query $main_query;
  91.         if(count($filters)){
  92.             $query $query->match()->addAnd($filters);
  93.         }
  94.         $query $this->grouping($main_query$query$groups);
  95.         $query $query->field('count')->sum(1)->field('ids')->push('$_id');
  96.         if($include_data){
  97.             return $query->field('data')->push('$$ROOT')->execute();
  98.         }
  99.         return $query->execute();
  100.     }
  101.     public function analysis(Request $request)
  102.     {
  103.         $data $request->request->all();
  104.         $this->dm->clear(); // to fix fetching from proxy
  105.         $out = [];
  106.         foreach($data as $key=>$val){
  107.             $model Helpers::get_module($val['model'] ?? $key);
  108.             $filters $val['filter'] ?? [];
  109.             $groups $val['group'] ?? [];
  110.             $out[$key] =$this->applyAnalysis($model$filters$groups$val);
  111.         }
  112.         $res $this->serializer->serialize($out'json');
  113.         return new Response($resResponse::HTTP_OK, ['Content-Type' => 'application/json']);
  114.     }
  115.     public function listAnalysis(Request $request)
  116.     {
  117.         $data $request->request->all();
  118.         $this->dm->clear(); // to fix fetching from proxy
  119.         $out = [];
  120.         foreach($data as $key=>$val){
  121.             $model Helpers::get_module($val['model'] ?? $key);
  122.             $filters $val['filter'] ?? [];
  123.             $groups $val['group'] ?? [];
  124.             $out[$key] =$this->applyListAnalysis($model$filters$groups$val['include'] ?? false);
  125.         }
  126.         $res $this->serializer->serialize($out'json');
  127.         return new Response($resResponse::HTTP_OK, ['Content-Type' => 'application/json']);
  128.     }
  129. }