Version 4.0.13.1

This commit is contained in:
Neo committed 2025-12-19 04:57:54 -08:00
1 parent f9e857d255
commit c6a86f0d9b
7517 files changed
+597400 -668041

No files matched your search

+638
View File
@@ -0,0 +1,638 @@
<?php
/**
* @brief Table Builder using an \IPS\Content\Item class datasource
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @since 16 Jul 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Helpers\Table;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* List Table Builder using an \IPS\Content\Item class datasource
*/
class _Content extends Table
{
/**
* @brief Database Table
*/
protected $class;
/**
* @brief Initial WHERE clause
*/
public $where;
/**
* @brief Container
*/
protected $container;
/**
* @brief Permission key to check
*/
protected $permCheck;
/**
* @brief Include hidden content flag with results
*/
protected $includeHiddenContent = NULL;
/**
* @brief Sort options
*/
public $sortOptions = array();
/**
* @brief Honor the pinned flag for sorting. Default exclusions include vnc and activity streams
*/
protected $honorPinned = TRUE;
/**
* Number of results
*/
public $count = 0;
/**
* @brief Join container data in getItemsWithPermission
*/
public $joinContainer = FALSE;
/**
* @brief Join comment data in getItemsWithPermission
*/
public $joinComments = FALSE;
/**
* @brief Join review data in getItemsWithPermission
*/
public $joinReviews = FALSE;
/**
* @brief Advanced search callback
*/
public $advancedSearchCallback = NULL;
/**
* Saved Actions (for multi-moderation)
*/
public $savedActions = array();
/**
* @brief Joins
*/
public $joins = array();
/**
* @brief Array of item IDs the current $member has posted in
*/
public $contentPostedIn = array();
/**
* Constructor
*
* @param string $class Content Class Name
* @param \IPS\Http\Url $baseUrl Base URL
* @param array|null $where WHERE clause (To restrict to a node, use $container instead)
* @param \IPS\Node\Model|NULL $container The container
* @param bool|null $includeHidden Flag to pass to getItemsWithPermission() method for $includeHiddenContent, defaults to NULL
* @param string|NULL $permCheck Permission key to check
* @return void
*/
public function __construct( $class, \IPS\Http\Url $baseUrl, $where=NULL, \IPS\Node\Model $container=NULL, $includeHidden=NULL, $permCheck='view', $honorPinned=TRUE )
{
/* Init */
$this->include = array();
$this->class = $class;
$this->where = $where;
$this->container = $container;
$this->includeHiddenContent = $includeHidden;
$this->honorPinned = $honorPinned;
$this->permCheck = $permCheck;
/* Init */
parent::__construct( $baseUrl );
$this->rowsTemplate = $class::contentTableTemplate();
/* Set container */
if ( $container !== NULL )
{
$this->where[] = array( $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['container'] . '=?', $container->_id );
$this->sortDirection = ( $this->sortDirection !== NULL ) ? $this->sortDirection : $container->_sortOrder;
if ( !$this->sortBy and $container->_sortBy !== NULL )
{
$this->sortBy = $container->_sortBy;
}
if ( !$this->filter )
{
$this->filter = $container->_filter;
}
if ( $this->includeHiddenContent === NULL )
{
$this->includeHiddenContent = $class::canViewHiddenItems( \IPS\Member::loggedIn(), $container );
}
/* Set breadcrumb */
foreach ( $container->parents() as $parent )
{
\IPS\Output::i()->breadcrumb[] = array( $parent->url(), $parent->_title );
}
\IPS\Output::i()->breadcrumb[] = array( NULL, $container->_title );
/* Meta tags */
\IPS\Output::i()->title = ( $this->page > 1 ) ? \IPS\Member::loggedIn()->language()->addToStack( 'title_with_page_number', FALSE, array( 'sprintf' => array( $container->_title, $this->page ) ) ) : $container->_title;
\IPS\Output::i()->metaTags['title'] = $container->_title;
\IPS\Output::i()->metaTags['description'] = $container->metaDescription();
\IPS\Output::i()->linkTags['canonical'] = (string) $baseUrl;
}
/* Set available sort options */
foreach ( array( 'updated', 'last_comment', 'title', 'rating', 'date', 'num_comments', 'num_reviews', 'views' ) as $k )
{
if ( isset( $class::$databaseColumnMap[ $k ] ) and !isset( $this->sortOptions[ $k ] ) )
{
$column = is_array( $class::$databaseColumnMap[ $k ] ) ? array_shift( $class::$databaseColumnMap[ $k ] ) : $class::$databaseColumnMap[ $k ];
$this->sortOptions[ $k ] = $class::$databasePrefix . $column;
}
}
if ( !$this->sortBy )
{
if ( isset( $class::$databaseColumnMap['updated'] ) )
{
$this->sortBy = $class::$databasePrefix . $class::$databaseColumnMap['updated'];
}
elseif ( isset( $class::$databaseColumnMap['last_comment'] ) )
{
$this->sortBy = $class::$databasePrefix . ( is_array( $class::$databaseColumnMap['last_comment'] ) ? $class::$databaseColumnMap['last_comment'][0] : $class::$databaseColumnMap['last_comment'] );
}
else
{
$this->sortBy = $class::$databasePrefix . $class::$databaseColumnMap['date'];
}
}
/* Do any multi-mod */
if ( isset( \IPS\Request::i()->modaction ) )
{
$this->multiMod();
}
}
/**
* Get rows
*
* @param array $advancedSearchValues Values from the advanced search form
* @return array
*/
public function getRows( $advancedSearchValues )
{
/* Init */
$class = $this->class;
/* Check sortBy */
$defaultSort = NULL;
foreach ( array( 'last_comment', 'last_review', 'date' ) as $k )
{
if ( isset( $class::$databaseColumnMap[ $k ] ) )
{
if ( is_array( $class::$databaseColumnMap[ $k ] ) )
{
$cols = $class::$databaseColumnMap[ $k ];
$defaultSort = $class::$databaseTable . '.' . $class::$databasePrefix . array_pop( $cols );
}
else
{
$defaultSort = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap[ $k ];
}
break;
}
}
$this->sortBy = in_array( $this->sortBy, $this->sortOptions ) ? $this->sortBy :
( array_key_exists( $this->sortBy, $this->sortOptions) ? $this->sortOptions[ $this->sortBy ] : $defaultSort );
/* Callback? */
if ( $this->advancedSearchCallback and !empty( $advancedSearchValues ) )
{
$obj = $this;
call_user_func( $this->advancedSearchCallback, $obj, $advancedSearchValues );
}
/* What are we sorting by? */
$sortBy = $this->sortBy . ' ' . ( mb_strtolower( $this->sortDirection ) == 'asc' ? 'asc' : 'desc' );
if ( in_array( 'IPS\Content\Pinnable', class_implements( $class ) ) and $this->honorPinned )
{
$column = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['pinned'];
$sortBy = "{$column} DESC, {$sortBy}";
}
/* Specify filter in where clause */
$where = $this->where ? is_array( $this->where ) ? $this->where : array( $this->where ) : array();
if ( $this->filter and isset( $this->filters[ $this->filter ] ) )
{
$where[] = is_array( $this->filters[ $this->filter ] ) ? $this->filters[ $this->filter ] : array( $this->filters[ $this->filter ] );
}
/* Get results */
$it = $class::getItemsWithPermission( $where, $sortBy, array( ( $this->limit * ( $this->page - 1 ) ), $this->limit ), $this->permCheck, $this->includeHiddenContent, \IPS\Db::SELECT_SQL_CALC_FOUND_ROWS, NULL, $this->joinContainer, $this->joinComments, $this->joinReviews, FALSE, $this->joins );
$this->count = $it->count( TRUE );
$this->pages = ceil( $this->count / $this->limit );
$rows = iterator_to_array( $it );
/* Pre load the contentPostedIn data to save separate DISTINCT queries later and a query for each unread item */
if ( isset( $class::$databaseColumnMap['container'] ) )
{
$containerItemIds = array();
foreach( $rows as $item )
{
$colContainer = $class::$databaseColumnMap['container'];
$colPrimary = $class::$databaseColumnId;
$containerItemIds[ $item->$colContainer ][] = $item->$colPrimary;
}
$nodeClass = $class::$containerNodeClass;
foreach( $containerItemIds as $container => $ids )
{
try
{
$node = $nodeClass::load( $container );
$this->contentPostedIn = array_merge( $node->contentPostedIn( NULL, $ids ), $this->contentPostedIn );
}
catch( \OutOfRangeException $ex ) {}
}
}
/* Pull in extra data */
if ( method_exists( $class, 'tableGetRows' ) )
{
$class::tableGetRows( $rows );
}
/* Return */
return $rows;
}
/**
* @brief Return table filters
*/
public $showFilters = TRUE;
/**
* Return the filters that are available for selecting table rows
*
* @return array
*/
public function getFilters()
{
if( $this->showFilters === FALSE )
{
return array();
}
$class = $this->class;
if( method_exists( $class, 'getTableFilters' ) )
{
return $class::getTableFilters();
}
return array();
}
/**
* @brief Disable moderation?
*/
public $noModerate = FALSE;
/**
* Does the user have permission to use the multi-mod checkboxes?
*
* @param string|null $action Specific action to check (hide/unhide, etc.) or NULL for a generic check
* @return bool
*/
public function canModerate( $action=NULL )
{
if ( $this->noModerate )
{
return FALSE;
}
$class = $this->class;
if ( $action )
{
return $class::modPermission( $action, \IPS\Member::loggedIn(), $this->container );
}
else
{
return $class::canSeeMultiModTools( \IPS\Member::loggedIn(), $this->container );
}
}
/**
* What multimod actions are available
*
* @param object $item Item
* @return array
*/
public function multimodActions( $item )
{
$return = array();
if ( $item instanceof \IPS\Content\Item )
{
if ( $item instanceof \IPS\Content\Featurable )
{
if ( $item->mapped('featured') and $item->canUnfeature() )
{
$return[] = 'unfeature';
}
elseif ( $item->canFeature() )
{
$return[] = 'feature';
}
}
if ( $item instanceof \IPS\Content\Pinnable )
{
if ( $item->mapped('pinned') and $item->canUnpin() )
{
$return[] = 'unpin';
}
elseif ( $item->canPin() )
{
$return[] = 'pin';
}
}
if ( $item instanceof \IPS\Content\Hideable )
{
if ( $item->hidden() === -1 and $item->canUnhide() )
{
$return[] = 'unhide';
}
elseif ( $item->hidden() === 1 and $item->canUnhide() )
{
$return[] = 'approve';
}
elseif ( $item->canHide() )
{
$return[] = 'hide';
}
}
if ( $item instanceof \IPS\Content\Lockable )
{
if ( $item->locked() AND $item->canUnlock() )
{
$return[] = 'unlock';
}
elseif ( $item->canLock() )
{
$return[] = 'lock';
}
}
if ( isset( $item::$databaseColumnMap['container'] ) )
{
if ( $item->canMove() )
{
$return[] = 'move';
}
}
if ( $item->canMerge() )
{
$return[] = 'merge';
}
if ( $item->canDelete() )
{
$return[] = 'delete';
}
/* Do we have any custom actions? */
$return = array_merge( $return, $item->customMultimodActions() );
}
foreach ( $this->savedActions as $k => $v )
{
$return[] = "savedAction-{$k}";
}
return $return;
}
/**
* What custom multimod actions are available
*
* @return array
*/
public function customActions()
{
$class = $this->class;
return $class::availableCustomMultimodActions();
}
/**
* Multimod
*
* @return void
*/
protected function multimod()
{
$class = $this->class;
$params = array();
/* Move: to where? */
if ( \IPS\Request::i()->modaction == 'move' )
{
$form = new \IPS\Helpers\Form( 'form', 'move' );
$form->class = 'ipsForm_vertical';
$form->hiddenValues['modaction'] = 'move';
$form->hiddenValues['moderate'] = \IPS\Request::i()->moderate;
$form->add( new \IPS\Helpers\Form\Node( 'move_to', NULL, TRUE, array(
'class' => $class::$containerNodeClass,
'url' => \IPS\Request::i()->url()->setQueryString( 'modaction', 'move' ),
'permissionCheck' => function( $node )
{
try
{
if ( $node->can( 'add' ) )
{
return true;
}
}
catch( \OutOfBoundsException $e ) { }
return false;
}
) ) );
if ( isset( $class::$databaseColumnMap['moved_to'] ) )
{
$form->add( new \IPS\Helpers\Form\Checkbox( 'move_keep_link' ) );
if ( \IPS\Settings::i()->topic_redirect_prune )
{
\IPS\Member::loggedIn()->language()->words['move_keep_link_desc'] = \IPS\Member::loggedIn()->language()->addToStack('_move_keep_link_desc', FALSE, array( 'pluralize' => array( \IPS\Settings::i()->topic_redirect_prune ) ) );
}
}
if ( $values = $form->values() )
{
$params[] = $values['move_to'];
$params[] = ( isset( $values['move_keep_link'] ) and $values['move_keep_link'] );
}
else
{
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( \IPS\Output::i()->output );
}
else
{
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( \IPS\Output::i()->title, \IPS\Output::i()->output, array( 'app' => \IPS\Dispatcher::i()->application->directory, 'module' => \IPS\Dispatcher::i()->module->key, 'controller' => \IPS\Dispatcher::i()->controller ) ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
}
return;
}
}
/* Hide: ask for reason */
if ( \IPS\Request::i()->modaction == 'hide' )
{
$form = new \IPS\Helpers\Form( 'form', 'hide' );
$form->class = 'ipsForm_vertical';
$form->hiddenValues['modaction'] = 'hide';
$form->hiddenValues['moderate'] = \IPS\Request::i()->moderate;
$form->add( new \IPS\Helpers\Form\Text( 'hide_reason' ) );
if ( $values = $form->values() )
{
$params = $values['hide_reason'];
}
else
{
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( \IPS\Output::i()->output );
}
else
{
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( \IPS\Output::i()->title, \IPS\Output::i()->output, array( 'app' => \IPS\Dispatcher::i()->application->directory, 'module' => \IPS\Dispatcher::i()->module->key, 'controller' => \IPS\Dispatcher::i()->controller ) ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
}
return;
}
}
/* Merge: what's the master? */
if ( \IPS\Request::i()->modaction == 'merge' )
{
$ids = array_keys( \IPS\Request::i()->moderate );
$options = array();
$descriptions = array();
foreach ( $ids as $id )
{
$item = $class::load( $id );
$options[ $id ] = $item->mapped('title');
$descriptions[ $id ] = \IPS\Member::loggedIn()->language()->addToStack( 'byline', FALSE, array( 'sprintf' => array( $item->author()->name ) ) ) . \IPS\DateTime::ts( $item->mapped('date') )->html();
}
if ( count( $options ) === 1 )
{
foreach ( $options as $id => $title )
{
\IPS\Output::i()->redirect( $class::load( $id )->url()->setQueryString( 'do', 'merge' ) );
}
}
else
{
$form = new \IPS\Helpers\Form( 'form', 'merge' );
$form->class = 'ipsForm_vertical';
$form->hiddenValues['modaction'] = 'merge';
$form->hiddenValues['moderate'] = \IPS\Request::i()->moderate;
$form->add( new \IPS\Helpers\Form\Radio( 'merge_master', NULL, TRUE, array( 'options' => $options, 'descriptions' => $descriptions ) ) );
if ( $values = $form->values() )
{
$otherItems = array();
foreach ( $ids as $id )
{
if ( $id != $values['merge_master'] )
{
$otherItems[] = $class::load( $id );
}
}
$class::load( $values['merge_master'] )->mergeIn( $otherItems );
}
else
{
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( \IPS\Output::i()->output );
}
else
{
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( \IPS\Output::i()->title, \IPS\Output::i()->output, array( 'app' => \IPS\Dispatcher::i()->application->directory, 'module' => \IPS\Dispatcher::i()->module->key, 'controller' => \IPS\Dispatcher::i()->controller ) ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
}
return;
}
}
}
/* Everything else: just do it */
else
{
foreach ( array_keys( \IPS\Request::i()->moderate ) as $id )
{
try
{
$object = $class::loadAndCheckPerms( $id );
$object->modAction( \IPS\Request::i()->modaction, \IPS\Member::loggedIn(), $params );
}
catch ( \Exception $e ) {}
}
}
\IPS\Output::i()->redirect( $this->baseUrl );
}
/**
* Return the table headers
*
* @param array|NULL $advancedSearchValues Advanced search values
* @return array
*/
public function getHeaders( $advancedSearchValues )
{
return array();
}
/**
* Return the container
*
* @return \IPS\Node\Model
*/
public function container()
{
return $this->container;
}
}
+123
View File
@@ -0,0 +1,123 @@
<?php
/**
* @brief Table Builder using an array datasource
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @since 18 Feb 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Helpers\Table;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* List Table Builder using an array datasource
*/
class _Custom extends Table
{
/**
* @brief Data
*/
protected $dataSource;
/**
* Constructor
*
* @param array $dataSource Data source
* @param \IPS\Http\Url $baseUrl Base URL
*/
public function __construct( $dataSource, \IPS\Http\Url $baseUrl )
{
$this->dataSource = $dataSource;
return parent::__construct( $baseUrl );
}
/**
* Get rows
*
* @param array $advancedSearchValues Values from the advanced search form
* @note $advancedSearchValues is currently ignored
* @return array
*/
public function getRows( $advancedSearchValues )
{
/* Get them */
$rows = array();
foreach ( $this->dataSource as $i => $data )
{
$row = $this->include ? array_combine( $this->include, array_fill( 0, count( $this->include ), NULL ) ) : array();
/* Get the columns from the XML */
foreach ( $data as $k => $v )
{
/* Are we including this one? */
if( ( $this->include !== NULL and !in_array( $k, $this->include ) ) or ( $this->exclude !== NULL and in_array( $k, $this->exclude ) ) )
{
continue;
}
/* Parse if necessary */
if( isset( $this->parsers[ $k ] ) )
{
$v = call_user_func( $this->parsers[ $k ], $v, $data );
}
else
{
$v = htmlentities( $v, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE );
}
/* Add to array */
$row[ $k ] = $v;
}
/* Add in some buttons if necessary */
if( $this->rowButtons !== NULL )
{
$row['_buttons'] = call_user_func( $this->rowButtons, $row, $i );
}
/* Add it to the array */
$rows[] = $row;
}
/* Quicksearch */
if ( $this->quickSearch !== NULL and \IPS\Request::i()->quicksearch )
{
$quickSearchColumn = $this->quickSearch;
$rows = array_filter( $rows, is_callable( $this->quickSearch ) ? $this->quickSearch : function( $row ) use ( $quickSearchColumn )
{
return mb_strpos( $row[ $quickSearchColumn ], \IPS\Request::i()->quicksearch ) !== FALSE;
} );
}
/* Do we need to sort? */
if( !empty( $rows ) and $this->sortBy and isset( $rows[0][ $this->sortBy ] ) )
{
$sortBy = $this->sortBy;
$sortDirection = $this->sortDirection;
uasort( $rows, function( $a, $b ) use ( $sortBy, $sortDirection )
{
if( $sortDirection === 'asc' )
{
return strnatcasecmp( mb_strtolower( $a[ $sortBy ] ), mb_strtolower( $b[ $sortBy ] ) );
}
else
{
return strnatcasecmp( mb_strtolower( $b[ $sortBy ] ), mb_strtolower( $a[ $sortBy ] ) );
}
});
}
return $rows;
}
}
+465
View File
@@ -0,0 +1,465 @@
<?php
/**
* @brief Table Builder using a database table datasource
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @since 18 Feb 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Helpers\Table;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* List Table Builder using a database table datasource
*/
class _Db extends Table
{
/**
* @brief Database Table
*/
protected $table;
/**
* @brief Selects
*/
public $selects = array();
/**
* @brief Initial WHERE clause
*/
public $where;
/**
* @brief Initial GROUP BY clause
*/
protected $group;
/**
* @brief Force index clause
*/
protected $index;
/**
* @brief Joins
*/
public $joins = array();
/**
* @brief Key field
*/
public $keyField = NULL;
/**
* Constructor
*
* @param array $table Database table
* @param \IPS\Http\Url $baseUrl Base URL
* @param array|null $where WHERE clause
* @param string|null $group GROUP clause
* @param array|null $forceIndex Index to force
* @return void
*/
public function __construct( $table, \IPS\Http\Url $baseUrl, $where=NULL, $group=NULL, $forceIndex=NULL )
{
$this->table = $table;
$this->where = $where;
$this->group = $group;
$this->index = $forceIndex;
return parent::__construct( $baseUrl );
}
/**
* Get rows
*
* @param array $advancedSearchValues Values from the advanced search form
* @return array
*/
public function getRows( $advancedSearchValues )
{
/* Specify filter in where clause */
$where = $this->where ? is_array( $this->where ) ? $this->where : array( $this->where ) : array();
if ( $this->filter and isset( $this->filters[ $this->filter ] ) )
{
$where[] = is_array( $this->filters[ $this->filter ] ) ? $this->filters[ $this->filter ] : array( $this->filters[ $this->filter ] );
}
/* Add quick search term to where clause if necessary */
if ( $this->quickSearch !== NULL and \IPS\Request::i()->quicksearch )
{
if ( is_callable( $this->quickSearch ) )
{
$where[] = call_user_func( $this->quickSearch, \IPS\Request::i()->quicksearch );
}
else
{
$columns = is_array( $this->quickSearch ) ? $this->quickSearch[0] : $this->quickSearch;
$columns = is_array( $columns ) ? $columns : array( $columns );
$_where = '';
foreach ( $columns as $c )
{
$_where[] = "LOWER(`{$c}`) LIKE CONCAT( '%', ?, '%' )";
}
$where[] = array_merge( array( '(' . implode( ' OR ', $_where ) . ')' ), array_fill( 0, count( $_where ), mb_strtolower( \IPS\Request::i()->quicksearch ) ) );
}
}
/* Add advanced search */
if ( !empty( $advancedSearchValues ) )
{
foreach ( $advancedSearchValues as $k => $v )
{
if ( isset( $this->advancedSearch[ $k ] ) )
{
$type = $this->advancedSearch[ $k ];
if ( is_array( $type ) )
{
if ( isset( $type[2] ) )
{
$lambda = $type[2];
$type = SEARCH_CUSTOM;
}
else
{
$options = $type[1];
$type = $type[0];
}
}
switch ( $type )
{
case SEARCH_CUSTOM:
if ( $clause = call_user_func( $lambda, $v ) )
{
$where[] = $clause;
}
break;
case SEARCH_CONTAINS_TEXT:
$where[] = array( "{$k} LIKE ?", '%' . $v . '%' );
break;
case SEARCH_DATE_RANGE:
if ( $v['start'] )
{
$where[] = array( "{$k}>?", $v['start']->getTimestamp() );
}
if ( $v['end'] )
{
$where[] = array( "{$k}<?", $v['end']->getTimestamp() );
}
break;
case SEARCH_SELECT:
$where[] = array( "{$k}=?", $v );
break;
case SEARCH_MEMBER:
$where[] = array( "{$k}=?", $v->member_id );
break;
case SEARCH_NODE:
$nodeClass = $options['class'];
$prop = isset( $options['searchProp'] ) ? $options['searchProp'] : '_id';
if ( !is_array( $v ) )
{
$v = array( $v );
}
$values = array();
foreach ( $v as $_v )
{
if ( !is_object( $_v ) )
{
if ( mb_substr( $_v, 0, 2 ) === 's.' )
{
$nodeClass = $nodeClass::$subnodeClass;
$_v = mb_substr( $_v, 2 );
}
try
{
$_v = $nodeClass::load( $_v );
}
catch ( \OutOfRangeException $e )
{
continue;
}
}
$values[] = $_v->$prop;
}
$where[] = array( \IPS\Db::i()->in( $k, $values ) );
break;
case SEARCH_NUMERIC:
switch ( $v[0] )
{
case 'gt':
$where[] = array( "{$k}>?", (float) $v[1] );
break;
case 'lt':
$where[] = array( "{$k}<?", (float) $v[1] );
break;
case 'eq':
$where[] = array( "{$k}=?", (float) $v[1] );
break;
}
break;
case SEARCH_BOOL:
$where[] = array( "{$k}=?", (bool) $v );
break;
}
}
}
}
$selects = $this->selects;
if ( count( $this->joins ) )
{
foreach( $this->joins as $join )
{
if ( isset( $join['select'] ) )
{
$selects[] = $join['select'];
}
}
}
/* Count results (for pagination) */
if ( $this->group === null )
{
$count = \IPS\Db::i()->select( 'count(*)', $this->table, $where );
if ( count( $this->joins ) )
{
foreach( $this->joins as $join )
{
$count->join( $join['from'], ( isset( $join['where'] ) ? $join['where'] : null ), 'LEFT' );
}
}
$count = $count->first();
$query = \IPS\Db::i()->select( '*' . ( count( $selects ) ? ', ' . implode( ', ', $selects ) : '' ), $this->table, $where, NULL, array( 0, 1 ) );
}
else
{
$query = \IPS\Db::i()->select( '*, count(DISTINCT( '.$this->table.'.' . $this->group . ')) as _count' . ( count( $selects ) ? ', ' . implode( ', ', $selects ) : '' ), $this->table, $where, NULL, array( 0, 1 ) );
}
if ( count( $this->joins ) )
{
foreach( $this->joins as $join )
{
$query->join( $join['from'], ( isset( $join['where'] ) ? $join['where'] : null ), 'LEFT' );
}
}
if ( $this->index )
{
$query->forceIndex( $this->index );
}
if ( $this->group === null )
{
try
{
$results = $query->first();
}
catch( \UnderflowException $e )
{
$results = array();
}
}
else
{
$count = $query->first();
$results = $count;
$count = $count['_count'];
}
$this->pages = ceil( $count / $this->limit );
/* What are we sorting by? */
$orderBy = NULL;
if ( $this->_isSqlSort( $results ) )
{
$orderBy = implode( ',', array_map( function( $v )
{
if ( ! mb_strstr( trim( $v ), ' ' ) )
{
return '`' . trim( $v ) . '`';
}
else
{
list( $field, $direction ) = explode( ' ', $v );
return '`' . trim( $field ) . '` ' . $direction;
}
}, explode( ',', $this->sortBy ) ) );
$orderBy .= $this->sortDirection == 'asc' ? ' asc' : ' desc';
}
/* Run query */
$rows = array();
$select = \IPS\Db::i()->select(
( count( $selects ) ) ? $this->table . '.*, ' . implode( ', ', $selects ) : '*',
$this->table,
$where,
$orderBy,
array( ( $this->limit * ( $this->page - 1 ) ), $this->limit ), $this->group
);
if ( $this->index )
{
$select->forceIndex( $this->index );
}
if ( count( $this->joins ) )
{
foreach( $this->joins as $join )
{
$select->join( $join['from'], $join['where'], 'LEFT' );
}
}
if ( $this->keyField !== NULL )
{
$select->setKeyField( $this->keyField );
}
foreach ( $select as $rowId => $row )
{
/* Add in any 'custom' fields */
$_row = $row;
if ( $this->include !== NULL )
{
$row = array();
foreach ( $this->include as $k )
{
$row[ $k ] = isset( $_row[ $k ] ) ? $_row[ $k ] : NULL;
}
if( !empty( $advancedSearchValues ) )
{
foreach ( $advancedSearchValues as $k => $v )
{
$row[ $k ] = isset( $_row[ $k ] ) ? $_row[ $k ] : NULL;
}
}
}
/* Loop the data */
foreach ( $row as $k => $v )
{
/* Parse if necessary (NB: deliberately do this before removing the row in case we need to do some processing, but don't want the column to actually show) */
if( isset( $this->parsers[ $k ] ) )
{
$v = call_user_func( $this->parsers[ $k ], $v, $_row );
}
else
{
$v = htmlentities( $v, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE );
}
/* Are we including this one? */
if( ( ( $this->include !== NULL and !in_array( $k, $this->include ) ) or ( $this->exclude !== NULL and in_array( $k, $this->exclude ) ) ) and !array_key_exists( $k, $advancedSearchValues ) )
{
unset( $row[ $k ] );
continue;
}
/* Add to array */
$row[ $k ] = $v;
}
/* Add in some buttons if necessary */
if( $this->rowButtons !== NULL )
{
$row['_buttons'] = call_user_func( $this->rowButtons, $_row );
}
$rows[ $rowId ] = $row;
}
/* If we're sorting on a column not in the DB, do it manually */
if ( $this->sortBy and $this->_isSqlSort( $results ) !== true )
{
$sortBy = $this->sortBy;
$sortDirection = $this->sortDirection;
uasort( $rows, function( $a, $b ) use ( $sortBy, $sortDirection )
{
if( $sortDirection === 'asc' )
{
return strnatcasecmp( mb_strtolower( $a[ $sortBy ] ), mb_strtolower( $b[ $sortBy ] ) );
}
else
{
return strnatcasecmp( mb_strtolower( $b[ $sortBy ] ), mb_strtolower( $a[ $sortBy ] ) );
}
});
}
/* Return */
return $rows;
}
/**
* User set sortBy is suitable for an SQL sort operation
* @param array $count Result of COUNT(*) query with field names included
* @return boolean
*/
protected function _isSqlSort( $count )
{
if ( !$this->sortBy )
{
return false;
}
if ( mb_strstr( $this->sortBy, ',' ) )
{
foreach( explode( ',', $this->sortBy ) as $field )
{
$field = trim($field);
if ( mb_strstr( $field, ' ' ) )
{
list( $field, $direction ) = explode( ' ', $field );
}
if ( !array_key_exists( trim($field), $count ) )
{
return false;
}
}
return true;
}
elseif ( array_key_exists( $this->sortBy, $count ) )
{
return true;
}
return false;
}
/**
* What custom multimod actions are available
*
* @return array
*/
public function customActions()
{
return array();
}
}
+661
View File
@@ -0,0 +1,661 @@
<?php
/**
* @brief Table Builder
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @since 18 Feb 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Helpers\Table;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
const SEARCH_CUSTOM = 0;
const SEARCH_CONTAINS_TEXT = 1;
const SEARCH_DATE_RANGE = 2;
const SEARCH_SELECT = 3;
const SEARCH_MEMBER = 4;
const SEARCH_NODE = 5;
const SEARCH_NUMERIC = 6;
const SEARCH_BOOL = 7;
const HEADER = 8;
const SEARCH_RADIO = 9;
/**
* List Table Builder
*/
abstract class _Table
{
/**
* @brief Base URL of the page the list table is on
*/
public $baseUrl;
/**
* @brief Elements to include (defaults to all - can use either this or $exclude)
*/
public $include = NULL;
/**
* @brief Elements to exclude (defaults to none - can use either this or $include)
*/
public $exclude = NULL;
/**
* @brief Column to sort results by
*/
public $sortBy;
/**
* @brief Sort Direction - "asc" or "desc"
*/
public $sortDirection = NULL;
/**
* @brief Columns that are not sortable
*/
public $noSort = array();
/**
* @brief Filters
*/
public $filters = array();
/**
* @brief Current filter
*/
public $filter = NULL;
/**
* @brief Field to enable quick search on
*/
public $quickSearch = NULL;
/**
* @brief Whether to show advanced search/sort button or not
* @note It is possible to recreate the form external to the helper (e.g. search) in which case you may not want to show the button
*/
public $showAdvancedSearch = TRUE;
/**
* @brief Fields to enable advanced sarch on
* @note Keys are the field names. Values are a IPS\Helpers\Table\SEARCH_* constant
*/
public $advancedSearch = array();
/**
* @brief Number of records to show
*/
public $limit = 25;
/**
* @brief Number of pages
* @see \IPS\Helpers\Table\getRows
*/
public $pages = 1;
/**
* @brief Current Page
*/
public $page = 1;
/**
* @brief Pagination parameter
*/
protected $paginationKey = 'page';
/**
* @brief Table resort parameter
*/
public $resortKey = 'listResort';
/**
* @brief Language prefix for column names
*/
public $langPrefix = '';
/**
* @brief Language key for table title
*/
public $title = '';
/**
* @brief Parsers
* @code
// Example of a parser that would convert value to uppercase:
$parsers = array(
'column_key' => function( $value )
{
return strtoupper( $value );
}
);
* @endcode
* @note When implementing, note that this will override the default parser which runs htmlentities, necessary for preventing XSS
*/
public $parsers = array();
/**
* @brief Column to highlight as the "main" column (e.g. the title)
*/
public $mainColumn = NULL;
/**
* @brief Additional CSS classes to apply to columns
*/
public $classes = array();
/**
* @brief Buttons to show on the "root row"
* @code
array(
array(
'icon' => array(
'icon.png' // Path to icon
'core' // Application icon belongs to
),
'title' => 'foo', // Language key to use for button's title parameter
'link' => \IPS\Http\Url::internal( 'app=foo...' ) // URI to link to
'class' => 'modalLink' // CSS Class to use on link (Optional)
),
... // Additional buttons
);
* @endcode
*/
public $rootButtons = NULL;
/**
* @brief Callback function to get buttons for a record
* @code
$rowButtons = function( $row )
{
return array( ... ); // Same format as IPS\Helpers\Table::$rootButtons
}
* @code
*/
public $rowButtons = NULL;
/**
* @brief Column widths (in percentages)
*/
public $widths = array();
/**
* @brief Template for table
*/
public $tableTemplate;
/**
* @brief Template for rows
*/
public $rowsTemplate;
/**
* @brief Sort options (used only on front-end)
*/
public $sortOptions;
/**
* @brief Unique ID for this table
*/
public $uniqueId;
/**
* @brief Extra HTML to show below filter/search bar
*/
public $extraHtml = '';
/**
* @brief Extra Data
*/
public $extra = NULL;
/**
* @brief Store advanced search values
*/
protected $advancedSearchValues = NULL;
/**
* Constructor
*
* @param \IPS\Http\Url $baseUrl Base URL of the page the list table is on
* @return void
*/
public function __construct( \IPS\Http\Url $baseUrl )
{
/* Set page */
$parameter = $this->paginationKey;
if ( \IPS\Request::i()->$parameter )
{
$this->page = intval( \IPS\Request::i()->$parameter );
if ( !$this->page OR $this->page < 1 )
{
$this->page = 1;
}
}
/* Set sort options */
if( \IPS\Request::i()->sortby )
{
$this->sortBy = \IPS\Request::i()->sortby;
}
if( \IPS\Request::i()->sortdirection )
{
$this->sortDirection = ( mb_strtolower( \IPS\Request::i()->sortdirection ) === 'desc' or mb_strtolower( \IPS\Request::i()->sortdirection ) === 'asc' ) ? mb_strtolower( \IPS\Request::i()->sortdirection ) : NULL;
}
/* Filter? */
if ( \IPS\Request::i()->filter )
{
$this->filter = \IPS\Request::i()->filter;
}
/* Set base URL */
$this->baseUrl = $baseUrl->setQueryString( array( 'filter' => $this->filter, 'sortby' => $this->sortBy, 'sortdirection' => $this->sortDirection, $this->paginationKey => $this->page ) );
/* Templates */
$this->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'tables', 'core' ), 'table' );
$this->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'tables', 'core' ), 'rows' );
/* Create a unique id used by the template - can be overriden manually if desired */
$this->uniqueId = md5( uniqid() );
}
/**
* Retrieve the pagination key
*
* @return string
*/
public function getPaginationKey()
{
return $this->paginationKey;
}
/**
* Setting the page parameter means we need to recalculate the pages
*
* @param string $property Property we are updating
* @param mixed $value Value being set
* @return void
*/
public function __set( $property, $value )
{
if( $property == 'paginationKey' )
{
$this->baseUrl = $this->baseUrl->stripQueryString( $this->paginationKey );
$this->paginationKey = $value;
if ( \IPS\Request::i()->$value )
{
$this->page = intval( \IPS\Request::i()->$value );
if ( !$this->page OR $this->page < 1 )
{
$this->page = 1;
}
}
$this->baseUrl = $this->baseUrl->setQueryString( array( $value => $this->page ) );
}
}
/**
* Build Advanced Search Form
*
* @return \IPS\Helpers\Form
*/
protected function advancedSearch()
{
$form = new \IPS\Helpers\Form( 'advanced_search', 'search', $this->baseUrl, array( 'data-role' => 'advancedSearch' ) );
$form->hiddenValues['filter'] = \IPS\Request::i()->filter;
$form->hiddenValues['sortby'] = \IPS\Request::i()->sortby;
$form->hiddenValues['sortdirection'] = \IPS\Request::i()->sortdirection;
foreach ( $this->advancedSearch as $k => $type )
{
$options = array();
if ( is_array( $type ) )
{
$options = $type[1];
$type = $type[0];
}
switch ( $type )
{
case SEARCH_CUSTOM:
$form->add( new \IPS\Helpers\Form\Custom( $this->langPrefix . $k, NULL, FALSE, $options ) );
break;
case SEARCH_CONTAINS_TEXT:
$form->add( new \IPS\Helpers\Form\Text( $this->langPrefix . $k, NULL, FALSE, $options ) );
break;
case SEARCH_DATE_RANGE:
$form->add( new \IPS\Helpers\Form\DateRange( $this->langPrefix . $k, array( 'start' => '', 'end' => '' ), FALSE, $options ) );
break;
case SEARCH_SELECT:
$form->add( new \IPS\Helpers\Form\Select( $this->langPrefix . $k, NULL, FALSE, $options ) );
break;
case SEARCH_RADIO:
$form->add( new \IPS\Helpers\Form\Radio( $this->langPrefix . $k, NULL, FALSE, $options ) );
break;
case SEARCH_MEMBER:
$form->add( new \IPS\Helpers\Form\Member( $this->langPrefix . $k, NULL, FALSE, $options ) );
break;
case SEARCH_NODE:
$form->add( new \IPS\Helpers\Form\Node( $this->langPrefix . $k, 0, FALSE, $options ) );
break;
case SEARCH_NUMERIC:
$form->add( new \IPS\Helpers\Form\Custom( $this->langPrefix . $k, NULL, FALSE, array(
'getHtml' => function( $element )
{
return \IPS\Theme::i()->getTemplate( 'forms', 'core' )->select( "{$element->name}[0]", $element->value[0], $element->required, array(
'any' => \IPS\Member::loggedIn()->language()->addToStack('any'),
'gt' => \IPS\Member::loggedIn()->language()->addToStack('gt'),
'lt' => \IPS\Member::loggedIn()->language()->addToStack('lt'),
'eq' => \IPS\Member::loggedIn()->language()->addToStack('exactly'),
),
FALSE,
NULL,
FALSE,
array(
'any' => array(),
'gt' => array( $element->name . '-qty' ),
'lt' => array( $element->name . '-qty' ),
'eq' => array( $element->name . '-qty' ),
) )
. ' '
. \IPS\Theme::i()->getTemplate( 'forms', 'core', 'global' )->number( "{$element->name}[1]", $element->value[1], $element->required, NULL, FALSE, NULL, NULL, NULL, 0, NULL, FALSE, NULL, array(), array(), array( $element->name . '-qty' ) );
}
) ) );
break;
case SEARCH_BOOL:
$form->add( new \IPS\Helpers\Form\YesNo( $this->langPrefix . $k, TRUE, FALSE, $options ) );
break;
case HEADER:
$form->addHeader( $this->langPrefix . $k );
break;
}
}
return $form;
}
/**
* Get HTML
*
* @return string
*/
public function __toString()
{
try
{
/* Advanced Search */
$advancedSearchValues = array();
if ( !empty( $this->advancedSearch ) )
{
/* Are we displaying the advanced search form? */
if ( \IPS\Request::i()->advancedSearchForm )
{
return (string) $this->advancedSearch();
}
/* No? Try getting some values then */
else
{
$advancedSearchValues = $this->getAdvancedSearchValues();
}
}
/* Get rows */
$rows = $this->getRows( $advancedSearchValues );
/* Check we're on a valid page (must come after getRows() as this is where $this->pages is set) */
if ( $this->page )
{
if ( $this->pages and $this->page > $this->pages )
{
\IPS\Output::i()->redirect( $this->baseUrl->setQueryString( $this->paginationKey, 1 ), NULL, 303 );
}
}
/* Add link tags */
if ( $this->page != 1 )
{
\IPS\Output::i()->linkTags['first'] = (string) $this->baseUrl->setQueryString( $this->paginationKey, 1 );
\IPS\Output::i()->linkTags['prev'] = (string) $this->baseUrl->setQueryString( $this->paginationKey, $this->page - 1 );
}
if ( $this->pages > $this->page )
{
\IPS\Output::i()->linkTags['next'] = (string) $this->baseUrl->setQueryString( $this->paginationKey, $this->page + 1 );
}
if ( $this->pages != $this->page )
{
\IPS\Output::i()->linkTags['last'] = (string) $this->baseUrl->setQueryString( $this->paginationKey, $this->pages );
}
/* Get table headers */
$headers = $this->getHeaders( $advancedSearchValues );
/* If this is an AJAX request, just return them, with pagination */
$resortKey = $this->resortKey;
if( \IPS\Request::i()->isAjax() and \IPS\Request::i()->$resortKey )
{
\IPS\Output::i()->json( array( 'rows' => call_user_func( $this->rowsTemplate, $this, $headers, $rows, $this->mainColumn, $this->rootButtons, array() ), 'pagination' => \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $this->baseUrl, $this->pages, $this->page, $this->limit, TRUE, $this->paginationKey ), 'extraHtml' => $this->extraHtml ) );
}
/* Otherwise, show the full table */
else
{
/* If there are no root buttons, but we have a callback for adding row buttons, make sure the column gets made */
if( $this->rootButtons === NULL and $this->rowButtons !== NULL )
{
$this->rootButtons = array();
}
/* Add JS */
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'global_core.js', 'core', 'global' ) );
/* Build table */
return call_user_func( $this->tableTemplate, $this, $headers, $rows, ( is_array( $this->quickSearch ) ? $this->quickSearch[1] : $this->quickSearch ), !empty( $this->advancedSearch ) );
}
}
catch ( \Exception $e )
{
\IPS\IPS::exceptionHandler( $e );
}
}
/**
* Convert the value of a search field into something we can put in the query string
*
* @param array $values The values
* @return array
*/
protected function _convertSearchValuesForQueryString( $values )
{
$return = array();
foreach( $values as $k => $v )
{
if ( is_array( $v ) )
{
$return[ $k ] = $this->_convertSearchValuesForQueryString( $v );
}
elseif ( $v instanceof \IPS\DateTime )
{
$return[ $k ] = $v->getTimestamp();
}
elseif ( $v instanceof \IPS\Member )
{
$return[ $k ] = $v->name;
}
elseif ( $v instanceof \IPS\Node\Model )
{
if ( isset( $this->advancedSearch[ mb_substr( $k, mb_strlen( $this->langPrefix ) ) ] ) AND
!( $v instanceof $this->advancedSearch[ mb_substr( $k, mb_strlen( $this->langPrefix ) ) ][1]['class'] ) )
{
$return[ $k ] = 's.' . $v->_id;
}
else
{
$return[ $k ] = $v->_id;
}
}
else if( isset( $this->advancedSearch[ mb_substr( $k, mb_strlen( $this->langPrefix ) ) ] ) and $this->advancedSearch[ mb_substr( $k, mb_strlen( $this->langPrefix ) ) ] === \IPS\Helpers\Table\SEARCH_BOOL )
{
$return[ $k . '_checkbox' ] = $v;
}
else
{
$return[ $k ] = $v;
}
}
return $return;
}
/**
* Get rows
*
* @param array $advancedSearchValues Values from the advanced search form
* @return array
*/
abstract public function getRows( $advancedSearchValues );
/**
* Return the table headers
*
* @param array|NULL $advancedSearchValues Advanced search values
* @return array
*/
public function getHeaders( $advancedSearchValues )
{
/* Get headers */
if ( empty( $this->include ) )
{
$headers = array();
foreach ( $this->getRows( $advancedSearchValues ) as $row )
{
foreach ( array_keys( $row ) as $header )
{
$headers[ $header ] = $header;
}
break;
}
}
else
{
if( !empty( $advancedSearchValues ) )
{
$headers = array_combine( array_merge( $this->include, array_keys( $advancedSearchValues ) ), array_merge( $this->include, array_keys( $advancedSearchValues ) ) );
}
else
{
$headers = $this->include;
}
}
if ( $this->exclude !== NULL )
{
$headers = array_diff( $headers, $this->exclude );
}
if ( $this->rootButtons !== NULL or $this->rowButtons !== NULL )
{
$headers['_buttons'] = '_buttons';
}
return $headers;
}
/**
* Does the user have permission to use the multi-mod checkboxes?
*
* @param string|null $action Specific action to check (hide/unhide, etc.) or NULL for a generic check
* @return bool
*/
public function canModerate( $action=NULL )
{
return FALSE;
}
/**
* Get the advanced search values
*
* @return array
*/
public function getAdvancedSearchValues()
{
/* Advanced Search */
$advancedSearchValues = array();
$advancedSearchValuesQuery = array();
if ( !empty( $this->advancedSearch ) )
{
/* Are we displaying the advanced search form? */
if ( \IPS\Request::i()->advancedSearchForm )
{
return (string) $this->advancedSearch();
}
/* No? Try getting some values then */
elseif ( $values = $this->advancedSearch()->values() )
{
$form = $this->advancedSearch();
/* Store these to prevent URL from being rebuilt on subsequent calls */
if ( $this->advancedSearchValues === NULL )
{
foreach ( $values as $k => $v )
{
if( array_key_exists( $k, $form->hiddenValues ) )
{
continue;
}
if ( $v )
{
if( \IPS\Request::i()->isAjax() )
{
if ( is_array( $v ) )
{
$newVal = array();
foreach( $v as $key => $val )
{
$newVal[ $key ] = urldecode( $val );
}
$v = $newVal;
}
else
{
$v = urldecode( $v );
}
}
$advancedSearchValuesQuery[ $k ] = $v;
$this->advancedSearchValues[ mb_substr( $k, mb_strlen( $this->langPrefix ) ) ] = $v;
}
}
if ( !empty( $this->advancedSearchValues ) )
{
$this->baseUrl = $this->baseUrl->setQueryString( array_merge( array( 'advanced_search_submitted' => 1, 'csrfKey' => \IPS\Session::i()->csrfKey ), $this->_convertSearchValuesForQueryString( $advancedSearchValuesQuery ) ) );
}
}
}
}
return $this->advancedSearchValues;
}
}
View File
Whitespace-only changes.