File: /home/posscale/subdomains/xibo/lib/Widget/DataSetView.php
<?php
/*
* Xibo - Digital Signage - http://www.xibo.org.uk
* Copyright (C) 2011-2015 Daniel Garner
*
* This file is part of Xibo.
*
* Xibo is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Xibo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Xibo. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Xibo\Widget;
use InvalidArgumentException;
use Respect\Validation\Validator as v;
use Xibo\Entity\DataSetColumn;
use Xibo\Exception\NotFoundException;
/**
* Class DataSetView
* @package Xibo\Widget
*/
class DataSetView extends ModuleWidget
{
/**
* Install Modules Files
*/
public function installFiles()
{
$this->mediaFactory->createModuleSystemFile(PROJECT_ROOT . '/web/modules/vendor/jquery-1.11.1.min.js')->save();
$this->mediaFactory->createModuleSystemFile(PROJECT_ROOT . '/web/modules/vendor/jquery-cycle-2.1.6.min.js')->save();
$this->mediaFactory->createModuleSystemFile(PROJECT_ROOT . '/web/modules/xibo-layout-scaler.js')->save();
$this->mediaFactory->createModuleSystemFile(PROJECT_ROOT . '/web/modules/xibo-dataset-render.js')->save();
$this->mediaFactory->createModuleSystemFile(PROJECT_ROOT . '/web/modules/xibo-image-render.js')->save();
}
/**
* @return string
*/
public function layoutDesignerJavaScript()
{
return 'datasetview-designer-javascript';
}
/**
* DataSets
* @return array[DataSet]
*/
public function dataSets()
{
return $this->dataSetFactory->query();
}
/**
* Get DataSet Columns
* @return array
*/
public function dataSetColumns()
{
return $this->dataSetColumnFactory->getByDataSetId($this->getOption('dataSetId'));
}
/**
* Get Data Set Columns
* @return array[DataSetColumn]
*/
public function dataSetColumnsSelected()
{
if ($this->getOption('dataSetId') == 0)
throw new \InvalidArgumentException(__('DataSet not selected'));
$columns = $this->dataSetColumnFactory->getByDataSetId($this->getOption('dataSetId'));
$columnsSelected = [];
$colIds = explode(',', $this->getOption('columns'));
// Cycle elements of the ordered columns Ids array $colIds
foreach ($colIds as $colId) {
// Cycle data set columns $columns
foreach ($columns as $column) {
// See if the element on the odered list is the column
if ($column->dataSetColumnId == $colId) {
$columnsSelected[] = $column;
}
}
}
return $columnsSelected;
}
/**
* Get Data Set Columns
* @return array[DataSetColumn]
*/
public function dataSetColumnsNotSelected()
{
if ($this->getOption('dataSetId') == 0)
throw new \InvalidArgumentException(__('DataSet not selected'));
$columns = $this->dataSetColumnFactory->getByDataSetId($this->getOption('dataSetId'));
$columnsNotSelected = [];
$colIds = explode(',', $this->getOption('columns'));
foreach ($columns as $column) {
/* @var DataSetColumn $column */
if (!in_array($column->dataSetColumnId, $colIds))
$columnsNotSelected[] = $column;
}
return $columnsNotSelected;
}
/**
* Get the Order Clause
* @return mixed
*/
public function getOrderClause()
{
return json_decode($this->getOption('orderClauses', "[]"), true);
}
/**
* Get the Filter Clause
* @return mixed
*/
public function getFilterClause()
{
return json_decode($this->getOption('filterClauses', "[]"), true);
}
/**
* Get Extra content for the form
* @return array
*/
public function getExtra()
{
return [
'templates' => $this->templatesAvailable(),
'orderClause' => $this->getOrderClause(),
'filterClause' => $this->getFilterClause(),
'columns' => $this->dataSetColumns(),
'dataSet' => ($this->getOption('dataSetId', 0) != 0) ? $this->dataSetFactory->getById($this->getOption('dataSetId')) : null
];
}
/**
* validate
*/
public function validate()
{
// Must have a duration
if ($this->getUseDuration() == 1 && $this->getDuration() == 0)
throw new \InvalidArgumentException(__('Please enter a duration'));
// Validate Data Set Selected
if ($this->getOption('dataSetId') == 0)
throw new \InvalidArgumentException(__('Please select a DataSet'));
// Check we have permission to use this DataSetId
if (!$this->getUser()->checkViewable($this->dataSetFactory->getById($this->getOption('dataSetId'))))
throw new \InvalidArgumentException(__('You do not have permission to use that dataset'));
if ($this->getWidgetId() != 0) {
if (!is_numeric($this->getOption('upperLimit')) || !is_numeric($this->getOption('lowerLimit')))
throw new \InvalidArgumentException(__('Limits must be numbers'));
if ($this->getOption('upperLimit') < 0 || $this->getOption('lowerLimit') < 0)
throw new \InvalidArgumentException(__('Limits cannot be lower than 0'));
// Check the bounds of the limits
if ($this->getOption('upperLimit') < $this->getOption('lowerLimit'))
throw new \InvalidArgumentException(__('Upper limit must be higher than lower limit'));
if (!v::int()->min(0)->validate($this->getOption('updateInterval')))
throw new InvalidArgumentException(__('Update Interval must be greater than or equal to 0'));
// Make sure we haven't entered a silly value in the filter
if (strstr($this->getOption('filter'), 'DESC'))
throw new InvalidArgumentException(__('Cannot user ordering criteria in the Filter Clause'));
}
}
/**
* Adds a dataSetView Widget
* @SWG\Post(
* path="/playlist/widget/dataSetView/{playlistId}",
* operationId="WidgetdataSetViewAdd",
* tags={"widget"},
* summary="Add a dataSetView Widget",
* description="Add a new dataSetView Widget to the specified playlist",
* @SWG\Parameter(
* name="playlistId",
* in="path",
* description="The playlist ID to add a Widget to",
* type="integer",
* required=true
* ),
* @SWG\Parameter(
* name="name",
* in="formData",
* description="Optional Widget Name",
* type="string",
* required=false
* ),
* @SWG\Parameter(
* name="dataSetId",
* in="formData",
* description="Create dataSetView Widget using provided dataSetId of an existing dataSet",
* type="integer",
* required=true
* ),
* @SWG\Parameter(
* name="columns",
* in="formData",
* description=" EDIT only - Array of dataSetColumn IDs to assign",
* type="array",
* required=false,
* @SWG\Items(type="integer")
* ),
* @SWG\Parameter(
* name="duration",
* in="formData",
* description="EDIT Only - The dataSetView Duration",
* type="integer",
* required=false
* ),
* @SWG\Parameter(
* name="useDuration",
* in="formData",
* description="Edit Only - (0, 1) Select 1 only if you will provide duration parameter as well",
* type="integer",
* required=false
* ),
* @SWG\Parameter(
* name="updateInterval",
* in="formData",
* description="EDIT Only - Update interval in minutes",
* type="integer",
* required=false
* ),
* @SWG\Parameter(
* name="rowsPerPage",
* in="formData",
* description="EDIT Only - Number of rows per page, 0 for no pages",
* type="integer",
* required=false
* ),
* @SWG\Parameter(
* name="showHeadings",
* in="formData",
* description="EDIT Only - Should the table show Heading? (0,1)",
* type="integer",
* required=false
* ),
* @SWG\Parameter(
* name="upperLimit",
* in="formData",
* description="EDIT Only - Upper low limit for this dataSet, 0 for nor limit",
* type="integer",
* required=false
* ),
* @SWG\Parameter(
* name="lowerLimit",
* in="formData",
* description="EDIT Only - Lower low limit for this dataSet, 0 for nor limit",
* type="integer",
* required=false
* ),
* @SWG\Parameter(
* name="filter",
* in="formData",
* description="EDIT Only - SQL clause for filter this dataSet",
* type="string",
* required=false
* ),
* @SWG\Parameter(
* name="ordering",
* in="formData",
* description="EDIT Only - SQL clause for how this dataSet should be ordered",
* type="string",
* required=false
* ),
* @SWG\Parameter(
* name="templateId",
* in="formData",
* description="EDIT Only - Template you'd like to apply, options available: empty, light-green",
* type="string",
* required=false
* ),
* @SWG\Parameter(
* name="overrideTemplate",
* in="formData",
* description="EDIT Only - flag (0, 1) override template checkbox",
* type="integer",
* required=false
* ),
* @SWG\Parameter(
* name="useOrderingClause",
* in="formData",
* description="EDIT Only - flag (0,1) Use advanced order clause - set to 1 if ordering is provided",
* type="integer",
* required=false
* ),
* @SWG\Parameter(
* name="useFilteringClause",
* in="formData",
* description="EDIT Only - flag (0,1) Use advanced filter clause - set to 1 if filter is provided",
* type="integer",
* required=false
* ),
* @SWG\Parameter(
* name="noDataMessage",
* in="formData",
* description="EDIT Only - A message to display when no data is returned from the source",
* type="string",
* required=false
* ),
* @SWG\Response(
* response=201,
* description="successful operation",
* @SWG\Schema(ref="#/definitions/Widget"),
* @SWG\Header(
* header="Location",
* description="Location of the new widget",
* type="string"
* )
* )
* )
*/
public function add()
{
$this->setOption('name', $this->getSanitizer()->getString('name'));
$this->setUseDuration(0);
$this->setDuration($this->getModule()->defaultDuration);
$this->setOption('dataSetId', $this->getSanitizer()->getInt('dataSetId'));
// Save the widget
$this->validate();
$this->saveWidget();
}
/**
* Edit Media in the Database
*/
public function edit()
{
// Columns
$columns = $this->getSanitizer()->getIntArray('dataSetColumnId');
if (count($columns) == 0)
$this->setOption('columns', '');
else
$this->setOption('columns', implode(',', $columns));
// Other properties
$this->setOption('name', $this->getSanitizer()->getString('name'));
$this->setUseDuration($this->getSanitizer()->getCheckbox('useDuration'));
$this->setDuration($this->getSanitizer()->getInt('duration', $this->getDuration()));
$this->setOption('updateInterval', $this->getSanitizer()->getInt('updateInterval', 120));
$this->setOption('rowsPerPage', $this->getSanitizer()->getInt('rowsPerPage'));
$this->setOption('showHeadings', $this->getSanitizer()->getCheckbox('showHeadings'));
$this->setOption('upperLimit', $this->getSanitizer()->getInt('upperLimit', 0));
$this->setOption('lowerLimit', $this->getSanitizer()->getInt('lowerLimit', 0));
$this->setOption('filter', $this->getSanitizer()->getParam('filter', null));
$this->setOption('ordering', $this->getSanitizer()->getString('ordering'));
$this->setOption('templateId', $this->getSanitizer()->getString('templateId'));
$this->setOption('overrideTemplate', $this->getSanitizer()->getCheckbox('overrideTemplate', 1));
$this->setOption('useOrderingClause', $this->getSanitizer()->getCheckbox('useOrderingClause'));
$this->setOption('useFilteringClause', $this->getSanitizer()->getCheckbox('useFilteringClause'));
$this->setRawNode('noDataMessage', $this->getSanitizer()->getParam('noDataMessage', ''));
$this->setRawNode('javaScript', $this->getSanitizer()->getParam('javaScript', ''));
if( $this->getOption('overrideTemplate') == 1 ){
$this->setRawNode('styleSheet', $this->getSanitizer()->getParam('styleSheet', null));
}
// Order and Filter criteria
$orderClauses = $this->getSanitizer()->getStringArray('orderClause');
$orderClauseDirections = $this->getSanitizer()->getStringArray('orderClauseDirection');
$orderClauseMapping = [];
$i = -1;
foreach ($orderClauses as $orderClause) {
$i++;
if ($orderClause == '')
continue;
// Map the stop code received to the stop ref (if there is one)
$orderClauseMapping[] = [
'orderClause' => $orderClause,
'orderClauseDirection' => isset($orderClauseDirections[$i]) ? $orderClauseDirections[$i] : '',
];
}
$this->setOption('orderClauses', json_encode($orderClauseMapping));
$filterClauses = $this->getSanitizer()->getStringArray('filterClause');
$filterClauseOperator = $this->getSanitizer()->getStringArray('filterClauseOperator');
$filterClauseCriteria = $this->getSanitizer()->getStringArray('filterClauseCriteria');
$filterClauseValue = $this->getSanitizer()->getStringArray('filterClauseValue');
$filterClauseMapping = [];
$i = -1;
foreach ($filterClauses as $filterClause) {
$i++;
if ($filterClause == '')
continue;
// Map the stop code received to the stop ref (if there is one)
$filterClauseMapping[] = [
'filterClause' => $filterClause,
'filterClauseOperator' => isset($filterClauseOperator[$i]) ? $filterClauseOperator[$i] : '',
'filterClauseCriteria' => isset($filterClauseCriteria[$i]) ? $filterClauseCriteria[$i] : '',
'filterClauseValue' => isset($filterClauseValue[$i]) ? $filterClauseValue[$i] : '',
];
}
$this->setOption('filterClauses', json_encode($filterClauseMapping));
// Save the widget
$this->validate();
$this->saveWidget();
}
/**
* @inheritdoc
*/
public function hoverPreview()
{
// Default Hover window contains a thumbnail, media type and duration
$output = '<div class="well">';
$output .= '<div class="preview-module-image"><img alt="' . __($this->module->name) . ' thumbnail" src="' . $this->getConfig()->uri('img/' . $this->module->imageUri) . '" /></div>';
$output .= '<div class="info">';
$output .= ' <ul>';
$output .= ' <li>' . __('Type') . ': ' . $this->module->name . '</li>';
$output .= ' <li>' . __('Name') . ': ' . $this->getName() . '</li>';
// Get the DataSet name
try {
$dataSet = $this->dataSetFactory->getById($this->getOption('dataSetId'));
$output .= ' <li>' . __('Source: DataSet named "%s".', $dataSet->dataSet) . '</li>';
} catch (NotFoundException $notFoundException) {
$this->getLog()->error('Layout Widget without a DataSet. widgetId: ' . $this->getWidgetId());
$output .= ' <li>' . __('Warning: No DataSet found.') . '</li>';
}
if ($this->getUseDuration() == 1)
$output .= ' <li>' . __('Duration') . ': ' . $this->widget->duration . ' ' . __('seconds') . '</li>';
$output .= ' </ul>';
$output .= '</div>';
$output .= '</div>';
return $output;
}
/**
* GetResource
* Return the rendered resource to be used by the client (or a preview)
* for displaying this content.
* @param integer $displayId If this comes from a real client, this will be the display id.
* @return mixed
*/
public function getResource($displayId = 0)
{
// Load in the template
$data = [];
$isPreview = ($this->getSanitizer()->getCheckbox('preview') == 1);
// Clear all linked media.
$this->clearMedia();
// Replace the View Port Width?
$data['viewPortWidth'] = ($isPreview) ? $this->region->width : '[[ViewPortWidth]]';
// Get CSS from the original template or from the input field
$styleSheet = '';
if ($this->getOption('overrideTemplate', 1) == 0) {
$template = $this->getTemplateById($this->getOption('templateId'));
if (isset($template))
$styleSheet = $template['css'];
} else {
$styleSheet = $this->getRawNode('styleSheet', '');
}
// Get the embedded HTML out of RAW
$styleSheet = $this->parseLibraryReferences($isPreview, $styleSheet);
// Get the JavaScript node
$javaScript = $this->parseLibraryReferences($isPreview, $this->getRawNode('javaScript', ''));
$options = array(
'type' => $this->getModuleType(),
'duration' => $this->getCalculatedDurationForGetResource(),
'originalWidth' => $this->region->width,
'originalHeight' => $this->region->height,
'rowsPerPage' => $this->getOption('rowsPerPage'),
'previewWidth' => $this->getSanitizer()->getDouble('width', 0),
'previewHeight' => $this->getSanitizer()->getDouble('height', 0),
'scaleOverride' => $this->getSanitizer()->getDouble('scale_override', 0)
);
// Add our fonts.css file
$headContent = '<link href="' . (($isPreview) ? $this->getApp()->urlFor('library.font.css') : 'fonts.css') . '" rel="stylesheet" media="screen">';
$headContent .= '<style type="text/css">' . file_get_contents($this->getConfig()->uri('css/client.css', true)) . '</style>';
$headContent .= '<style type="text/css">' . $styleSheet . '</style>';
$data['head'] = $headContent;
$data['body'] = $this->dataSetTableHtml($displayId, $isPreview);
// Build some JS nodes
$javaScriptContent = '<script type="text/javascript" src="' . $this->getResourceUrl('vendor/jquery-1.11.1.min.js') . '"></script>';
$javaScriptContent .= '<script type="text/javascript" src="' . $this->getResourceUrl('vendor/jquery-cycle-2.1.6.min.js') . '"></script>';
$javaScriptContent .= '<script type="text/javascript" src="' . $this->getResourceUrl('xibo-layout-scaler.js') . '"></script>';
$javaScriptContent .= '<script type="text/javascript" src="' . $this->getResourceUrl('xibo-dataset-render.js') . '"></script>';
$javaScriptContent .= '<script type="text/javascript" src="' . $this->getResourceUrl('xibo-image-render.js') . '"></script>';
$javaScriptContent .= '<script type="text/javascript">';
$javaScriptContent .= ' var options = ' . json_encode($options) . ';';
$javaScriptContent .= ' $(document).ready(function() { ';
$javaScriptContent .= ' $("#DataSetTableContainer").dataSetRender(options); $("body").xiboLayoutScaler(options); $("#DataSetTableContainer").find("img").xiboImageRender(options); ';
$javaScriptContent .= ' }); ';
$javaScriptContent .= $javaScript;
$javaScriptContent .= '</script>';
// Replace the Head Content with our generated javascript
$data['javaScript'] = $javaScriptContent;
// Update and save widget if we've changed our assignments.
if ($this->hasMediaChanged())
$this->widget->save(['saveWidgetOptions' => false, 'notifyDisplays' => true, 'audit' => false]);
return $this->renderTemplate($data);
}
/**
* Get the Data Set Table
* @param int $displayId
* @param bool $isPreview
* @return string
*/
public function dataSetTableHtml($displayId = 0, $isPreview = true)
{
// Show a preview of the data set table output.
$dataSetId = $this->getOption('dataSetId');
$upperLimit = $this->getOption('upperLimit');
$lowerLimit = $this->getOption('lowerLimit');
$columnIds = $this->getOption('columns');
$showHeadings = $this->getOption('showHeadings');
$rowsPerPage = $this->getOption('rowsPerPage');
if ($columnIds == '')
return __('No columns');
// Ordering
$ordering = '';
if ($this->getOption('useOrderingClause', 1) == 1) {
$ordering = $this->getOption('ordering');
} else {
// Build an order string
foreach (json_decode($this->getOption('orderClauses', '[]'), true) as $clause) {
$ordering .= $clause['orderClause'] . ' ' . $clause['orderClauseDirection'] . ',';
}
$ordering = rtrim($ordering, ',');
}
// Filtering
$filter = '';
if ($this->getOption('useFilteringClause', 1) == 1) {
$filter = $this->getOption('filter');
} else {
// Build
$i = 0;
foreach (json_decode($this->getOption('filterClauses', '[]'), true) as $clause) {
$i++;
$criteria = '';
switch ($clause['filterClauseCriteria']) {
case 'starts-with':
$criteria = 'LIKE \'' . $clause['filterClauseValue'] . '%\'';
break;
case 'ends-with':
$criteria = 'LIKE \'%' . $clause['filterClauseValue'] . '\'';
break;
case 'contains':
$criteria = 'LIKE \'%' . $clause['filterClauseValue'] . '%\'';
break;
case 'equals':
$criteria = '= \'' . $clause['filterClauseValue'] . '\'';
break;
case 'not-contains':
$criteria = 'NOT LIKE \'%' . $clause['filterClauseValue'] . '%\'';
break;
case 'not-starts-with':
$criteria = 'NOT LIKE \'' . $clause['filterClauseValue'] . '%\'';
break;
case 'not-ends-with':
$criteria = 'NOT LIKE \'%' . $clause['filterClauseValue'] . '\'';
break;
case 'not-equals':
$criteria = '<> \'' . $clause['filterClauseValue'] . '\'';
break;
case 'greater-than':
$criteria = '> \'' . $clause['filterClauseValue'] . '\'';
break;
case 'less-than':
$criteria = '< \'' . $clause['filterClauseValue'] . '\'';
break;
default:
continue;
}
if ($i > 1)
$filter .= ' ' . $clause['filterClauseOperator'] . ' ';
$filter .= $clause['filterClause'] . ' ' . $criteria;
}
}
// Array of columnIds we want
$columnIds = explode(',', $columnIds);
// Set an expiry time for the media
$expires = time() + ($this->getOption('updateInterval', 3600) * 60);
// Create a data set object, to get the results.
try {
$dataSet = $this->dataSetFactory->getById($dataSetId);
// Get an array representing the id->heading mappings
$mappings = [];
foreach ($columnIds as $dataSetColumnId) {
// Get the column definition this represents
$column = $dataSet->getColumn($dataSetColumnId);
/* @var DataSetColumn $column */
$mappings[] = [
'dataSetColumnId' => $dataSetColumnId,
'heading' => $column->heading,
'dataTypeId' => $column->dataTypeId
];
}
$this->getLog()->debug('Resolved column mappings: %s', json_encode($columnIds));
$filter = [
'filter' => $filter,
'order' => $ordering,
'displayId' => $displayId
];
// limits?
if ($lowerLimit != 0 || $upperLimit != 0) {
// Start should be the lower limit
// Size should be the distance between upper and lower
$filter['start'] = $lowerLimit;
$filter['size'] = $upperLimit - $lowerLimit;
}
// Set the timezone for SQL
$dateNow = $this->getDate()->parse();
if ($displayId != 0) {
$display = $this->displayFactory->getById($displayId);
$timeZone = $display->getSetting('displayTimeZone', '');
$timeZone = ($timeZone == '') ? $this->getConfig()->GetSetting('defaultTimezone') : $timeZone;
$dateNow->timezone($timeZone);
$this->getLog()->debug('Display Timezone Resolved: %s. Time: %s.', $timeZone, $dateNow->toDateTimeString());
}
$this->getStore()->setTimeZone($this->getDate()->getLocalDate($dateNow, 'P'));
// Get the data (complete table, filtered)
$dataSetResults = $dataSet->getData($filter);
if (count($dataSetResults) <= 0) {
if ($this->getRawNode('noDataMessage') == '')
throw new NotFoundException(__('Empty Result Set with filter criteria.'));
else
return $this->getRawNode('noDataMessage');
}
$rowCount = 1;
$rowCountThisPage = 1;
$totalRows = count($dataSetResults);
if ($rowsPerPage > 0)
$totalPages = $totalRows / $rowsPerPage;
else
$totalPages = 1;
$table = '<div id="DataSetTableContainer" totalRows="' . $totalRows . '" totalPages="' . $totalPages . '">';
// Parse each result and
foreach ($dataSetResults as $row) {
if (($rowsPerPage > 0 && $rowCountThisPage >= $rowsPerPage) || $rowCount == 1) {
// Reset the row count on this page
$rowCountThisPage = 0;
if ($rowCount > 1) {
$table .= '</tbody>';
$table .= '</table>';
}
// Output the table header
$table .= '<table class="DataSetTable">';
if ($showHeadings == 1) {
$table .= '<thead>';
$table .= ' <tr class="HeaderRow">';
foreach ($mappings as $mapping)
$table .= '<th class="DataSetColumnHeaderCell">' . $mapping['heading'] . '</th>';
$table .= ' </tr>';
$table .= '</thead>';
}
$table .= '<tbody>';
}
$table .= '<tr class="DataSetRow DataSetRow' . (($rowCount % 2) ? 'Odd' : 'Even') . '" id="row_' . $rowCount . '">';
// Output each cell for these results
$i = 0;
foreach ($mappings as $mapping) {
$i++;
// Pull out the cell for this row / column
$replace = $row[$mapping['heading']];
// If the value is empty, then move on
if ($replace == '')
continue;
// What if this column is an image column type?
if ($mapping['dataTypeId'] == 4) {
// Grab the external image
$file = $this->mediaFactory->queueDownload('datasetview_' . md5($dataSetId . $mapping['dataSetColumnId'] . $replace), str_replace(' ', '%20', htmlspecialchars_decode($replace)), $expires);
$replace = ($isPreview)
? '<img src="' . $this->getApp()->urlFor('library.download', ['id' => $file->mediaId, 'type' => 'image']) . '?preview=1" />'
: '<img src="' . $file->storedAs . '" />';
} else if ($mapping['dataTypeId'] == 5) {
// Library Image
// The content is the ID of the image
try {
$file = $this->mediaFactory->getById($replace);
// Already in the library - assign this mediaId to the Layout immediately.
$this->assignMedia($file->mediaId);
}
catch (NotFoundException $e) {
$this->getLog()->error('Library Image [%s] not found in DataSetId %d.', $replace, $dataSetId);
continue;
}
$replace = ($isPreview)
? '<img src="' . $this->getApp()->urlFor('library.download', ['id' => $file->mediaId, 'type' => 'image']) . '?preview=1" />'
: '<img src="' . $file->storedAs . '" />';
}
$table .= '<td class="DataSetColumn" id="column_' . ($i + 1) . '"><span class="DataSetCellSpan" id="span_' . $rowCount . '_' . ($i + 1) . '">' . $replace . '</span></td>';
}
// Process queued downloads
$this->mediaFactory->processDownloads(function($media) {
// Success
$this->getLog()->debug('Successfully downloaded ' . $media->mediaId);
// Tag this layout with this file
$this->assignMedia($media->mediaId);
});
$table .= '</tr>';
$rowCount++;
$rowCountThisPage++;
}
$table .= '</tbody>';
$table .= '</table>';
$table .= '</div>';
return $table;
}
catch (NotFoundException $e) {
$this->getLog()->error('Request failed for dataSet id=%d. Widget=%d. Due to %s', $dataSetId, $this->getWidgetId(), $e->getMessage());
$this->getLog()->debug($e->getTraceAsString());
return '';
}
}
/**
* Is Valid
* @return int
*/
public function IsValid()
{
// DataSet rendering will be valid
return 1;
}
}