/**
 * @param $dashboardId
 * @return array
 */
function gd_dashboard_admin_page_edit ( $dashboardId ) {
    $dashboardNode = gd_dashboard_load($dashboardId);
    if ( !$dashboardNode ) {
        return MENU_NOT_FOUND;
    }

    gd_datasource_set_active(get_node_field_value($dashboardNode,'field_dashboard_datasource'));

    if ( !gd_account_user_is_admin() && !gd_account_user_is_datasource_admin(null,gd_datasource_get_active()) ) {
        return MENU_ACCESS_DENIED;
    }

    drupal_add_library('gd_dashboard_admin', 'GD_Admin_DashboardSection_Builder');
    drupal_add_js(drupal_get_path('module','gd_dashboard_admin').'/js/builder/button/action/DashboardDeleteButton.js');

    drupal_add_library('gd','datatables');
    drupal_add_library('gd','highcharts');
    drupal_add_js('sites/all/libraries/sparkline/jquery.sparkline.min.js');

    $options = array('fields'=>array('filters','drilldowns','reports','css'));
    $dashboard = gd_dashboard_create_api_object_from_node($dashboardNode,$options);

    drupal_add_http_header('Cache-Control','no-cache, max-age=0, must-revalidate, no-store');

    return gd_dashboard_admin_page($dashboard);
}
    public function apply ( $patients ) {

        if ( !is_array($patients) ) {
            $patients = array($patients);
        }

        foreach ( $patients as $patient ) {
            \LogHelper::log_info('Applying ReportConfigRemoveColumnConfig treatment to: ' . $patient->reportNodeId);

            $node = node_load($patient->reportNodeId);

            $reportConfigText = get_node_field_value($node, 'field_report_conf', 0, 'value', FALSE);
            $reportConfig = isset($reportConfigText) ? json_decode($reportConfigText) : NULL;
            if (!isset($reportConfig)) {
                \LogHelper::log_info('Report configuration is EMPTY');
                return;
            }

            // check column configs
            if (!empty($reportConfig->columnConfigs)) {
                foreach ($reportConfig->columnConfigs as $key => $value) {
                    if (empty($value->columnId)) {
                        unset($reportConfig->columnConfigs[$key]);
                    }
                }

                $node->field_report_conf[$node->language][0]['value'] = json_encode($reportConfig);
                node_save($node);
            }
        }
    }
    public function apply ( $patients ) {

        if ( !is_array($patients) ) {
            $patients = array($patients);
        }

        foreach ( $patients as $patient ) {
            \LogHelper::log_info('Applying ReportConfigRemoveFilter treatment to: ' . $patient->reportNodeId);

            $node = node_load($patient->reportNodeId);

            $reportConfigText = get_node_field_value($node, 'field_report_conf', 0, 'value', FALSE);
            $reportConfig = isset($reportConfigText) ? json_decode($reportConfigText) : NULL;
            if (!isset($reportConfig)) {
                \LogHelper::log_info('Report configuration is EMPTY');
                return;
            }

            // check column configs
            if (!empty($reportConfig->model->filters)) {
                $preservedFilters = array();
                foreach ($reportConfig->model->filters as $key => $filter) {
                    if ( $patient->filter != $filter ) {
                        $preservedFilters[] = $filter;
                    }
                }
                $reportConfig->model->filters = $preservedFilters;

                $node->field_report_conf[$node->language][0]['value'] = json_encode($reportConfig);
                node_save($node);
            }
        }
    }
    public function apply ( $patients ) {
        if ( !is_array($patients) ) {
            $patients = array($patients);
        }

        foreach ( $patients as $patient ) {
            \LogHelper::log_info('Applying ReportRepairDataset treatment to: ' . $patient->reportNodeId);

            $reportNode = node_load($patient->reportNodeId);
            $reportConfigText = get_node_field_value($reportNode, 'field_report_conf', 0, 'value', FALSE);

            $reportConfig = isset($reportConfigText) ? json_decode($reportConfigText) : NULL;
            if (!isset($reportConfig)) {
                \LogHelper::log_info('Report configuration is EMPTY');
                continue;
            }

            // check columns
            if (!empty($reportConfig->model->datasets)) {
                $reportNode->field_report_dataset_sysnames[$reportNode->language] = array();
                foreach ($reportConfig->model->datasets as $datasetName) {
                    $reportNode->field_report_dataset_sysnames[$reportNode->language][] = array('value' => $datasetName);
                }
                node_save($reportNode);
            }

        }
    }
