protected function finishImpl(array &$records = NULL) {
        parent::finishImpl($records);

        if (!isset($records)) {
            return;
        }

        $valueMin = $valueMax = NULL;
        // preparing minimum and maximum values
        foreach ($records as $record) {
            if (!isset($record[$this->valueColumnName])) {
                continue;
            }

            $value = $record[$this->valueColumnName];

            $valueMin = MathHelper::min($valueMin, $value);
            $valueMax = MathHelper::max($value, $valueMax);
        }
        $valueRange = $valueMax - $valueMin;

        // generating weighted grade
        foreach ($records as &$record) {
            if (!isset($record[$this->valueColumnName])) {
                continue;
            }

            $value = $record[$this->valueColumnName];

            $rank = ($valueRange == 0) ? 1 : ($value - $valueMin) / $valueRange;
            $record[$this->memberRankColumnName] = $rank;
        }
        unset($record);
    }
 public function postFormatRecords(array &$records = NULL)
 {
     parent::postFormatRecords($records);
     if (!isset($records)) {
         return;
     }
     $valueMin = NULL;
     $valueMax = NULL;
     // preparing minimum and maximum values
     foreach ($records as $record) {
         if (!isset($record[$this->valuePropertyName])) {
             continue;
         }
         $value = $record[$this->valuePropertyName];
         $valueMin = MathHelper::min($valueMin, $value);
         $valueMax = MathHelper::max($value, $valueMax);
     }
     // generating weighted grade
     foreach ($records as &$record) {
         if (!isset($record[$this->valuePropertyName])) {
             continue;
         }
         $value = $record[$this->valuePropertyName];
         $weightedGrade = ($value - $valueMin) / ($valueMax - $valueMin);
         $record[$this->weightedGradeProperyName] = $weightedGrade;
     }
 }
    protected function removeTraceFilePath($message) {
        $prefix = 'File "';
        $suffix = '"';

        $index = 0;
        while (($startIndex = strpos($message, $prefix, $index)) !== FALSE) {
            $startIndex += strlen($prefix);
            $endIndex = strpos($message, $suffix, $startIndex);

            $fileName = substr($message, $startIndex, $endIndex - $startIndex);

            $p1 = strrpos($fileName, '\\');
            if ($p1 === FALSE) {
                $p1 = NULL;
            }
            $p2 = strrpos($fileName, '/');
            if ($p2 === FALSE) {
                $p2 = NULL;
            }
            $p = MathHelper::max($p1, $p2);
            if (isset($p)) {
                $message = substr_replace($message, '', $startIndex, $p + 1);
            }

            $index = $endIndex + 1;
        }

        return $message;
    }
    protected function submitRecordImpl(RecordMetaData $recordMetaData, $recordNumber, array &$record) {
        $datatypeFactory = DataTypeFactory::getInstance();

        foreach ($recordMetaData->getColumns(FALSE) as $column) {
            if (!isset($record[$column->columnIndex])) {
                continue;
            }
            $columnValue = $record[$column->columnIndex];

            // calculating length of the column value
            $column->type->length = MathHelper::max(
                (isset($column->type->length) ? $column->type->length : NULL),
                strlen($columnValue));

            if (isset($column->type->applicationType) && ($column->type->applicationType === StringDataTypeHandler::DATA_TYPE)) {
                continue;
            }

            $columnDataType = $datatypeFactory->autoDetectDataType($columnValue, DATA_TYPE__ALL);
            if (isset($column->type->applicationType)) {
                try {
                    $column->type->applicationType = $datatypeFactory->selectCompatibleDataType(
                        array($column->type->applicationType, $columnDataType));
                }
                catch (IncompatibleDataTypeException $e) {
                    // if the two types are incompatible only 'string' type can resolve the problem
                    $column->type->applicationType = StringDataTypeHandler::DATA_TYPE;
                }
            }
            else  {
                $column->type->applicationType = $columnDataType;
            }

            // calculating scale for numeric columns
            $handler = $datatypeFactory->getHandler($column->type->applicationType);
            if ($handler instanceof AbstractNumberDataTypeHandler) {
                $numericColumnValue = $handler->castValue($columnValue);

                $decimalSeparatorIndex = strpos($numericColumnValue, $handler->decimalSeparatorSymbol);
                if ($decimalSeparatorIndex !== FALSE) {
                    $scale = strlen($numericColumnValue) - $decimalSeparatorIndex - 1;

                    if (!isset($column->type->scale) || ($column->type->scale < $scale)) {
                        $column->type->scale = $scale;
                    }
                }
            }
        }
    }
    public function doBeforeRecordSubmitted(RecordMetaData $recordMetaData, $recordNumber, array &$record) {
        $result = parent::doBeforeRecordSubmitted($recordMetaData, $recordNumber, $record);

        if ($result) {
            foreach ($record as &$columnValue) {
                if (!is_string($columnValue)) {
                    continue;
                }

                if (strlen($columnValue) > $this->maxValueLength) {
                    $columnValue = substr($columnValue, 0, MathHelper::max($this->maxValueLength - 3, 0)) . '...';
                }
            }
            unset($columnValue);
        }

        return $result;
    }
    public function getMaximumColumnCount() {
        $count = isset($this->columnNames) ? count($this->columnNames) : NULL;

        if (isset($this->nestedLinks)) {
            foreach ($this->nestedLinks as $nestedLink) {
                $count = MathHelper::max($count, $nestedLink->getMaximumColumnCount());
            }
        }

        return $count;
    }
 protected function prepareColumnDatabaseType(DataSourceHandler $handler, ColumnMetaData $column)
 {
     if (isset($column->type->applicationType)) {
         $storageDataType = NULL;
         list($datasetName) = ReferencePathHelper::splitReference($column->type->applicationType);
         if (isset($datasetName)) {
             $storageDataType = Sequence::getSequenceColumnType()->applicationType;
         } else {
             $datatypeHandler = DataTypeFactory::getInstance()->getHandler($column->type->applicationType);
             $storageDataType = $datatypeHandler->getStorageDataType();
         }
         switch ($storageDataType) {
             case StringDataTypeHandler::$DATA_TYPE:
                 break;
             case IntegerDataTypeHandler::$DATA_TYPE:
                 $this->prepareInteger($column);
                 break;
             case NumberDataTypeHandler::$DATA_TYPE:
             case CurrencyDataTypeHandler::$DATA_TYPE:
             case PercentDataTypeHandler::$DATA_TYPE:
                 $this->prepareNumber($column);
                 break;
             case BooleanDataTypeHandler::$DATA_TYPE:
                 // calculating length of mapping of TRUE and FALSE values
                 $valueTrue = $handler->castValue(BooleanDataTypeHandler::$DATA_TYPE, TRUE);
                 $valueFalse = $handler->castValue(BooleanDataTypeHandler::$DATA_TYPE, FALSE);
                 // length of the field depends on length of the mappings
                 $lengthValueTrue = strlen($valueTrue);
                 $lengthValueFalse = strlen($valueFalse);
                 $length = MathHelper::max($lengthValueTrue, $lengthValueFalse);
                 // detecting type for each value and selecting primary type
                 $datatype = DataTypeFactory::getInstance()->selectDataType(array(DataTypeFactory::getInstance()->autoDetectDataType($valueTrue), DataTypeFactory::getInstance()->autoDetectDataType($valueFalse)));
                 // for numeric values we use integer storage type, for rest - string
                 if ($datatype === IntegerDataTypeHandler::$DATA_TYPE) {
                     $this->prepareInteger($column, $length);
                 } elseif ($lengthValueTrue === $lengthValueFalse) {
                     $this->prepareFixedLengthString($column, $length);
                 } else {
                     $this->prepareVariableLengthString($column, $length);
                 }
                 break;
             case DateTimeDataTypeHandler::$DATA_TYPE:
                 $this->prepareDate($column, TRUE, TRUE);
                 break;
             case DateDataTypeHandler::$DATA_TYPE:
                 $this->prepareDate($column);
                 break;
             case TimeDataTypeHandler::$DATA_TYPE:
                 $this->prepareDate($column, FALSE, TRUE);
                 break;
             default:
                 throw new UnsupportedOperationException(t("Unsupported data type for '@columnName' column: @columnType", array('@columnName' => $column->publicName, '@columnType' => $column->type->applicationType)));
         }
     }
     if (!isset($column->type->databaseType)) {
         $this->prepareVariableLengthString($column);
     }
     return $column->type->databaseType;
 }
    protected function prepareDatasetSequence(ReferenceCallContext $callcontext, MetaModel $metamodel, ReferenceLink $link, $referencePath) {
        $referenceParts = ReferencePathHelper::splitReference($referencePath);

        $parentColumnName = array_pop($referenceParts);
        $parentDatasetName = array_pop($referenceParts);
        $referencedColumnName = $referencedDatasetName = NULL;

        $leftReferencePartCount = count($referenceParts);

        $nestedReferencePath = $referencePath;
        if ($link->dataset->name == $parentDatasetName) {
            // dataset is there and it is link's dataset
            if ($leftReferencePartCount == 0) {
                return;
            }

            // assembling new reference path
            $nestedReferencePath = ReferencePathHelper::assembleReferenceParts($referenceParts);

            $referencedColumnName = array_pop($referenceParts);
            $referencedDatasetName = array_pop($referenceParts);

            if (!isset($referencedDatasetName)) {
                throw new UnsupportedOperationException(t(
                    'Dataset name is not set in the reference path: %referencePath',
                    array('%referencePath' => $referencePath)));
            }
        }
        elseif (isset($parentDatasetName)) {
            $referencedColumnName = $parentColumnName;
            $referencedDatasetName = $parentDatasetName;
            $parentColumnName = $parentDatasetName = NULL;
        }
        else {
            if ($leftReferencePartCount > 0) {
                throw new UnsupportedOperationException(t(
                    'Dataset name is not set in the reference path: %referencePath',
                    array('%referencePath' => $referencePath)));
            }

            // it means that we just point to column in link's dataset
            return;
        }

        // checking if there any references which could be used to find required dataset
        $references = $metamodel->findReferencesByDatasetName($link->dataset->name);
        if (!isset($references)) {
            return;
        }

        // maximum number of columns in direct references
        $directReferencePointColumnCount = NULL;

        // checking if there is any reference which directly link to referenced dataset
        $parentReferencePointIndex4References = $directReferencePointIndex4References = $transitionalReferencePointIndexes4References = NULL;
        foreach ($references as $reference) {
            $referencePointColumnCount = $reference->getPointColumnCount();

            // checking if the reference can be used to link with other datasets
            $parentReferencePointIndex4Reference = $directReferencePointIndex4Reference = $transitionalReferencePointIndexes4Reference = NULL;
            for ($referencePointColumnIndex = 0; $referencePointColumnIndex < $referencePointColumnCount; $referencePointColumnIndex++) {
                $parentReferencePointIndex = $directReferencePointIndex = $transitionalReferencePointIndexes = NULL;
                foreach ($reference->points as $referencePointIndex => $referencePoint) {
                    $datasetName = $referencePoint->columns[$referencePointColumnIndex]->datasetName;

                    if (($link->dataset->name == $datasetName)
                            && (!isset($parentColumnName) || ($parentColumnName == $referencePoint->columns[$referencePointColumnIndex]->columnName))) {
                        if (isset($parentReferencePointIndex)) {
                            // Found several possible ways to start a join from the referring dataset.
                            // That happens because we do not have parent column name and possible join is ambiguous
                            // We cannot use this way to proceed
                            continue 3;
                        }
                        else {
                            $parentReferencePointIndex = $referencePointIndex;
                        }
                    }
                    elseif ($datasetName == $referencedDatasetName) {
                        if (isset($directReferencePointIndex)) {
                            // found several possible ways to join with the referenced dataset
                            continue 3;
                        }
                        else {
                            $directReferencePointIndex[$referencePointIndex] = TRUE;
                        }
                    }
                    else {
                        $transitionalReferencePointIndexes[$referencePointIndex] = FALSE;
                    }
                }

                // this reference cannot be used because none of the reference points linked with parent dataset
                if (!isset($parentReferencePointIndex)) {
                    continue 2;
                }

                if (isset($directReferencePointIndex)) {
                    // if we have direct reference we do not care about indirect ones
                    $transitionalReferencePointIndexes = NULL;
                }
                else {
                    // there is no direct or indirect ways. This reference is useless :)
                    if (!isset($transitionalReferencePointIndexes)) {
                        continue 2;
                    }
                }

                $parentReferencePointIndex4Reference[$referencePointColumnIndex] = $parentReferencePointIndex;
                if (isset($directReferencePointIndex)) {
                    $directReferencePointIndex4Reference[$referencePointColumnIndex] = $directReferencePointIndex;
                }
                if (isset($transitionalReferencePointIndexes)) {
                    $transitionalReferencePointIndexes4Reference[$referencePointColumnIndex] = $transitionalReferencePointIndexes;
                }
            }

            // we support only direct references between datasets
            // in this case we have direct reference based on some columns only. Rest columns are connected indirectly
            if (isset($directReferencePointIndex4Reference) && isset($transitionalReferencePointIndexes4Reference)) {
                continue;
            }

            $parentReferencePointIndex4References[$reference->name] = $parentReferencePointIndex4Reference;
            if (isset($directReferencePointIndex4Reference)) {
                $directReferencePointIndex4References[$reference->name] = $directReferencePointIndex4Reference;
                $directReferencePointColumnCount = MathHelper::max($directReferencePointColumnCount, $referencePointColumnCount);
            }
            if (isset($transitionalReferencePointIndexes4Reference)) {
                $transitionalReferencePointIndexes4References[$reference->name] = $transitionalReferencePointIndexes4Reference;
            }
        }
        // we could use none of the selected references
        if (!isset($parentReferencePointIndex4References)) {
            return;
        }

        // removing all useless direct and indirect references if there is a direct way
        if (isset($directReferencePointColumnCount)) {
            foreach ($parentReferencePointIndex4References as $referenceName => $parentReferencePointIndex4Reference) {
                $referencePointColumnCount = count($parentReferencePointIndex4Reference);

                if (isset($directReferencePointIndex4References[$referenceName])) {
                    // we preserve only direct ways with maximum number of columns
                    if ($referencePointColumnCount == $directReferencePointColumnCount) {
                        continue;
                    }
                }
                else {
                    // we preserve only indirect ways with more columns than in direct way
                    if ($referencePointColumnCount > $directReferencePointColumnCount) {
                        continue;
                    }
                }

                unset($parentReferencePointIndex4References[$referenceName]);
                unset($directReferencePointIndex4References[$referenceName]);
                unset($transitionalReferencePointIndexes4References[$referenceName]);
            }
        }

        foreach ($parentReferencePointIndex4References as $referenceName => $parentReferencePointIndex4Reference) {
            $reference = $references[ArrayHelper::search($references, 'name', $referenceName)];

            $referencePointColumnCount = $reference->getPointColumnCount();

            $referencePointIndexes4Reference = isset($directReferencePointIndex4References[$referenceName])
                ? $directReferencePointIndex4References[$referenceName]
                : NULL;
            $isDirectReference = isset($referencePointIndexes4Reference);

            if (!$isDirectReference) {
                // 01/09/2014 reference can be reused only for direct references
                if (isset($callcontext->referenceNameStack[$referenceName])) {
                    continue;
                }

                $referencePointIndexes4Reference = isset($transitionalReferencePointIndexes4References[$referenceName])
                    ? $transitionalReferencePointIndexes4References[$referenceName]
                    : NULL;
            }

            // registering the reference in a stack to avoid excessive calls
            // registration was moved here because we could have date[->month->quarter->year] and year columns in one dataset
            // if references related to date and year are registered before we start to process individual references
            // we will end up with nested links for date->month->quarter->year which do not contain a reference to year
            // which leads to GOVDB-1313 issue
            $callcontext->referenceNameStack[$reference->name] = TRUE;

            // preparing dataset names for each reference point
            $referencePointDatasetNames = NULL;
            for ($referencePointColumnIndex = 0; $referencePointColumnIndex < $referencePointColumnCount; $referencePointColumnIndex++) {
                foreach ($referencePointIndexes4Reference[$referencePointColumnIndex] as $referencePointIndex => $directReferencePointFlag) {
                    $referencePointColumn = $reference->points[$referencePointIndex]->columns[$referencePointColumnIndex];
                    $datasetName = $referencePointColumn->datasetName;

                    // it is expected that dataset name is the same for all columns in a reference point
                    if (isset($referencePointDatasetNames[$referencePointIndex])) {
                        if ($referencePointDatasetNames[$referencePointIndex] != $datasetName) {
                            // Dataset name is not the same for all columns for the reference point
                            $referencePointDatasetNames[$referencePointIndex] = FALSE;
                        }
                    }
                    else {
                        $referencePointDatasetNames[$referencePointIndex] = $datasetName;
                    }
                }
            }
            // removing all reference points which we cannot support now
            foreach ($referencePointDatasetNames as $referencePointIndex => $datasetName) {
                if ($datasetName === FALSE) {
                    unset($referencePointDatasetNames[$referencePointIndex]);
                }
            }
            // if nothing left there is not need to proceed
            if (count($referencePointDatasetNames) == 0) {
                continue;
            }

            // preparing list of parent column names
            $parentColumnNames = NULL;
            for ($referencePointColumnIndex = 0; $referencePointColumnIndex < $referencePointColumnCount; $referencePointColumnIndex++) {
                $parentReferencePointIndex = $parentReferencePointIndex4Reference[$referencePointColumnIndex];
                $parentReferencePointColumnName = $reference->points[$parentReferencePointIndex]->columns[$referencePointColumnIndex]->columnName;

                $parentColumnNames[$referencePointColumnIndex] = $parentReferencePointColumnName;
            }

            $referenceCallContext = $isDirectReference ? $callcontext : (clone $callcontext);

            // adding all indirect datasets in stack to prevent recursive calls
            if (!$isDirectReference) {
                foreach ($referencePointDatasetNames as $referencePointIndex => $datasetName) {
                    if (isset($referenceCallContext->datasetNameStack[$datasetName])) {
                        unset($referencePointDatasetNames[$referencePointIndex]);
                    }
                    else {
                        $referenceCallContext->datasetNameStack[$datasetName] = TRUE;
                    }
                }
            }

            foreach ($referencePointDatasetNames as $referencePointIndex => $datasetName) {
                // looking for existing link
                $referencedLink = $link->findNestedLinkByDatasetNameAndParentColumnNames($datasetName, $parentColumnNames);
                if (!isset($referencedLink)) {
                    $dataset = $metamodel->getDataset($datasetName);

                    $referencedLink = new ReferenceLink($dataset);
                    foreach ($parentColumnNames as $referencePointColumnIndex => $parentReferencePointColumnName) {
                        $referencePointColumn = $reference->points[$referencePointIndex]->columns[$referencePointColumnIndex];
                        $referencedLink->linkColumnWithParent($referencePointColumnIndex, $parentReferencePointColumnName, $referencePointColumn->columnName);
                    }

                    $link->registerNestedLink($referencedLink);
                }
                ArrayHelper::addUniqueValue($referencedLink->referenceNames, $referenceName);

                // marking the link as required for the branch so it will not be deleted by the optimizer later
                if ($isDirectReference) {
                    $referencedLink->required = TRUE;
                }

                // because this reference path is not processed completely we need to continue scanning this branch
                if (isset($nestedReferencePath)) {
                    LogHelper::log_debug(t(
                        'Checking sub-path[linkId: @linkId; stackSize: @stackSize]: @referencePath',
                        array('@linkId' => $referencedLink->linkId, '@stackSize' => count($callcontext->referenceNameStack), '@referencePath' => $referencePath)));
                    $referencePointCallContext = clone $referenceCallContext;
                    $this->prepareDatasetSequence($referencePointCallContext, $metamodel, $referencedLink, $nestedReferencePath);
                }
            }
        }
    }
Beispiel #9
0
 public function findLastColumnIndex()
 {
     $lastColumnIndex = NULL;
     foreach ($this->columns as $column) {
         $lastColumnIndex = MathHelper::max($lastColumnIndex, $column->columnIndex);
     }
     return $lastColumnIndex;
 }