public function doc2object($doc)
 {
     $dataset = $doc['fields']['dataset'][0];
     $id = $doc['fields']['id'][0];
     if ($dataset == null or $id == null) {
         throw new InternalErrorException("Empty dataset or id: " . $dataset . ' ' . $id);
     }
     $output = array('id' => $id, 'dataset' => $dataset, 'url' => Dataobject::apiUrl($dataset, $id), 'mp_url' => Dataobject::mpUrl($dataset, $id), 'schema_url' => Dataobject::schemaUrl($dataset), 'global_id' => $doc['_id'], 'slug' => $doc['fields']['slug'][0], 'score' => $doc['_score'], 'data' => $doc['fields']['source'][0]['data']);
     if (@$doc['inner_hits']['collection']['hits']['total'] && @$doc['inner_hits']['collection']['hits']['hits'][0]['_source']) {
         $output['collection'] = $doc['inner_hits']['collection']['hits']['hits'][0]['_source'];
         $output['collection']['id'] = (int) $doc['inner_hits']['collection']['hits']['hits'][0]['_id'];
     }
     if (isset($doc['fields']['source'][0]['static']) && !empty($doc['fields']['source'][0]['static'])) {
         $output['static'] = $doc['fields']['source'][0]['static'];
     }
     if (isset($doc['fields']['source'][0]['contexts']) && !empty($doc['fields']['source'][0]['contexts'])) {
         $force_context = false;
         if (@$doc['inner_hits']['alert-data']['hits']['total'] && isset($doc['inner_hits']['alert-data']['hits']['hits'][0]['fields']['context'][0])) {
             $force_context = $doc['inner_hits']['alert-data']['hits']['hits'][0]['fields']['context'][0];
         }
         $context = array();
         foreach ($doc['fields']['source'][0]['contexts'] as $key => $value) {
             if (!$force_context || $force_context && strpos($key, $force_context) !== false) {
                 $key_parts = explode('.', $key);
                 $value_parts = explode("\n\r", $value);
                 $context[] = array('creator' => array('dataset' => $key_parts[0], 'id' => $key_parts[1], 'global_id' => $value_parts[0], 'name' => $value_parts[1], 'slug' => $value_parts[2], 'url' => @$value_parts[5]), 'action' => $key_parts[2], 'label' => $value_parts[3], 'sentence' => $value_parts[4]);
             }
         }
         $output['contexts'] = $context;
     }
     if (isset($doc['highlight']['text']) && is_array($doc['highlight']['text']) && isset($doc['highlight']['text'][0])) {
         $output['highlight'] = array($doc['highlight']['text']);
     }
     if (isset($doc['inner_hits']) && isset($doc['inner_hits']['inner']) && isset($doc['inner_hits']['inner']['hits']) && isset($doc['inner_hits']['inner']['hits']['hits'])) {
         foreach ($doc['inner_hits']['inner']['hits']['hits'] as $hit) {
             $output['inner_hits'][] = array('id' => $hit['_id'], 'title' => @$hit['fields']['title'][0]);
         }
     }
     return $output;
 }
 public function series()
 {
     $metric_id = @$this->request->query['metric_id'];
     $slice = @$this->request->query['slice'];
     $time_range = @$this->request->query['time_range'];
     $wojewodztwo_id = @$this->request->query['wojewodztwo_id'];
     $powiat_id = @$this->request->query['powiat_id'];
     $gmina_id = @$this->request->query['gmina_id'];
     $meta = @$this->request->query['meta'];
     if ($metric_id === null) {
         throw new BadRequestException('Query parameter is required: metric_id');
     }
     $metric = $this->Dataobject->find('first', array('conditions' => array('bdl_wskazniki.okres' => 'R', 'dataset' => 'bdl_wskazniki', 'id' => $metric_id)));
     if (!$metric) {
         throw new ApiException(API_BDL_INVALID_INPUT, array('param' => 'metric_id'));
     }
     $metric_depths = array('0' => 'pl', '2' => 'wojewodztwo', '4' => 'powiat', '5' => 'gmina');
     $dims = $this->Dataobject->getObjectLayer('bdl_wskazniki', $metric_id, 'dimennsions');
     // check if slices match metrics
     if ($slice != null) {
         $slice = preg_replace('/\\s+/', '', $slice);
         if (!preg_match('/^\\[((\\d+|\\*)(,(\\d+|\\*))*)\\]$/', $slice, $slices)) {
             throw new ApiException(API_BDL_INVALID_INPUT, array('param' => 'slice'));
         }
         $slices = explode(',', $slices[1]);
         if (count($slices) != count($dims)) {
             throw new ApiException(API_BDL_MISMATCHED_DIMS_COUNT, array('expected' => count($dims), 'was' => count($slices)));
         }
     } else {
         $slices = array_fill(0, count($dims), '*');
     }
     $w = array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0);
     for ($i = 0; $i < count($slices); $i++) {
         $dim_slices = array_map(function ($el) {
             return $el['id'];
         }, $dims[$i]['options']);
         if ($slices[$i] == '*') {
             $w[$i] = $dim_slices;
         } elseif (!in_array($slices[$i], $dim_slices)) {
             throw new ApiException(API_BDL_INVALID_SLICE, $slices[$i]);
         } else {
             $w[$i] = $slices[$i];
         }
     }
     if (($wojewodztwo_id != null) + ($powiat_id != null) + ($gmina_id != null) > 1) {
         throw new ApiException(API_BDL_INVALID_INPUT, array('param' => array('wojewodztwo_id', 'powiat_id', 'gmina_id')), 'Only one of these parameters can be specified');
     }
     $conditions = array();
     $fields = array('w1', 'w2', 'w3', 'w4', 'w5', 'rocznik', 'v', 'kombinacja_id');
     // choose datasource
     $region = null;
     if ($wojewodztwo_id != null) {
         $model = 'DataWojewodztwa';
         $fields[] = 'wojewodztwo_id';
         if ($metric['data']['bdl_wskazniki.poziom_id'] < 2) {
             throw new ApiException(API_BDL_LEVEL_DATA_NOTAVAILABLE, array('requested' => $metric_depths[2], 'available_till' => $metric_depths[$metric['data']['poziom_id']]), 'Data at this regional level is not available');
         }
         if ($wojewodztwo_id != '*') {
             if (!preg_match('/^\\d+$/', $wojewodztwo_id)) {
                 throw new ApiException(API_BDL_INVALID_INPUT, array('param' => 'wojewodztwo_id'));
             }
             $wojewodztwo_id = intval($wojewodztwo_id);
             $region = $this->Dataobject->find('first', array('conditions' => array('dataset' => 'wojewodztwa', 'id' => $wojewodztwo_id)));
             if (!$region) {
                 throw new ApiException(API_BDL_INVALID_INPUT, array('param' => 'wojewodztwo_id'));
             }
             $conditions["wojewodztwo_id"] = $wojewodztwo_id;
         }
     } else {
         if ($powiat_id != null) {
             $model = 'DataPowiaty';
             $fields[] = 'powiat_id';
             if ($metric['data']['bdl_wskazniki.poziom_id'] < 4) {
                 throw new ApiException(API_BDL_LEVEL_DATA_NOTAVAILABLE, array('requested' => $metric_depths[4], 'available_till' => $metric_depths[$metric['data']['bdl_wskazniki.poziom_id']]), 'Data at this regional level is not available');
             }
             if ($powiat_id != '*') {
                 if (!preg_match('/^\\d+$/', $powiat_id)) {
                     throw new ApiException(API_BDL_INVALID_INPUT, array('param' => 'powiat_id'));
                 }
                 $powiat_id = intval($powiat_id);
                 $region = $this->Dataobject->find('first', array('conditions' => array('dataset' => 'powiaty', 'id' => $powiat_id)));
                 if (!$region) {
                     throw new ApiException(API_BDL_INVALID_INPUT, array('param' => 'powiat_id'));
                 }
                 $conditions["powiat_id"] = $powiat_id;
             }
         } else {
             if ($gmina_id != null) {
                 $model = 'DataGminy';
                 $fields[] = 'gmina_id';
                 if ($metric['data']['bdl_wskazniki.poziom_id'] < 5) {
                     throw new ApiException(API_BDL_LEVEL_DATA_NOTAVAILABLE, array('requested' => $metric_depths[5], 'available_till' => $metric_depths[$metric['data']['bdl_wskazniki.poziom_id']]), 'Data at this regional level is not available');
                 }
                 if ($gmina_id != '*') {
                     if (!preg_match('/^\\d+$/', $gmina_id)) {
                         throw new ApiException(API_BDL_INVALID_INPUT, array('param' => 'gmina_id'));
                     }
                     $gmina_id = intval($gmina_id);
                     $region = $this->Dataobject->find('first', array('conditions' => array('dataset' => 'gminy', 'id' => $gmina_id)));
                     if (!$region) {
                         throw new ApiException(API_BDL_INVALID_INPUT, array('param' => 'gmina_id'));
                     }
                     $conditions["gmina_id"] = $gmina_id;
                 }
             } else {
                 $model = 'DataPl';
             }
         }
     }
     // choose time range
     if ($time_range != null) {
         if (!preg_match('/^(\\d{4}):(\\d{4})$/', $time_range, $time_ranges)) {
             throw new ApiException(API_BDL_INVALID_INPUT, array('param' => 'time_range', 'value' => $time_range, 'expected_format' => 'year_start:year_end'));
         }
         if ($time_ranges[0] <= $time_ranges[1]) {
             $conditions['rocznik >='] = intval($time_ranges[0]);
             $conditions['rocznik <='] = intval($time_ranges[1]);
         } else {
             $conditions['rocznik >='] = intval($time_ranges[1]);
             $conditions['rocznik <='] = intval($time_ranges[2]);
         }
     }
     // choose series
     $series_ids = $this->WymiaryKombinacje->find('all', array('conditions' => array('podgrupa_id' => $metric_id, 'w1' => $w[0], 'w2' => $w[1], 'w3' => $w[2], 'w4' => $w[3], 'w5' => $w[4]), 'fields' => array('id', 'jednostka')));
     $units = array();
     foreach ($series_ids as $s) {
         $units[$s['WymiaryKombinacje']['id']] = trim($s['WymiaryKombinacje']['jednostka'], '[]');
     }
     $conditions['kombinacja_id'] = array_keys($units);
     $conditions['deleted'] = 0;
     $data_count = $this->{$model}->find('count', array('conditions' => $conditions, 'fields' => $fields));
     if ($data_count > DATA_POINTS_LIMIT) {
         throw new ApiException(API_BDL_TOO_MANY_POINTS, array('limit' => DATA_POINTS_LIMIT, 'found' => $data_count));
     }
     $order = array('kombinacja_id', 'rocznik');
     if ($wojewodztwo_id != null) {
         array_splice($order, 1, 0, 'wojewodztwo_id');
     }
     if ($powiat_id != null) {
         array_splice($order, 1, 0, 'powiat_id');
     }
     if ($gmina_id != null) {
         array_splice($order, 1, 0, 'gmina_id');
     }
     $data = $this->{$model}->find('all', array('conditions' => $conditions, 'fields' => $fields, 'order' => $order));
     $slice_parts = array_slice(array('w1' => 0, 'w2' => 0, 'w3' => 0, 'w4' => 0, 'w5' => 0), 0, count($slices));
     $response = MpUtils::maptable2tree($data, array(array('name' => 'slices', 'key' => function ($r) use($model) {
         return $r[$model]['kombinacja_id'] . '-' . @$r[$model]['wojewodztwo_id'] . @$r[$model]['powiat_id'] . @$r[$model]['gmina_id'];
     }, 'content' => function ($r) use($model, $slice_parts, $units) {
         $legend = array('slice' => array_values(array_intersect_key($r[$model], $slice_parts)), 'units' => $units[$r[$model]['kombinacja_id']]);
         if (@$r[$model]['wojewodztwo_id']) {
             $legend['wojewodztwo_id'] = $r[$model]['wojewodztwo_id'];
         }
         if (@$r[$model]['powiat_id']) {
             $legend['powiat_id'] = $r[$model]['powiat_id'];
         }
         if (@$r[$model]['gmina_id']) {
             $legend['gmina_id'] = $r[$model]['gmina_id'];
         }
         return $legend;
     }), array('content' => function ($r) use($model) {
         return array('year' => intval($r[$model]['rocznik']), 'value' => $r[$model]['v']);
     })), 'series');
     if ($meta !== '0') {
         // include meta by default
         $response['meta'] = array('metric_id' => Dataobject::apiUrl($metric['dataset'], $metric['id']), 'metric_name' => $metric['data']['bdl_wskazniki.tytul'], 'metric_depth' => $metric_depths[$metric['data']['bdl_wskazniki.poziom_id']], 'metric_mpurl' => Dataobject::mpUrl($metric['dataset'], $metric['id']), 'group_name' => $metric['data']['bdl_wskazniki.grupa_tytul'], 'category_name' => $metric['data']['bdl_wskazniki.kategoria_tytul'], 'dimensions' => $dims);
     }
     if (empty($response)) {
         $response = new object();
     }
     $this->setSerialized('response', $response);
 }