Ejemplo n.º 5
0
function get_node_field_object_value($node, $propertyName, $index = 0, $storageSuffixName = 'value', $required = FALSE)
{
    $value = get_node_field_value($node, $propertyName, $index, $storageSuffixName, $required);
    if (isset($value)) {
        $value = json_decode($value, FALSE);
    }
    return $value;
}
    private function scanReports () {
        $this->affected = array();

        $query = new \EntityFieldQuery();
        $query->entityCondition('entity_type', 'node');
        $query->propertyCondition('type', NODE_TYPE_REPORT);
        $query->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT');
        $result = $query->execute();
        $reportNids = isset($result['node']) ? array_keys($result['node']) : NULL;
        $reportNodes = node_load_multiple($reportNids);
        
        foreach ( $reportNodes as $node ) {
            $datasetName = get_node_field_value($node,'field_report_dataset_sysnames');
            if ( empty($datasetName) ) {
                $patient = array(
                    'info' => array(
                        'reportNodeId' => $node->nid,
                        'reportTitle' => $node->title,
                        'published' => $node->status,
                        'type' => $node->type,
                        'datasetName' => $datasetName
                    ),
                    'notes' => 'Dataset field is empty.'
                );

                $this->attachTreatment($patient);
                $this->affected[] = $patient;
                continue;
            }

            // lookup dataset
            $datasourceQuery = new \EntityFieldQuery();
            $datasourceQuery->entityCondition('entity_type', 'node');
            $datasourceQuery->propertyCondition('type', NODE_TYPE_DATASET);
            $datasourceQuery->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT');
            $datasourceQuery->fieldCondition('field_dataset_sysname', 'value', $datasetName);
            $datasourceQuery->fieldCondition('field_dataset_datasource', 'value', get_node_field_value($node,'field_report_datasource'));
            $datasourceEntities = $datasourceQuery->execute();
            $datasource_nids = isset($datasourceEntities['node']) ? array_keys($datasourceEntities['node']) : NULL;

            if (count($datasource_nids) != 1) {
                $patient = array(
                    'info' => array(
                        'reportNodeId' => $node->nid,
                        'reportTitle' => $node->title,
                        'published' => $node->status,
                        'type' => $node->type,
                        'datasetName' => $datasetName
                    ),
                    'notes' => 'Dataset does not exist.'
                );

                $this->attachTreatment($patient);
                $this->affected[] = $patient;
                continue;
            }
        }
    }
    public function getConfig($report) {
        $id = null;
        if ( !empty($report->nid) ) {
            $id = $report->nid;
        } else if ( !empty($report->id) ) {
            $id = $report->id;
        }

        if (isset($id) && isset(self::$configList[$id])) {
            return self::$configList[$id];
        } else {
            $conf = null;
            if ( !empty($report->nid) && !is_null($report->nid) ) {
                $config = json_decode(trim(get_node_field_value($report,'field_report_conf')), true);
                $conf = new GD_ReportConfig($config);
                $conf->setNode($report);
                $conf->setDescription(get_node_field_value($report,'field_report_desc'));
                $conf->setTitle($report->title);
            } else {
                if (is_array($report->config)) {
                    $config = $report->config;
                    $conf = new GD_ReportConfig($config);
                    if (!empty($report->style)) {
                        $conf->setStyle($report->style);
                    } else {
                        $conf->setStyle('');
                    }
                    if (isset($report->title)) {
                        $conf->setTitle($report->title);
                    }
                } else {
                    $config = json_decode(trim($report->config), true);
                    $conf = new GD_ReportConfig($config['config']);
                    if ( !empty($report->style) ) {
                        $conf->setStyle($report->style);
                    } else {
                        $conf->setStyle('');
                    }
                }
            }

            if (isset($id)) {
                $conf->setId($id);
                self::$configList[$id] = $conf;
            }
            return $conf;
        }
    }
    public function export(Export\ExportStream $stream, Export\ExportContext $context) {

        $metamodel = data_controller_get_metamodel();
        $datasetUuidMappings = array();

        // get datasets
        $datasetNids = array();
        foreach ($metamodel->datasets as $dataset) {
            $datasetUuidMappings[$dataset->source] = DatasetExportHelper::getExportDatasetName($dataset->name, $metamodel);
            if (!isset($dataset->nid)) {
                continue;
            }
            $datasetNids[] = $dataset->nid;
        }

        // find all references with above reference points
        $measures = array();
        if (!empty($datasetNids)) {
            $measureNodes = gd_measure_get_measures_4_dataset($datasetNids, LOAD_ENTITY);
            if (!empty($measureNodes)) {
                foreach ( $measureNodes as $measure ) {
                    $export = new stdClass();

                    $export->id = (int) $measure->nid;
                    $export->title = $measure->title;

                    $export->sysname = get_node_field_value($measure,'field_measure_sysname');
                    $export->description = get_node_field_value($measure,'field_measure_desc');

                    $dataset = node_load(get_node_field_value($measure, 'field_measure_dataset', 0, 'nid'));
                    $export->dataset = get_node_field_value($dataset, 'field_dataset_uuid');

                    $function = get_node_field_value($measure,'field_measure_function');

                    foreach($datasetUuidMappings as $source => $uuid) {
                        $function = str_replace($source, $uuid, $function);
                    }

                    $export->function = $function;

                    $measures[] = $export;
                }
            }
        }

        $stream->set('measures',$measures);
    }
    private function scanReportConfigs () {
        $this->affected = array();

        $query = new \EntityFieldQuery();
        $query->entityCondition('entity_type', 'node');
        $query->propertyCondition('type', NODE_TYPE_REPORT);
        $query->propertyCondition('status', NODE_PUBLISHED);
        $query->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT');
        $result = $query->execute();
        $reportNids = isset($result['node']) ? array_keys($result['node']) : NULL;
        $reportNodes = node_load_multiple($reportNids);
        
        foreach ( $reportNodes as $node ) {

            \LogHelper::log_info(t('Inspecting report @nid', array('@nid' => $node->nid)));

            $reportConfigText = get_node_field_value($node, 'field_report_conf', 0, 'value', FALSE);
            $reportConfig = isset($reportConfigText) ? json_decode($reportConfigText) : NULL;
            if (!isset($reportConfig)) {
                \LogHelper::log_info('Report configuration is EMPTY');
                continue;
            }

            // loop through filters
            if (!empty($reportConfig->model->filters)) {
                foreach ($reportConfig->model->filters as $key => $value) {
                    $result = $this->detectInvalidFilter($value);
                    if ($result) {
                        $patient = array(
                            'info' => array(
                                'reportNodeId' => $node->nid,
                                'reportTitle' => $node->title,
                                'filter' => $value,
                                'published' => $node->status,
                                'configPath' => 'model/filters'
                            ),
                            'notes' => $result
                        );
                        $this->attachTreatment($patient);
                        $this->affected[] = $patient;
                    }
                }
            }
        }
    }
    protected function getConstants(array $options) {
        $dashboards = gd_dashboard_findall_by_datasource(LOAD_ENTITY);
        $dashboardMetadata = array();
        foreach($dashboards as $dashboard) {
            $metadata = new stdClass();
            $metadata->name = $dashboard->title;
            $metadata->id = $dashboard->nid;
            $metadata->alias = get_node_field_value($dashboard,'field_dashboard_alias',0);
            $dashboardMetadata[] = $metadata;
        }

        $admin = !empty($options['admin']) ? 'true' : 'false';
        $public = !empty($options['public']) ? 'true' : 'false';

        return 'var ReportConstants = {};
                            ReportConstants.reportTitle = "' . $this->ReportConfig->title . '";
                            ReportConstants.reportId = ' . intval($this->ReportConfig->getId()) .';
                            ReportConstants.dashboards = ' . json_encode($dashboardMetadata) .';
                            ReportConstants.host = "' . GOVDASH_HOST .'";
                            ReportConstants.adminView = ' . $admin . ';
                            ReportConstants.publicView = ' . $public . ';';
    }
    public static function prepareDataSource(EnvironmentMetaModel $environment_metamodel, $datamartNode) {
        $datasource = new DataSourceMetaData();
        $datasource->name = self::prepareDataSourceName($datamartNode);
        $datasource->publicName = $datamartNode->title;
        $datasource->description = get_node_field_value($datamartNode, 'field_datamart_desc');

        $datasource->parentName = get_node_field_value($datamartNode, 'field_datamart_parent_sysname');
        $datasource->type = get_node_field_value($datamartNode, 'field_datamart_type');
        $datasource->readonly = get_node_field_boolean_value($datamartNode, 'field_datamart_readonly');

        $datasource->initializeFrom(get_node_field_object_value($datamartNode, 'field_datamart_options'));

        // datasource system properties
        $datasource->nid = $datamartNode->nid;

        // marking as public to prevent the property from being populated from parent data source (which can be private)
        $datasource->markAsPublic();

        $environment_metamodel->registerDataSource($datasource);

        return $datasource;
    }
    public function export(Export\ExportStream $stream, Export\ExportContext $context) {
        $metamodel = data_controller_get_metamodel();

        $reports = array();
        foreach (gd_report_findall_by_datasource(LOAD_ENTITY,$context->get('datasourceName')) as $report) {
            $export = new stdClass();

            $export->id = (int) $report->nid;
            $export->title = $report->title;

            $export->description = get_node_field_value($report,'field_report_desc',0,'value');
            $export->uuid = get_node_field_value($report,'field_report_uuid',0,'value',true);
            $export->config = json_decode(get_node_field_value($report,'field_report_conf',0,'value',true));
            $export->custom_view = get_node_field_value($report,'field_report_custom_view');
            $export->datasets = (array) get_node_field_value($report,'field_report_dataset_sysnames',null,'value',true);
            $export->tags = array();
            if (!empty($report->field_report_tags)) {
                foreach($report->field_report_tags[$report->language] as $tag) {
                    $export->tags[] = $tag['tid'];
                }
            }

            // replace dataset name with dataset uuid
            foreach ( $export->datasets as $key => $value ) {
                $dataset = $metamodel->getDataset($value);
                if (isset($dataset->uuid)) {
                    $export->datasets[$key] = $dataset->uuid;
                } else {
                    $export->datasets[$key] = NameSpaceHelper::removeNameSpace($dataset->name);
                }
            }

            // replace dataset name with dataset uuid
            $this->processConfig($export->config);

            $reports[] = $export;
        }
        $stream->set('reports',$reports);
    }
