2014-05-14 23:24:20 +10:00
< ? php namespace Backend\Widgets ;
2015-02-04 20:03:44 +11:00
use Db ;
2016-12-10 09:02:06 +11:00
use Html ;
2014-05-14 23:24:20 +10:00
use Lang ;
use Backend ;
2014-05-20 15:45:20 +10:00
use DbDongle ;
2014-05-27 13:44:28 +10:00
use Carbon\Carbon ;
2015-03-07 12:48:39 +11:00
use October\Rain\Html\Helper as HtmlHelper ;
2014-05-14 23:24:20 +10:00
use October\Rain\Router\Helper as RouterHelper ;
2015-09-17 05:15:12 +10:00
use System\Helpers\DateTime as DateTimeHelper ;
2016-10-21 07:15:08 +11:00
use System\Classes\PluginManager ;
2020-08-21 17:54:31 -06:00
use System\Classes\MediaLibrary ;
use System\Classes\ImageResizer ;
2014-05-14 23:24:20 +10:00
use Backend\Classes\ListColumn ;
use Backend\Classes\WidgetBase ;
use October\Rain\Database\Model ;
2016-12-10 09:02:06 +11:00
use ApplicationException ;
2019-10-10 00:41:53 +02:00
use BackendAuth ;
2014-05-14 23:24:20 +10:00
/**
* List Widget
* Used for building back end lists , renders a list of model objects
*
* @ package october\backend
* @ author Alexey Bobkov , Samuel Georges
*/
class Lists extends WidgetBase
{
2019-06-08 11:28:08 +08:00
use Backend\Traits\PreferenceMaker ;
2015-02-28 12:41:45 +11:00
//
// Configurable properties
//
2015-02-28 11:50:27 +11:00
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var array List column configuration .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
public $columns ;
2014-05-14 23:24:20 +10:00
/**
* @ var Model List model object .
*/
public $model ;
/**
2015-02-28 12:41:45 +11:00
* @ var string Link for each record row . Replace : id with the record id .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
public $recordUrl ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var string Click event for each record row . Replace : id with the record id .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
public $recordOnClick ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var string Message to display when there are no records in the list .
2014-05-14 23:24:20 +10:00
*/
2015-09-23 15:14:10 +02:00
public $noRecordsMessage = 'backend::lang.list.no_records' ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var int Maximum rows to display for each page .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
public $recordsPerPage ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var bool Shows the sorting options for each column .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
public $showSorting = true ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var mixed A default sort column to look for .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
public $defaultSort ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var bool Display a checkbox next to each record row .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
public $showCheckboxes = false ;
2014-05-14 23:24:20 +10:00
2015-02-07 10:24:28 +11:00
/**
2015-02-28 12:41:45 +11:00
* @ var bool Display the list set up used for column visibility and ordering .
2015-02-07 10:24:28 +11:00
*/
2015-02-28 12:41:45 +11:00
public $showSetup = false ;
2015-02-07 10:24:28 +11:00
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var bool Display parent / child relationships in the list .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
public $showTree = false ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var bool Expand the tree nodes by default .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
public $treeExpanded = false ;
2014-08-13 21:23:19 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var bool | string Display pagination when limiting records per page .
2014-08-13 21:23:19 +10:00
*/
2015-02-28 12:41:45 +11:00
public $showPagination = 'auto' ;
2017-09-05 13:33:51 +10:00
/**
2017-09-06 09:00:53 +10:00
* @ var bool Display page numbers with pagination , disable to improve performance .
2017-09-05 13:33:51 +10:00
*/
public $showPageNumbers = true ;
2016-10-29 14:10:21 +11:00
/**
* @ var string Specify a custom view path to override partials used by the list .
*/
public $customViewPath ;
2015-02-28 12:41:45 +11:00
//
// Object properties
//
2014-05-14 23:24:20 +10:00
/**
2017-03-16 06:26:14 +11:00
* @ inheritDoc
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
protected $defaultAlias = 'list' ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var array Collection of all list columns used in this list .
* @ see Backend\Classes\ListColumn
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
protected $allColumns ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var array Override default columns with supplied key names .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
protected $columnOverride ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var array Columns to display and their order .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
protected $visibleColumns ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var array Model data collection .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
protected $records ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var int Current page number .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
protected $currentPageNumber ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var string Filter the records by a search term .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
protected $searchTerm ;
2014-05-14 23:24:20 +10:00
2016-04-19 19:54:22 +10:00
/**
* @ var string If searching the records , specifies a policy to use .
* - all : result must contain all words
* - any : result can contain any word
* - exact : result must contain the exact phrase
*/
protected $searchMode ;
/**
* @ var string Use a custom scope method for performing searches .
*/
protected $searchScope ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var array Collection of functions to apply to each list query .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
protected $filterCallbacks = [];
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var array All sortable columns .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
protected $sortableColumns ;
2014-05-14 23:24:20 +10:00
/**
2015-02-28 12:41:45 +11:00
* @ var string Sets the list sorting column .
2014-05-14 23:24:20 +10:00
*/
2015-02-28 12:41:45 +11:00
protected $sortColumn ;
/**
* @ var string Sets the list sorting direction ( asc , desc )
*/
protected $sortDirection ;
2014-05-14 23:24:20 +10:00
2014-06-30 19:57:53 +10:00
/**
* @ var array List of CSS classes to apply to the list container element
*/
public $cssClasses = [];
2014-05-14 23:24:20 +10:00
/**
* Initialize the widget , called by the constructor and free from its parameters .
*/
public function init ()
{
2015-02-28 12:41:45 +11:00
$this -> fillFromConfig ([
'columns' ,
'model' ,
'recordUrl' ,
'recordOnClick' ,
'noRecordsMessage' ,
2017-09-05 13:33:51 +10:00
'showPageNumbers' ,
2015-02-28 12:41:45 +11:00
'recordsPerPage' ,
'showSorting' ,
'defaultSort' ,
'showCheckboxes' ,
'showSetup' ,
'showTree' ,
'treeExpanded' ,
'showPagination' ,
2016-10-29 14:10:21 +11:00
'customViewPath' ,
2015-02-28 12:41:45 +11:00
]);
2014-05-14 23:24:20 +10:00
/*
* Configure the list widget
*/
2020-02-10 07:24:09 +01:00
if ( $this -> showSetup ) {
$this -> recordsPerPage = $this -> getUserPreference ( 'per_page' , $this -> recordsPerPage );
}
2015-02-28 12:41:45 +11:00
if ( $this -> showPagination == 'auto' ) {
$this -> showPagination = $this -> recordsPerPage && $this -> recordsPerPage > 0 ;
}
2016-10-29 14:10:21 +11:00
if ( $this -> customViewPath ) {
$this -> addViewPath ( $this -> customViewPath );
}
2015-02-28 12:41:45 +11:00
$this -> validateModel ();
2014-05-14 23:24:20 +10:00
$this -> validateTree ();
}
/**
2017-03-16 06:26:14 +11:00
* @ inheritDoc
2014-05-14 23:24:20 +10:00
*/
2015-08-04 19:32:51 +10:00
protected function loadAssets ()
2014-05-14 23:24:20 +10:00
{
2014-05-24 16:57:38 +10:00
$this -> addJs ( 'js/october.list.js' , 'core' );
2014-05-14 23:24:20 +10:00
}
/**
* Renders the widget .
*/
public function render ()
{
$this -> prepareVars ();
2014-06-30 18:27:17 +10:00
return $this -> makePartial ( 'list-container' );
2014-05-14 23:24:20 +10:00
}
/**
* Prepares the list data
*/
public function prepareVars ()
{
2014-06-30 19:57:53 +10:00
$this -> vars [ 'cssClasses' ] = implode ( ' ' , $this -> cssClasses );
2015-01-27 20:02:20 +11:00
$this -> vars [ 'columns' ] = $this -> getVisibleColumns ();
2014-05-14 23:24:20 +10:00
$this -> vars [ 'columnTotal' ] = $this -> getTotalColumns ();
$this -> vars [ 'records' ] = $this -> getRecords ();
$this -> vars [ 'noRecordsMessage' ] = trans ( $this -> noRecordsMessage );
$this -> vars [ 'showCheckboxes' ] = $this -> showCheckboxes ;
$this -> vars [ 'showSetup' ] = $this -> showSetup ;
$this -> vars [ 'showPagination' ] = $this -> showPagination ;
2017-09-05 13:33:51 +10:00
$this -> vars [ 'showPageNumbers' ] = $this -> showPageNumbers ;
2014-05-14 23:24:20 +10:00
$this -> vars [ 'showSorting' ] = $this -> showSorting ;
$this -> vars [ 'sortColumn' ] = $this -> getSortColumn ();
$this -> vars [ 'sortDirection' ] = $this -> sortDirection ;
$this -> vars [ 'showTree' ] = $this -> showTree ;
$this -> vars [ 'treeLevel' ] = 0 ;
if ( $this -> showPagination ) {
2015-02-05 19:47:20 +11:00
$this -> vars [ 'pageCurrent' ] = $this -> records -> currentPage ();
2018-03-08 16:52:21 +00:00
// Store the currently visited page number in the session so the same
// data can be displayed when the user returns to this list.
$this -> putSession ( 'lastVisitedPage' , $this -> vars [ 'pageCurrent' ]);
2017-09-05 13:33:51 +10:00
if ( $this -> showPageNumbers ) {
$this -> vars [ 'recordTotal' ] = $this -> records -> total ();
$this -> vars [ 'pageLast' ] = $this -> records -> lastPage ();
$this -> vars [ 'pageFrom' ] = $this -> records -> firstItem ();
$this -> vars [ 'pageTo' ] = $this -> records -> lastItem ();
2017-09-06 09:00:53 +10:00
}
else {
2017-09-05 13:33:51 +10:00
$this -> vars [ 'hasMorePages' ] = $this -> records -> hasMorePages ();
}
2014-11-01 12:00:45 +11:00
}
else {
2014-05-14 23:24:20 +10:00
$this -> vars [ 'recordTotal' ] = $this -> records -> count ();
$this -> vars [ 'pageCurrent' ] = 1 ;
}
}
/**
* Event handler for refreshing the list .
*/
2014-07-03 18:35:35 +10:00
public function onRefresh ()
2014-05-14 23:24:20 +10:00
{
$this -> prepareVars ();
return [ '#' . $this -> getId () => $this -> makePartial ( 'list' )];
}
/**
* Event handler for switching the page number .
*/
public function onPaginate ()
{
2015-02-07 10:24:28 +11:00
$this -> currentPageNumber = post ( 'page' );
2014-07-03 18:35:35 +10:00
return $this -> onRefresh ();
2014-05-14 23:24:20 +10:00
}
2018-07-16 08:43:47 -05:00
/**
* Event handler for changing the filter
*/
public function onFilter ()
{
$this -> currentPageNumber = 1 ;
return $this -> onRefresh ();
}
2014-05-14 23:24:20 +10:00
/**
* Validate the supplied form model .
* @ return void
*/
protected function validateModel ()
{
2014-10-11 00:39:34 +02:00
if ( ! $this -> model ) {
throw new ApplicationException ( Lang :: get (
'backend::lang.list.missing_model' ,
[ 'class' => get_class ( $this -> controller )]
));
}
2014-05-14 23:24:20 +10:00
2014-10-11 00:39:34 +02:00
if ( ! $this -> model instanceof Model ) {
throw new ApplicationException ( Lang :: get (
'backend::lang.model.invalid_class' ,
[ 'model' => get_class ( $this -> model ), 'class' => get_class ( $this -> controller )]
));
}
2014-05-14 23:24:20 +10:00
return $this -> model ;
}
/**
* Replaces the @ symbol with a table name in a model
* @ param string $sql
* @ param string $table
* @ return string
*/
2014-08-01 18:18:09 +10:00
protected function parseTableName ( $sql , $table )
2014-05-14 23:24:20 +10:00
{
return str_replace ( '@' , $table . '.' , $sql );
}
/**
* Applies any filters to the model .
*/
2018-12-30 16:25:01 +08:00
public function prepareQuery ()
2014-05-14 23:24:20 +10:00
{
$query = $this -> model -> newQuery ();
2014-08-16 14:08:51 +10:00
$primaryTable = $this -> model -> getTable ();
$selects = [ $primaryTable . '.*' ];
2014-05-14 23:24:20 +10:00
$joins = [];
2014-08-16 14:08:51 +10:00
$withs = [];
2019-04-19 23:31:12 +01:00
$bindings = [];
2014-05-14 23:24:20 +10:00
2018-08-13 08:11:35 -06:00
/**
* @ event backend . list . extendQueryBefore
* Provides an opportunity to modify the `$query` object before the List widget applies its scopes to it .
*
* Example usage :
*
2019-08-15 16:14:54 +01:00
* Event :: listen ( 'backend.list.extendQueryBefore' , function ( $listWidget , $query ) {
2018-08-13 08:11:35 -06:00
* $query -> whereNull ( 'deleted_at' );
* });
*
* Or
*
* $listWidget -> bindEvent ( 'list.extendQueryBefore' , function ( $query ) {
* $query -> whereNull ( 'deleted_at' );
* });
*
2014-05-14 23:24:20 +10:00
*/
2016-12-10 09:02:06 +11:00
$this -> fireSystemEvent ( 'backend.list.extendQueryBefore' , [ $query ]);
2014-05-14 23:24:20 +10:00
/*
2014-08-16 14:08:51 +10:00
* Prepare searchable column names
2014-05-14 23:24:20 +10:00
*/
2014-08-16 14:08:51 +10:00
$primarySearchable = [];
$relationSearchable = [];
2014-05-14 23:24:20 +10:00
2014-08-16 14:08:51 +10:00
$columnsToSearch = [];
if ( ! empty ( $this -> searchTerm ) && ( $searchableColumns = $this -> getSearchableColumns ())) {
foreach ( $searchableColumns as $column ) {
/*
* Related
*/
if ( $this -> isColumnRelated ( $column )) {
$table = $this -> model -> makeRelation ( $column -> relation ) -> getTable ();
$columnName = isset ( $column -> sqlSelect )
? DbDongle :: raw ( $this -> parseTableName ( $column -> sqlSelect , $table ))
2014-09-17 19:08:49 +10:00
: $table . '.' . $column -> valueFrom ;
2014-08-16 14:08:51 +10:00
$relationSearchable [ $column -> relation ][] = $columnName ;
2014-11-01 12:00:45 +11:00
}
2014-08-16 14:08:51 +10:00
/*
* Primary
*/
2014-11-01 12:00:45 +11:00
else {
2014-08-16 14:08:51 +10:00
$columnName = isset ( $column -> sqlSelect )
? DbDongle :: raw ( $this -> parseTableName ( $column -> sqlSelect , $primaryTable ))
2016-06-04 17:14:05 +10:00
: DbDongle :: cast ( Db :: getTablePrefix () . $primaryTable . '.' . $column -> columnName , 'TEXT' );
2014-08-16 14:08:51 +10:00
$primarySearchable [] = $columnName ;
}
}
}
2014-05-14 23:24:20 +10:00
2014-08-16 14:08:51 +10:00
/*
* Prepare related eager loads ( withs ) and custom selects ( joins )
*/
2015-01-27 20:02:20 +11:00
foreach ( $this -> getVisibleColumns () as $column ) {
2018-01-25 16:54:06 -06:00
// If useRelationCount is enabled, eager load the count of the relation into $relation_count
if ( $column -> relation && @ $column -> config [ 'useRelationCount' ]) {
$query -> withCount ( $column -> relation );
}
2014-10-11 00:39:34 +02:00
if ( ! $this -> isColumnRelated ( $column ) || ( ! isset ( $column -> sqlSelect ) && ! isset ( $column -> valueFrom ))) {
2014-08-16 14:08:51 +10:00
continue ;
2014-10-11 00:39:34 +02:00
}
2014-08-16 14:08:51 +10:00
2014-10-11 00:39:34 +02:00
if ( isset ( $column -> valueFrom )) {
2014-08-16 14:08:51 +10:00
$withs [] = $column -> relation ;
2014-10-11 00:39:34 +02:00
}
2014-06-05 18:52:53 +10:00
2014-05-14 23:24:20 +10:00
$joins [] = $column -> relation ;
}
2014-08-16 14:08:51 +10:00
/*
* Add eager loads to the query
*/
if ( $withs ) {
$query -> with ( array_unique ( $withs ));
}
2014-05-14 23:24:20 +10:00
2015-04-06 16:25:43 +10:00
/*
* Apply search term
*/
$query -> where ( function ( $innerQuery ) use ( $primarySearchable , $relationSearchable , $joins ) {
/*
* Search primary columns
*/
if ( count ( $primarySearchable ) > 0 ) {
2016-04-19 19:54:22 +10:00
$this -> applySearchToQuery ( $innerQuery , $primarySearchable , 'or' );
2015-04-06 16:25:43 +10:00
}
/*
* Search relation columns
*/
if ( $joins ) {
foreach ( array_unique ( $joins ) as $join ) {
/*
* Apply a supplied search term for relation columns and
* constrain the query only if there is something to search for
*/
$columnsToSearch = array_get ( $relationSearchable , $join , []);
if ( count ( $columnsToSearch ) > 0 ) {
$innerQuery -> orWhereHas ( $join , function ( $_query ) use ( $columnsToSearch ) {
2016-04-19 19:54:22 +10:00
$this -> applySearchToQuery ( $_query , $columnsToSearch );
2015-04-06 16:25:43 +10:00
});
}
}
}
});
2014-05-14 23:24:20 +10:00
/*
* Custom select queries
*/
2015-01-27 20:02:20 +11:00
foreach ( $this -> getVisibleColumns () as $column ) {
2014-10-11 00:39:34 +02:00
if ( ! isset ( $column -> sqlSelect )) {
2014-05-14 23:24:20 +10:00
continue ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2016-01-10 14:10:49 +01:00
$alias = $query -> getQuery () -> getGrammar () -> wrap ( $column -> columnName );
2014-08-16 14:08:51 +10:00
/*
* Relation column
*/
if ( isset ( $column -> relation )) {
2015-07-18 08:47:02 +10:00
// @todo Find a way...
2014-08-16 14:08:51 +10:00
$relationType = $this -> model -> getRelationType ( $column -> relation );
2015-07-18 08:47:02 +10:00
if ( $relationType == 'morphTo' ) {
throw new ApplicationException ( 'The relationship morphTo is not supported for list columns.' );
}
$table = $this -> model -> makeRelation ( $column -> relation ) -> getTable ();
2014-08-16 14:08:51 +10:00
$sqlSelect = $this -> parseTableName ( $column -> sqlSelect , $table );
/*
* Manipulate a count query for the sub query
*/
$relationObj = $this -> model -> { $column -> relation }();
2017-05-16 18:50:41 +10:00
$countQuery = $relationObj -> getRelationExistenceQuery ( $relationObj -> getRelated () -> newQueryWithoutScopes (), $query );
2014-08-16 14:08:51 +10:00
$joinSql = $this -> isColumnRelated ( $column , true )
? DbDongle :: raw ( " group_concat( " . $sqlSelect . " separator ', ') " )
: DbDongle :: raw ( $sqlSelect );
$joinSql = $countQuery -> select ( $joinSql ) -> toSql ();
$selects [] = Db :: raw ( " ( " . $joinSql . " ) as " . $alias );
2019-06-08 11:28:08 +08:00
2019-04-19 23:31:12 +01:00
/*
* If this is a polymorphic relation there will be bindings that need to be added to the query
*/
$bindings = array_merge ( $bindings , $countQuery -> getBindings ());
2014-11-01 12:00:45 +11:00
}
2014-08-16 14:08:51 +10:00
/*
* Primary column
*/
2014-11-01 12:00:45 +11:00
else {
2014-08-16 14:08:51 +10:00
$sqlSelect = $this -> parseTableName ( $column -> sqlSelect , $primaryTable );
$selects [] = DbDongle :: raw ( $sqlSelect . ' as ' . $alias );
}
2014-05-14 23:24:20 +10:00
}
/*
2014-08-16 14:08:51 +10:00
* Apply sorting
2014-05-14 23:24:20 +10:00
*/
2020-07-30 10:54:09 -06:00
if (( $sortColumn = $this -> getSortColumn ()) && ! $this -> showTree && in_array ( $sortColumn , array_keys ( $this -> getVisibleColumns ()))) {
2015-02-28 12:41:45 +11:00
if (( $column = array_get ( $this -> allColumns , $sortColumn )) && $column -> valueFrom ) {
2015-08-05 19:53:05 +10:00
$sortColumn = $this -> isColumnPivot ( $column )
? 'pivot_' . $column -> valueFrom
: $column -> valueFrom ;
2014-10-11 00:39:34 +02:00
}
2014-08-23 17:35:18 +10:00
2018-01-25 16:54:06 -06:00
// Set the sorting column to $relation_count if useRelationCount enabled
if ( isset ( $column -> relation ) && @ $column -> config [ 'useRelationCount' ]) {
$sortColumn = $column -> relation . '_count' ;
}
2014-05-14 23:24:20 +10:00
$query -> orderBy ( $sortColumn , $this -> sortDirection );
}
/*
2014-08-13 21:23:19 +10:00
* Apply filters
2014-05-14 23:24:20 +10:00
*/
2014-08-13 21:23:19 +10:00
foreach ( $this -> filterCallbacks as $callback ) {
$callback ( $query );
}
2014-05-14 23:24:20 +10:00
2014-08-23 13:07:39 +10:00
/*
* Add custom selects
*/
2018-01-25 16:54:06 -06:00
$query -> addSelect ( $selects );
2019-06-08 11:28:08 +08:00
2019-04-19 23:31:12 +01:00
/*
* Add bindings for polymorphic relations
*/
$query -> addBinding ( $bindings , 'select' );
2014-08-23 13:07:39 +10:00
2018-08-13 08:11:35 -06:00
/**
* @ event backend . list . extendQuery
* Provides an opportunity to modify and / or return the `$query` object after the List widget has applied its scopes to it and before it ' s used to get the records .
*
* Example usage :
*
2019-08-15 16:14:54 +01:00
* Event :: listen ( 'backend.list.extendQuery' , function ( $listWidget , $query ) {
2018-08-13 08:11:35 -06:00
* $newQuery = MyModel :: newQuery ();
* return $newQuery ;
* });
*
* Or
*
* $listWidget -> bindEvent ( 'list.extendQuery' , function ( $query ) {
* $query -> whereNull ( 'deleted_at' );
* });
*
2014-05-14 23:24:20 +10:00
*/
2016-12-10 09:02:06 +11:00
if ( $event = $this -> fireSystemEvent ( 'backend.list.extendQuery' , [ $query ])) {
2015-02-28 22:07:06 +11:00
return $event ;
}
2014-05-14 23:24:20 +10:00
return $query ;
}
2018-12-30 16:25:01 +08:00
public function prepareModel ()
{
traceLog ( 'Method ' . __METHOD__ . '() has been deprecated, please use the ' . __CLASS__ . '::prepareQuery() method instead.' );
return $this -> prepareQuery ();
}
2014-05-14 23:24:20 +10:00
/**
* Returns all the records from the supplied model , after filtering .
* @ return Collection
*/
protected function getRecords ()
{
2018-12-30 16:25:01 +08:00
$query = $this -> prepareQuery ();
2016-02-27 11:29:07 +11:00
2014-05-14 23:24:20 +10:00
if ( $this -> showTree ) {
2018-12-30 16:25:01 +08:00
$records = $query -> getNested ();
2016-02-27 11:29:07 +11:00
}
elseif ( $this -> showPagination ) {
2018-03-08 16:52:21 +00:00
$method = $this -> showPageNumbers ? 'paginate' : 'simplePaginate' ;
2018-12-31 02:49:42 +08:00
$currentPageNumber = $this -> getCurrentPageNumber ( $query );
2018-12-30 16:25:01 +08:00
$records = $query -> { $method }( $this -> recordsPerPage , $currentPageNumber );
2014-11-01 12:00:45 +11:00
}
else {
2018-12-30 16:25:01 +08:00
$records = $query -> get ();
2014-05-14 23:24:20 +10:00
}
2018-08-13 08:11:35 -06:00
/**
* @ event backend . list . extendRecords
* Provides an opportunity to modify and / or return the `$records` Collection object before the widget uses it .
*
* Example usage :
*
2019-08-15 16:14:54 +01:00
* Event :: listen ( 'backend.list.extendRecords' , function ( $listWidget , $records ) {
2018-08-13 08:11:35 -06:00
* $model = MyModel :: where ( 'always_include' , true ) -> first ();
* $records -> prepend ( $model );
* });
*
* Or
*
* $listWidget -> bindEvent ( 'list.extendRecords' , function ( $records ) {
* $model = MyModel :: where ( 'always_include' , true ) -> first ();
* $records -> prepend ( $model );
* });
*
2016-03-18 21:05:23 -03:00
*/
2017-02-15 05:58:44 +11:00
if ( $event = $this -> fireSystemEvent ( 'backend.list.extendRecords' , [ & $records ])) {
2016-03-18 21:05:23 -03:00
$records = $event ;
}
2014-05-14 23:24:20 +10:00
return $this -> records = $records ;
}
2018-12-31 02:49:42 +08:00
/**
* Returns the current page number for the list .
*
* This will override the current page number provided by the user if it is past the last page of available records .
*
* @ param object $query
* @ return int
*/
protected function getCurrentPageNumber ( $query )
{
$currentPageNumber = $this -> currentPageNumber ;
2020-02-12 16:52:09 +01:00
if ( empty ( $currentPageNumber )) {
2018-12-31 02:49:42 +08:00
$currentPageNumber = $this -> getSession ( 'lastVisitedPage' );
}
$currentPageNumber = intval ( $currentPageNumber );
if ( $currentPageNumber > 1 ) {
$count = $query -> count ();
// If the current page number is higher than the amount of available pages, go to the last available page
if ( $count <= (( $currentPageNumber - 1 ) * $this -> recordsPerPage )) {
$currentPageNumber = ceil ( $count / $this -> recordsPerPage );
}
}
return $currentPageNumber ;
}
2014-05-14 23:24:20 +10:00
/**
* Returns the record URL address for a list row .
* @ param Model $record
* @ return string
*/
public function getRecordUrl ( $record )
{
2014-10-11 00:39:34 +02:00
if ( isset ( $this -> recordOnClick )) {
2014-05-14 23:24:20 +10:00
return 'javascript:;' ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2014-10-11 00:39:34 +02:00
if ( ! isset ( $this -> recordUrl )) {
2014-05-14 23:24:20 +10:00
return null ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2018-12-18 09:03:03 -07:00
$url = RouterHelper :: replaceParameters ( $record , $this -> recordUrl );
2014-05-14 23:24:20 +10:00
return Backend :: url ( $url );
}
/**
* Returns the onclick event for a list row .
* @ param Model $record
* @ return string
*/
public function getRecordOnClick ( $record )
{
2014-10-11 00:39:34 +02:00
if ( ! isset ( $this -> recordOnClick )) {
2014-05-14 23:24:20 +10:00
return null ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2018-12-18 09:03:03 -07:00
$recordOnClick = RouterHelper :: replaceParameters ( $record , $this -> recordOnClick );
2014-05-14 23:24:20 +10:00
return Html :: attributes ([ 'onclick' => $recordOnClick ]);
}
2014-08-23 21:46:03 +10:00
/**
* Get all the registered columns for the instance .
* @ return array
*/
public function getColumns ()
{
2015-02-28 12:41:45 +11:00
return $this -> allColumns ? : $this -> defineListColumns ();
2014-08-23 21:46:03 +10:00
}
/**
* Get a specified column object
* @ param string $column
* @ return mixed
*/
public function getColumn ( $column )
{
2019-10-10 00:41:53 +02:00
if ( ! isset ( $this -> allColumns [ $column ])) {
throw new ApplicationException ( 'No definition for column ' . $column );
}
2015-02-28 12:41:45 +11:00
return $this -> allColumns [ $column ];
2014-08-23 21:46:03 +10:00
}
2014-05-14 23:24:20 +10:00
/**
* Returns the list columns that are visible by list settings or default
*/
2015-01-27 20:02:20 +11:00
public function getVisibleColumns ()
2014-05-14 23:24:20 +10:00
{
2014-08-23 21:46:03 +10:00
$definitions = $this -> defineListColumns ();
2014-05-14 23:24:20 +10:00
$columns = [];
/*
* Supplied column list
*/
2020-02-10 07:24:09 +01:00
if ( $this -> showSetup && $this -> columnOverride === null ) {
2019-06-08 11:28:08 +08:00
$this -> columnOverride = $this -> getUserPreference ( 'visible' , null );
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
if ( $this -> columnOverride && is_array ( $this -> columnOverride )) {
$invalidColumns = array_diff ( $this -> columnOverride , array_keys ( $definitions ));
2014-10-11 00:39:34 +02:00
if ( ! count ( $definitions )) {
throw new ApplicationException ( Lang :: get (
'backend::lang.list.missing_column' ,
[ 'columns' => implode ( ',' , $invalidColumns )]
));
}
2014-05-14 23:24:20 +10:00
2015-01-20 23:48:38 +02:00
$availableColumns = array_intersect ( $this -> columnOverride , array_keys ( $definitions ));
foreach ( $availableColumns as $columnName ) {
2014-05-14 23:24:20 +10:00
$definitions [ $columnName ] -> invisible = false ;
$columns [ $columnName ] = $definitions [ $columnName ];
}
2014-11-01 12:00:45 +11:00
}
2014-05-14 23:24:20 +10:00
/*
* Use default column list
*/
2014-11-01 12:00:45 +11:00
else {
2014-05-14 23:24:20 +10:00
foreach ( $definitions as $columnName => $column ) {
2014-10-11 00:39:34 +02:00
if ( $column -> invisible ) {
2014-05-14 23:24:20 +10:00
continue ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
$columns [ $columnName ] = $definitions [ $columnName ];
}
}
return $this -> visibleColumns = $columns ;
}
/**
* Builds an array of list columns with keys as the column name and values as a ListColumn object .
*/
2014-08-23 21:46:03 +10:00
protected function defineListColumns ()
2014-05-14 23:24:20 +10:00
{
2015-02-28 12:41:45 +11:00
if ( ! isset ( $this -> columns ) || ! is_array ( $this -> columns ) || ! count ( $this -> columns )) {
2016-05-17 05:17:40 +10:00
$class = get_class ( $this -> model instanceof Model ? $this -> model : $this -> controller );
throw new ApplicationException ( Lang :: get ( 'backend::lang.list.missing_columns' , compact ( 'class' )));
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2015-02-28 12:41:45 +11:00
$this -> addColumns ( $this -> columns );
2014-06-08 10:52:46 +10:00
2018-08-13 08:11:35 -06:00
/**
* @ event backend . list . extendColumns
* Provides an opportunity to modify the columns of a List widget
*
* Example usage :
*
2019-08-15 16:14:54 +01:00
* Event :: listen ( 'backend.list.extendColumns' , function ( $listWidget ) {
2018-08-13 08:11:35 -06:00
* // Only for the User controller
* if ( ! $listWidget -> getController () instanceof \Backend\Controllers\Users ) {
* return ;
* }
*
* // Only for the User model
* if ( ! $listWidget -> model instanceof \Backend\Models\User ) {
* return ;
* }
*
* // Add an extra birthday column
* $listWidget -> addColumns ([
* 'birthday' => [
* 'label' => 'Birthday'
* ]
* ]);
*
* // Remove a Surname column
* $listWidget -> removeColumn ( 'surname' );
* });
*
* Or
*
* $listWidget -> bindEvent ( 'list.extendColumns' , function () use ( $listWidget ) {
* // Only for the User controller
* if ( ! $listWidget -> getController () instanceof \Backend\Controllers\Users ) {
* return ;
* }
*
* // Only for the User model
* if ( ! $listWidget -> model instanceof \Backend\Models\User ) {
* return ;
* }
*
* // Add an extra birthday column
* $listWidget -> addColumns ([
* 'birthday' => [
* 'label' => 'Birthday'
* ]
* ]);
*
* // Remove a Surname column
* $listWidget -> removeColumn ( 'surname' );
* });
*
2014-06-08 10:52:46 +10:00
*/
2016-12-10 09:02:06 +11:00
$this -> fireSystemEvent ( 'backend.list.extendColumns' );
2014-05-14 23:24:20 +10:00
/*
* Use a supplied column order
*/
if ( $columnOrder = $this -> getSession ( 'order' , null )) {
$orderedDefinitions = [];
foreach ( $columnOrder as $column ) {
2015-02-28 12:41:45 +11:00
if ( isset ( $this -> allColumns [ $column ])) {
$orderedDefinitions [ $column ] = $this -> allColumns [ $column ];
2014-10-11 17:58:48 +11:00
}
2014-05-14 23:24:20 +10:00
}
2015-02-28 12:41:45 +11:00
$this -> allColumns = array_merge ( $orderedDefinitions , $this -> allColumns );
2014-05-14 23:24:20 +10:00
}
2015-02-28 12:41:45 +11:00
return $this -> allColumns ;
2014-06-08 10:52:46 +10:00
}
/**
* Programatically add columns , used internally and for extensibility .
2015-05-02 10:50:19 +10:00
* @ param array $columns Column definitions
2014-06-08 10:52:46 +10:00
*/
public function addColumns ( array $columns )
{
2014-05-14 23:24:20 +10:00
/*
* Build a final collection of list column objects
*/
2014-06-08 10:52:46 +10:00
foreach ( $columns as $columnName => $config ) {
2019-10-10 00:41:53 +02:00
// Check if user has permissions to show this column
$permissions = array_get ( $config , 'permissions' );
if ( ! empty ( $permissions ) && ! BackendAuth :: getUser () -> hasAccess ( $permissions , false )) {
continue ;
}
2015-02-28 12:41:45 +11:00
$this -> allColumns [ $columnName ] = $this -> makeListColumn ( $columnName , $config );
2014-05-14 23:24:20 +10:00
}
}
2015-05-01 09:09:56 +02:00
/**
* Programatically remove a column , used for extensibility .
2015-05-02 10:50:19 +10:00
* @ param string $column Column name
2015-05-01 09:09:56 +02:00
*/
public function removeColumn ( $columnName )
{
if ( isset ( $this -> allColumns [ $columnName ])) {
unset ( $this -> allColumns [ $columnName ]);
}
}
2014-05-14 23:24:20 +10:00
/**
* Creates a list column object from it ' s name and configuration .
*/
protected function makeListColumn ( $name , $config )
{
2014-10-11 00:39:34 +02:00
if ( is_string ( $config )) {
2014-05-14 23:24:20 +10:00
$label = $config ;
2014-11-01 12:00:45 +11:00
}
elseif ( isset ( $config [ 'label' ])) {
2014-05-14 23:24:20 +10:00
$label = $config [ 'label' ];
2014-11-01 12:00:45 +11:00
}
else {
2014-05-14 23:24:20 +10:00
$label = studly_case ( $name );
2014-10-11 00:39:34 +02:00
}
2015-03-19 20:00:31 +11:00
2016-11-08 07:02:31 +11:00
/*
* Auto configure pivot relation
*/
2015-08-05 19:53:05 +10:00
if ( starts_with ( $name , 'pivot[' ) && strpos ( $name , ']' ) !== false ) {
$_name = HtmlHelper :: nameToArray ( $name );
2016-11-08 07:02:31 +11:00
$relationName = array_shift ( $_name );
$valueFrom = array_shift ( $_name );
if ( count ( $_name ) > 0 ) {
$valueFrom .= '[' . implode ( '][' , $_name ) . ']' ;
}
$config [ 'relation' ] = $relationName ;
$config [ 'valueFrom' ] = $valueFrom ;
2015-08-05 19:53:05 +10:00
$config [ 'searchable' ] = false ;
}
2016-11-08 07:02:31 +11:00
/*
* Auto configure standard relation
*/
2015-08-05 19:53:05 +10:00
elseif ( strpos ( $name , '[' ) !== false && strpos ( $name , ']' ) !== false ) {
2015-03-19 20:00:31 +11:00
$config [ 'valueFrom' ] = $name ;
$config [ 'sortable' ] = false ;
$config [ 'searchable' ] = false ;
}
2014-05-14 23:24:20 +10:00
2018-08-15 19:15:13 +02:00
$columnType = $config [ 'type' ] ? ? null ;
2014-05-14 23:24:20 +10:00
2014-07-31 19:34:38 +10:00
$column = new ListColumn ( $name , $label );
$column -> displayAs ( $columnType , $config );
2014-05-14 23:24:20 +10:00
return $column ;
}
/**
* Calculates the total columns used in the list , including checkboxes
* and other additions .
*/
protected function getTotalColumns ()
{
2015-01-27 20:02:20 +11:00
$columns = $this -> visibleColumns ? : $this -> getVisibleColumns ();
2014-05-14 23:24:20 +10:00
$total = count ( $columns );
2016-12-10 09:02:06 +11:00
2014-10-11 00:39:34 +02:00
if ( $this -> showCheckboxes ) {
$total ++ ;
}
2016-12-10 09:02:06 +11:00
2014-10-11 00:39:34 +02:00
if ( $this -> showSetup ) {
$total ++ ;
}
2016-12-10 09:02:06 +11:00
2019-07-07 13:05:18 +08:00
if ( $this -> showTree ) {
$total ++ ;
}
2014-05-14 23:24:20 +10:00
return $total ;
}
/**
* Looks up the column header
*/
public function getHeaderValue ( $column )
{
$value = Lang :: get ( $column -> label );
2018-08-13 08:11:35 -06:00
/**
* @ event backend . list . overrideHeaderValue
* Overrides the column header value in a list widget .
*
* If a value is returned from this event , it will be used as the value for the provided column .
* `$value` is passed by reference so modifying the variable in place is also supported . Example usage :
*
2019-08-15 16:14:54 +01:00
* Event :: listen ( 'backend.list.overrideHeaderValue' , function ( $listWidget , $column , & $value ) {
2018-08-13 08:11:35 -06:00
* $value .= '-modified' ;
* });
*
* Or
*
* $listWidget -> bindEvent ( 'list.overrideHeaderValue' , function ( $column , $value ) {
* return 'Custom header value' ;
* });
*
2014-05-14 23:24:20 +10:00
*/
2018-08-13 08:11:35 -06:00
if ( $response = $this -> fireSystemEvent ( 'backend.list.overrideHeaderValue' , [ $column , & $value ])) {
2014-05-15 17:23:46 +10:00
$value = $response ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
return $value ;
}
/**
2016-10-06 18:43:53 +11:00
* Returns a raw column value
* @ return string
2014-05-14 23:24:20 +10:00
*/
2016-10-06 18:43:53 +11:00
public function getColumnValueRaw ( $record , $column )
2014-05-14 23:24:20 +10:00
{
2014-08-16 14:08:51 +10:00
$columnName = $column -> columnName ;
/*
2014-12-05 18:24:48 +11:00
* Handle taking value from model relation .
2014-08-16 14:08:51 +10:00
*/
2014-12-05 18:24:48 +11:00
if ( $column -> valueFrom && $column -> relation ) {
$columnName = $column -> relation ;
2014-10-11 00:39:34 +02:00
if ( ! array_key_exists ( $columnName , $record -> getRelations ())) {
2014-08-16 14:08:51 +10:00
$value = null ;
2014-11-01 12:00:45 +11:00
}
elseif ( $this -> isColumnRelated ( $column , true )) {
2016-09-28 16:31:21 +10:00
$value = $record -> { $columnName } -> lists ( $column -> valueFrom );
2014-11-01 12:00:45 +11:00
}
2015-08-05 19:53:05 +10:00
elseif ( $this -> isColumnRelated ( $column ) || $this -> isColumnPivot ( $column )) {
2016-11-08 07:02:31 +11:00
$value = $record -> { $columnName }
? $column -> getValueFromData ( $record -> { $columnName })
: null ;
2014-11-01 12:00:45 +11:00
}
else {
2014-12-05 18:24:48 +11:00
$value = null ;
2014-10-11 00:39:34 +02:00
}
2014-12-05 18:24:48 +11:00
}
/*
* Handle taking value from model attribute .
*/
elseif ( $column -> valueFrom ) {
2016-11-08 07:02:31 +11:00
$value = $column -> getValueFromData ( $record );
2014-12-05 18:24:48 +11:00
}
2014-06-29 09:12:11 +10:00
/*
2014-08-16 14:08:51 +10:00
* Otherwise , if the column is a relation , it will be a custom select ,
2014-06-29 09:12:11 +10:00
* so prevent the Model from attempting to load the relation
* if the value is NULL .
*/
2014-11-01 12:00:45 +11:00
else {
2014-10-11 00:39:34 +02:00
if ( $record -> hasRelation ( $columnName ) && array_key_exists ( $columnName , $record -> attributes )) {
2014-08-16 14:08:51 +10:00
$value = $record -> attributes [ $columnName ];
2018-01-25 16:54:06 -06:00
// Load the value from the relationship counter if useRelationCount is specified
} elseif ( $column -> relation && @ $column -> config [ 'useRelationCount' ]) {
$value = $record -> { " { $column -> relation } _count " };
} else {
2014-08-16 14:08:51 +10:00
$value = $record -> { $columnName };
2014-10-11 00:39:34 +02:00
}
2014-08-16 14:08:51 +10:00
}
2018-01-25 16:54:06 -06:00
2017-10-18 10:57:17 -06:00
/**
* @ event backend . list . overrideColumnValueRaw
2018-01-25 16:54:06 -06:00
* Overrides the raw column value in a list widget .
2017-10-18 10:57:17 -06:00
*
* If a value is returned from this event , it will be used as the raw value for the provided column .
* `$value` is passed by reference so modifying the variable in place is also supported . Example usage :
*
2019-08-15 16:14:54 +01:00
* Event :: listen ( 'backend.list.overrideColumnValueRaw' , function ( $listWidget , $record , $column , & $value ) {
2017-10-18 10:57:17 -06:00
* $value .= '-modified' ;
* });
*
* Or
*
* $listWidget -> bindEvent ( 'list.overrideColumnValueRaw' , function ( $record , $column , $value ) {
* return 'No values for you!' ;
* });
*
*/
if ( $response = $this -> fireSystemEvent ( 'backend.list.overrideColumnValueRaw' , [ $record , $column , & $value ])) {
$value = $response ;
}
2014-05-14 23:24:20 +10:00
2016-10-06 18:43:53 +11:00
return $value ;
}
/**
* Returns a column value , with filters applied
* @ return string
*/
public function getColumnValue ( $record , $column )
{
$value = $this -> getColumnValueRaw ( $record , $column );
2014-10-11 00:39:34 +02:00
if ( method_exists ( $this , 'eval' . studly_case ( $column -> type ) . 'TypeValue' )) {
2014-08-06 18:18:10 +10:00
$value = $this -> { 'eval' . studly_case ( $column -> type ) . 'TypeValue' }( $record , $column , $value );
2014-10-11 00:39:34 +02:00
}
2016-10-21 07:15:08 +11:00
else {
$value = $this -> evalCustomListType ( $column -> type , $record , $column , $value );
}
2014-05-14 23:24:20 +10:00
2015-06-27 10:39:07 +10:00
/*
* Apply default value .
*/
2020-04-12 22:47:45 +05:30
if (( $value === '' || is_null ( $value )) && ! empty ( $column -> defaults )) {
$value = Lang :: get ( $column -> defaults );
2015-06-27 10:39:07 +10:00
}
2017-10-18 10:57:17 -06:00
/**
* @ event backend . list . overrideColumnValue
2018-01-25 16:54:06 -06:00
* Overrides the column value in a list widget .
2017-10-18 10:57:17 -06:00
*
* If a value is returned from this event , it will be used as the value for the provided column .
* `$value` is passed by reference so modifying the variable in place is also supported . Example usage :
*
2019-08-15 16:14:54 +01:00
* Event :: listen ( 'backend.list.overrideColumnValue' , function ( $listWidget , $record , $column , & $value ) {
2017-10-18 10:57:17 -06:00
* $value .= '-modified' ;
* });
*
* Or
*
* $listWidget -> bindEvent ( 'list.overrideColumnValue' , function ( $record , $column , $value ) {
* return 'No values for you!' ;
* });
*
2014-05-14 23:24:20 +10:00
*/
2016-12-10 09:02:06 +11:00
if ( $response = $this -> fireSystemEvent ( 'backend.list.overrideColumnValue' , [ $record , $column , & $value ])) {
2014-05-15 17:23:46 +10:00
$value = $response ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
return $value ;
}
/**
* Adds a custom CSS class string to a record row
* @ param Model $record Populated model
* @ return string
*/
public function getRowClass ( $record )
{
$value = '' ;
2018-08-13 08:11:35 -06:00
/**
* @ event backend . list . injectRowClass
* Provides opportunity to inject a custom CSS row class
*
* If a value is returned from this event , it will be used as the value for the row class .
* `$value` is passed by reference so modifying the variable in place is also supported . Example usage :
*
2019-08-15 16:14:54 +01:00
* Event :: listen ( 'backend.list.injectRowClass' , function ( $listWidget , $record , & $value ) {
2018-08-13 08:11:35 -06:00
* $value .= '-modified' ;
* });
*
* Or
*
* $listWidget -> bindEvent ( 'list.injectRowClass' , function ( $record , $value ) {
* return 'strike' ;
* });
*
2014-05-14 23:24:20 +10:00
*/
2018-08-13 08:11:35 -06:00
if ( $response = $this -> fireSystemEvent ( 'backend.list.injectRowClass' , [ $record , & $value ])) {
2014-05-15 17:23:46 +10:00
$value = $response ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
return $value ;
}
//
// Value processing
//
2016-10-21 07:15:08 +11:00
/**
* Process a custom list types registered by plugins .
*/
protected function evalCustomListType ( $type , $record , $column , $value )
{
$plugins = PluginManager :: instance () -> getRegistrationMethodValues ( 'registerListColumnTypes' );
foreach ( $plugins as $availableTypes ) {
if ( ! isset ( $availableTypes [ $type ])) {
continue ;
}
$callback = $availableTypes [ $type ];
if ( is_callable ( $callback )) {
return call_user_func_array ( $callback , [ $value , $column , $record ]);
}
}
2019-10-10 00:41:53 +02:00
2019-07-09 08:25:08 -06:00
$customMessage = '' ;
if ( $type === 'relation' ) {
2019-07-09 09:52:30 -06:00
$customMessage = 'Type: relation is not supported, instead use the relation property to specify a relationship to pull the value from and set the type to the type of the value expected.' ;
2019-07-09 08:25:08 -06:00
}
2016-10-21 07:15:08 +11:00
2019-07-09 08:25:08 -06:00
throw new ApplicationException ( sprintf ( 'List column type "%s" could not be found. %s' , $type , $customMessage ));
2016-10-21 07:15:08 +11:00
}
2014-08-01 17:42:00 +10:00
/**
2015-02-21 19:16:44 +11:00
* Process as text , escape the value
2019-11-02 14:52:00 +11:00
* @ return string
2015-02-21 19:16:44 +11:00
*/
protected function evalTextTypeValue ( $record , $column , $value )
{
2016-09-28 16:31:21 +10:00
if ( is_array ( $value ) && count ( $value ) == count ( $value , COUNT_RECURSIVE )) {
$value = implode ( ', ' , $value );
}
2018-12-20 10:52:07 +08:00
if ( is_string ( $column -> format ) && ! empty ( $column -> format )) {
$value = sprintf ( $column -> format , $value );
}
2015-02-21 19:16:44 +11:00
return htmlentities ( $value , ENT_QUOTES , 'UTF-8' , false );
}
2020-08-21 17:54:31 -06:00
/**
* Process an image value
* @ return string
*/
protected function evalImageTypeValue ( $record , $column , $value )
{
$config = $column -> config ;
// Get config options with defaults
$width = isset ( $config [ 'width' ]) ? $config [ 'width' ] : 50 ;
$height = isset ( $config [ 'height' ]) ? $config [ 'height' ] : 50 ;
$options = isset ( $config [ 'options' ]) ? $config [ 'options' ] : [];
// Handle attachMany relationships
if ( isset ( $record -> attachMany [ $column -> columnName ])) {
$image = $value -> first ();
// Handle attachOne relationships
} elseif ( isset ( $record -> attachOne [ $column -> columnName ])) {
$image = $value ;
// Handle absolute URLs
} elseif ( str_contains ( $value , '://' )) {
2020-08-30 02:08:06 -06:00
$image = $value ;
2020-08-21 17:54:31 -06:00
// Assume all other values to be from the media library
} else {
2020-08-30 02:08:06 -06:00
$image = MediaLibrary :: url ( $value );
2020-08-21 17:54:31 -06:00
}
2020-08-30 02:08:06 -06:00
if ( ! is_null ( $image )) {
2020-08-21 17:54:31 -06:00
$imageUrl = ImageResizer :: filterGetUrl ( $image , $width , $height , $options );
return " <img src=' $imageUrl ' width=' $width ' height=' $height ' /> " ;
}
}
2016-10-22 03:10:50 +11:00
/**
* Process as number , proxy to text
2019-11-02 14:52:00 +11:00
* @ return string
2016-10-22 03:10:50 +11:00
*/
protected function evalNumberTypeValue ( $record , $column , $value )
{
return $this -> evalTextTypeValue ( $record , $column , $value );
}
2015-02-21 19:16:44 +11:00
/**
* Process as partial reference
2014-08-01 17:42:00 +10:00
*/
2014-08-06 18:18:10 +10:00
protected function evalPartialTypeValue ( $record , $column , $value )
2014-08-01 17:42:00 +10:00
{
2014-08-06 18:18:10 +10:00
return $this -> controller -> makePartial ( $column -> path ? : $column -> columnName , [
'listColumn' => $column ,
2014-08-23 11:11:49 +10:00
'listRecord' => $record ,
'listValue' => $value ,
'column' => $column ,
2014-08-06 18:18:10 +10:00
'record' => $record ,
'value' => $value
]);
2014-08-01 17:42:00 +10:00
}
2014-05-14 23:24:20 +10:00
/**
* Process as boolean switch
*/
2014-08-06 18:18:10 +10:00
protected function evalSwitchTypeValue ( $record , $column , $value )
2014-05-14 23:24:20 +10:00
{
2015-09-26 22:03:05 -04:00
$contents = '' ;
2015-10-17 08:41:10 +11:00
if ( $value ) {
$contents = Lang :: get ( 'backend::lang.list.column_switch_true' );
2015-09-26 22:03:05 -04:00
}
else {
2015-10-17 08:41:10 +11:00
$contents = Lang :: get ( 'backend::lang.list.column_switch_false' );
2015-09-26 22:03:05 -04:00
}
return $contents ;
2014-05-14 23:24:20 +10:00
}
/**
* Process as a datetime value
*/
2014-08-06 18:18:10 +10:00
protected function evalDatetimeTypeValue ( $record , $column , $value )
2014-05-14 23:24:20 +10:00
{
2014-10-11 00:39:34 +02:00
if ( $value === null ) {
2014-05-14 23:24:20 +10:00
return null ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2016-04-23 13:17:04 +10:00
$dateTime = $this -> validateDateTimeValue ( $value , $column );
2014-06-20 19:30:37 +10:00
2014-10-11 00:39:34 +02:00
if ( $column -> format !== null ) {
2016-04-23 13:17:04 +10:00
$value = $dateTime -> format ( $column -> format );
}
else {
$value = $dateTime -> toDayDateTimeString ();
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2017-09-10 22:39:15 -06:00
$options = [
2016-04-26 06:59:02 +10:00
'defaultValue' => $value ,
2016-04-23 13:17:04 +10:00
'format' => $column -> format ,
'formatAlias' => 'dateTimeLongMin'
2017-09-10 22:39:15 -06:00
];
if ( ! empty ( $column -> config [ 'ignoreTimezone' ])) {
$options [ 'ignoreTimezone' ] = true ;
}
return Backend :: dateTime ( $dateTime , $options );
2014-05-14 23:24:20 +10:00
}
/**
* Process as a time value
*/
2014-08-06 18:18:10 +10:00
protected function evalTimeTypeValue ( $record , $column , $value )
2014-05-14 23:24:20 +10:00
{
2014-10-11 00:39:34 +02:00
if ( $value === null ) {
2014-05-14 23:24:20 +10:00
return null ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2016-04-23 13:17:04 +10:00
$dateTime = $this -> validateDateTimeValue ( $value , $column );
2014-06-20 19:30:37 +10:00
2018-08-15 19:15:13 +02:00
$format = $column -> format ? ? 'g:i A' ;
2014-05-14 23:24:20 +10:00
2016-04-23 13:17:04 +10:00
$value = $dateTime -> format ( $format );
2017-09-10 22:39:15 -06:00
$options = [
2016-04-26 06:59:02 +10:00
'defaultValue' => $value ,
2016-04-23 13:17:04 +10:00
'format' => $column -> format ,
'formatAlias' => 'time'
2017-09-10 22:39:15 -06:00
];
if ( ! empty ( $column -> config [ 'ignoreTimezone' ])) {
$options [ 'ignoreTimezone' ] = true ;
}
return Backend :: dateTime ( $dateTime , $options );
2014-05-14 23:24:20 +10:00
}
/**
* Process as a date value
*/
2014-08-06 18:18:10 +10:00
protected function evalDateTypeValue ( $record , $column , $value )
2014-05-14 23:24:20 +10:00
{
2014-10-11 00:39:34 +02:00
if ( $value === null ) {
2014-05-14 23:24:20 +10:00
return null ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2016-04-23 13:17:04 +10:00
$dateTime = $this -> validateDateTimeValue ( $value , $column );
2014-06-20 19:30:37 +10:00
2014-10-11 00:39:34 +02:00
if ( $column -> format !== null ) {
2016-04-23 13:17:04 +10:00
$value = $dateTime -> format ( $column -> format );
}
else {
$value = $dateTime -> toFormattedDateString ();
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2017-09-10 22:39:15 -06:00
$options = [
2016-04-26 06:59:02 +10:00
'defaultValue' => $value ,
2016-04-23 13:17:04 +10:00
'format' => $column -> format ,
'formatAlias' => 'dateLongMin'
2017-09-10 22:39:15 -06:00
];
if ( ! empty ( $column -> config [ 'ignoreTimezone' ])) {
$options [ 'ignoreTimezone' ] = true ;
}
return Backend :: dateTime ( $dateTime , $options );
2014-05-14 23:24:20 +10:00
}
/**
* Process as diff for humans ( 1 min ago )
*/
2014-08-06 18:18:10 +10:00
protected function evalTimesinceTypeValue ( $record , $column , $value )
2014-05-14 23:24:20 +10:00
{
2014-10-11 00:39:34 +02:00
if ( $value === null ) {
2014-05-14 23:24:20 +10:00
return null ;
2014-10-11 00:39:34 +02:00
}
2014-05-27 13:44:28 +10:00
2016-04-23 13:17:04 +10:00
$dateTime = $this -> validateDateTimeValue ( $value , $column );
$value = DateTimeHelper :: timeSince ( $dateTime );
2014-06-20 19:30:37 +10:00
2017-09-10 22:39:15 -06:00
$options = [
2016-04-26 06:59:02 +10:00
'defaultValue' => $value ,
2016-04-23 13:17:04 +10:00
'timeSince' => true
2017-09-10 22:39:15 -06:00
];
if ( ! empty ( $column -> config [ 'ignoreTimezone' ])) {
$options [ 'ignoreTimezone' ] = true ;
}
return Backend :: dateTime ( $dateTime , $options );
2015-09-17 05:15:12 +10:00
}
/**
* Process as time as current tense ( Today at 0 : 00 )
*/
protected function evalTimetenseTypeValue ( $record , $column , $value )
{
if ( $value === null ) {
return null ;
}
2016-04-23 13:17:04 +10:00
$dateTime = $this -> validateDateTimeValue ( $value , $column );
$value = DateTimeHelper :: timeTense ( $dateTime );
2015-09-17 05:15:12 +10:00
2017-09-10 22:39:15 -06:00
$options = [
2016-04-26 06:59:02 +10:00
'defaultValue' => $value ,
2016-04-23 13:17:04 +10:00
'timeTense' => true
2017-09-10 22:39:15 -06:00
];
if ( ! empty ( $column -> config [ 'ignoreTimezone' ])) {
$options [ 'ignoreTimezone' ] = true ;
}
return Backend :: dateTime ( $dateTime , $options );
2014-06-20 19:30:37 +10:00
}
2018-01-04 19:54:30 +01:00
/**
* Process as background color , to be seen at list
*/
protected function evalColorPickerTypeValue ( $record , $column , $value )
{
return '<span style="width:30px; height:30px; display:inline-block; background:' . e ( $value ) . '; padding:10px"><span>' ;
}
2014-06-20 19:30:37 +10:00
/**
* Validates a column type as a date
*/
2014-08-01 18:18:09 +10:00
protected function validateDateTimeValue ( $value , $column )
2014-06-20 19:30:37 +10:00
{
2016-04-23 13:17:04 +10:00
$value = DateTimeHelper :: makeCarbon ( $value , false );
2014-05-27 13:44:28 +10:00
2014-10-11 00:39:34 +02:00
if ( ! $value instanceof Carbon ) {
throw new ApplicationException ( Lang :: get (
'backend::lang.list.invalid_column_datetime' ,
[ 'column' => $column -> columnName ]
));
}
2014-05-27 13:44:28 +10:00
2014-06-20 19:30:37 +10:00
return $value ;
2014-05-14 23:24:20 +10:00
}
2014-08-13 21:23:19 +10:00
//
// Filtering
//
public function addFilter ( callable $filter )
{
$this -> filterCallbacks [] = $filter ;
}
2014-05-14 23:24:20 +10:00
//
// Searching
//
/**
* Applies a search term to the list results , searching will disable tree
* view if a value is supplied .
* @ param string $term
2020-02-12 16:52:09 +01:00
* @ param boolean $resetPagination
2014-05-14 23:24:20 +10:00
*/
2020-02-12 16:52:09 +01:00
public function setSearchTerm ( $term , $resetPagination = false )
2014-05-14 23:24:20 +10:00
{
2015-02-28 12:41:45 +11:00
if ( ! empty ( $term )) {
2014-05-14 23:24:20 +10:00
$this -> showTree = false ;
}
2020-02-12 16:52:09 +01:00
if ( $resetPagination ) {
$this -> currentPageNumber = 1 ;
}
2014-05-14 23:24:20 +10:00
$this -> searchTerm = $term ;
}
2016-04-19 19:54:22 +10:00
/**
* Applies a search options to the list search .
* @ param array $options
*/
public function setSearchOptions ( $options = [])
{
extract ( array_merge ([
'mode' => null ,
'scope' => null
], $options ));
$this -> searchMode = $mode ;
$this -> searchScope = $scope ;
}
2014-05-14 23:24:20 +10:00
/**
* Returns a collection of columns which can be searched .
* @ return array
*/
protected function getSearchableColumns ()
{
2014-08-23 21:46:03 +10:00
$columns = $this -> getColumns ();
2014-05-14 23:24:20 +10:00
$searchable = [];
foreach ( $columns as $column ) {
2014-10-11 00:39:34 +02:00
if ( ! $column -> searchable ) {
2014-05-14 23:24:20 +10:00
continue ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
$searchable [] = $column ;
}
return $searchable ;
}
2016-04-19 19:54:22 +10:00
/**
* Applies the search constraint to a query .
*/
protected function applySearchToQuery ( $query , $columns , $boolean = 'and' )
{
$term = $this -> searchTerm ;
if ( $scopeMethod = $this -> searchScope ) {
2016-04-20 05:29:24 +10:00
$searchMethod = $boolean == 'and' ? 'where' : 'orWhere' ;
2017-04-24 13:38:19 +02:00
$query -> $searchMethod ( function ( $q ) use ( $term , $columns , $scopeMethod ) {
2016-11-29 06:46:52 +11:00
$q -> $scopeMethod ( $term , $columns );
2016-04-20 05:29:24 +10:00
});
2016-04-19 19:54:22 +10:00
}
else {
$searchMethod = $boolean == 'and' ? 'searchWhere' : 'orSearchWhere' ;
$query -> $searchMethod ( $term , $columns , $this -> searchMode );
}
}
2014-05-14 23:24:20 +10:00
//
// Sorting
//
/**
* Event handler for sorting the list .
*/
public function onSort ()
{
if ( $column = post ( 'sortColumn' )) {
/*
* Toggle the sort direction and set the sorting column
*/
$sortOptions = [ 'column' => $this -> getSortColumn (), 'direction' => $this -> sortDirection ];
2014-10-11 00:39:34 +02:00
if ( $column != $sortOptions [ 'column' ] || $sortOptions [ 'direction' ] == 'asc' ) {
2014-05-14 23:24:20 +10:00
$this -> sortDirection = $sortOptions [ 'direction' ] = 'desc' ;
2014-11-01 12:00:45 +11:00
}
else {
2014-05-14 23:24:20 +10:00
$this -> sortDirection = $sortOptions [ 'direction' ] = 'asc' ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
$this -> sortColumn = $sortOptions [ 'column' ] = $column ;
/*
* Persist the page number
*/
2015-02-07 10:24:28 +11:00
$this -> currentPageNumber = post ( 'page' );
2014-05-14 23:24:20 +10:00
2019-11-29 08:26:37 +01:00
/*
* Try to refresh the list with the new sortOptions . Put the
* new sortOptions in to the session if the query succeeded .
*/
$result = $this -> onRefresh ();
$this -> putSession ( 'sort' , $sortOptions );
return $result ;
2014-05-14 23:24:20 +10:00
}
}
/**
* Returns the current sorting column , saved in a session or cached .
*/
2019-12-04 01:29:24 -07:00
public function getSortColumn ()
2014-05-14 23:24:20 +10:00
{
2014-10-11 00:39:34 +02:00
if ( ! $this -> isSortable ()) {
2014-05-14 23:24:20 +10:00
return false ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2014-10-11 00:39:34 +02:00
if ( $this -> sortColumn !== null ) {
2014-05-14 23:24:20 +10:00
return $this -> sortColumn ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
/*
* User preference
*/
if ( $this -> showSorting && ( $sortOptions = $this -> getSession ( 'sort' ))) {
$this -> sortColumn = $sortOptions [ 'column' ];
$this -> sortDirection = $sortOptions [ 'direction' ];
2014-11-01 12:00:45 +11:00
}
2018-08-15 18:45:37 +02:00
/*
* Supplied default
*/
2014-11-01 12:00:45 +11:00
else {
2014-05-14 23:24:20 +10:00
if ( is_string ( $this -> defaultSort )) {
$this -> sortColumn = $this -> defaultSort ;
$this -> sortDirection = 'desc' ;
2014-11-01 12:00:45 +11:00
}
elseif ( is_array ( $this -> defaultSort ) && isset ( $this -> defaultSort [ 'column' ])) {
2014-05-14 23:24:20 +10:00
$this -> sortColumn = $this -> defaultSort [ 'column' ];
2018-08-15 19:15:13 +02:00
$this -> sortDirection = $this -> defaultSort [ 'direction' ] ? ? 'desc' ;
2014-05-14 23:24:20 +10:00
}
}
/*
* First available column
*/
if ( $this -> sortColumn === null || ! $this -> isSortable ( $this -> sortColumn )) {
2015-01-27 20:02:20 +11:00
$columns = $this -> visibleColumns ? : $this -> getVisibleColumns ();
2019-07-07 14:49:56 +08:00
$columns = array_filter ( $columns , function ( $column ) {
return $column -> sortable ;
});
2014-05-14 23:24:20 +10:00
$this -> sortColumn = key ( $columns );
$this -> sortDirection = 'desc' ;
}
return $this -> sortColumn ;
}
2019-12-04 01:29:24 -07:00
/*
* Returns the current sort direction or default of 'asc'
*/
public function getSortDirection ()
{
return $this -> sortDirection ? ? 'asc' ;
}
2014-05-14 23:24:20 +10:00
/**
* Returns true if the column can be sorted .
*/
protected function isSortable ( $column = null )
{
2014-10-11 00:39:34 +02:00
if ( $column === null ) {
2014-05-14 23:24:20 +10:00
return ( count ( $this -> getSortableColumns ()) > 0 );
2014-11-01 12:00:45 +11:00
}
2018-08-15 19:25:42 +02:00
return array_key_exists ( $column , $this -> getSortableColumns ());
2014-05-14 23:24:20 +10:00
}
/**
* Returns a collection of columns which are sortable .
*/
protected function getSortableColumns ()
{
2014-10-11 00:39:34 +02:00
if ( $this -> sortableColumns !== null ) {
2014-05-14 23:24:20 +10:00
return $this -> sortableColumns ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
2014-08-23 21:46:03 +10:00
$columns = $this -> getColumns ();
2017-04-24 13:38:19 +02:00
$sortable = array_filter ( $columns , function ( $column ) {
2015-01-15 17:25:52 +11:00
return $column -> sortable ;
});
2014-05-14 23:24:20 +10:00
return $this -> sortableColumns = $sortable ;
}
//
// List Setup
//
/**
* Event handler to display the list set up .
*/
public function onLoadSetup ()
{
$this -> vars [ 'columns' ] = $this -> getSetupListColumns ();
$this -> vars [ 'perPageOptions' ] = $this -> getSetupPerPageOptions ();
$this -> vars [ 'recordsPerPage' ] = $this -> recordsPerPage ;
return $this -> makePartial ( 'setup_form' );
}
/**
* Event handler to apply the list set up .
*/
public function onApplySetup ()
{
if (( $visibleColumns = post ( 'visible_columns' )) && is_array ( $visibleColumns )) {
2016-12-14 19:14:41 +11:00
$this -> columnOverride = $visibleColumns ;
2019-06-08 11:28:08 +08:00
$this -> putUserPreference ( 'visible' , $this -> columnOverride );
2014-05-14 23:24:20 +10:00
}
2016-06-10 07:43:21 +10:00
$this -> recordsPerPage = post ( 'records_per_page' , $this -> recordsPerPage );
2014-05-14 23:24:20 +10:00
$this -> putSession ( 'order' , post ( 'column_order' ));
2019-06-08 11:28:08 +08:00
$this -> putUserPreference ( 'per_page' , $this -> recordsPerPage );
return $this -> onRefresh ();
}
/**
* Event handler to apply the list set up .
*/
public function onResetSetup ()
{
$this -> clearUserPreference ( 'visible' );
$this -> clearUserPreference ( 'per_page' );
2014-07-03 18:35:35 +10:00
return $this -> onRefresh ();
2014-05-14 23:24:20 +10:00
}
/**
* Returns an array of allowable records per page .
*/
protected function getSetupPerPageOptions ()
{
$perPageOptions = [ 20 , 40 , 80 , 100 , 120 ];
2014-10-11 00:39:34 +02:00
if ( ! in_array ( $this -> recordsPerPage , $perPageOptions )) {
2014-05-14 23:24:20 +10:00
$perPageOptions [] = $this -> recordsPerPage ;
2014-10-11 00:39:34 +02:00
}
2014-05-14 23:24:20 +10:00
sort ( $perPageOptions );
return $perPageOptions ;
}
/**
* Returns all the list columns used for list set up .
*/
protected function getSetupListColumns ()
{
/*
* Force all columns invisible
*/
2014-08-23 21:46:03 +10:00
$columns = $this -> defineListColumns ();
foreach ( $columns as $column ) {
2014-05-14 23:24:20 +10:00
$column -> invisible = true ;
}
2015-01-27 20:02:20 +11:00
return array_merge ( $columns , $this -> getVisibleColumns ());
2014-05-14 23:24:20 +10:00
}
//
// Tree
//
/**
* Validates the model and settings if showTree is used
* @ return void
*/
public function validateTree ()
{
2014-10-11 00:39:34 +02:00
if ( ! $this -> showTree ) {
return ;
}
2014-05-14 23:24:20 +10:00
$this -> showSorting = $this -> showPagination = false ;
2014-10-11 00:39:34 +02:00
if ( ! $this -> model -> methodExists ( 'getChildren' )) {
throw new ApplicationException (
'To display list as a tree, the specified model must have a method "getChildren"'
);
}
2014-05-14 23:24:20 +10:00
2014-10-11 00:39:34 +02:00
if ( ! $this -> model -> methodExists ( 'getChildCount' )) {
throw new ApplicationException (
'To display list as a tree, the specified model must have a method "getChildCount"'
);
}
2014-05-14 23:24:20 +10:00
}
/**
* Checks if a node ( model ) is expanded in the session .
* @ param Model $node
* @ return boolean
*/
public function isTreeNodeExpanded ( $node )
{
return $this -> getSession ( 'tree_node_status_' . $node -> getKey (), $this -> treeExpanded );
}
/**
* Sets a node ( model ) to an expanded or collapsed state , stored in the
* session , then renders the list again .
* @ return string List HTML contents .
*/
public function onToggleTreeNode ()
{
$this -> putSession ( 'tree_node_status_' . post ( 'node_id' ), post ( 'status' ) ? 0 : 1 );
2014-07-03 18:35:35 +10:00
return $this -> onRefresh ();
2014-05-14 23:24:20 +10:00
}
2014-08-16 14:08:51 +10:00
//
// Helpers
//
2014-08-23 17:35:18 +10:00
2014-08-16 14:08:51 +10:00
/**
* Check if column refers to a relation of the model
* @ param ListColumn $column List column object
* @ param boolean $multi If set , returns true only if the relation is a " multiple relation type "
* @ return boolean
*/
protected function isColumnRelated ( $column , $multi = false )
{
2015-08-05 19:53:05 +10:00
if ( ! isset ( $column -> relation ) || $this -> isColumnPivot ( $column )) {
2014-08-16 14:08:51 +10:00
return false ;
2014-10-11 00:39:34 +02:00
}
2014-08-16 14:08:51 +10:00
2014-10-11 00:39:34 +02:00
if ( ! $this -> model -> hasRelation ( $column -> relation )) {
throw new ApplicationException ( Lang :: get (
'backend::lang.model.missing_relation' ,
[ 'class' => get_class ( $this -> model ), 'relation' => $column -> relation ]
));
}
2014-08-16 14:08:51 +10:00
2014-10-11 00:39:34 +02:00
if ( ! $multi ) {
2014-08-16 14:08:51 +10:00
return true ;
2014-10-11 00:39:34 +02:00
}
2014-08-16 14:08:51 +10:00
$relationType = $this -> model -> getRelationType ( $column -> relation );
return in_array ( $relationType , [
'hasMany' ,
'belongsToMany' ,
'morphToMany' ,
'morphedByMany' ,
'morphMany' ,
'attachMany' ,
'hasManyThrough'
]);
}
2015-08-05 19:53:05 +10:00
/**
* Checks if a column refers to a pivot model specifically .
* @ param ListColumn $column List column object
* @ return boolean
*/
protected function isColumnPivot ( $column )
{
if ( ! isset ( $column -> relation ) || $column -> relation != 'pivot' ) {
return false ;
}
return true ;
}
2014-10-11 00:39:34 +02:00
}