Version 4.5.0

This commit is contained in:
Neo committed 2025-12-19 05:51:58 -08:00
1 parent 1a0c7fd3c2
commit f79dcf067a
3791 files changed
+248032 -76372

No files matched your search

@@ -12,7 +12,7 @@
namespace IPS\gallery\modules\admin\gallery;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _categories extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
@@ -53,4 +58,112 @@ class _categories extends \IPS\Node\Controller
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('add_category');
}
}
/**
* Build the form to mass move content
*
* @param \IPS\Helpers\Form $form The form helper object
* @param mixed $data Data from the wizard helper
* @param string $nodeClass Node class
* @param \IPS\Node\Model $node Node we are working with
* @param string $contentItemClass Content item class (if there is one)
* @return \IPS\Helpers\Form
*/
protected function _buildMassMoveForm( $form, $data, $nodeClass, $node, $contentItemClass )
{
/* Add an option to move or delete albums - we won't worry about filters */
$form->addHeader('node_mass_move_delete_albums');
$form->add( new \IPS\Helpers\Form\Node( 'node_move_subalbums', isset( $data['moveToAlbums'] ) ? $data['moveToClassAlbums']::load( $data['moveToAlbums'] ) : 0, TRUE, array( 'class' => $nodeClass, 'disabled' => array( $node->_id ), 'disabledLang' => 'node_move_delete', 'zeroVal' => 'node_delete_content', 'subnodes' => FALSE, 'permissionCheck' => function( $node )
{
return $node->can('add');
} ) ) );
return parent::_buildMassMoveForm( $form, $data, $nodeClass, $node, $contentItemClass );
}
/**
* Process the mass move form submission
*
* @param array $values Values from form submission
* @param mixed $data Data from the wizard helper
* @param string $nodeClass Node class
* @param \IPS\Node\Model $node Node we are working with
* @param string $contentItemClass Content item class (if there is one)
* @return array Wizard helper data
*/
protected function _processMassMoveForm( $values, $data, $nodeClass, $node, $contentItemClass )
{
$data = parent::_processMassMoveForm( $values, $data, $nodeClass, $node, $contentItemClass );
/* What are we doing with the albums? */
if ( \is_object( $values['node_move_subalbums'] ) )
{
$data['moveToClassAlbums'] = \get_class( $values['node_move_subalbums'] );
$data['moveToAlbums'] = $values['node_move_subalbums']->_id;
}
else
{
unset( $data['moveToClassAlbums'] );
unset( $data['moveToAlbums'] );
}
return $data;
}
/**
* Actually perform the mass move operation (called from the wizard helper)
*
* @param mixed $data Data from the wizard helper
* @param \IPS\Node\Model $node Node we are working with
* @param string $contentItemClass Content item class (if there is one)
* @return mixed
*/
protected function _performMassMove( $data, $node, $contentItemClass )
{
/* If we have confirmed the move, just handle albums now and then pass to the parent */
if ( isset( \IPS\Request::i()->confirm ) )
{
\IPS\Session::i()->csrfCheck();
/* Loop over our albums */
foreach( \IPS\gallery\Album\Item::getItemsWithPermission( array( array( 'album_category_id=?', $node->_id ) ), NULL, 1000, NULL, TRUE, 0, NULL, FALSE, FALSE, FALSE, FALSE, NULL, TRUE, FALSE, FALSE, FALSE ) as $album )
{
$album = $album->asNode();
/* Are we moving albums? */
if ( isset( $data['moveToAlbums'] ) )
{
$album->moveTo( $data['moveToClassAlbums']::load( $data['moveToAlbums'] ) );
}
else
{
/* Store the task for deleting */
\IPS\Task::queue( 'core', 'DeleteOrMoveContent', array( 'class' => 'IPS\gallery\Category', 'id' => $album->_id, 'deleteWhenDone' => FALSE ) );
}
}
if ( isset( $data['moveToAlbums'] ) )
{
$newNode = $data['moveToClassAlbums']::load( $data['moveToAlbums'] );
\IPS\Session::i()->log( 'acplog__catalbum_mass_move', array( $this->title => TRUE, $node->titleForLog() => FALSE, $newNode->titleForLog() => FALSE ) );
}
else
{
\IPS\Session::i()->log( 'acplog__catalbum_mass_delete', array( $this->title => TRUE, $node->titleForLog() => FALSE ) );
}
/* Then let the parent take over */
return parent::_performMassMove( $data, $node, $contentItemClass );
}
/* Otherwise show a slightly more useful confirmation message */
else
{
$albumCount = \IPS\gallery\Album\Item::getItemsWithPermission( array( array( 'album_category_id=?', $node->_id ) ), NULL, 1000, NULL, TRUE, 0, NULL, FALSE, FALSE, FALSE, TRUE, NULL, TRUE, FALSE, FALSE, FALSE );
$itemDeletionWhere = $node->massMoveorDeleteWhere( $data );
$itemDeletionWhere[] = array( 'image_album_id=?', 0 );
return \IPS\Theme::i()->getTemplate( 'global', 'gallery' )->nodeMoveDeleteContent( $this->url->setQueryString( array( 'do' => 'massManageContent', 'id' => $node->_id ) ), \IPS\Member::loggedIn()->language()->addToStack( $contentItemClass::$title . '_pl_lc' ), $node->getContentItems( NULL, NULL, $itemDeletionWhere, TRUE ), isset( $data['moveTo'] ) ? $data['moveToClass']::load( $data['moveTo'] ) : NULL, $albumCount, isset( $data['moveToAlbums'] ) ? $data['moveToClassAlbums']::load( $data['moveToAlbums'] ) : NULL );
}
}
}
@@ -12,7 +12,7 @@
namespace IPS\gallery\modules\admin\gallery;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _settings extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -76,6 +81,11 @@ class _settings extends \IPS\Dispatcher\Controller
$form->addHeader( 'gallery_options' );
$form->add( new \IPS\Helpers\Form\YesNo( 'gallery_rss_enabled', \IPS\Settings::i()->gallery_rss_enabled ) );
if( \IPS\GeoLocation::enabled() )
{
$form->add( new \IPS\Helpers\Form\YesNo( 'gallery_maps_default', \IPS\Settings::i()->gallery_maps_default ) );
}
if ( $values = $form->values() )
{
$form->saveAsSettings( array(
@@ -12,7 +12,7 @@
namespace IPS\gallery\modules\admin\stats;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _bandwidth extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -50,7 +55,7 @@ class _bandwidth extends \IPS\Dispatcher\Controller
'chartArea' => array( 'left' => 120, 'width' => '75%' ),
'vAxis' => array(
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'filesize_raw_k' )
)
)
), 'AreaChart', 'daily', array( 'start' => 0, 'end' => 0 ), array( 'member_id', 'image_id', 'bdate', 'bsize' ) );
$chart->addSeries( \IPS\Member::loggedIn()->language()->addToStack('bandwidth'), 'number', 'ROUND((SUM(bsize)/1024),2)', FALSE );
@@ -12,7 +12,7 @@
namespace IPS\gallery\modules\admin\stats;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -24,6 +24,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
class _diskspace extends \IPS\Dispatcher\Controller
{
const PER_PAGE = 25;
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
@@ -43,69 +48,97 @@ class _diskspace extends \IPS\Dispatcher\Controller
*/
protected function manage()
{
$values = NULL;
$where = array();
if ( isset( \IPS\Request::i()->form ) )
{
$form = new \IPS\Helpers\Form( 'form', 'go' );
$form->add( new \IPS\Helpers\Form\DateRange( 'stats_date_range', NULL, FALSE, array( 'start' => array( 'max' => new \IPS\DateTime() ), 'end' => array( 'max' => new \IPS\DateTime() ) ) ) );
if ( $values = $form->values() )
{
if ( $values['stats_date_range']['start'] )
{
$where[] = array( 'image_date>?', $values['stats_date_range']['start']->getTimestamp() );
}
if ( $values['stats_date_range']['end'] )
{
$where[] = array( 'image_date<?', $values['stats_date_range']['end']->getTimestamp() );
}
}
else
$default = array(
'start' => \IPS\Request::i()->start ? \IPS\DateTime::ts( \IPS\Request::i()->start ) : NULL,
'end' => \IPS\Request::i()->end ? \IPS\DateTime::ts( \IPS\Request::i()->end ) : NULL
);
$form->add( new \IPS\Helpers\Form\DateRange( 'stats_date_range', $default, FALSE, array( 'start' => array( 'max' => \IPS\DateTime::ts( time() )->setTime( 0, 0, 0 ), 'time' => FALSE ), 'end' => array( 'max' => \IPS\DateTime::ts( time() )->setTime( 23, 59, 59 ), 'time' => FALSE ) ) ) );
if ( !$values = $form->values() )
{
\IPS\Output::i()->output = $form;
return;
}
}
$page = isset( \IPS\Request::i()->page ) ? intval( \IPS\Request::i()->page ) : 1;
/* Figure out start and end parameters for links */
$params = array(
'start' => !empty( $values['stats_date_range']['start'] ) ? $values['stats_date_range']['start']->getTimestamp() : \IPS\Request::i()->start,
'end' => !empty( $values['stats_date_range']['end'] ) ? $values['stats_date_range']['end']->getTimestamp() : \IPS\Request::i()->end
);
if( $params['start'] )
{
$where[] = array( 'image_date>?', $params['start'] );
}
if( $params['end'] )
{
$where[] = array( 'image_date<?', $params['end'] );
}
$page = isset( \IPS\Request::i()->page ) ? \intval( \IPS\Request::i()->page ) : 1;
if( $page < 1 )
{
$page = 1;
}
try
{
$total = \IPS\Db::i()->select( 'COUNT(DISTINCT(image_member_id))', 'gallery_images', $where )->first();
}
catch( \UnderflowException $e )
{
$total = 0;
}
$select = \IPS\Db::i()->select( 'image_member_id, COUNT(*) as images', 'gallery_images', $where, 'images DESC', array( ( $page - 1 ) * static::PER_PAGE, static::PER_PAGE ), 'image_member_id', NULL, \IPS\Db::SELECT_SQL_CALC_FOUND_ROWS )->join( 'core_members', 'core_members.member_id=gallery_images.image_member_id' );
$mids = array();
foreach( $select as $row )
if( $total > 0 )
{
$mids[] = $row['image_member_id'];
$select = \IPS\Db::i()->select( 'image_member_id, count(*) as images', 'gallery_images', $where, 'images DESC', array( ( $page - 1 ) * static::PER_PAGE, static::PER_PAGE ), 'image_member_id' )->join( 'core_members', 'core_members.member_id=gallery_images.image_member_id' );
$mids = array();
foreach( $select as $row )
{
$mids[] = $row['image_member_id'];
}
$members = array();
if ( \count( $mids ) )
{
$members = iterator_to_array( \IPS\Db::i()->select( '*', 'core_members', array( \IPS\Db::i()->in( 'member_id', $mids ) ) )->setKeyField('member_id') );
}
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination(
\IPS\Http\Url::internal( 'app=gallery&module=stats&controller=diskspace' )->setQueryString( $params ),
ceil( $total / static::PER_PAGE ),
$page,
static::PER_PAGE,
FALSE
);
\IPS\Output::i()->sidebar['actions'] = array(
'settings' => array(
'title' => 'stats_date_range',
'icon' => 'calendar',
'link' => \IPS\Http\Url::internal( 'app=gallery&module=stats&controller=diskspace&form=1' )->setQueryString( $params ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('stats_date_range') )
)
);
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global', 'core' )->message( \IPS\Member::loggedIn()->language()->addToStack( 'stats_include_hidden_content' ), 'info' );
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate('stats')->uploadersTable( $select, $pagination, $members );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__gallery_stats_diskspace');
}
if ( count( $mids ) )
else
{
$members = iterator_to_array( \IPS\Db::i()->select( '*', 'core_members', array( \IPS\Db::i()->in( 'member_id', $mids ) ) )->setKeyField('member_id') );
/* Return the no results message */
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global', 'core' )->block( \IPS\Member::loggedIn()->language()->addToStack('menu__gallery_stats_diskspace'), \IPS\Member::loggedIn()->language()->addToStack('no_results'), FALSE , 'ipsPad', NULL, TRUE );
}
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination(
\IPS\Http\Url::internal( 'app=gallery&module=stats&controller=diskspace' )->setQueryString( $values ),
ceil( $select->count( TRUE ) / static::PER_PAGE ),
$page,
static::PER_PAGE,
FALSE
);
\IPS\Output::i()->sidebar['actions'] = array(
'settings' => array(
'title' => 'stats_date_range',
'icon' => 'calendar',
'link' => \IPS\Http\Url::internal( 'app=gallery&module=stats&controller=diskspace&form=1' )->setQueryString( $values ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('stats_date_range') )
)
);
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global', 'core' )->message( \IPS\Member::loggedIn()->language()->addToStack( 'stats_include_hidden_content' ), 'info' );
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate('stats')->uploadersTable( $select, $pagination, $members );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__gallery_stats_diskspace');
}
}
@@ -12,7 +12,7 @@
namespace IPS\gallery\modules\admin\stats;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _member extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Images
*
@@ -12,7 +12,7 @@
namespace IPS\gallery\modules\front\gallery;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -45,6 +45,7 @@ class _browse extends \IPS\Content\Controller
\IPS\Member::loggedIn()->language()->words[ "sort_title" ] = \IPS\Member::loggedIn()->language()->addToStack( "album_sort_caption", FALSE );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('front_browse.js', 'gallery' ) );
\IPS\gallery\Application::outputCss();
parent::execute();
}
@@ -72,6 +73,13 @@ class _browse extends \IPS\Content\Controller
if ( \IPS\Settings::i()->gallery_rss_enabled )
{
\IPS\Output::i()->rssFeeds['gallery_rss_title'] = \IPS\Http\Url::internal( 'app=gallery&module=gallery&controller=browse&do=rss', 'front', 'gallery_rss' );
if ( \IPS\Member::loggedIn()->member_id )
{
$key = md5( ( \IPS\Member::loggedIn()->members_pass_hash ?: \IPS\Member::loggedIn()->email ) . \IPS\Member::loggedIn()->members_pass_salt );
\IPS\Output::i()->rssFeeds['gallery_rss_title'] = \IPS\Output::i()->rssFeeds['gallery_rss_title']->setQueryString( array( 'member' => \IPS\Member::loggedIn()->member_id , 'key' => $key ) );
}
}
/* And load data and display */
@@ -79,18 +87,29 @@ class _browse extends \IPS\Content\Controller
{
try
{
$category = \IPS\gallery\Category::loadAndCheckPerms( \IPS\Request::i()->category, 'view' );
$category = \IPS\gallery\Category::loadAndCheckPerms( \IPS\Request::i()->category, 'view' );
$category->clubCheckRules();
/* If we cannot view images and there's a custom error, show it now */
if( !$category->can( 'read' ) AND \IPS\Member::loggedIn()->language()->checkKeyExists( "gallery_category_{$category->id}_permerror" ) )
{
\IPS\Output::i()->error( "gallery_category_{$category->id}_permerror", '1G189/B', 403, '' );
\IPS\Output::i()->error( $category->errorMessage(), '1G189/B', 403, '' );
}
/* Add RSS feed */
if ( \IPS\Settings::i()->gallery_rss_enabled )
{
\IPS\Output::i()->rssFeeds[ \IPS\Member::loggedIn()->language()->addToStack( 'gallery_rss_title_container', FALSE, array( 'sprintf' => array( $category->_title ) ) ) ] = \IPS\Http\Url::internal( 'app=gallery&module=gallery&controller=browse&do=rss&category=' . $category->id, 'front', 'gallery_rss' );
$rssUrl = \IPS\Http\Url::internal( 'app=gallery&module=gallery&controller=browse&do=rss&category=' . $category->id, 'front', 'gallery_rss' );
if ( \IPS\Member::loggedIn()->member_id )
{
$key = md5( ( \IPS\Member::loggedIn()->members_pass_hash ?: \IPS\Member::loggedIn()->email ) . \IPS\Member::loggedIn()->members_pass_salt );
$rssUrl = $rssUrl->setQueryString( array( 'member' => \IPS\Member::loggedIn()->member_id , 'key' => $key ) );
}
\IPS\Output::i()->rssFeeds[ \IPS\Member::loggedIn()->language()->addToStack( 'gallery_rss_title_container', FALSE, array( 'sprintf' => array( $category->_title ) ) ) ] = $rssUrl;
}
$this->_category( $category );
@@ -105,11 +124,22 @@ class _browse extends \IPS\Content\Controller
try
{
$album = \IPS\gallery\Album::loadAndCheckPerms( \IPS\Request::i()->album, 'view' );
$album->category()->clubCheckRules();
/* Add RSS feed */
if ( \IPS\Settings::i()->gallery_rss_enabled )
{
\IPS\Output::i()->rssFeeds[\IPS\Member::loggedIn()->language()->addToStack('gallery_rss_title_container', FALSE, array('sprintf' => array($album->_title)))] = \IPS\Http\Url::internal('app=gallery&module=gallery&controller=browse&do=rss&album=' . $album->id, 'front', 'gallery_rss');
$rssUrl = \IPS\Http\Url::internal('app=gallery&module=gallery&controller=browse&do=rss&album=' . $album->id, 'front', 'gallery_rss');
if ( \IPS\Member::loggedIn()->member_id )
{
$key = md5( ( \IPS\Member::loggedIn()->members_pass_hash ?: \IPS\Member::loggedIn()->email ) . \IPS\Member::loggedIn()->members_pass_salt );
$rssUrl = $rssUrl->setQueryString( array( 'member' => \IPS\Member::loggedIn()->member_id , 'key' => $key ) );
}
\IPS\Output::i()->rssFeeds[ \IPS\Member::loggedIn()->language()->addToStack( 'gallery_rss_title_container', FALSE, array( 'sprintf' => array( $album->_title ) ) ) ] = $rssUrl;
}
$this->_album( $album );
}
@@ -186,12 +216,12 @@ class _browse extends \IPS\Content\Controller
\IPS\Output::i()->breadcrumb = array();
\IPS\Output::i()->breadcrumb['module'] = array( \IPS\Http\Url::internal( 'app=gallery&module=gallery&controller=browse', 'front', 'gallery' ), \IPS\Dispatcher::i()->module->_title );
if( !count( \IPS\gallery\Image::getItemsWithPermission( array( array( 'image_category_id=? AND image_album_id=?', $category->_id, 0 ) ) ) ) )
if( !\count( \IPS\gallery\Image::getItemsWithPermission( array( array( 'image_category_id=? AND image_album_id=?', $category->_id, 0 ) ) ) ) )
{
$table = ( $category->childrenCount() or $albums ) ? '' : \IPS\Theme::i()->getTemplate( 'browse' )->noImages( $category );
$parents = iterator_to_array( $category->parents() );
if ( count( $parents ) )
if ( \count( $parents ) )
{
foreach( $parents AS $parent )
{
@@ -229,18 +259,10 @@ class _browse extends \IPS\Content\Controller
}
}
/* If we're viewing a club, set the breadcrumbs appropriately */
if ( $club = $category->club() )
{
\IPS\core\FrontNavigation::$clubTabActive = TRUE;
\IPS\Output::i()->breadcrumb = array();
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=core&module=clubs&controller=directory', 'front', 'clubs_list' ), \IPS\Member::loggedIn()->language()->addToStack('module__core_clubs') );
\IPS\Output::i()->breadcrumb[] = array( $club->url(), $club->name );
\IPS\Output::i()->breadcrumb[] = array( $category->url(), $category->_title );
if ( \IPS\Settings::i()->clubs_header == 'sidebar' )
{
\IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate( 'clubs', 'core' )->header( $club, $category, 'sidebar' );
}
$club->setBreadcrumbs( $category );
}
\IPS\Output::i()->contextualSearchOptions[ \IPS\Member::loggedIn()->language()->addToStack( 'search_contextual_item_categories' ) ] = array( 'type' => 'gallery_image', 'nodes' => $category->_id );
@@ -255,7 +277,7 @@ class _browse extends \IPS\Content\Controller
*/
protected function _album( $album )
{
if( !count( \IPS\gallery\Image::getItemsWithPermission( array( array( 'image_album_id=?', $album->id ) ) ) ) )
if( !\count( \IPS\gallery\Image::getItemsWithPermission( array( array( 'image_album_id=?', $album->id ) ) ) ) )
{
/* Show a 'no images' template if there's nothing to display */
$table = \IPS\Theme::i()->getTemplate( 'browse' )->noImages( $album );
@@ -303,9 +325,9 @@ class _browse extends \IPS\Content\Controller
$tab = isset( \IPS\Request::i()->tab ) ? \IPS\Request::i()->tab : array_shift( $_tabs );
$activeTabContents = $asItem->commentReviews( $tab );
if ( count( $tabs ) > 1 )
if ( \count( $tabs ) > 1 )
{
$commentsAndReviews = count( $tabs ) ? \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $tab, $activeTabContents, $album->url(), 'tab', FALSE, TRUE ) : NULL;
$commentsAndReviews = \count( $tabs ) ? \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $tab, $activeTabContents, $album->url(), 'tab', FALSE, TRUE ) : NULL;
}
else
{
@@ -344,7 +366,7 @@ class _browse extends \IPS\Content\Controller
{
\IPS\Output::i()->breadcrumb['module'] = array( \IPS\Http\Url::internal( 'app=gallery&module=gallery&controller=browse', 'front', 'gallery' ), \IPS\Dispatcher::i()->module->_title );
$parents = iterator_to_array( $album->category()->parents() );
if ( count( $parents ) )
if ( \count( $parents ) )
{
foreach( $parents AS $parent )
{
@@ -394,57 +416,6 @@ class _browse extends \IPS\Content\Controller
}
}
/**
* Latest images RSS
*
* @return void
* @note We use a template so that we can embed image directly into feed while still allowing it to be customized
*/
protected function rss()
{
if( !\IPS\Settings::i()->gallery_rss_enabled )
{
\IPS\Output::i()->error( 'gallery_rss_offline', '2G189/3', 403, 'gallery_rss_offline_admin' );
}
$where = array();
if( isset( \IPS\Request::i()->category ) )
{
try
{
$category = \IPS\gallery\Category::loadAndCheckPerms( \IPS\Request::i()->category, 'read' );
$where[] = array( 'image_category_id=?', $category->id );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2G189/8', 404, '' );
}
}
else if ( isset( \IPS\Request::i()->album ) )
{
try
{
$album = \IPS\gallery\Album::loadAndCheckPerms( \IPS\Request::i()->album, 'read' );
$where[] = array( 'image_album_id=?', $album->id );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2G189/9', 404, '' );
}
}
$document = \IPS\Xml\Rss::newDocument( isset( $category ) ? $category->url() : ( isset( $album ) ? $album->url() : \IPS\Http\Url::internal( 'app=gallery&module=gallery&controller=browse', 'front', 'gallery' ) ), \IPS\Member::loggedIn()->language()->addToStack('gallery_rss_title'), \IPS\Member::loggedIn()->language()->addToStack('gallery_rss_title') );
foreach ( \IPS\gallery\Image::getItemsWithPermission( $where ) as $image )
{
$document->addItem( $image->caption, $image->url(), \IPS\Theme::i()->getTemplate( 'view' )->rssContent( $image ), \IPS\DateTime::ts( $image->updated ), $image->id );
}
/* @note application/rss+xml is not a registered IANA mime-type so we need to stick with text/xml for RSS */
\IPS\Output::i()->sendOutput( $document->asXML(), 200, 'text/xml' );
}
/**
* Edit album
*
@@ -490,7 +461,7 @@ class _browse extends \IPS\Content\Controller
$form->elements['']['album_category']->error = \IPS\Member::loggedIn()->language()->addToStack('form_required');
}
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
return;
}
@@ -501,7 +472,7 @@ class _browse extends \IPS\Content\Controller
/* Display form */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'edit_album' );
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
}
/**
@@ -536,7 +507,22 @@ class _browse extends \IPS\Content\Controller
$form->add( new \IPS\Helpers\Form\Node( 'move_image_category', NULL, FALSE, array(
'class' => 'IPS\gallery\Category',
'permissionCheck' => 'add',
'permissionCheck' => function( $node ) {
/* Do we have permission to add? */
if( !$node->can( 'add' ) )
{
return false;
}
// Otherwise, if the node *requires* albums, also return FALSE
if( $node->allow_albums == 2 )
{
return FALSE;
}
return TRUE;
}
), NULL, NULL, NULL, 'move_image_category' ) );
$form->add( new \IPS\Helpers\Form\Node( 'move_image_album', NULL, FALSE, array(
@@ -555,7 +541,7 @@ class _browse extends \IPS\Content\Controller
return false;
}
return true;
return TRUE;
}
), NULL, NULL, NULL, 'move_image_album' ) );
@@ -587,7 +573,7 @@ class _browse extends \IPS\Content\Controller
{
$form->error = \IPS\Member::loggedIn()->language()->addToStack('gallery_cat_or_album');
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
return;
}
@@ -623,7 +609,7 @@ class _browse extends \IPS\Content\Controller
}
/* Display form */
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
}
/**
@@ -15,7 +15,7 @@
namespace IPS\gallery\modules\front\gallery;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -127,7 +127,7 @@ class _notes extends \IPS\Dispatcher\Controller
$notes = $this->image->_notes;
$position = explode( ',', $position );
if( count( $position ) != 4 )
if( \count( $position ) != 4 )
{
return FALSE;
}
@@ -189,7 +189,7 @@ class _notes extends \IPS\Dispatcher\Controller
$notes[ $key ]['NOTE'] = trim( str_replace( "\n", ' ', str_replace( ' ', ' ', $noteText ) ) );
}
if( count( $position ) == 4 )
if( \count( $position ) == 4 )
{
$notes[ $key ]['LEFT'] = round( $position[0], 5 );
$notes[ $key ]['TOP'] = round( $position[1], 5 );
@@ -12,7 +12,7 @@
namespace IPS\gallery\modules\front\gallery;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -33,13 +33,18 @@ class _submit extends \IPS\Dispatcher\Controller
/* Init */
$url = \IPS\Http\Url::internal( 'app=gallery&module=gallery&controller=submit', 'front', 'gallery_submit' );
if( isset( \IPS\Request::i()->_pi ) )
{
$url = $url->setQueryString( '_pi', \IPS\Request::i()->_pi );
}
/* Init our form variables and check container */
$container = $this->chooseContainerForm( $url );
$images = NULL;
$errors = array();
/* If we've submitted that and have our values we need, it's time to show the upload form */
if( is_array( $container ) )
if( \is_array( $container ) )
{
$url = $url->setQueryString( 'category', $container['category']->_id );
@@ -51,6 +56,11 @@ class _submit extends \IPS\Dispatcher\Controller
{
$url = $url->setQueryString( 'noAlbum', 1 );
}
if ( isset( $container['guest_email'] ) )
{
$url = $url->setQueryString( 'guest_email', $container['guest_email'] );
}
$images = $this->chooseImagesForm( $url, $container );
@@ -65,7 +75,7 @@ class _submit extends \IPS\Dispatcher\Controller
/* Are we in da club? */
$club = NULL;
if ( is_array( $container ) AND isset( $container['category'] ) AND $container['category'] )
if ( \is_array( $container ) AND isset( $container['category'] ) AND $container['category'] )
{
try
{
@@ -90,10 +100,11 @@ class _submit extends \IPS\Dispatcher\Controller
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=gallery&module=gallery&controller=submit', 'front', 'gallery_submit' ), array(), 'loc_gallery_adding_image' );
/* Output */
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'submit.css' ), \IPS\Theme::i()->css( 'gallery.css' ) );
\IPS\gallery\Application::outputCss();
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'submit.css' ) );
if ( \IPS\Theme::i()->settings['responsive'] )
{
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'submit_responsive.css', 'gallery', 'front' ), \IPS\Theme::i()->css( 'gallery_responsive.css', 'gallery', 'front' ) );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'submit_responsive.css', 'gallery', 'front' ) );
}
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'jquery/jquery-ui.js', 'core', 'interface' ) );
@@ -108,7 +119,7 @@ class _submit extends \IPS\Dispatcher\Controller
$imageTagsField = $tagsField;
/* Tags */
if ( is_array( $container ) AND isset( $container['category'] ) AND $container['category'] AND \IPS\gallery\Image::canTag( NULL, $container['category'] ) )
if ( \is_array( $container ) AND isset( $container['category'] ) AND $container['category'] AND \IPS\gallery\Image::canTag( NULL, $container['category'] ) )
{
$tagsField = \IPS\gallery\Image::tagsFormField( NULL, $container['category'] );
$imageTagsField = $tagsField;
@@ -125,8 +136,8 @@ class _submit extends \IPS\Dispatcher\Controller
}
\IPS\Output::i()->json( array(
'container' => is_string( $container ) ? $container : NULL,
'containerInfo' => is_string( $container ) ? '' : \IPS\Theme::i()->getTemplate( 'submit' )->container( $container ),
'container' => \is_string( $container ) ? $container : NULL,
'containerInfo' => \is_string( $container ) ? '' : \IPS\Theme::i()->getTemplate( 'submit' )->container( $container ),
'images' => $images,
'imageTags' => preg_replace( '/data-ipsAutocomplete(?!\-)/', '', $imageTagsField ),
'tagsField' => $tagsField,
@@ -139,10 +150,14 @@ class _submit extends \IPS\Dispatcher\Controller
$allImagesForm = new \IPS\Helpers\Form( 'all_images_form', 'submit' );
$allImagesForm->add( new \IPS\Helpers\Form\TextArea( 'image_credit_info', NULL, FALSE ) );
$allImagesForm->add( new \IPS\Helpers\Form\Text( 'image_copyright', NULL, FALSE, array( 'maxLength' => 255 ) ) );
$allImagesForm->add( new \IPS\Helpers\Form\YesNo( 'image_auto_follow', (bool) \IPS\Member::loggedIn()->auto_follow['content'], FALSE, array(), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack( 'image_auto_follow_suffix' ) ) );
if( \IPS\Member::loggedIn()->member_id )
{
$allImagesForm->add( new \IPS\Helpers\Form\YesNo( 'image_auto_follow', (bool) \IPS\Member::loggedIn()->auto_follow['content'], FALSE, array(), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack( 'image_auto_follow_suffix' ) ) );
}
/* Tags */
if ( is_array( $container ) AND isset( $container['category'] ) AND $container['category'] AND \IPS\gallery\Image::canTag( NULL, $container['category'] ) )
if ( \is_array( $container ) AND isset( $container['category'] ) AND $container['category'] AND \IPS\gallery\Image::canTag( NULL, $container['category'] ) )
{
if( $tagsField = \IPS\gallery\Image::tagsFormField( NULL, $container['category'] ) )
{
@@ -156,7 +171,7 @@ class _submit extends \IPS\Dispatcher\Controller
{
if( $element->name == 'image_tags' )
{
if ( !is_array( $container ) OR !isset( $container['category'] ) OR !$container['category'] OR !\IPS\gallery\Image::canTag( NULL, $container['category'] ) )
if ( !\is_array( $container ) OR !isset( $container['category'] ) OR !$container['category'] OR !\IPS\gallery\Image::canTag( NULL, $container['category'] ) )
{
continue;
}
@@ -169,7 +184,7 @@ class _submit extends \IPS\Dispatcher\Controller
$allImagesForm->add( new \IPS\Helpers\Form\TextArea( 'image_textarea_DEFAULT', NULL, FALSE ) );
/* These fields are conditional and will not always show for each image */
$allImagesForm->add( new \IPS\Helpers\Form\YesNo( "image_gps_show_DEFAULT", TRUE, FALSE ) );
$allImagesForm->add( new \IPS\Helpers\Form\YesNo( "image_gps_show_DEFAULT", \IPS\Settings::i()->gallery_maps_default, FALSE ) );
$allImagesForm->add( new \IPS\Helpers\Form\Upload( "image_thumbnail_DEFAULT", NULL, FALSE, array(
'storageExtension' => 'gallery_Images',
'image' => TRUE,
@@ -177,7 +192,8 @@ class _submit extends \IPS\Dispatcher\Controller
) ) );
/* And output */
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'submit' )->wrapper( $container, $images, $club, \IPS\gallery\Image::moderateNewItems( \IPS\Member::loggedIn() ), $allImagesForm );
$category = ( \is_array( $container ) AND isset( $container['category'] ) AND $container['category'] ) ? $container['category'] : NULL;
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'submit' )->wrapper( $container, $images, $club, $allImagesForm );
}
}
@@ -209,20 +225,27 @@ class _submit extends \IPS\Dispatcher\Controller
try
{
$album = \IPS\gallery\Album::loadAndCheckPerms( \IPS\Request::i()->album, 'add' );
/* If it's an album, make sure we grab the current category */
try
{
$category = \IPS\gallery\Category::load( $album->category_id );
}
catch ( \OutOfRangeException $e ) { }
}
catch ( \OutOfRangeException $e ) { }
}
/* If we have chosen an album we can return now */
if( $category AND $album )
{
return array( 'category' => $category, 'album' => $album );
return array( 'category' => $category, 'album' => $album, 'guest_email' => isset( \IPS\Request::i()->guest_email ) ? \IPS\Request::i()->guest_email : NULL );
}
/* If we have chosen no album specifically, we can just return now */
if ( isset( \IPS\Request::i()->noAlbum ) AND \IPS\Request::i()->noAlbum AND $category AND $category->allow_albums != 2 )
{
return array( 'category' => $category, 'album' => NULL );
return array( 'category' => $category, 'album' => NULL, 'guest_email' => isset( \IPS\Request::i()->guest_email ) ? \IPS\Request::i()->guest_email : NULL );
}
/* If we haven't selected a category yet... */
@@ -265,6 +288,37 @@ class _submit extends \IPS\Dispatcher\Controller
}
}
}
/* Do we have any posting information to show? */
$guestEmailError = NULL;
if ( isset( \IPS\Request::i()->guest_email_submit ) )
{
if ( !\IPS\Request::i()->guest_email )
{
$guestEmailError = 'form_required';
}
else
{
try
{
\IPS\Helpers\Form\Email::validateEmail( \IPS\Request::i()->guest_email, TRUE );
\IPS\Request::i()->_pi = TRUE;
}
catch ( \Exception $e )
{
$guestEmailError = $e->getMessage();
}
}
}
if ( !isset( \IPS\Request::i()->_pi ) )
{
$guestPostBeforeRegister = ( !\IPS\Member::loggedIn()->member_id ) ? ( $category and !$category->can( 'add', \IPS\Member::loggedIn(), FALSE ) ) : NULL;
$modQueued = \IPS\gallery\Image::moderateNewItems( \IPS\Member::loggedIn(), $category, $guestPostBeforeRegister );
if ( $guestPostBeforeRegister or $modQueued )
{
return \IPS\Theme::i()->getTemplate('submit')->postingInformation( $guestPostBeforeRegister, $modQueued, $url->setQueryString( array( 'category' => $category->_id ) ), $guestEmailError );
}
}
/* Can we create an album in this category? */
$canCreateAlbum = ( $category->allow_albums and \IPS\Member::loggedIn()->group['g_create_albums'] );
@@ -279,6 +333,7 @@ class _submit extends \IPS\Dispatcher\Controller
$createAlbumForm = new \IPS\Helpers\Form( 'new_album', 'create_new_album' );
$createAlbumForm->class .= 'ipsForm_vertical';
$createAlbumForm->hiddenValues['category'] = $category->_id;
$createAlbumForm->hiddenValues['_pi'] = \IPS\Request::i()->_pi;
$album = new \IPS\gallery\Album;
$album->form( $createAlbumForm );
@@ -287,11 +342,13 @@ class _submit extends \IPS\Dispatcher\Controller
/* And when we submit it, create an album... */
if ( $createAlbumFormValues = $createAlbumForm->values() )
{
unset( $createAlbumFormValues['category'] );
unset( $createAlbumFormValues['category'], $createAlbumFormValues['_pi'] );
$createAlbumFormValues['album_category'] = $category;
$album->saveForm( $album->formatFormValues( $createAlbumFormValues ) );
\IPS\Api\Webhook::fire( 'galleryAlbum_create', $album, $album->webhookFilters() );
return array( 'category' => $category, 'album' => $album );
return array( 'category' => $category, 'album' => $album, 'guest_email' => isset( \IPS\Request::i()->guest_email ) ? \IPS\Request::i()->guest_email : NULL );
}
/* Otherwise, display it*/
@@ -302,12 +359,13 @@ class _submit extends \IPS\Dispatcher\Controller
$existingAlbumForm = NULL;
$albumsInCategory = \IPS\Member::loggedIn()->member_id ? \IPS\gallery\Album::loadForSubmit( $category ) : array();
if ( count( $albumsInCategory ) )
if ( \count( $albumsInCategory ) )
{
/* Build the existing album form... */
$existingAlbumForm = new \IPS\Helpers\Form( 'choose_album', 'choose_selected_album' );
$existingAlbumForm->class .= 'ipsForm_vertical';
$existingAlbumForm->hiddenValues['category'] = $category->_id;
$existingAlbumForm->hiddenValues['_pi'] = \IPS\Request::i()->_pi;
$albums = array();
foreach( $albumsInCategory as $id => $album )
{
@@ -318,7 +376,7 @@ class _submit extends \IPS\Dispatcher\Controller
/* When we submit it, we can continue... */
if ( $existingAlbumFormValues = $existingAlbumForm->values() )
{
return array( 'category' => $category, 'album' => \IPS\gallery\Album::loadAndCheckPerms( $existingAlbumFormValues['existing_album'], 'add' ) );
return array( 'category' => $category, 'album' => \IPS\gallery\Album::loadAndCheckPerms( $existingAlbumFormValues['existing_album'], 'add' ), 'guest_email' => isset( \IPS\Request::i()->guest_email ) ? \IPS\Request::i()->guest_email : NULL );
}
/* Otherwise, display it */
@@ -328,7 +386,7 @@ class _submit extends \IPS\Dispatcher\Controller
/* If there's nothing we can do, we can just continue */
if ( !$canCreateAlbum )
{
return array( 'category' => $category, 'album' => NULL );
return array( 'category' => $category, 'album' => NULL, 'guest_email' => isset( \IPS\Request::i()->guest_email ) ? \IPS\Request::i()->guest_email : NULL );
}
/* Otherwise, ask the user what they want to do */
else
@@ -345,7 +403,7 @@ class _submit extends \IPS\Dispatcher\Controller
* @return string|array
*/
public function chooseImagesForm( $url, $data )
{
{
$album = $data['album'];
$category = $data['category'];
@@ -367,7 +425,11 @@ class _submit extends \IPS\Dispatcher\Controller
$form->add( new \IPS\Helpers\Form\TextArea( 'prefix_all', NULL, FALSE ) );
$form->add( new \IPS\Helpers\Form\TextArea( 'images_order', NULL, FALSE ) );
$form->add( new \IPS\Helpers\Form\TextArea( 'images_info', NULL, FALSE ) );
$form->add( new \IPS\Helpers\Form\Number( 'images_autofollow_all', 1, FALSE ) );
if( \IPS\Member::loggedIn()->member_id )
{
$form->add( new \IPS\Helpers\Form\Number( 'images_autofollow_all', 1, FALSE ) );
}
/* Add upload field */
$maxFileSizes = array();
@@ -398,13 +460,13 @@ class _submit extends \IPS\Dispatcher\Controller
$maxFileSizes['movie'] = \IPS\Member::loggedIn()->group['g_movie_size'] / 1024;
}
}
if ( count( $maxFileSizes ) )
if ( \count( $maxFileSizes ) )
{
$options['maxFileSize'] = max( $maxFileSizes );
}
$form->add( new \IPS\Helpers\Form\Upload( 'images', array(), TRUE, $options, function( $val ) use ( $maxNumberOfImages, $maxFileSizes ) {
if ( $maxNumberOfImages !== NULL and count( $val ) > $maxNumberOfImages )
if ( $maxNumberOfImages !== NULL and \count( $val ) > $maxNumberOfImages )
{
if ( $maxNumberOfImages < 1 )
{
@@ -419,16 +481,16 @@ class _submit extends \IPS\Dispatcher\Controller
foreach ( $val as $file )
{
$ext = mb_substr( $file->filename, ( mb_strrpos( $file->filename, '.' ) + 1 ) );
if ( in_array( $ext, \IPS\Image::$imageExtensions ) )
if ( \in_array( mb_strtolower( $ext ), \IPS\Image::$imageExtensions ) )
{
/* The size was saved as kb, then divided by 1024 above to figure out how many MB to allow. So now we have '2' for 2MB for instance, so we need
to multiply that by 1024*1024 in order to get the byte size again */
if ( count( $maxFileSizes ) == 2 and $file->filesize() > ( $maxFileSizes['image'] * 1048576 ) )
if ( \count( $maxFileSizes ) == 2 and $file->filesize() > ( $maxFileSizes['image'] * 1048576 ) )
{
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack( 'upload_image_too_big', FALSE, array( 'sprintf' => array( \IPS\Output\Plugin\Filesize::humanReadableFilesize( $maxFileSizes['image'] * 1048576 ) ) ) ) );
}
}
elseif ( count( $maxFileSizes ) == 2 and $file->filesize() > ( $maxFileSizes['movie'] * 1048576 ) )
elseif ( \count( $maxFileSizes ) == 2 and $file->filesize() > ( $maxFileSizes['movie'] * 1048576 ) )
{
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack( 'upload_movie_too_big', FALSE, array( 'sprintf' => array( \IPS\Output\Plugin\Filesize::humanReadableFilesize( $maxFileSizes['movie'] * 1048576 ) ) ) ) );
}
@@ -471,7 +533,7 @@ class _submit extends \IPS\Dispatcher\Controller
$checkboxInput = $tagsFieldName . '_freechoice_prefix';
$prefixinput = $tagsFieldName . '_prefix';
\IPS\Request::i()->$tagsFieldName = ( is_array( $tagsValue ) ) ? implode( "\n", $tagsValue ) : $tagsValue;
\IPS\Request::i()->$tagsFieldName = ( \is_array( $tagsValue ) ) ? implode( "\n", $tagsValue ) : $tagsValue;
\IPS\Request::i()->$checkboxInput = 1;
\IPS\Request::i()->$prefixinput = $tagsPrefix;
@@ -544,7 +606,7 @@ class _submit extends \IPS\Dispatcher\Controller
{
/* Get any records we had before in case we need to delete them */
$existing = iterator_to_array( \IPS\Db::i()->select( '*', 'gallery_images_uploads', array( 'upload_session=?', session_id() ) )->setKeyField( 'upload_location' ) );
/* Get our image order first, as that's the order we want to loop through in */
$imageOrder = json_decode( $values['images_order'], true );
@@ -562,13 +624,13 @@ class _submit extends \IPS\Dispatcher\Controller
$imageData = array();
if( is_array( $imagesData ) )
if( \is_array( $imagesData ) )
{
foreach( $imagesData as $dataEntry )
{
if( mb_strpos( $dataEntry['name'], '_' . $image->tempId ) !== FALSE )
{
$imageData[ str_replace( '_' . $image->tempId, '', $dataEntry['name'] ) ] = $dataEntry['value'];
$imageData[ str_replace( '_' . $image->tempId, '', str_replace( 'filedata__', '', $dataEntry['name'] ) ) ] = $dataEntry['value'];
}
}
}
@@ -579,7 +641,7 @@ class _submit extends \IPS\Dispatcher\Controller
$imageData['image_copyright'] = $values['copyright_all'];
}
if( !isset( $imageData['image_credit'] ) OR !$imageData['image_credit'] )
if( !isset( $imageData['image_credit_info'] ) OR !$imageData['image_credit_info'] )
{
$imageData['image_credit_info'] = $values['credit_all'];
}
@@ -590,7 +652,10 @@ class _submit extends \IPS\Dispatcher\Controller
$imageData['image_tags_prefix'] = $values['prefix_all'];
}
$imageData['image_auto_follow'] = $values['images_autofollow_all'];
if( \IPS\Member::loggedIn()->member_id )
{
$imageData['image_auto_follow'] = $values['images_autofollow_all'];
}
/* Fix descriptions */
$imageData['image_description'] = ( isset( $imageData['image_textarea'] ) AND $imageData['image_textarea'] ) ? $imageData['image_textarea'] : ( ( isset( $imageData['image_description'] ) ) ? $imageData['image_description'] : '' );
@@ -603,8 +668,9 @@ class _submit extends \IPS\Dispatcher\Controller
'upload_location' => (string) $image,
'upload_file_name' => $image->originalFilename,
'upload_date' => time(),
'upload_order' => ( is_array( $imageOrder ) ) ? array_search( $image->tempId, $imageOrder ) : $i,
'upload_data' => json_encode( $imageData )
'upload_order' => ( \is_array( $imageOrder ) ) ? array_search( $image->tempId, $imageOrder ) : $i,
'upload_data' => json_encode( $imageData ),
'upload_exif' => $image->exifData ? json_encode( $image->exifData ) : NULL
);
}
@@ -612,7 +678,7 @@ class _submit extends \IPS\Dispatcher\Controller
}
/* Insert them into the database */
if( count( $inserts ) )
if( \count( $inserts ) )
{
\IPS\Db::i()->insert( 'gallery_images_uploads', $inserts );
}
@@ -633,6 +699,10 @@ class _submit extends \IPS\Dispatcher\Controller
$totalImages = \IPS\Db::i()->select( 'count(*)', 'gallery_images_uploads', array( 'upload_session=?', session_id() ) )->first();
$url = $url->setQueryString( 'totalImages', $totalImages );
if ( isset( $data['guest_email'] ) )
{
$url = $url->setQueryString( 'guest_email', $data['guest_email'] );
}
/* Now return the multiredirector */
return $this->saveImages( $url );
@@ -648,13 +718,13 @@ class _submit extends \IPS\Dispatcher\Controller
{
/* Process */
$url = $url ? $url->setQueryString( 'do', 'saveImages' ) : \IPS\Request::i()->url()->stripQueryString( array( 'mr' ) );
/* Return the multiredirector */
$multiRedirect = (string) new \IPS\Helpers\MultipleRedirect( $url,
/* Function to process each image */
function( $offset ) use ( $url )
{
$offset = intval( $offset );
$offset = \intval( $offset );
$existing = \IPS\Db::i()->select( '*', 'gallery_images_uploads', array( 'upload_session=?', session_id() ), 'upload_order ASC', array( 0, 1 ) )->setKeyField( 'upload_location' );
@@ -667,20 +737,22 @@ class _submit extends \IPS\Dispatcher\Controller
$values = array(
'category' => $data['category']->_id,
'imageLocation' => $location,
'album' => $data['album'] ? $data['album']->_id : NULL
'album' => $data['album'] ? $data['album']->_id : NULL,
'guest_email' => isset( $data['guest_email'] ) ? $data['guest_email'] : NULL
);
/* Get the data from the row and set */
$fileData = json_decode( $file['upload_data'], TRUE );
if( count( $fileData ) )
if( \count( $fileData ) )
{
foreach( $fileData as $k => $v )
{
$values[ preg_replace("/^filedata_[0-9]+_/i", '', $k ) ] = $v;
$values[ preg_replace("/^filedata_[0-9]*_/i", '', $k ) ] = $v;
}
}
if( isset( $values['image_tags'] ) AND $values['image_tags'] AND !is_array( $values['image_tags'] ) )
if( isset( $values['image_tags'] ) AND $values['image_tags'] AND !\is_array( $values['image_tags'] ) )
{
$values['image_tags'] = explode( "\n", $values['image_tags'] );
}
@@ -722,16 +794,14 @@ class _submit extends \IPS\Dispatcher\Controller
/* If GPS is supported but the admin did not specify whether to show the map or not, then default to showing it */
$image = \IPS\File::get( 'gallery_Images', $location );
if( \IPS\GeoLocation::enabled() and \IPS\Image::exifSupported() and $image->isImage() )
{
$exif = \IPS\Image::create( $image->contents() )->parseExif();
$exif = $file['upload_exif'] ? json_decode( $file['upload_exif'], true ) : NULL;
$values['_exif'] = $exif;
if( count( $exif ) )
if( \IPS\GeoLocation::enabled() and $exif )
{
if( isset( $exif['GPS.GPSLatitudeRef'] ) && isset( $exif['GPS.GPSLatitude'] ) && isset( $exif['GPS.GPSLongitudeRef'] ) && isset( $exif['GPS.GPSLongitude'] ) )
{
if( isset( $exif['GPS.GPSLatitudeRef'] ) && isset( $exif['GPS.GPSLatitude'] ) && isset( $exif['GPS.GPSLongitudeRef'] ) && isset( $exif['GPS.GPSLongitude'] ) )
{
$values['image_gps_show'] = ( isset( $values['image_gps_show'] ) ) ? (int) ( isset( $values['image_gps_show_checkbox'] ) ) : 1;
}
$values['image_gps_show'] = ( isset( $values['image_gps_show'] ) ) ? (int) ( isset( $values['image_gps_show_checkbox'] ) ) : \IPS\Settings::i()->gallery_maps_default;
}
}
@@ -741,13 +811,26 @@ class _submit extends \IPS\Dispatcher\Controller
foreach( $formElements as $key => $element )
{
/* If this is a guest posting before registration, we can't check the CAPTCHA as none is added to the form */
if( $key == 'captcha' )
{
continue;
}
$testValuesForm->add( $element );
$name = 'image_' . $key;
if( isset( $values[ $name ] ) )
{
\IPS\Request::i()->$name = ( is_array( $values[ $name ] ) ) ? implode( "\n", $values[ $name ] ) : $values[ $name ];
if( $name == 'image_description' )
{
\IPS\Request::i()->filedata__image_description = $values[ $name ];
}
else
{
\IPS\Request::i()->$name = ( \is_array( $values[ $name ] ) ) ? implode( "\n", $values[ $name ] ) : $values[ $name ];
}
if( $name == 'image_tags' )
{
@@ -759,7 +842,7 @@ class _submit extends \IPS\Dispatcher\Controller
unset( $values[ $name . '_prefix' ] );
}
elseif( $name == 'image_auto_follow' )
elseif( $name == 'image_auto_follow' AND \IPS\Member::loggedIn()->member_id )
{
$checkboxInput = $name . '_checkbox';
@@ -779,7 +862,7 @@ class _submit extends \IPS\Dispatcher\Controller
{
foreach( $cleaned as $k => $v )
{
$values[ $k ] = $v;
$values[ str_replace( 'filedata__', '', $k ) ] = $v;
}
}
@@ -800,7 +883,11 @@ class _submit extends \IPS\Dispatcher\Controller
/* Function to call when done */
function() use( $url )
{
if ( \IPS\Request::i()->totalImages === 1 )
if ( isset( \IPS\Request::i()->guest_email ) )
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=register', 'front', 'register' ) );
}
elseif ( \IPS\Request::i()->totalImages === 1 )
{
/* If we are only sending one image, send a normal notification */
$image = \IPS\gallery\Image::constructFromData( \IPS\Db::i()->select( '*', 'gallery_images', NULL, 'image_id DESC', 1 )->first() );
@@ -808,7 +895,7 @@ class _submit extends \IPS\Dispatcher\Controller
{
$image->sendNotifications();
}
else if( $image->hidden() !== -1 )
else if( !\in_array( $image->hidden(), array( -1, -3 ) ) )
{
$image->sendUnapprovedNotification();
}
@@ -864,7 +951,7 @@ class _submit extends \IPS\Dispatcher\Controller
{
$exif = \IPS\Image::create( \IPS\File::get( $temporaryImage['storage_extension'], $temporaryImage['contents'] )->contents() )->parseExif();
if( count( $exif ) )
if( \count( $exif ) )
{
if( isset( $exif['GPS.GPSLatitudeRef'] ) && isset( $exif['GPS.GPSLatitude'] ) && isset( $exif['GPS.GPSLongitudeRef'] ) && isset( $exif['GPS.GPSLongitude'] ) )
{
@@ -12,7 +12,7 @@
namespace IPS\gallery\modules\front\gallery;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -27,12 +27,6 @@ class _view extends \IPS\Content\Controller
* [Content\Controller] Class
*/
protected static $contentModel = 'IPS\gallery\Image';
/**
* @brief Should views and item markers be updated by AJAX requests?
* @note For Gallery images, AJAX requests handle the next/previous links and using those needs to mark as read, etc.
*/
protected $updateViewsAndMarkersOnAjax = TRUE;
/**
* Init
@@ -47,6 +41,8 @@ class _view extends \IPS\Content\Controller
{
$this->image = \IPS\gallery\Image::load( \IPS\Request::i()->id );
$this->image->container()->clubCheckRules();
if ( !$this->image->canView( \IPS\Member::loggedIn() ) )
{
\IPS\Output::i()->error( $this->image->container()->errorMessage(), '2G188/1', 403, '' );
@@ -58,6 +54,14 @@ class _view extends \IPS\Content\Controller
}
}
/* When preloading we don't want to update stuff */
if( isset( \IPS\Request::i()->preload ) AND \IPS\Request::i()->preload )
{
$this->updateViewsAndMarkersOnAjax = FALSE;
}
\IPS\gallery\Application::outputCss();
parent::execute();
}
@@ -104,7 +108,7 @@ class _view extends \IPS\Content\Controller
\IPS\Output::i()->metaTags['og:video:type'] = $this->image->file_type;
\IPS\Output::i()->metaTags['og:type'] = 'video';
if( count( $this->image->tags() ) )
if( \count( $this->image->tags() ) )
{
\IPS\Output::i()->metaTags['og:video:tag'] = $this->image->tags();
}
@@ -119,7 +123,7 @@ class _view extends \IPS\Content\Controller
\IPS\Output::i()->metaTags['og:image'] = \IPS\File::get( 'gallery_Images', $this->image->masked_file_name )->url;
\IPS\Output::i()->metaTags['og:image:type'] = $this->image->file_type;
if( count( $this->image->tags() ) )
if( \count( $this->image->tags() ) )
{
\IPS\Output::i()->metaTags['og:object:tag'] = $this->image->tags();
}
@@ -138,9 +142,9 @@ class _view extends \IPS\Content\Controller
$tab = isset( \IPS\Request::i()->tab ) ? \IPS\Request::i()->tab : array_shift( $_tabs );
$activeTabContents = $this->image->commentReviews( $tab, \IPS\Request::i()->lightbox );
if ( count( $tabs ) > 1 )
if ( \count( $tabs ) > 1 )
{
$commentsAndReviews = count( $tabs ) ? \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $tab, $activeTabContents, \IPS\Request::i()->lightbox ? $this->image->url()->setQueryString( 'lightbox', 1 ) : $this->image->url(), 'tab', FALSE, TRUE, \IPS\Request::i()->lightbox ? 'ipsTabs_small ipsTabs_stretch' : '' ) : NULL;
$commentsAndReviews = \count( $tabs ) ? \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $tab, $activeTabContents, \IPS\Request::i()->lightbox ? $this->image->url()->setQueryString( 'lightbox', 1 ) : $this->image->url(), 'tab', FALSE, TRUE, \IPS\Request::i()->lightbox ? 'ipsTabs_small ipsTabs_stretch' : '' ) : NULL;
}
else
{
@@ -156,7 +160,7 @@ class _view extends \IPS\Content\Controller
/* Media items should get the file size of the original file instead of a thumbnail */
if( $this->image->media )
{
$displayedImage = \IPS\File::get( 'gallery_Images', $this->image->original_file_name );
$displayedImage = \IPS\File::get( 'gallery_Images', $this->image->original_file_name, $this->image->file_size );
}
/* Otherwise, fetch the thumbnails */
else
@@ -189,7 +193,7 @@ class _view extends \IPS\Content\Controller
'@id' => (string) $this->image->url(),
'url' => (string) $this->image->url(),
'name' => $this->image->mapped('title'),
'description' => strip_tags( $this->image->truncated() ),
'description' => $this->image->truncated( TRUE, NULL ),
'dateCreated' => \IPS\DateTime::ts( $this->image->date )->format( \IPS\DateTime::ISO8601 ),
'fileFormat' => $this->image->file_type,
'keywords' => $this->image->tags(),
@@ -272,7 +276,7 @@ class _view extends \IPS\Content\Controller
'height' => $dimensions['large'][1],
);
if( count( $this->image->metadata ) )
if( \count( $this->image->metadata ) )
{
\IPS\Output::i()->jsonLd['gallery']['image']['exifData'] = array();
@@ -338,10 +342,42 @@ class _view extends \IPS\Content\Controller
*/
protected function download()
{
if( $this->image->canDownloadOriginal() == \IPS\gallery\Image::DOWNLOAD_ORIGINAL_NONE )
{
\IPS\Output::i()->error( 'cannot_download_original_image', '2G188/E', 403, '' );
}
try
{
/* Get file and data */
$file = \IPS\File::get( 'gallery_Images', $this->image->original_file_name ?: $this->image->masked_file_name );
$image = NULL;
try
{
switch( $this->image->canDownloadOriginal() )
{
case \IPS\gallery\Image::DOWNLOAD_ORIGINAL_WATERMARKED:
/* We need to watermark the original image on the fly in this case */
$file = \IPS\File::get( 'gallery_Images', $this->image->original_file_name );
$image = $this->image->createImageFile( $file, NULL );
break;
case \IPS\gallery\Image::DOWNLOAD_ORIGINAL_RAW:
$file = \IPS\File::get( 'gallery_Images', $this->image->original_file_name );
break;
}
if( $file->filesize() === false )
{
throw new \RuntimeException( 'DOES_NOT_EXIST' );
}
}
catch( \RuntimeException $e )
{
\IPS\Log::log( "Original image for {$this->image->id} is missing, falling back to masked image", 'gallery_image_missing' );
$file = \IPS\File::get( 'gallery_Images', $this->image->masked_file_name );
}
$headers = array_merge( \IPS\Output::getCacheHeaders( time(), 360 ), array( "Content-Disposition" => \IPS\Output::getContentDisposition( 'attachment', $file->originalFilename ), "X-Content-Type-Options" => "nosniff" ) );
/* Send headers and print file */
@@ -352,10 +388,20 @@ class _view extends \IPS\Content\Controller
{
\IPS\Output::i()->sendHeader( $key . ': ' . $header );
}
\IPS\Output::i()->sendHeader( "Content-Security-Policy: default-src 'none'; sandbox" );
\IPS\Output::i()->sendHeader( "X-Content-Security-Policy: default-src 'none'; sandbox" );
\IPS\Output::i()->sendHeader( "Content-Length: " . $file->filesize() );
$file->printFile();
if( $image !== NULL )
{
\IPS\Output::i()->sendHeader( "Content-Length: " . \strlen( (string) $image ) );
print (string) $image;
}
else
{
\IPS\Output::i()->sendHeader( "Content-Length: " . $file->filesize() );
$file->printFile();
}
exit;
}
catch ( \UnderflowException $e )
@@ -364,6 +410,44 @@ class _view extends \IPS\Content\Controller
}
}
/**
* Mark the image as read
*
* @note We preload the next/prev image in the lightbox and do not want those images marked as read when doing so. While this speeds up the loading to the end user, we still need to separately mark the image as read when it's pulled into view.
* @return void
*/
public function markread()
{
/* Run CSRF check */
\IPS\Session::i()->csrfCheck();
/* Mark image as read */
$this->image->markRead();
/* We also want to update the views */
$countUpdated = false;
if ( \IPS\REDIS_ENABLED and \IPS\CACHE_METHOD == 'Redis' and \IPS\CACHE_CONFIG )
{
try
{
\IPS\Redis::i()->zIncrBy( 'topic_views', 1, static::$contentModel .'__' . $this->image->id );
$countUpdated = true;
}
catch( \Exception $e ) {}
}
if ( ! $countUpdated )
{
\IPS\Db::i()->insert( 'core_view_updates', array(
'classname' => static::$contentModel,
'id' => $this->image->id
) );
}
/* And return an AJAX response */
\IPS\Output::i()->json('OK');
}
/**
* View all of the metadata for this image
*
@@ -520,7 +604,7 @@ class _view extends \IPS\Content\Controller
}
/* Display form */
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
}
/**
@@ -584,7 +668,7 @@ class _view extends \IPS\Content\Controller
throw new \DomainException;
}
$form = \IPS\gallery\Image\Table::buildMoveForm( $item->container(), 'IPS\\gallery\\Image', array( 'forceOwner' => $item->author() ) );
$form = \IPS\gallery\Image\Table::buildMoveForm( $item->container(), 'IPS\\gallery\\Image', array( 'where' => array( "album_owner_id=? OR " . \IPS\Db::i()->in( 'album_submit_type', array( \IPS\gallery\Album::AUTH_SUBMIT_PUBLIC, \IPS\gallery\Album::AUTH_SUBMIT_GROUPS, \IPS\gallery\Album::AUTH_SUBMIT_MEMBERS, \IPS\gallery\Album::AUTH_SUBMIT_CLUB ) ), $item->author()->member_id ) ), $item->author() );
if ( $values = $form->values() )
{
@@ -614,7 +698,7 @@ class _view extends \IPS\Content\Controller
$item->move( $target, FALSE );
\IPS\Output::i()->redirect( $item->url() );
}
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
}
catch ( \Exception $e )
{
@@ -667,7 +751,7 @@ class _view extends \IPS\Content\Controller
\IPS\Output::i()->breadcrumb[] = array( $link ? $this->image->url() : NULL, $this->image->mapped('title') );
$title = ( isset( \IPS\Request::i()->page ) and \IPS\Request::i()->page > 1 ) ? \IPS\Member::loggedIn()->language()->addToStack( 'title_with_page_number', FALSE, array( 'sprintf' => array( $this->image->mapped('title'), intval( \IPS\Request::i()->page ) ) ) ) : $this->image->mapped('title');
$title = ( isset( \IPS\Request::i()->page ) and \IPS\Request::i()->page > 1 ) ? \IPS\Member::loggedIn()->language()->addToStack( 'title_with_page_number', FALSE, array( 'sprintf' => array( $this->image->mapped('title'), \intval( \IPS\Request::i()->page ) ) ) ) : $this->image->mapped('title');
\IPS\Output::i()->title = $container ? ( $title . ' - ' . $container->_title ) : $title;
}
}