destroy() public static method

For more information: {@link https://github.com/piwik/piwik/issues/374}
public static destroy ( mixed &$var )
$var mixed The object to destroy.
Example #1
0
 private function aggregateByLabel($labelSQL, $recordName)
 {
     $metrics = $this->getLogAggregator()->getMetricsFromVisitByDimension($labelSQL);
     if (in_array($recordName, array(self::DEVICE_TYPE_RECORD_NAME, self::DEVICE_BRAND_RECORD_NAME, self::DEVICE_MODEL_RECORD_NAME))) {
         $labelSQL = str_replace('log_visit.', 'log_conversion.', $labelSQL);
         $query = $this->getLogAggregator()->queryConversionsByDimension(array($labelSQL));
         if ($query === false) {
             return;
         }
         while ($conversionRow = $query->fetch()) {
             $metrics->sumMetricsGoals($conversionRow[$labelSQL], $conversionRow);
         }
         $metrics->enrichMetricsWithConversions();
     }
     $table = $metrics->asDataTable();
     $report = $table->getSerialized($this->maximumRows, null, Metrics::INDEX_NB_VISITS);
     Common::destroy($table);
     $this->getProcessor()->insertBlobRecord($recordName, $report);
     unset($table, $report);
 }
Example #2
0
 /**
  * Deletes (unsets) the datatable given its id and removes it from the manager
  * Subsequent get for this table will fail
  *
  * @param int $id
  */
 public function deleteTable($id)
 {
     if (isset($this->tables[$id])) {
         Common::destroy($this->tables[$id]);
         $this->setTableDeleted($id);
     }
 }
Example #3
0
 /**
  * Pivots to table.
  *
  * @param DataTable $table The table to manipulate.
  */
 public function filter($table)
 {
     // set of all column names in the pivoted table mapped with the sum of all column
     // values. used later in truncating and ordering the pivoted table's columns.
     $columnSet = array();
     // if no pivot column was set, use the first one found in the row
     if (empty($this->pivotColumn)) {
         $this->pivotColumn = $this->getNameOfFirstNonLabelColumnInTable($table);
     }
     Log::debug("PivotByDimension::%s: pivoting table with pivot column = %s", __FUNCTION__, $this->pivotColumn);
     foreach ($table->getRows() as $row) {
         $row->setColumns(array('label' => $row->getColumn('label')));
         $associatedTable = $this->getIntersectedTable($table, $row);
         if (!empty($associatedTable)) {
             foreach ($associatedTable->getRows() as $columnRow) {
                 $pivotTableColumn = $columnRow->getColumn('label');
                 $columnValue = $this->getColumnValue($columnRow, $this->pivotColumn);
                 if (isset($columnSet[$pivotTableColumn])) {
                     $columnSet[$pivotTableColumn] += $columnValue;
                 } else {
                     $columnSet[$pivotTableColumn] = $columnValue;
                 }
                 $row->setColumn($pivotTableColumn, $columnValue);
             }
             Common::destroy($associatedTable);
             unset($associatedTable);
         }
     }
     Log::debug("PivotByDimension::%s: pivoted columns set: %s", __FUNCTION__, $columnSet);
     $others = Piwik::translate('General_Others');
     $defaultRow = $this->getPivotTableDefaultRowFromColumnSummary($columnSet, $others);
     Log::debug("PivotByDimension::%s: un-prepended default row: %s", __FUNCTION__, $defaultRow);
     // post process pivoted datatable
     foreach ($table->getRows() as $row) {
         // remove subtables from rows
         $row->removeSubtable();
         $row->deleteMetadata('idsubdatatable_in_db');
         // use default row to ensure column ordering and add missing columns/aggregate cut-off columns
         $orderedColumns = $defaultRow;
         foreach ($row->getColumns() as $name => $value) {
             if (isset($orderedColumns[$name])) {
                 $orderedColumns[$name] = $value;
             } else {
                 $orderedColumns[$others] += $value;
             }
         }
         $row->setColumns($orderedColumns);
     }
     $table->clearQueuedFilters();
     // TODO: shouldn't clear queued filters, but we can't wait for them to be run
     //       since generic filters are run before them. remove after refactoring
     //       processed metrics.
     // prepend numerals to columns in a queued filter (this way, disable_queued_filters can be used
     // to get machine readable data from the API if needed)
     $prependedColumnNames = $this->getOrderedColumnsWithPrependedNumerals($defaultRow, $others);
     Log::debug("PivotByDimension::%s: prepended column name mapping: %s", __FUNCTION__, $prependedColumnNames);
     $table->queueFilter(function (DataTable $table) use($prependedColumnNames) {
         foreach ($table->getRows() as $row) {
             $row->setColumns(array_combine($prependedColumnNames, $row->getColumns()));
         }
     });
 }
Example #4
0
 /**
  * Destructor. Makes sure DataTable memory will be cleaned up.
  */
 public function __destruct()
 {
     static $depth = 0;
     // destruct can be called several times
     if ($depth < self::$maximumDepthLevelAllowed && isset($this->rows)) {
         $depth++;
         foreach ($this->rows as $row) {
             Common::destroy($row);
         }
         if (isset($this->summaryRow)) {
             Common::destroy($this->summaryRow);
         }
         unset($this->rows);
         Manager::getInstance()->setTableDeleted($this->currentId);
         $depth--;
     }
 }
Example #5
0
 /**
  * Sums records for every subperiod of the current period and inserts the result as the record
  * for this period.
  *
  * DataTables are summed recursively so subtables will be summed as well.
  *
  * @param string|array $recordNames Name(s) of the report we are aggregating, eg, `'Referrers_type'`.
  * @param int $maximumRowsInDataTableLevelZero Maximum number of rows allowed in the top level DataTable.
  * @param int $maximumRowsInSubDataTable Maximum number of rows allowed in each subtable.
  * @param string $columnToSortByBeforeTruncation The name of the column to sort by before truncating a DataTable.
  * @param array $columnsAggregationOperation Operations for aggregating columns, see {@link Row::sumRow()}.
  * @param array $columnsToRenameAfterAggregation Columns mapped to new names for columns that must change names
  *                                               when summed because they cannot be summed, eg,
  *                                               `array('nb_uniq_visitors' => 'sum_daily_nb_uniq_visitors')`.
  * @return array Returns the row counts of each aggregated report before truncation, eg,
  *               
  *                   array(
  *                       'report1' => array('level0' => $report1->getRowsCount,
  *                                          'recursive' => $report1->getRowsCountRecursive()),
  *                       'report2' => array('level0' => $report2->getRowsCount,
  *                                          'recursive' => $report2->getRowsCountRecursive()),
  *                       ...
  *                   )
  * @api
  */
 public function aggregateDataTableRecords($recordNames, $maximumRowsInDataTableLevelZero = null, $maximumRowsInSubDataTable = null, $columnToSortByBeforeTruncation = null, &$columnsAggregationOperation = null, $columnsToRenameAfterAggregation = null)
 {
     if (!is_array($recordNames)) {
         $recordNames = array($recordNames);
     }
     $nameToCount = array();
     foreach ($recordNames as $recordName) {
         $latestUsedTableId = Manager::getInstance()->getMostRecentTableId();
         $table = $this->aggregateDataTableRecord($recordName, $columnsAggregationOperation, $columnsToRenameAfterAggregation);
         $rowsCount = $table->getRowsCount();
         $nameToCount[$recordName]['level0'] = $rowsCount;
         $rowsCountRecursive = $rowsCount;
         if ($this->isAggregateSubTables()) {
             $rowsCountRecursive = $table->getRowsCountRecursive();
         }
         $nameToCount[$recordName]['recursive'] = $rowsCountRecursive;
         $blob = $table->getSerialized($maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable, $columnToSortByBeforeTruncation);
         Common::destroy($table);
         $this->insertBlobRecord($recordName, $blob);
         unset($blob);
         DataTable\Manager::getInstance()->deleteAll($latestUsedTableId);
     }
     return $nameToCount;
 }
 /**
  * @group Core
  */
 public function testSubDataTableIsDestructed()
 {
     $mockedDataTable = $this->getMock('\\Piwik\\DataTable', array('__destruct'));
     $mockedDataTable->expects($this->once())->method('__destruct');
     $rowBeingDestructed = new Row();
     $rowBeingDestructed->setSubtable($mockedDataTable);
     Common::destroy($rowBeingDestructed);
 }
Example #7
0
 /**
  * Merges the rows of every child {@link DataTable} into a new one and
  * returns it. This function will also set the label of the merged rows
  * to the label of the {@link DataTable} they were originally from.
  *
  * The result of this function is determined by the type of DataTable
  * this instance holds. If this DataTable\Map instance holds an array
  * of DataTables, this function will transform it from:
  * 
  *     Label 0:
  *       DataTable(row1)
  *     Label 1:
  *       DataTable(row2)
  * 
  * to:
  * 
  *     DataTable(row1[label = 'Label 0'], row2[label = 'Label 1'])
  *
  * If this instance holds an array of DataTable\Maps, this function will
  * transform it from:
  * 
  *     Outer Label 0:            // the outer DataTable\Map
  *       Inner Label 0:            // one of the inner DataTable\Maps
  *         DataTable(row1)
  *       Inner Label 1:
  *         DataTable(row2)
  *     Outer Label 1:
  *       Inner Label 0:
  *         DataTable(row3)
  *       Inner Label 1:
  *         DataTable(row4)
  * 
  * to:
  * 
  *     Inner Label 0:
  *       DataTable(row1[label = 'Outer Label 0'], row3[label = 'Outer Label 1'])
  *     Inner Label 1:
  *       DataTable(row2[label = 'Outer Label 0'], row4[label = 'Outer Label 1'])
  *
  * If this instance holds an array of DataTable\Maps, the
  * metadata of the first child is used as the metadata of the result.
  *
  * This function can be used, for example, to smoosh IndexedBySite archive
  * query results into one DataTable w/ different rows differentiated by site ID.
  *
  * Note: This DataTable/Map will be destroyed and will be no longer usable after the tables have been merged into
  *       the new dataTable to reduce memory usage. Destroying all DataTables witihn the Map also seems to fix a
  *       Segmentation Fault that occurred in the AllWebsitesDashboard when having > 16k sites.
  *
  * @return DataTable|Map
  */
 public function mergeChildren()
 {
     $firstChild = reset($this->array);
     if ($firstChild instanceof Map) {
         $result = $firstChild->getEmptyClone();
         /** @var $subDataTableMap Map */
         foreach ($this->getDataTables() as $label => $subDataTableMap) {
             foreach ($subDataTableMap->getDataTables() as $innerLabel => $subTable) {
                 if (!isset($result->array[$innerLabel])) {
                     $dataTable = new DataTable();
                     $dataTable->setMetadataValues($subTable->getAllTableMetadata());
                     $result->addTable($dataTable, $innerLabel);
                 }
                 $this->copyRowsAndSetLabel($result->array[$innerLabel], $subTable, $label);
             }
         }
     } else {
         $result = new DataTable();
         foreach ($this->getDataTables() as $label => $subTable) {
             $this->copyRowsAndSetLabel($result, $subTable, $label);
             Common::destroy($subTable);
         }
         $this->array = array();
     }
     return $result;
 }
Example #8
0
 /**
  * @param int $idSite
  * @param string $period
  * @param string $date
  * @param string|false $segment
  * @param bool $expanded
  * @param DataTable $dataTable
  */
 private function buildExpandedTableForFlattenGetSocials($idSite, $period, $date, $segment, $expanded, $dataTable)
 {
     $urlsTable = Archive::createDataTableFromArchive(Archiver::WEBSITES_RECORD_NAME, $idSite, $period, $date, $segment, $expanded, $flat = true);
     $urlsTable->filter('ColumnCallbackDeleteRow', array('label', function ($url) {
         return !Social::getInstance()->isSocialUrl($url);
     }));
     $urlsTable = $urlsTable->mergeSubtables();
     foreach ($dataTable->getRows() as $row) {
         $row->removeSubtable();
         $social = $row->getColumn('label');
         $newTable = $urlsTable->getEmptyClone();
         $rows = $urlsTable->getRows();
         foreach ($rows as $id => $urlsTableRow) {
             $url = $urlsTableRow->getColumn('label');
             if (Social::getInstance()->isSocialUrl($url, $social)) {
                 $newTable->addRow($urlsTableRow);
                 $urlsTable->deleteRow($id);
             }
         }
         if ($newTable->getRowsCount()) {
             $newTable->filter('Piwik\\Plugins\\Referrers\\DataTable\\Filter\\UrlsForSocial', array($expanded));
             $row->setSubtable($newTable);
         }
     }
     Common::destroy($urlsTable);
     $urlsTable = null;
 }
Example #9
0
 private function buildDataTable($idSitesOrIdSite, $period, $date, $segment, $_restrictSitesToLogin, $enhanced, $multipleWebsitesRequested)
 {
     $allWebsitesRequested = $idSitesOrIdSite == 'all';
     if ($allWebsitesRequested) {
         // First clear cache
         Site::clearCache();
         // Then, warm the cache with only the data we should have access to
         if (Piwik::hasUserSuperUserAccess() && !TaskScheduler::isTaskBeingExecuted()) {
             APISitesManager::getInstance()->getAllSites();
         } else {
             APISitesManager::getInstance()->getSitesWithAtLeastViewAccess($limit = false, $_restrictSitesToLogin);
         }
         // Both calls above have called Site::setSitesFromArray. We now get these sites:
         $sitesToProblablyAdd = Site::getSites();
     } else {
         $sitesToProblablyAdd = array(APISitesManager::getInstance()->getSiteFromId($idSitesOrIdSite));
     }
     // build the archive type used to query archive data
     $archive = Archive::build($idSitesOrIdSite, $period, $date, $segment, $_restrictSitesToLogin);
     // determine what data will be displayed
     $fieldsToGet = array();
     $columnNameRewrites = array();
     $apiECommerceMetrics = array();
     $apiMetrics = API::getApiMetrics($enhanced);
     foreach ($apiMetrics as $metricName => $metricSettings) {
         $fieldsToGet[] = $metricSettings[self::METRIC_RECORD_NAME_KEY];
         $columnNameRewrites[$metricSettings[self::METRIC_RECORD_NAME_KEY]] = $metricName;
         if ($metricSettings[self::METRIC_IS_ECOMMERCE_KEY]) {
             $apiECommerceMetrics[$metricName] = $metricSettings;
         }
     }
     // get the data
     // $dataTable instanceOf Set
     $dataTable = $archive->getDataTableFromNumeric($fieldsToGet);
     $dataTable = $this->mergeDataTableMapAndPopulateLabel($idSitesOrIdSite, $multipleWebsitesRequested, $dataTable);
     if ($dataTable instanceof DataTable\Map) {
         foreach ($dataTable->getDataTables() as $table) {
             $this->addMissingWebsites($table, $fieldsToGet, $sitesToProblablyAdd);
         }
     } else {
         $this->addMissingWebsites($dataTable, $fieldsToGet, $sitesToProblablyAdd);
     }
     // calculate total visits/actions/revenue
     $this->setMetricsTotalsMetadata($dataTable, $apiMetrics);
     // if the period isn't a range & a lastN/previousN date isn't used, we get the same
     // data for the last period to show the evolution of visits/actions/revenue
     list($strLastDate, $lastPeriod) = Range::getLastDate($date, $period);
     if ($strLastDate !== false) {
         if ($lastPeriod !== false) {
             // NOTE: no easy way to set last period date metadata when range of dates is requested.
             //       will be easier if DataTable\Map::metadata is removed, and metadata that is
             //       put there is put directly in DataTable::metadata.
             $dataTable->setMetadata(self::getLastPeriodMetadataName('date'), $lastPeriod);
         }
         $pastArchive = Archive::build($idSitesOrIdSite, $period, $strLastDate, $segment, $_restrictSitesToLogin);
         $pastData = $pastArchive->getDataTableFromNumeric($fieldsToGet);
         $pastData = $this->mergeDataTableMapAndPopulateLabel($idSitesOrIdSite, $multipleWebsitesRequested, $pastData);
         // use past data to calculate evolution percentages
         $this->calculateEvolutionPercentages($dataTable, $pastData, $apiMetrics);
         Common::destroy($pastData);
     }
     // remove eCommerce related metrics on non eCommerce Piwik sites
     // note: this is not optimal in terms of performance: those metrics should not be retrieved in the first place
     if ($enhanced) {
         if ($dataTable instanceof DataTable\Map) {
             foreach ($dataTable->getDataTables() as $table) {
                 $this->removeEcommerceRelatedMetricsOnNonEcommercePiwikSites($table, $apiECommerceMetrics);
             }
         } else {
             $this->removeEcommerceRelatedMetricsOnNonEcommercePiwikSites($dataTable, $apiECommerceMetrics);
         }
     }
     // move the site id to a metadata column
     $dataTable->filter('ColumnCallbackAddMetadata', array('label', 'group', array('\\Piwik\\Site', 'getGroupFor'), array()));
     $dataTable->filter('ColumnCallbackAddMetadata', array('label', 'main_url', array('\\Piwik\\Site', 'getMainUrlFor'), array()));
     $dataTable->filter('ColumnCallbackAddMetadata', array('label', 'idsite'));
     // set the label of each row to the site name
     if ($multipleWebsitesRequested) {
         $dataTable->filter('ColumnCallbackReplace', array('label', '\\Piwik\\Site::getNameFor'));
     } else {
         $dataTable->filter('ColumnDelete', array('label'));
     }
     Site::clearCache();
     // replace record names with user friendly metric names
     $dataTable->filter('ReplaceColumnNames', array($columnNameRewrites));
     // Ensures data set sorted, for Metadata output
     $dataTable->filter('Sort', array(self::NB_VISITS_METRIC, 'desc', $naturalSort = false));
     // filter rows without visits
     // note: if only one website is queried and there are no visits, we can not remove the row otherwise
     // ResponseBuilder throws 'Call to a member function getColumns() on a non-object'
     if ($multipleWebsitesRequested && !$enhanced) {
         $dataTable->filter('ColumnCallbackDeleteRow', array(self::NB_VISITS_METRIC, function ($value) {
             return $value == 0;
         }));
     }
     return $dataTable;
 }