/**
 * @param $reportId
 * @return array
 * @throws Exception
 * @throws IllegalArgumentException
 */
function gd_report_admin_page_edit ( $reportId ) {
    $reportNode = gd_report_load($reportId);
    if ( !$reportNode ) {
        return MENU_NOT_FOUND;
    }

    gd_datasource_set_active(get_node_field_value($reportNode,'field_report_datasource'));

    if ( !gd_account_user_is_admin() && !gd_account_user_is_datasource_admin(null,gd_datasource_get_active()) ) {
        return MENU_ACCESS_DENIED;
    }

    drupal_add_library('gd_report_admin', 'GD_Admin_ReportSection_Builder');

    $options = array('fields' => array('datasource', 'config', 'filters', 'data', 'customview', 'tags'));
    $report = gd_report_create_api_object_from_node($reportNode,$options);

    $reportDataset = gd_data_controller_ui_metadata_get_dataset_ui_metadata($report->config->model->datasets[0],array_slice($report->config->model->datasets,1));

    drupal_add_http_header('Cache-Control','no-cache, max-age=0, must-revalidate, no-store');

    return gd_report_admin_page($report,$reportDataset);
}
function get_node_field_object_value($node, $fieldName, $index = 0, $storageSuffixName = 'value', $required = FALSE) {
    $value = get_node_field_value($node, $fieldName, $index, $storageSuffixName, $required);

    $result = NULL;
    if (is_array($value)) {
        $vs = array();
        foreach ($value as $i => $v) {
            $vs[$i] = validate_node_field_composite_value($node, $fieldName, $index, $v, FALSE);
        }
        $result = $vs;
    }
    elseif (isset($value)) {
        $result = validate_node_field_composite_value($node, $fieldName, $index, $value, FALSE);
    }

    return $result;
}
    private function attachTreatment ( &$diagnosis ) {
        $diagnosis['treatments'] = array();
        $diagnosis['treatments'][] = 'ReportConfigRemoveColumnLevel';

        $reportNode = node_load($diagnosis['info']['reportNodeId']);
        // lookup datasource
        $datasourceQuery = new \EntityFieldQuery();
        $datasourceQuery->entityCondition('entity_type', 'node');
        $datasourceQuery->propertyCondition('type', NODE_TYPE_DATAMART);
        $datasourceQuery->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT');
        $datasourceQuery->fieldCondition('field_datamart_sysname', 'value', get_node_field_value($reportNode, 'field_report_datasource', 0, 'value', FALSE));
        $datasourceEntities = $datasourceQuery->execute();
        $datasource_nids = isset($datasourceEntities['node']) ? array_keys($datasourceEntities['node']) : NULL;
        if (count($datasource_nids) != 1) {
            $diagnosis['treatments'][] = 'ReportDelete';
            $diagnosis['notes'] .= ' Datasource could not be found.';
        } else {
            $datamartNode = node_load($datasource_nids[0]);
            if ( $datamartNode->status == NODE_PUBLISHED ) {
                $diagnosis['notes'] .= ' Datasource is published.';
            } else {
                $diagnosis['treatments'][] = 'ReportDelete';
                $diagnosis['notes'] .= ' Datasource is not published.';
            }

        }


    }
    protected function processConfig ( $export ) {
        $metamodel = data_controller_get_metamodel();

        // replace report nid with report uuid
        foreach ( $export->config->items as $key => $item ) {
            if ( $item->type == 'report' ) {
                $reportNode = node_load($item->content);
                $export->config->items[$key]->content = get_node_field_value($reportNode,'field_report_uuid',0,'value',true);
            }
        }

        // array cast to deal with json decoder creating objects for arrays with missing keys
        $export->config->drilldowns = (array) $export->config->drilldowns;

        // replace report nid with report uuid
        // replace dashboard nid with dashboard uuid
        // replace dataset column reference with dataset uuid
        $updated_drilldowns = array();
        foreach ( $export->config->drilldowns as $drilldown ) {

            $reportNode = gd_report_get_by_nid($drilldown->report);
            $dashboardNode = gd_dashboard_get_by_nid($drilldown->dashboard);

            if ( !$reportNode || !$dashboardNode ) {
                $message = t('Skipping corrupt drilldown for node: @nodeId.',array('@nodeId' => $export->id));
                drupal_set_message($message, 'warning');
                LogHelper::log_warn($message);
            } else {
                $updated_drilldown = $drilldown;
                $updated_drilldown->report = get_node_field_value($reportNode,'field_report_uuid',0,'value',true);
                $updated_drilldown->column = DatasetExportHelper::getExportColumnName($drilldown->column,$metamodel);
                $updated_drilldown->dashboard = get_node_field_value($dashboardNode,'field_dashboard_uuid',0,'value',true);
                $updated_drilldown->id = count($updated_drilldowns);
                $updated_drilldowns[] = $updated_drilldown;
            }
        }

        $export->config->drilldowns = $updated_drilldowns;
    }
    protected function findExistingMeasure ( $measureSysname ) {

        $metamodel = data_controller_get_metamodel();

        // get datasets
        $datasetNids = array();
        foreach ($metamodel->datasets as $dataset) {
            if (!isset($dataset->nid)) {
                continue;
            }
            $datasetNids[] = $dataset->nid;
        }

        $measureNodes = (array) gd_measure_get_measures_4_dataset($datasetNids, LOAD_ENTITY);

        $matchedMeasure = null;
        foreach ( $measureNodes as $measureNode ) {
            if (get_node_field_value($measureNode, 'field_measure_sysname') == $measureSysname) {
                $matchedMeasure = $measureNode;
                break;
            }
        }

        return $matchedMeasure;
    }
function gd_sync_admin_datamart_form ( $form, &$form_state ) {
    // Enable language column if translation module is enabled or if we have any
    // node with language.
    $multilanguage = (module_exists('translation') || db_query_range("SELECT 1 FROM {node} WHERE language <> :language", 0, 1, array(':language' => LANGUAGE_NONE))->fetchField());

    // Build the sortable table header.
    $header = array(
        'title' => array('data' => t('Title'), 'field' => 'n.title'),
        'author' => t('Author'),
        'changed' => array('data' => t('Updated'), 'field' => 'n.changed', 'sort' => 'desc'),
        'datasets' => t('Datasets'),
        'reports' => t('Reports'),
        'dashboards' => t('Dashboards')
    );
    if ($multilanguage) {
        $header['language'] = array('data' => t('Language'), 'field' => 'n.language');
    }
    $header['operations'] = array('data' => t('Operations'));

    $nodes = gd_datamart_get_datamarts(LOAD_ENTITY);

    // Prepare the list of nodes.
    $languages = language_list();
    $destination = drupal_get_destination();
    $options = array();
    foreach ($nodes as $node) {
        $langcode = entity_language('node', $node);
        $l_options = $langcode != LANGUAGE_NONE && isset($languages[$langcode]) ? array('language' => $languages[$langcode]) : array();
        $options[$node->nid] = array(
            'title' => array(
                'data' => array(
                    '#type' => 'link',
                    '#title' => $node->title,
                    '#href' => 'admin/structure/govdashboard/sync/datamart/' . $node->nid,
                    '#options' => $l_options,
                    '#suffix' => ' ' . theme('mark', array('type' => node_mark($node->nid, $node->changed))),
                ),
            ),
            'author' => theme('username', array('account' => $node)),
            'changed' => format_date($node->changed, 'short'),
            'datasets' => count(gd_dataset_findall_by_datasource(!LOAD_ENTITY,get_node_field_value($node,'field_datamart_sysname'))),
            'reports' => count(gd_report_findall_by_datasource(!LOAD_ENTITY,get_node_field_value($node,'field_datamart_sysname'))),
            'dashboards' => count(gd_dashboard_findall_by_datasource(!LOAD_ENTITY,get_node_field_value($node,'field_datamart_sysname')))
        );
        if ($multilanguage) {
            if ($langcode == LANGUAGE_NONE || isset($languages[$langcode])) {
                $options[$node->nid]['language'] = $langcode == LANGUAGE_NONE ? t('Language neutral') : t($languages[$langcode]->name);
            }
            else {
                $options[$node->nid]['language'] = t('Undefined language (@langcode)', array('@langcode' => $langcode));
            }
        }
        // Build a list of all the accessible operations for the current node.
        $operations = array();
        if (node_access('update', $node)) {
            $operations['edit'] = array(
                'title' => t('edit'),
                'href' => 'node/' . $node->nid . '/edit',
                'query' => $destination,
            );
        }
        $options[$node->nid]['operations'] = array();
        if (count($operations) > 1) {
            // Render an unordered list of operations links.
            $options[$node->nid]['operations'] = array(
                'data' => array(
                    '#theme' => 'links__node_operations',
                    '#links' => $operations,
                    '#attributes' => array('class' => array('links', 'inline')),
                ),
            );
        }
        elseif (!empty($operations)) {
            // Render the first and only operation as a link.
            $link = reset($operations);
            $options[$node->nid]['operations'] = array(
                'data' => array(
                    '#type' => 'link',
                    '#title' => $link['title'],
                    '#href' => $link['href'],
                    '#options' => array('query' => $link['query']),
                ),
            );
        }
    }

    $form['nodes'] = array(
        '#type' => 'tableselect',
        '#header' => $header,
        '#options' => $options,
        '#empty' => t('No content available.'),
    );

    return $form;
}
    public static function prepareReference(MetaModel $metamodel, $referenceNode, array $referencePointNodes = NULL) {
        $referencePoints = $lookupReferencePoints = $interlookupReferences = NULL;

        // loading reference points
        $referencePointIndex = 0;
        while (TRUE) {
            $point_nid = get_node_field_int_value($referenceNode, 'field_reference_point', $referencePointIndex, 'nid');
            if (!isset($point_nid)) {
                break;
            }

            $referencePointNode = $referencePointNodes[$point_nid];

            $datasetName = get_node_field_value($referencePointNode, 'field_ref_point_dataset_sysname', 0, 'value', TRUE);
            $dataset = $metamodel->findDataset($datasetName);
            if (isset($dataset)) {
                $referencePoint = new DatasetReferencePoint();
                $lookupReferencePoint = new DatasetReferencePoint();

                $loader = MetaModelFactory::getInstance()->getLoader($dataset->loaderName);

                $cube = $metamodel->getCube($dataset->name);
                $referenceDatasetName = $cube->factsDatasetName;

                // preparing list of columns
                $referencePointColumnIndex = 0;
                while (TRUE) {
                    $columnName = get_node_field_value($referencePointNode, 'field_ref_point_column_sysname', $referencePointColumnIndex);
                    if (isset($columnName) || ($referencePointColumnIndex === 0)) {
                        $referencePointColumn = $referencePoint->initiateColumn();
                        $referencePointColumn->datasetName = $referenceDatasetName;
                        $referencePoint->registerColumnInstance($referencePointColumn);
                        if (isset($columnName)) {
                            $referencePointColumn->columnName = $columnName;
                        }

                        $interlookupLookupReferencePointColumn = $lookupReferencePoint->initiateColumn();
                        $interlookupLookupReferencePointColumn->datasetName = $referenceDatasetName;
                        $interlookupLookupReferencePointColumn->columnName = $referencePointColumn->columnName;
                        ReferenceMetaModelLoaderHelper::adjustReferencePointColumn($loader, $metamodel, $interlookupLookupReferencePointColumn);
                        if (!$interlookupLookupReferencePointColumn->isShared()) {
                            $interlookupReferences[$referencePointColumnIndex][$referencePointIndex] = $interlookupLookupReferencePointColumn;
                        }

                        $lookupReferencePointColumn = clone $interlookupLookupReferencePointColumn;
                        $lookupReferencePointColumn->columnName = NULL;
                        $lookupReferencePoint->registerColumnInstance($lookupReferencePointColumn);
                    }
                    if (!isset($columnName)) {
                        break;
                    }

                    $referencePointColumnIndex++;
                }

                $referencePoints[$referencePointIndex] = $referencePoint;
                $lookupReferencePoints[$referencePointIndex] = $lookupReferencePoint;
            }

            $referencePointIndex++;
        }

        $referencePointCount = count($referencePoints);
        if ($referencePointCount == 0) {
            return;
        }

        // checking if we need to add references between lookup reference point columns (second reference point in each reference)
        if (isset($interlookupReferences)) {
            // creating separate references for each reference point
            foreach ($referencePoints as $referencePointIndex => $referencePoint) {
                $lookupReferencePoint = $lookupReferencePoints[$referencePointIndex];

                $reference = new DatasetReference();
                $reference->name = get_node_field_value($referenceNode, 'field_reference_sysname', 0, 'value', TRUE) . '_rp' . $referencePointIndex;

                $reference->registerPointInstance($referencePoint);
                $reference->registerPointInstance($lookupReferencePoint);
                $metamodel->registerReference($reference);
            }

            // linking lookup reference point columns
            foreach ($interlookupReferences as $columnIndex => $interlookupReferencePointColumns) {
                if (count($interlookupReferencePointColumns) < $referencePointCount) {
                    throw new UnsupportedOperationException(t('All reference point columns with the same reference point column index have to be non-shared'));
                }

                $interLookupReferenceName = get_node_field_value($referenceNode, 'field_reference_sysname', 0, 'value', TRUE) . '_rpci' . $columnIndex;
                foreach ($interlookupReferencePointColumns as $interlookupReferencePointColumn) {
                    $metamodel->registerSimpleReferencePoint(
                        $interLookupReferenceName,
                        $interlookupReferencePointColumn->datasetName, $interlookupReferencePointColumn->columnName);
                }
            }
        }
        else {
            // checking that all lookup reference points are the same
            $masterLookupReferencePoint = NULL;
            foreach ($lookupReferencePoints as $lookupReferencePoint) {
                if (isset($masterLookupReferencePoint)) {
                    if (!$masterLookupReferencePoint->equals($lookupReferencePoint)) {
                        throw new UnsupportedOperationException(t('Unlinkable lookup reference points are not the same'));
                    }
                }
                else {
                    $masterLookupReferencePoint = $lookupReferencePoint;
                }
            }

            // combining all reference points into one reference
            $reference = new DatasetReference();
            $reference->name = get_node_field_value($referenceNode, 'field_reference_sysname', 0, 'value', TRUE);
            foreach ($referencePoints as $referencePointIndex => $referencePoint) {
                $lookupReferencePoint = $lookupReferencePoints[$referencePointIndex];

                $reference->registerPointInstance($referencePoint);
                $reference->registerPointInstance($lookupReferencePoint);
            }
            $metamodel->registerReference($reference);
        }
    }
/**
 * @param $dashboardNode
 * @return array
 */
function gd_dashboard_build_page ( $dashboardNode ) {
    $event = new DefaultEvent();
    gd_datasource_set_active(get_node_field_value($dashboardNode,'field_dashboard_datasource'));

    ob_start();

    /**
     * Build current dashboard config
     */
    $DashboardConfig = new GD_DashboardConfig($dashboardNode,$_GET);
    drupal_add_library('gd_dashboard', 'GD_Dashboard_View');

    print '<div id="dashboard-view" class="gd-container">';


    // dashboard view
    echo '<div class="row">';

    echo '  <div class="col-md-6">';
    echo '    <h2>'.$dashboardNode->title.'</h2>';
    if ( get_node_field_value($dashboardNode, 'field_dashboard_desc') ) {
        echo '<p>'.get_node_field_value($dashboardNode, 'field_dashboard_desc').'</p>';
    }
    echo '  </div>';
    echo '  <div class="col-md-6">';

    echo '<div class="pull-right">';
    // is not public
    if ( arg(0) != 'public' ) {
        $edit = false;
        if ( gd_account_user_is_admin() || gd_account_user_is_datasource_admin(null,$DashboardConfig->getDatasource()) ) {
            $edit = true;
        }

        if ($edit) {
            echo '<a role="button" type="button" id="editButton" tabindex="100" class="btn btn-default gd-dashboard-editbtn" href="/cp/dashboard/'.$dashboardNode->nid.'">Edit</a>';
        }
    }

    if ( gd_dashboard_get_setting('export') && $DashboardConfig->isExportable() ) {
        echo ' <button role="button" type="button" id="exportButton" tabindex="100" class="btn btn-default gd-dashboard-exportbtn" data-dashboard="'.$dashboardNode->nid.'">Export</button>';
    }
    echo '</div>';

    echo '  </div>';
    echo '</div>';

    $options = array();
    if ( $DashboardConfig->isPublic() && arg(0) == 'public' ) {
        $options['public'] = TRUE;
        drupal_add_http_header('Cache-Control','no-transform,public,max-age=3600,s-maxage=3600');
        drupal_add_http_header('Expires',gmdate('D, d M Y H:i:s \G\M\T', time() + 3600));
    }
    $configView = new GD_DashboardView($DashboardConfig);
    print $configView->getView($options);

    print '</div>';

    $DashboardConfig->attachRequiredLibs(); // must be called after building view, or libs won't be set yet

    $page = array(
        '#show_messages' => false,
        '#theme' => 'page',
        '#type' => 'page',
        'content' => array(
            'system_main' => array(
                '#markup' => ob_get_clean()
            )
        ),
        'post_header' => array(
            '#markup' => ''
        ),
        'pre_content' => array(
            '#markup' => ''
        )
    );

    if (isset($dashboardNode->nid)) {
        $event->type = 1; // see gd_health_monitoring_database_install() for more details
        $event->owner = $dashboardNode->nid;

        EventRecorderFactory::getInstance()->record($event);
    }

    return $page;
}
    public function export(Export\ExportStream $stream, Export\ExportContext $context) {
        $datasource = gd_datasource_get_active();
        $readOnly = gd_datasource_is_property($datasource, 'readonly');
        if ($readOnly) {
            return;
        }

        $metamodel = data_controller_get_metamodel();

        // get reference points that have ref to the dataset in this datamart
        $datasetNames = array();
        foreach ( $stream->get('datasets') as $d ) {
            $datasetNames[] = $d->name;
        }

        $referencePoints = array();
        $referencePointNodes = gd_reference_get_reference_points_by_dataset($datasetNames, LOAD_ENTITY);
        $referencePointNids = array();
        foreach ( $referencePointNodes as $ref_point ) {
            $export = new stdClass();

            $export->id = (int) $ref_point->nid;
            $export->title = $ref_point->title;

            $dataset = $metamodel->getDataset(get_node_field_value($ref_point,'field_ref_point_dataset_sysname',0,'value',true));
            $export->dataset = $dataset->uuid;

            $export->columns = array();
            foreach ( (array) get_node_field_value($ref_point,'field_ref_point_column_sysname',null) as $column ) {
                $export->columns[] = $column;
            }

            $referencePoints[] = $export;
            $referencePointNids[] = (int) $ref_point->nid;
        }

        // find all references with above reference points
        $references = array();
        $referenceNodes = gd_reference_get_references_by_reference_points($referencePointNids, LOAD_ENTITY);
        foreach ( $referenceNodes as $reference ) {
            $export = new stdClass();

            $export->id = (int) $reference->nid;
            $export->title = $reference->title;

            $export->sysname = get_node_field_value($reference,'field_reference_sysname');

            foreach ( (array) get_node_field_node_ref($reference,'field_reference_point',null) as $referencePointNid ) {
                foreach ( $referencePoints as $referencePoint ){
                    if ( $referencePointNid == $referencePoint->id ) {
                        $export->referencePoints[] = $referencePoint;
                    }
                }
            }

            if ( empty($export->referencePoints) ) {
                throw new Exception('Reference missing reference points.');
            }

            $references[] = $export;
        }

        $stream->set('references',$references);
    }
 public function getDatasource () {
     if ( $this->reportNode ) {
         return get_node_field_value($this->reportNode,'field_report_datasource');
     }
     return null;
 }
    private function scanReportConfigs () {
        $this->affected = array();

        $query = new \EntityFieldQuery();
        $query->entityCondition('entity_type', 'node');
        $query->propertyCondition('type', NODE_TYPE_REPORT);
        $query->propertyCondition('status', NODE_PUBLISHED);
        $query->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT');
        $result = $query->execute();
        $reportNids = isset($result['node']) ? array_keys($result['node']) : NULL;
        $reportNodes = node_load_multiple($reportNids);
        
        foreach ( $reportNodes as $node ) {

            \LogHelper::log_info(t('Inspecting report @nid', array('@nid' => $node->nid)));

            $reportConfigText = get_node_field_value($node, 'field_report_conf', 0, 'value', FALSE);
            $reportConfig = isset($reportConfigText) ? json_decode($reportConfigText) : NULL;
            if (!isset($reportConfig)) {
                \LogHelper::log_info('Report configuration is EMPTY');
                continue;
            }

            // check columns
            if (!empty($reportConfig->model->columns)) {
                foreach ($reportConfig->model->columns as $old) {
                    if (!isset($old)) {
                        continue;
                    }
                    \LogHelper::log_debug(t('Inspecting report model column @old', array('@old' => $old)));
                    $result = $this->detectEmptyColumn($old);
                    if ($result) {
                        $patient = array(
                            'info' => array(
                                'reportNodeId' => $node->nid,
                                'reportTitle' => $node->title,
                                'columnName' => $old,
                                'published' => $node->status,
                                'configPath' => 'model/columns'
                            ),
                            'notes' => $result
                        );
                        $this->attachTreatment($patient);
                        $this->affected[] = $patient;
                    }
                }
            }

            // check column configs
            if (!empty($reportConfig->columnConfigs)) {
                foreach ($reportConfig->columnConfigs as $key => $value) {
                    $old = $value->columnId;
                     \LogHelper::log_debug(t('Inspecting report column config @old', array('@old' => $old)));
                    $result = $this->detectEmptyColumn($old);
                    if ($result) {
                        $patient = array(
                            'info' => array(
                                'reportNodeId' => $node->nid,
                                'reportTitle' => $node->title,
                                'columnName' => $old,
                                'published' => $node->status,
                                'configPath' => 'columnConfigs'
                            ),
                            'notes' => $result
                        );
                        $this->attachTreatment($patient);
                        $this->affected[] = $patient;
                    }
                }
            }

            // check column orders
            if (!empty($reportConfig->model->columnOrder)) {
                foreach ($reportConfig->model->columnOrder as $old) {
                    if (isset($old)) {
                         \LogHelper::log_debug(t('Inspecting report column sequence config @old', array('@old' => $old)));
                        $result = $this->detectEmptyColumn($old);
                        if ($result) {
                            $patient = array(
                                'info' => array(
                                    'reportNodeId' => $node->nid,
                                    'reportTitle' => $node->title,
                                    'columnName' => $old,
                                    'published' => $node->status,
                                    'configPath' => 'model/columnOrder'
                                ),
                                'notes' => $result
                            );
                            $this->attachTreatment($patient);
                            $this->affected[] = $patient;
                        }
                    }
                }
            }

            // check column sorts
            if (!empty($reportConfig->model->orderBy)) {
                foreach ($reportConfig->model->orderBy as $key => $value) {
                    $old = $value->column;
                     \LogHelper::log_debug(t('Inspecting report data sorting column @old', array('@old' => $old)));
                    $result = $this->detectEmptyColumn($old);
                    if ($result) {
                        $patient = array(
                            'info' => array(
                                'reportNodeId' => $node->nid,
                                'reportTitle' => $node->title,
                                'columnName' => $old,
                                'published' => $node->status,
                                'configPath' => 'model/orderBy'
                            ),
                            'notes' => $result
                        );
                        $this->attachTreatment($patient);
                        $this->affected[] = $patient;
                    }
                }
            }

            // check visual series
            if (!empty($reportConfig->visual->series)) {
                foreach ($reportConfig->visual->series as $old => $value) {
                     \LogHelper::log_debug(t('Inspecting report visual series column @old', array('@old' => $old)));
                    $result = $this->detectEmptyColumn($old);
                    if ($result) {
                        $patient = array(
                            'info' => array(
                                'reportNodeId' => $node->nid,
                                'reportTitle' => $node->title,
                                'columnName' => $old,
                                'published' => $node->status,
                                'configPath' => 'visual/series'
                            ),
                            'notes' => $result
                        );
                        $this->attachTreatment($patient);
                        $this->affected[] = $patient;
                    }
                }
            }

            // check traffic column
            if (!empty($reportConfig->visual->trafficColumn)) {
                $old = $reportConfig->visual->trafficColumn;
                 \LogHelper::log_debug(t('Inspecting report visual traffic column @old', array('@old' => $old)));
                $result = $this->detectEmptyColumn($old);
                if ($result) {
                    $patient = array(
                        'info' => array(
                            'reportNodeId' => $node->nid,
                            'reportTitle' => $node->title,
                            'columnName' => $old,
                            'published' => $node->status,
                            'configPath' => 'visual/trafficColumn'
                        ),
                        'notes' => $result
                    );
                    $this->attachTreatment($patient);
                    $this->affected[] = $patient;
                }
            }

            // check traffic columns (v2)
            if (!empty($reportConfig->visual->traffic)) {
                foreach ($reportConfig->visual->traffic as $key => $value) {
                    $old = $value->trafficColumn;
                    $result = $this->detectEmptyColumn($old);
                    if ($result) {
                        $patient = array(
                            'info' => array(
                                'reportNodeId' => $node->nid,
                                'reportTitle' => $node->title,
                                'columnName' => $old,
                                'published' => $node->status,
                                'configPath' => 'visual/traffic'
                            ),
                            'notes' => $result
                        );
                        $this->attachTreatment($patient);
                        $this->affected[] = $patient;
                    }
                }
            }

            // update filters
            if (!empty($reportConfig->model->filters)) {
                foreach ($reportConfig->model->filters as $key => $value) {
                    $old = $value->column;
                    $result = $this->detectEmptyColumn($old);
                    if ($result) {
                        $patient = array(
                            'info' => array(
                                'reportNodeId' => $node->nid,
                                'reportTitle' => $node->title,
                                'columnName' => $old,
                                'published' => $node->status,
                                'configPath' => 'model/filters'
                            ),
                            'notes' => $result
                        );
                        $this->attachTreatment($patient);
                        $this->affected[] = $patient;
                    }
                }
            }

            // update color column
            if (!empty($reportConfig->visual->useColumnDataForColor)) {
                $old = $reportConfig->visual->useColumnDataForColor;
                $result = $this->detectEmptyColumn($old);
                if ($result) {
                    $patient = array(
                        'info' => array(
                            'reportNodeId' => $node->nid,
                            'reportTitle' => $node->title,
                            'columnName' => $old,
                            'published' => $node->status,
                            'configPath' => 'visual/useColumnDataForColor'
                        ),
                        'notes' => $result
                    );
                    $this->attachTreatment($patient);
                    $this->affected[] = $patient;
                }
            }
        }
    }
    protected function getDataTableScript( $tableId, $scrollHeight, $tableSummary = '', $admin = TRUE, $public = FALSE, $external = FALSE, $sorting = null ) {
        $datasourceName = $this->ReportConfig->getNode() != null ? get_node_field_value($this->ReportConfig->getNode(), 'field_report_datasource') : null;
        if (!isset($datasourceName)) {
            $datasourceName = gd_datasource_get_active();
        }
        //  We can't use repeating background images because IE 9 does not reliably print them
        $overlay = gd_datasource_is_property($datasourceName, 'draft') ?
            '$("#' . $tableId . '").dataTable().fnSettings().aoDrawCallback.push({
                "fn": function () {
                    if ($("#' . $tableId . '").width() > $("#' . $tableId . '_wrapper > .table-content").width()) {
                        $("#report-'.intval($this->ReportConfig->getId()).'-overlay").height($("#' . $tableId . '_wrapper > .table-content").height() - 14);
                    }
                    if ($("#' . $tableId . '").height() > $("#' . $tableId . '_wrapper > .table-content").height()) {
                        $("#report-'.intval($this->ReportConfig->getId()).'-overlay").width($("#' . $tableId . '_wrapper > .table-content").width() - 14);
                    }

                    //  Table is taller than the actual image forcing us to manually repeat the image
                    if ($("#' . $tableId . '_wrapper > .table-content").height() > 1008) {
                        var diff = $("#' . $tableId . '").height() - 1008;
                        var num = Math.ceil(diff/1008);
                        for (var i = 1; i <= num; i++) {
                            $("#' . $tableId . '_wrapper").append($(\'<img alt="Draft Overlay" title="Draft Overlay" aria-label="Draft Overlay" class="report-draft-overlay" src="/sites/all/modules/custom/report/includes/images/draft.png"/>\').css("top", (1008 * i) + "px"));
                        }
                    } else if ($("#' . $tableId . '_wrapper > .table-content").width() > 1080) {
                        var diff = $("#' . $tableId . '").width() - 1008;
                        var num = Math.ceil(diff/1008);
                        for (var i = 1; i <= num; i++) {
                            $("#' . $tableId . '_wrapper").append($(\'<img alt="Draft Overlay" title="Draft Overlay" aria-label="Draft Overlay" class="report-draft-overlay" src="/sites/all/modules/custom/report/includes/images/draft.png"/>\').css("left", (1008 * i) + "px"));
                        }
                    }
                }
           });
           $("#' . $tableId . '_wrapper").append(\'<img alt="Draft Overlay" title="Draft Overlay" aria-label="Draft Overlay" id="report-'.intval($this->ReportConfig->getId()).'-overlay" class="report-draft-overlay" src="/sites/all/modules/custom/report/includes/images/draft.png"/>\');
           $("#report-'.intval($this->ReportConfig->getId()).'-overlay").bind("mouseenter mouseleave click dblclick focusout hover mousedown mousemove mouseout mouseover mouseup", function (e) {
                if (navigator.appName == "Microsoft Internet Explorer") {
                    jQuery("#report-'.intval($this->ReportConfig->getId()).'-overlay").hide();
                    var target = document.elementFromPoint(e.clientX, e.clientY);
                    if (jQuery(target).is("a") && jQuery(target).attr("href") != "#" && e.type == "click") {
                        window.location = jQuery(target).attr("href");
                    }
                    jQuery(target).trigger(e.type);
                    jQuery("#report-'.intval($this->ReportConfig->getId()).'-overlay").show();
                }
           });' : '';

        /*
         * TODO Move to actual JS file
         * For right now this has to kept in PHP due to how report render is done.
         * The JS below needs report configuration data (tableID, scrollHeight, etc.) for the table;
         *  which means that to move this to a separate JS file, we need to send back
         *  the raw table HTML + the configuration information that the JS needs, which
         *  isn't done right now.
         */
        $dataTableScript =
            '<script type="text/javascript">
                (function (global) {
                !function($,undefined) {
                    var func = function() {
                        $("#report-' . intval($this->ReportConfig->getId()) . '").on("ready.report.render", function() {
                            if ($.fn.DataTable.isDataTable("#' . $tableId . '"))' . (!$admin ? ('return;') : '$("#' . $tableId . '").dataTable().fnDestroy();') . '
                            var ROWS_PER_PAGE = ' . (GD_TABLE_ROWS_PER_PAGE) . ';

                            var dashboardId = $("#dash_viewer").attr("dashboard_id");
                            //$.fn.dataTableExt.sErrMode = "throw";
                            var sortable = [];
                            var sortableColumns = [];

                            $("#' . $tableId . '").find("th").each(function () {
                                if ( $(this).attr("column-name").indexOf("measure") != -1 ) {
                                    sortableColumns[$(this).attr("column-index")] = true;
                                } else if ( $(this).attr("column-name").indexOf("column") != -1 ) {
                                    sortableColumns[$(this).attr("column-index")] = false;
                                } else {
                                    sortableColumns[$(this).attr("column-index")] = null;
                                }
                            });

                            var disableMeasures = $.inArray(true, sortableColumns) != -1 && $.inArray(false, sortableColumns) != -1;
                            if ( disableMeasures ) {
                                $.each(sortableColumns, function (i, v) {
                                    if ( v === true ) {
                                        sortable.push( {"bSortable": false} );
                                    } else {
                                        sortable.push(null);
                                    }
                                });
                            } else {
                                $.each(sortableColumns, function (i, v) {
                                    sortable.push(null);
                                });
                            }
                            $("#' . $tableId . '").dataTable({
                                "sDom": \'<"clear-table clearfix"i><"table-content"rt><"table-paging clearfix"p>\',
                                "bServerSide": true,
                                "bProcessing": true,
                                "aoColumns": sortable,
                                ' . (isset($sorting) ? '"aaSorting": ' . $sorting . ',' : '') . '
                                "iDisplayLength": ROWS_PER_PAGE,
                                "oLanguage": {
                                    "sInfo": "Showing _START_ to _END_ of _TOTAL_ records",
                                    "sProcessing": "<div class=\"ldng datatableProcessing\"></div>"
                                },
                                "fnServerData": function  ( sSource, aoData, fnCallback, oSettings ) {
                                    var page = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength);
                                    var orderBys = [];
                                    $.each(oSettings.aaSorting, function(i, sorting) {
                                        var sortedColumn = sorting[0];
                                        var columnName = $("#' . $tableId . ' > thead > tr > th[column-index=" + sortedColumn + "]").attr("sort-column");
                                        orderBys.push({ "column": columnName, "order": sorting[1] });
                                    });
                                    oSettings.jqXHR = $.ajax({
                                        "dataType": ' . ($external ? '"jsonp"' : '"json"') . ',
                                        "type": "' . ($admin ? "POST" : "GET") . '",
                                        "url": "' . ($this->getCallbackUrl($admin, $public, $external)) . '",
                                        "data": {
                                            ' . $this->getServerArgs($admin) . ',
                                            "orderBy": orderBys,
                                            "offset": page * ROWS_PER_PAGE,
                                            "limit": ROWS_PER_PAGE
                                        },
                                        "beforeSend": function(xhr, settings) {
                                            xhr.setRequestHeader("X-CSRF-Token",((typeof GovDashboard !== "undefined")? GovDashboard.token : GD.options.csrf));
                                        },
                                        "success": function (data) {
                                            if ($("#' . $tableId . '").length) {
                                                var json = {};
                                                if (data["code"] == null || data["code"] == 200) {
                                                    $.each(aoData, function (i, o) {
                                                        if ( o["name"] == "sEcho" ) {
                                                            json.sEcho = o["value"];
                                                            return false;
                                                        }
                                                    });
                                                    json.iTotalDisplayRecords = data["response"]["totalRows"];
                                                    json.iTotalRecords = data["response"]["totalRows"];
                                                    json.aaData = [];

                                                    var columns = [];
                                                    for ( var i = 0; i < oSettings.aoColumns.length; i++ ) {
                                                        columns.push($("#' . $tableId . ' > thead > tr > th[column-index=\'" + i + "\']").attr("column-name"));
                                                    }

                                                    $.each(data["response"]["data"], function (i, r) {
                                                        var row = r["record"];
                                                        var obj = [];
                                                        $.each(columns, function (i, c) {
                                                            obj.push(row[c]);
                                                        });
                                                        json.aaData.push(obj);
                                                    });

                                                    $("#' . $tableId . '_wrapper").find("th").attr("title", function () {
                                                        return "Click to sort column";
                                                    });

                                                    if (data["response"]["totalRows"] > json.aaData.length) {
                                                        var height = $("#' . $tableId . '_wrapper > div.table-content").css("height");
                                                        $("#' . $tableId . '_wrapper > div.table-content").css("height", ' . $scrollHeight . ' - 45 - $("#gd-report-footer-' . intval($this->ReportConfig->getId()) . '").height());
                                                        $("#' . $tableId . '_wrapper").find("div.dataTables_paginate").css("line-height", 0);
                                                        $("#' . $tableId . '_wrapper > div.table-paging").find("a").attr("tabindex", "3000");
                                                    } else {
                                                        $("#' . $tableId . '_wrapper > div.table-content").css("height", ' . $scrollHeight . ' - $("#gd-report-footer-' . intval($this->ReportConfig->getId()) . '").height());
                                                        $("#' . $tableId . '_wrapper > div.table-paging").hide();
                                                    }
                                                    $("#' . $tableId . '_wrapper > div.table-content").find("thead").addClass("gd-table-header");
                                                    $("#' . $tableId . '_wrapper > div.table-content").find("th").attr("scope", "col");
                                                    $("#' . $tableId . '_wrapper > div.table-content").find("th").attr("tabindex", "3000");
                                                    $("#' . $tableId . '_wrapper > div.table-content").find("tbody").removeAttr("role");
                                                    $("#' . $tableId . '_wrapper > div.table-content").find("tbody").removeAttr("aria-live");
                                                    $("#' . $tableId . '_wrapper > div.table-content").find("tbody").removeAttr("aria-relevant");
                                                    ' . ((!isset($this->ReportConfig->options['visual']['advTableDisplayHeader'])) || $this->ReportConfig->options['visual']['advTableDisplayHeader'] === TRUE ? '' : '$("#' . $tableId . '_wrapper > div.table-content").find("thead").hide();') . '
                                                    fnCallback(json);
                                                    $("#' . $tableId . '_wrapper > div.table-content").find("th").attr("title", function() { return $(this).attr("column-title") + ": activate to sort column " + ($(this).hasClass("sorting_desc") ? "descending" : "ascending"); });
                                                    $("#' . $tableId . '_wrapper > div.table-paging").find("li.paginate_button, a").attr("tabindex", "3000");

                                                    //$("div.dataTables_info").show();
                                                } else if(data["code"] == 500) {
                                                    $("#' . $tableId . '").dataTable().fnSettings().oLanguage.sEmptyTable = "There was an error retrieving table data. Please contact the site administrator.";
                                                    $("#' . $tableId . '").dataTable().fnDraw();
                                                }
                                            }
                                        }
                                    }).fail(function (jqXHR, textStatus, errorThrown) {
                                        ' . ($admin ? $this->getAdminError() : '') . '
                                    });
                                }
                            });

                            $("#' . $tableId . '_wrapper > .table-content").css("width", "100%");
                            $("#' . $tableId . '_wrapper > .table-content").attr("tabindex", "3000");
                            $("#' . $tableId . '_wrapper > .table-content").css("overflow", "auto");
                            $("#' . $tableId . '_wrapper > div.table-content > table").attr("summary", "' . $tableSummary . '");
                            ' . $overlay . '
                        });
                    };
                    ' . (!$external ? ('func();') : ('GD.ExecuteTable' . intval($this->ReportConfig->getId()) . ' = func;')) . '
                    }(global.GD_jQuery ? global.GD_jQuery : jQuery);
                })(!window ? this : window);
            </script>'
        ;

        return $dataTableScript;
    }
    public function finalize(AbstractMetaModel $metamodel) {
        parent::finalize($metamodel);

        $loaderName = $this->getName();

        // initializing all cubes. We separated registration from initialization to support inter-cube references
        $loadedDatasets = NULL;
        foreach ($metamodel->datasets as $dataset) {
            // working only with datasets which are created by this loader
            if ($dataset->loaderName != $loaderName) {
                continue;
            }

            StarSchemaCubeMetaData::registerFromDataset($metamodel, $dataset);

            $loadedDatasets[$dataset->nid] = $dataset;
        }

        if (isset($loadedDatasets)) {
            $dataset_nids = array_keys($loadedDatasets);

            // loading measures
            $measureNodes = gd_measure_get_measures_4_dataset($dataset_nids, LOAD_ENTITY);
            // grouping measures in context of dataset
            $datasetsMeasureNodes = $this->groupNodesByDataset($measureNodes, 'field_measure_dataset');

            // creating cubes for all datasets
            foreach ($loadedDatasets as $dataset) {
                // preparing corresponding cube
                $cube = StarSchemaCubeMetaData::initializeFromDataset($metamodel, $dataset);
                // assigning a loader which created the cube
                $cube->factsDataset->loaderName = $loaderName;
                $cube->loaderName = $loaderName;
                // preparing additional measures
                $datasetMeasureNodes = isset($datasetsMeasureNodes[$dataset->nid]) ? $datasetsMeasureNodes[$dataset->nid] : NULL;
                if (isset($datasetMeasureNodes)) {
                    foreach ($datasetMeasureNodes as $measureNode) {
                        $measure = $cube->registerMeasure(get_node_field_value($measureNode, 'field_measure_sysname', 0, 'value', TRUE));
                        $measure->publicName = $measureNode->title;
                        $measure->description = get_node_field_value($measureNode, 'field_measure_desc');
                        $measure->function = get_node_field_value($measureNode, 'field_measure_function', 0, 'value', TRUE);
                    }
                }
            }
        }

        // processing references
        $referenceNodes = gd_reference_get_references(LOAD_ENTITY);
        $referencePointNodes = isset($referenceNodes) ? gd_reference_get_reference_points(LOAD_ENTITY) : NULL;
        if (isset($referencePointNodes)) {
            foreach ($referenceNodes as $referenceNode) {
                GD_DatasetMetaModelLoaderHelper::prepareReference($metamodel, $referenceNode, $referencePointNodes);
            }
        }
    }
    /**
     * Find existing reference via datasets
     *
     * @param $reference
     * @return null
     * @throws Exception
     */
    protected function findExistingReference ( $reference ) {

        $referenceCandidateNodes = (array) gd_reference_get_references(LOAD_ENTITY);

        // find references with exact same reference points
        $matchedReferences = array();
        foreach ( $referenceCandidateNodes as $referenceCandidateNode ) {
            $match = false;
            // don't go any further if reference point counts don't match
            if ( count((array) get_node_field_node_ref($referenceCandidateNode,'field_reference_point',null)) == count($reference->referencePoints) ) {
                continue;
            }
            // must match all reference points
            foreach ( (array) get_node_field_node_ref($referenceCandidateNode,'field_reference_point',null) as $referencePointNid ) {
                $referencePointNode = node_load($referencePointNid);
                foreach ( $reference->referencePoints as $referencePoint ) {
                    if ( $referencePoint->dataset == get_node_field_value($referencePointNode,'field_ref_point_dataset_sysname') ) {
                        $match = true;
                    } else {
                        $match = false;
                    }
                }
            }

            if ( $match ) {
                $matchedReferences[] = $referenceCandidateNode;
            }
        }

        if ( count($matchedReferences) == 1 ) {
            return $matchedReferences[0];
        } else if ( count($matchedReferences) > 1 ) {
            throw new Exception('More than one identical reference found.');
        } else {
            return null;
        }

    }