Version 4.7.0

This commit is contained in:
Neo committed 2025-12-19 16:00:35 -08:00
1 parent 517a5e1f70
commit 8ba7d43898
1933 files changed
+65613 -11332

No files matched your search

+5 -7
View File
@@ -354,7 +354,7 @@ EOF;
/**
* @brief Stores a \IPS\Widget object if this is a custom block with an embedded widget
*/
protected $widgetLoaded = NULL;
protected $widgetLoaded = [];
/**
* @brief Orientation for an embedded widget
@@ -601,8 +601,6 @@ EOF;
if ( $block_type === 'plugin' )
{
$form->addHtml( \IPS\Theme::i()->getTemplate( 'blocks', 'cms', 'admin' )->previewBlock() );
$templates = array( '_default_' => \IPS\Member::loggedIn()->language()->addToStack('content_block_template_use_default') );
foreach( \IPS\cms\Templates::getTemplates( \IPS\cms\Templates::RETURN_BLOCK ) as $id => $obj )
@@ -718,7 +716,7 @@ EOF;
\IPS\Output::i()->globalControllers[] = 'cms.admin.blocks.form';
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_blocks.js', 'cms' ) );
\IPS\Output::i()->title = ( $this->id ) ? \IPS\Member::loggedIn()->language()->addToStack('content_block_block_editing', NULL, array( 'sprintf' => array( $this->_title ) ) ) : \IPS\Member::loggedIn()->language()->addToStack('content_block_block_add');
\IPS\Output::i()->title = ( $this->id ) ? \IPS\Member::loggedIn()->language()->addToStack( 'content_block_block_editing', FALSE, array( 'sprintf' => array( $this->_title ) ) ) : \IPS\Member::loggedIn()->language()->addToStack('content_block_block_add');
}
/**
@@ -1028,12 +1026,12 @@ EOF;
$this->plugin = 'RecordFeed';
}
if ( ! $this->widgetLoaded )
if ( empty( $this->widgetLoaded[ $this->orientation ] ) )
{
$this->widgetLoaded = \IPS\Widget::load( $this->plugin_app ? \IPS\Application::load( $this->plugin_app ) : \IPS\Plugin::load( $this->plugin_plugin ), $this->plugin, mt_rand(), $this->_plugin_config, NULL, $this->orientation );
$this->widgetLoaded[ $this->orientation ]= \IPS\Widget::load( $this->plugin_app ? \IPS\Application::load( $this->plugin_app ) : \IPS\Plugin::load( $this->plugin_plugin ), $this->plugin, mt_rand(), $this->_plugin_config, NULL, $this->orientation );
}
return $this->widgetLoaded;
return $this->widgetLoaded[ $this->orientation ];
}
throw new \OutOfRangeException;
@@ -99,6 +99,16 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
* @brief [Node] Description suffix. If specified, will look for a language key with "{$titleLangPrefix}_{$id}_{$descriptionLangSuffix}" as the key
*/
public static $descriptionLangSuffix = '_desc';
/**
* @breif Used by the dataLayer, overwritten by \IPS\cms\Application
*/
public static $contentArea = 'pages_database';
/**
* @breif Used by the dataLayer, overwritten by \IPS\cms\Application
*/
public static $containerType = 'pages_database_category';
/**
* @brief [Node] ACP Restrictions
@@ -1155,18 +1165,26 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
protected function get__title()
{
/* If the DB is in a page, and we're not using categories, then return the page title, not the category title for continuity */
if ( ! \IPS\cms\Databases::load( $this->database_id )->use_categories )
$database = \IPS\cms\Databases::load( $this->database_id );
if ( ! $database->use_categories )
{
if ( ! $this->_catTitle )
{
try
if ( $database->use_as_page_title )
{
$page = \IPS\cms\Pages\Page::loadByDatabaseId( $this->database_id );
$this->_catTitle = $page->_title;
$this->_catTitle = $database->_title;
}
catch( \OutOfRangeException $e )
else
{
$this->_catTitle = parent::get__title();
try
{
$page = \IPS\cms\Pages\Page::loadByDatabaseId( $this->database_id );
$this->_catTitle = $page->_title;
}
catch ( \OutOfRangeException $e )
{
$this->_catTitle = parent::get__title();
}
}
}
@@ -1606,11 +1624,12 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
foreach( $this->children() as $child )
{
$childLastPost = $child->lastPost();
if( !$result OR $childLastPost['date'] > $result['date'] )
if ( $childLastPost = $child->lastPost() )
{
$result = $childLastPost;
if ( !$result or $childLastPost['date'] > $result['date'] )
{
$result = $childLastPost;
}
}
}
@@ -1854,4 +1873,32 @@ class _Categories extends \IPS\Node\Model implements \IPS\Node\Permissions
return $node->database_id == static::$customDatabaseId;
} );
}
/**
* Get the properties that can be added to the datalayer for this key
*
* @return array
*/
public function getDataLayerProperties()
{
if ( empty( $this->_dataLayerProperties ) )
{
$db = $this->database();
if ( $db->use_categories )
{
$properties = parent::getDataLayerProperties();
$properties['content_area'] = static::$contentArea;
$properties['container_type'] = static::$containerType;
}
else
{
$properties = $db->getDataLayerProperties();
}
$this->_dataLayerProperties = $properties;
}
return $this->_dataLayerProperties;
}
}
@@ -167,6 +167,34 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
* @brief Page title
*/
protected $pageTitle = NULL;
/**
* @breif Used by the dataLayer
*/
public static $contentArea = 'pages_database';
/**
* @breif Used by the dataLayer
*/
public static $containerType = 'pages_database_category';
/**
* Get the properties that can be added to the datalayer for this key
*
* @return array
*/
public function getDataLayerProperties()
{
if ( empty( $this->_dataLayerProperties ) )
{
$properties = parent::getDataLayerProperties();
$properties['content_area'] = $this->_title;
$properties['container_type'] = "{$this->key}_database";
$this->_dataLayerProperties = $properties;
}
return $this->_dataLayerProperties;
}
/**
* Return all databases
@@ -1047,6 +1075,8 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
\IPS\Lang::deleteCustom( 'cms', "cms_create_menu_records_" . $this->id );
\IPS\Lang::deleteCustom( 'cms', "cms_records" . $this->id . '_pl' );
\IPS\Lang::deleteCustom( 'cms', "module__cms_records" . $this->id );
\IPS\Lang::deleteCustom( 'cms', "digest_area_cms_records" . $this->id );
\IPS\Lang::deleteCustom( 'cms', "digest_area_cms_categories" . $this->id );
/* Unclaim attachments */
\IPS\File::unclaimAttachments( 'cms_Records', NULL, NULL, $this->id );
@@ -325,6 +325,40 @@ class _Dispatcher extends \IPS\Dispatcher
/* Execute */
$controller->execute();
/* Data Layer Context */
if ( $this->databaseId AND \IPS\Settings::i()->core_datalayer_enabled )
{
try
{
$databaseOrCategory = \IPS\cms\Databases::load( $this->databaseId );
}
catch ( \UnderflowException $e )
{
return $this->finish();
}
/* Use the category instead of the database if there is one */
if ( $this->categoryId AND $databaseOrCategory->use_categories )
{
try
{
$catClass = '\IPS\cms\Categories' . $this->databaseId;
$databaseOrCategory = $catClass::load( $this->categoryId );
}
catch ( \UnderflowException $e ) {}
}
/* Add the database's/category's data layer properties to the page context */
foreach ( $databaseOrCategory->getDataLayerProperties() as $key => $property )
{
\IPS\core\DataLayer::i()->addContextProperty( $key, $property, true );
if ( $key === 'content_area' )
{
\IPS\core\DataLayer::i()->addContextProperty( 'community_area', $property, true );
}
}
}
return $this->finish();
}
+36 -13
View File
@@ -135,6 +135,11 @@ class _Fields extends \IPS\CustomField implements \IPS\Node\Permissions
* @brief [CustomField] Upload storage extension
*/
protected static $uploadStorageExtension = 'cms_Records';
/**
* @brief [CustomField] Set to TRUE if uploads fields are capable of holding the submitted content for moderation
*/
public static $uploadsCanBeModerated = TRUE;
/**
* @brief [CustomField] Cache retrieved fields
@@ -334,6 +339,8 @@ class _Fields extends \IPS\CustomField implements \IPS\Node\Permissions
foreach( static::roots( $permissionCheck ) as $row )
{
$row->required = (bool) $row->required;
if ( $container !== NULL AND $database->use_categories )
{
if ( $container->fields !== '*' AND $container->fields !== NULL )
@@ -1480,15 +1487,15 @@ class _Fields extends \IPS\CustomField implements \IPS\Node\Permissions
if ( $start and $end )
{
return \IPS\Member::loggedIn()->language()->addToStack('field_daterange_start_end', NULL, array( 'sprintf' => array( $start, $end ) ) );
return \IPS\Member::loggedIn()->language()->addToStack( 'field_daterange_start_end', FALSE, array( 'sprintf' => array( $start, $end ) ) );
}
else if ( $start )
{
return \IPS\Member::loggedIn()->language()->addToStack('field_daterange_start', NULL, array( 'sprintf' => array( $start ) ) );
return \IPS\Member::loggedIn()->language()->addToStack( 'field_daterange_start', FALSE, array( 'sprintf' => array( $start ) ) );
}
else if ( $end )
{
return \IPS\Member::loggedIn()->language()->addToStack('field_daterange_end', NULL, array( 'sprintf' => array( $end ) ) );
return \IPS\Member::loggedIn()->language()->addToStack( 'field_daterange_end', FALSE, array( 'sprintf' => array( $end ) ) );
}
else
{
@@ -1718,7 +1725,7 @@ class _Fields extends \IPS\CustomField implements \IPS\Node\Permissions
if ( !$ok )
{
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->message( \IPS\Member::loggedIn()->language()->addToStack( 'cms_field_no_type_warning', NULL, array( 'sprintf' => array( $this->type ) ) ), 'warning', NULL, FALSE );
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->message( \IPS\Member::loggedIn()->language()->addToStack( 'cms_field_no_type_warning', FALSE, array( 'sprintf' => array( $this->type ) ) ), 'warning', NULL, FALSE );
}
}
@@ -1765,7 +1772,7 @@ class _Fields extends \IPS\CustomField implements \IPS\Node\Permissions
'Email' => array_merge( array( 'field_max_length', 'field_default_value', 'field_unique' ), $displayDefaults ),
'Item' => array_merge( array( 'field_is_multiple', 'field_relational_db', 'field_crosslink' ), $displayDefaults ),
'Member' => array_merge( array( 'field_is_multiple', 'field_unique' ), $displayDefaults ),
'Number' => array_merge( array( 'field_default_value', 'field_number_decimals_on', 'field_number_decimals', 'field_unique' ), $displayDefaults ),
'Number' => array_merge( array( 'field_default_value', 'field_number_decimals_on', 'field_number_decimals', 'field_unique', 'field_number_min', 'field_number_max' ), $displayDefaults ),
'Password' => array_merge( array( 'field_default_value' ), $displayDefaults ),
'Radio' => array_merge( array( 'field_extra', 'field_default_value', 'field_truncate', 'field_unique' ), $displayDefaults ),
'Select' => array_merge( array( 'field_extra', 'field_default_value', 'field_is_multiple', 'field_truncate', 'field_unique' ), $displayDefaults ),
@@ -1851,7 +1858,7 @@ class _Fields extends \IPS\CustomField implements \IPS\Node\Permissions
else
{
$disabled[] = $db->id;
$databases[ $db->id ] = \IPS\Member::loggedIn()->language()->addToStack( 'cms_db_relational_with_name_disabled', NULL, array( 'sprintf' => array( $db->_title ) ) );
$databases[ $db->id ] = \IPS\Member::loggedIn()->language()->addToStack( 'cms_db_relational_with_name_disabled', FALSE, array( 'sprintf' => array( $db->_title ) ) );
}
}
if ( ! \count( $databases ) )
@@ -1865,9 +1872,11 @@ class _Fields extends \IPS\CustomField implements \IPS\Node\Permissions
}
/* Number specific */
$form->add( new \IPS\Helpers\Form\Number( 'field_number_min', $this->id and isset( $this->extra['min'] ) ? $this->extra['min'] : NULL, FALSE, array( 'unlimited' => '', 'unlimitedLang' => 'any' ), NULL, NULL, NULL, 'field_number_min' ) );
$form->add( new \IPS\Helpers\Form\Number( 'field_number_max', $this->id and isset( $this->extra['max'] ) ? $this->extra['max'] : NULL, FALSE, array( 'unlimited' => '', 'unlimitedLang' => 'any' ), NULL, NULL, NULL, 'field_number_max' ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'field_number_decimals_on', $this->id ? ( ( isset( $this->extra['on'] ) and $this->extra['on'] ) ? TRUE : FALSE ) : FALSE, FALSE, array( 'togglesOn' => array( 'field_number_decimals' ) ), NULL, NULL, NULL, 'field_number_decimals_on' ) );
$form->add( new \IPS\Helpers\Form\Number( 'field_number_decimals', $this->id ? ( ( isset( $this->extra['places'] ) and $this->extra['places'] ) ? $this->extra['places'] : 0 ) : 0, FALSE, array( 'max' => 6 ), NULL, NULL, NULL, 'field_number_decimals' ) );
/* Upload specific */
$form->add( new \IPS\Helpers\Form\YesNo( 'field_upload_is_multiple', $this->id ? $this->is_multiple : 0, FALSE, array( ), NULL, NULL, NULL, 'field_upload_is_multiple' ) );
@@ -2007,10 +2016,9 @@ class _Fields extends \IPS\CustomField implements \IPS\Node\Permissions
if ( isset( \IPS\Request::i()->database_id ) )
{
$usingForum = \IPS\cms\Databases::load( \IPS\Request::i()->database_id )->forum_record;
if ( ! $usingForum and $this->id )
{
$usingForum = \IPS\Db::i()->select( 'COUNT(*)', 'cms_database_categories', array( 'category_database_id=? and category_forum_override=1 and category_forum_record=1', $this->id ) );
$usingForum = \IPS\Db::i()->select( 'COUNT(*)', 'cms_database_categories', array( 'category_database_id=? and category_forum_override=1 and category_forum_record=1', $this->id ) )->first();
}
if ( $usingForum )
@@ -2277,6 +2285,7 @@ class _Fields extends \IPS\CustomField implements \IPS\Node\Permissions
$columnDefinition['type'] = 'INT';
$columnDefinition['length'] = 10;
$values['field_extra'] = '';
$values['default_value'] = ( isset( $values['default_value'] ) ) ? (int) $values['default_value'] : NULL;
break;
case 'Number':
if ( isset( $values['field_number_decimals_on'] ) and $values['field_number_decimals_on'] and $values['field_number_decimals'] )
@@ -2711,9 +2720,9 @@ class _Fields extends \IPS\CustomField implements \IPS\Node\Permissions
}
/* Special number stuff */
if ( isset( $values['field_type'] ) AND $values['field_type'] === 'Number' AND isset( $values['field_number_decimals_on'] ) )
if ( isset( $values['field_type'] ) AND $values['field_type'] === 'Number' AND ( isset( $values['field_number_decimals_on'] ) or isset( $values['field_number_min'] ) or isset( $values['field_number_max'] ) ) )
{
$values['extra'] = array( 'on' => (boolean) $values['field_number_decimals_on'], 'places' => $values['field_number_decimals'] );
$values['extra'] = array( 'on' => (boolean) $values['field_number_decimals_on'], 'places' => $values['field_number_decimals'], 'min' => $values['field_number_min'], 'max' => $values['field_number_max'] );
}
/* Remove the filter flag if this field cannot be filtered */
@@ -2728,7 +2737,7 @@ class _Fields extends \IPS\CustomField implements \IPS\Node\Permissions
$this->_oldDefaultValue = $this->default_value;
}
foreach( array( 'field_crosslink', 'field_number_decimals_on', 'field_number_decimals', 'field_format_opts_on', 'field_relational_db', 'field_upload_is_multiple', 'field_default_update_existing', 'field_date_time_override', 'field_date_timezone', 'field_date_time_time', 'field_upload_is_image', 'field_image_size', 'field_upload_thumb', 'field_title', 'field_display_display_json_badge', 'field_display_display_json_custom', 'field_display_listing_json_badge', 'field_display_listing_json_custom', 'field_display_listing_json_badge_right', 'media_display_listing_method', 'media_display_display_method', 'field_show_map_listing', 'field_show_map_listing_dims', 'field_show_map_display', 'field_show_map_display_dims', 'field_display_display_json_where' ) as $field )
foreach( array( 'field_crosslink', 'field_number_decimals_on', 'field_number_decimals', 'field_number_min', 'field_number_max', 'field_format_opts_on', 'field_relational_db', 'field_upload_is_multiple', 'field_default_update_existing', 'field_date_time_override', 'field_date_timezone', 'field_date_time_time', 'field_upload_is_image', 'field_image_size', 'field_upload_thumb', 'field_title', 'field_display_display_json_badge', 'field_display_display_json_custom', 'field_display_listing_json_badge', 'field_display_listing_json_custom', 'field_display_listing_json_badge_right', 'media_display_listing_method', 'media_display_display_method', 'field_show_map_listing', 'field_show_map_listing_dims', 'field_show_map_display', 'field_show_map_display_dims', 'field_display_display_json_where' ) as $field )
{
if ( array_key_exists( $field, $values ) )
{
@@ -2867,6 +2876,9 @@ class _Fields extends \IPS\CustomField implements \IPS\Node\Permissions
}
catch( \IPS\Db\Exception $e ) { }
}
\IPS\Lang::deleteCustom( 'cms', "content_field_{$this->id}_desc" );
\IPS\Lang::deleteCustom( 'cms', "content_field_{$this->id}_validation_error" );
}
/**
@@ -2929,13 +2941,14 @@ class _Fields extends \IPS\CustomField implements \IPS\Node\Permissions
break;
case 'Upload':
$options['storageExtension'] = static::$uploadStorageExtension;
$options['canBeModerated'] = static::$uploadsCanBeModerated;
if ( isset( $this->extra['type'] ) )
{
if ( $this->extra['type'] === 'image' )
{
$options['allowStockPhotos'] = TRUE;
$options['image'] = array( 'maxWidth' => $this->extra['maxsize'][0], 'maxHeight' => $this->extra['maxsize'][1] );
$options['image'] = array( 'maxWidth' => $this->extra['maxsize'][0] ?: NULL, 'maxHeight' => $this->extra['maxsize'][1] ?: NULL );
}
else
{
@@ -3098,6 +3111,16 @@ class _Fields extends \IPS\CustomField implements \IPS\Node\Permissions
$options['decimals'] = $this->extra['places'];
}
if ( isset( $this->extra['min'] ) and $this->extra['min'] )
{
$options['min'] = $this->extra['min'];
}
if ( isset( $this->extra['max'] ) and $this->extra['max'])
{
$options['max'] = $this->extra['max'];
}
if( !$this->required )
{
$options['unlimited'] = '';
+32 -6
View File
@@ -551,8 +551,13 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
}
catch( \Exception $ex )
{
if( $httpStatusCode !== 200 )
{
/* Unset page token */
unset( \IPS\Output::i()->jsVars['page_token'] );
}
\IPS\Output::i()->sidebar['enabled'] = FALSE;
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( $title, \IPS\Theme::i()->getTemplate( 'global', 'core' )->error( $title, $message, $code, NULL, \IPS\Member::loggedIn() ), array( 'app' => \IPS\Dispatcher::i()->application ? \IPS\Dispatcher::i()->application->directory : NULL, 'module' => \IPS\Dispatcher::i()->module ? \IPS\Dispatcher::i()->module->key : NULL, 'controller' => \IPS\Dispatcher::i()->controller ) ), $httpStatusCode, 'text/html', $httpHeaders, FALSE, FALSE );
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( $title, \IPS\Theme::i()->getTemplate( 'global', 'core' )->error( $title, $message, $code, NULL, \IPS\Member::loggedIn() ), \IPS\Dispatcher::i()->getLocationData() ), $httpStatusCode, 'text/html', $httpHeaders, FALSE, FALSE );
}
}
@@ -1554,7 +1559,7 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
$form->canSaveAndReload = true;
}
\IPS\Output::i()->title = $this->id ? \IPS\Member::loggedIn()->language()->addToStack('content_editing_page', NULL, array( 'sprintf' => array( $this->_title ) ) ) : \IPS\Member::loggedIn()->language()->addToStack('content_add_page');
\IPS\Output::i()->title = $this->id ? \IPS\Member::loggedIn()->language()->addToStack( 'content_editing_page', FALSE, array( 'sprintf' => array( $this->_title ) ) ) : \IPS\Member::loggedIn()->language()->addToStack('content_add_page');
}
/**
@@ -1887,12 +1892,33 @@ class _Page extends \IPS\Node\Model implements \IPS\Node\Permissions
}
else
{
/* Nope, not database tag spotted, assume it has been removed */
try
/* Nope, not database tag spotted, now check widgets to be sure... */
$keep = FALSE;
foreach( \IPS\Db::i()->select( '*', 'cms_page_widget_areas', array( 'area_page_id=?', $this->id ) ) as $k => $widgetMain )
{
$this->removeDatabaseMap();
$widgets = json_decode( $widgetMain['area_widgets'], TRUE );
if ( \is_array( $widgets ) )
{
foreach( $widgets as $row )
{
if ( $row['key'] == 'Database' and $row['configuration']['database'] == $database->id )
{
$keep = TRUE;
break;
}
}
}
}
if ( ! $keep )
{
try
{
$this->removeDatabaseMap();
}
catch( \LogicException $e ) { }
}
catch( \LogicException $e ) { }
}
}
}
@@ -100,6 +100,11 @@ class _Comment extends \IPS\Content\Comment implements \IPS\Content\EditHistory,
*/
protected static $searchIndexTitles = array();
/**
* @brief Whether to track the sentiment scores in cloud_sentiment_scores for this content
*/
public $trackSentimentScore = true;
/**
* Load Record
*
@@ -158,6 +163,16 @@ class _Comment extends \IPS\Content\Comment implements \IPS\Content\EditHistory,
{
return array( array( static::$databasePrefix . static::$databaseColumnMap['item'] . '=?', $id ), array( static::$databasePrefix . 'database_id=?', static::$customDatabaseId ) );
}
/**
* Return custom where for IP tools
*
* @return string
*/
public static function findByIPWhere()
{
return " AND comment_database_id=" . static::$customDatabaseId;
}
/**
* Get items with permisison check
@@ -171,13 +171,14 @@ class _CommentTopicSync extends \IPS\cms\Records\Comment
*
* @param string $reportContent Report content message from member
* @param int $reportType Report type (see constants in \IPS\core\Reports\Report
* @param \IPS\Member|NULL $member Member making the report (or NULL for loggedIn())
* @return \\PS\core\Reports\Report
* @throws \UnexpectedValueException If there is a permission error - you should only call this method after checking canReport
*/
public function report( $reportContent, $reportType=1 )
public function report( $reportContent, $reportType=1, $member=NULL )
{
$comment = \IPS\forums\Topic\Post::load( $this->pid );
return $comment->report( $reportContent, $reportType );
return $comment->report( $reportContent, $reportType, $member );
}
/**
+166 -27
View File
@@ -78,11 +78,6 @@ class _Records extends \IPS\Content\Item implements
*/
public static $module = 'records';
/**
* @brief Database Column Map
*/
public static $databaseColumnMap = NULL;
/**
* @brief Node Class
*/
@@ -123,6 +118,43 @@ class _Records extends \IPS\Content\Item implements
*/
protected static $standardFields = array( 'record_publish_date', 'record_expiry_date', 'record_allow_comments', 'record_comment_cutoff' );
/**
* The real definition of this happens in the magic autoloader inside the cms\Application class, but we need this one which contains all the "none database id related" fields for the Content Widget
*
* @var string[]
*/
public static $databaseColumnMap = array(
'author' => 'member_id',
'container' => 'category_id',
'date' => 'record_publish_date',
'is_future_entry' => 'record_future_date',
'future_date' => 'record_publish_date',
'num_comments' => 'record_comments',
'unapproved_comments' => 'record_comments_queued',
'hidden_comments' => 'record_comments_hidden',
'last_comment' => 'record_last_comment',
'last_comment_by' => 'record_last_comment_by',
'last_comment_name' => 'record_last_comment_name',
'views' => 'record_views',
'approved' => 'record_approved',
'pinned' => 'record_pinned',
'locked' => 'record_locked',
'featured' => 'record_featured',
'rating' => 'record_rating',
'rating_hits' => 'rating_hits',
'rating_average' => 'record_rating',
'rating_total' => 'rating_value',
'num_reviews' => 'record_reviews',
'last_review' => 'record_last_review',
'last_review_by' => 'record_last_review_by',
'last_review_name' => 'record_last_review_name',
'updated' => 'record_last_comment',
'meta_data' => 'record_meta_data',
'author_name' => 'record_author_name',
'is_anon' => 'record_is_anon',
);
/**
* @brief Icon
*/
@@ -148,6 +180,33 @@ class _Records extends \IPS\Content\Item implements
return (bool) \IPS\cms\Databases::load( static::$customDatabaseId )->search;
}
/**
* Most, if not all of these are the same for different events, so we can just have one method
*
* @param IPS\Content\Comment $comment A comment item, leave null for these keys to be omitted
*
* @return array
*/
public function getDataLayerProperties( ?\IPS\Content\Comment $comment = null )
{
$commentIdColumn = $comment ? $comment::$databaseColumnId : null;
$index = $commentIdColumn ? ( $comment->$commentIdColumn ?: 0 ) : 0;
if ( isset( $this->_dataLayerProperties[$index] ) )
{
return $this->_dataLayerProperties[$index];
}
/* Set the content_type and comment_type to lower case for consistency */
$properties = parent::getDataLayerProperties( $comment );
if ( isset( $properties['content_type'] ) )
{
$properties['content_type'] = \strtolower( \IPS\Lang::load( \IPS\Lang::defaultLanguage() )->addToStack( static::$title ) );
}
$this->_dataLayerProperties[$index] = $properties;
return $properties;
}
/**
* Construct ActiveRecord from database row
*
@@ -591,7 +650,7 @@ class _Records extends \IPS\Content\Item implements
$dims = array( 'maxWidth' => $fixedFieldSettings['record_image']['image_dims'][0], 'maxHeight' => $fixedFieldSettings['record_image']['image_dims'][1] );
}
$formElements['record_image'] = new \IPS\Helpers\Form\Upload( 'record_image', ( ( $item and $item->record_image ) ? \IPS\File::get( 'cms_Records', $item->record_image ) : NULL ), FALSE, array( 'image' => $dims, 'storageExtension' => 'cms_Records', 'multiple' => false, 'allowStockPhotos' => true ), NULL, NULL, NULL, 'record_image' );
$formElements['record_image'] = new \IPS\Helpers\Form\Upload( 'record_image', ( ( $item and $item->record_image ) ? \IPS\File::get( 'cms_Records', $item->record_image ) : NULL ), FALSE, array( 'image' => $dims, 'storageExtension' => 'cms_Records', 'multiple' => false, 'allowStockPhotos' => true, 'canBeModerated' => TRUE ), NULL, NULL, NULL, 'record_image' );
}
if ( $fieldsClass::fixedFieldFormShow( 'record_expiry_date' ) )
@@ -776,13 +835,16 @@ class _Records extends \IPS\Content\Item implements
*/
public function processForm( $values )
{
$isNew = $this->_new;
$fieldsClass = 'IPS\cms\Fields' . static::$customDatabaseId;
$database = \IPS\cms\Databases::load( static::$customDatabaseId );
$categoryClass = 'IPS\cms\Categories' . static::$customDatabaseId;
$container = ( ! isset( $values['content_record_form_container'] ) ? $categoryClass::load( $this->category_id ) : $values['content_record_form_container'] );
$autoSaveKeys = [];
$imageUploads = [];
/* Store a revision */
if ( $database->revisions AND ! $this->_new )
if ( $database->revisions AND !$isNew )
{
$revision = new \IPS\cms\Records\Revisions;
$revision->database_id = static::$customDatabaseId;
@@ -797,7 +859,7 @@ class _Records extends \IPS\Content\Item implements
$this->post_key = \IPS\Request::i()->postKey;
}
if ( $this->_new )
if ( $isNew )
{
/* Peanut Butter Registering */
if ( !\IPS\Member::loggedIn()->member_id and $container and !$container->can( 'add', \IPS\Member::loggedIn(), FALSE ) )
@@ -875,7 +937,7 @@ class _Records extends \IPS\Content\Item implements
}
/* Edit stuff */
if ( ! $this->_new )
if ( !$isNew )
{
if ( isset( $values['record_edit_reason'] ) )
{
@@ -919,6 +981,7 @@ class _Records extends \IPS\Content\Item implements
}
else
{
$imageUploads[] = $values['record_image'];
$fixedFieldSettings = static::database()->fixed_field_settings;
if ( isset( $fixedFieldSettings['record_image']['thumb_dims'] ) )
@@ -963,7 +1026,7 @@ class _Records extends \IPS\Content\Item implements
/* Custom fields */
$customValues = array();
$afterEditNotificationsExclude = array();
$afterEditNotificationsExclude = [ 'quotes' => [], 'mentions' => [] ];
foreach( $values as $k => $v )
{
@@ -977,17 +1040,18 @@ class _Records extends \IPS\Content\Item implements
if ( static::$customFields === NULL )
{
static::$customFields = $fieldsClass::fields( $customValues, ( $this->_new ? 'add' : 'edit' ), $container, 0, ( $this->_new ? NULL : $this ) );
static::$customFields = $fieldsClass::fields( $customValues, ( $isNew ? 'add' : 'edit' ), $container, 0, ( $isNew ? NULL : $this ) );
}
$seen = [];
foreach( static::$customFields as $key => $field )
{
$seen[] = $key;
$key = 'field_' . $key;
$fieldId = $key;
$seen[] = $fieldId;
$key = 'field_' . $fieldId;
if ( !$this->_new )
if ( !$isNew )
{
$afterEditNotificationsExclude = array_merge_recursive( static::_getQuoteAndMentionIdsFromContent( $this->$key ) );
}
@@ -999,12 +1063,14 @@ class _Records extends \IPS\Content\Item implements
$items = array();
foreach( $customValues[ $field->name ] as $obj )
{
$imageUploads[] = $obj;
$items[] = (string) $obj;
}
$this->$key = implode( ',', $items );
}
else
{
$imageUploads[] = $customValues[ $field->name ];
$this->$key = (string) $customValues[ $field->name ];
}
}
@@ -1015,12 +1081,17 @@ class _Records extends \IPS\Content\Item implements
}
else
{
if ( \get_class( $field ) == 'IPS\Helpers\Form\Editor' )
{
$autoSaveKeys[] = $isNew ? "RecordField_new_{$fieldId}" : [ $this->_id, $fieldId, static::$customDatabaseId ];
}
$this->$key = $field::stringValue( isset( $customValues[ $field->name ] ) ? $customValues[ $field->name ] : NULL );
}
}
/* Now set up defaults */
if ( $this->_new )
if ( $isNew )
{
foreach ( $fieldObjects as $obj )
{
@@ -1034,7 +1105,7 @@ class _Records extends \IPS\Content\Item implements
}
/* Other data */
if ( $this->_new OR $database->_comment_bump & \IPS\cms\Databases::BUMP_ON_EDIT )
if ( $isNew OR $database->_comment_bump & \IPS\cms\Databases::BUMP_ON_EDIT )
{
$this->record_saved = time();
$this->record_updated = time();
@@ -1060,7 +1131,7 @@ class _Records extends \IPS\Content\Item implements
}
else
{
if( $this->_new )
if( $isNew )
{
$this->record_static_furl = NULL;
}
@@ -1072,12 +1143,12 @@ class _Records extends \IPS\Content\Item implements
}
}
$sendFilterNotifications = $this->checkProfanityFilters( FALSE, $this->_new );
$sendFilterNotifications = $this->checkProfanityFilters( FALSE, !$isNew, NULL, NULL, 'cms_Records' . static::$customDatabaseId, $autoSaveKeys, $imageUploads );
if ( $this->_new )
if ( $isNew )
{
/* Set the author ID on 'new' only */
$this->member_id = (int) \IPS\Member::loggedIn()->member_id;
$this->member_id = (int) ( static::$createWithMember ? static::$createWithMember->member_id : \IPS\Member::loggedIn()->member_id );
}
elseif ( !$sendFilterNotifications )
{
@@ -1089,7 +1160,6 @@ class _Records extends \IPS\Content\Item implements
$this->category_id = ( $values['content_record_form_container'] === 0 ) ? 0 : $values['content_record_form_container']->id;
}
$isNew = $this->_new;
$idColumn = static::$databaseColumnId;
if ( ! $this->$idColumn )
{
@@ -1567,7 +1637,7 @@ class _Records extends \IPS\Content\Item implements
}
}
return \count( $attachments ) ? $attachments : NULL;
return \count( $attachments ) ? \array_slice( $attachments, 0, $limit ) : NULL;
}
/**
@@ -1839,7 +1909,7 @@ class _Records extends \IPS\Content\Item implements
*/
public function get__record_image_thumb()
{
return $this->record_image_thumb ? $this->record_image_thumb : $this->record_image;
return $this->record_image_thumb ?: $this->record_image;
}
/**
@@ -2099,7 +2169,15 @@ class _Records extends \IPS\Content\Item implements
*/
public function useForumComments()
{
return $this->_forum_record and $this->_forum_comments and $this->record_topicid and \IPS\Application::appIsEnabled('forums');
try
{
return $this->_forum_record and $this->_forum_comments and $this->record_topicid and \IPS\Application::appIsEnabled('forums');
}
catch( \Exception $e)
{
return FALSE;
}
}
/**
@@ -2358,6 +2436,11 @@ class _Records extends \IPS\Content\Item implements
*/
protected static $creatingRecord = FALSE;
/**
* @brief Store the member we are creating with if not the logged in member
*/
protected static $createWithMember = NULL;
/**
* Create from form
*
@@ -2368,6 +2451,11 @@ class _Records extends \IPS\Content\Item implements
*/
public static function createFromForm( $values, \IPS\Node\Model $container = NULL, $sendNotification = TRUE )
{
if ( isset( $values['record_author_choice'] ) and $values['record_author_choice'] == 'notme' )
{
static::$createWithMember = $values['record_member_id'];
}
static::$creatingRecord = TRUE;
$record = parent::createFromForm( $values, $container, $sendNotification );
static::$creatingRecord = FALSE;
@@ -2384,6 +2472,22 @@ class _Records extends \IPS\Content\Item implements
return $record;
}
/**
* Create generic object
*
* @param \IPS\Member $author The author
* @param string|NULL $ipAddress The IP address
* @param \IPS\DateTime $time The time
* @param \IPS\Node\Model|NULL $container Container (e.g. forum), if appropriate
* @param bool|NULL $hidden Hidden? (NULL to work our automatically)
* @return static
*/
public static function createItem( \IPS\Member $author, $ipAddress, \IPS\DateTime $time, \IPS\Node\Model $container = NULL, $hidden=NULL )
{
/* This is fired inside createFromForm, and we need to switch the author? */
return parent::createItem( static::$createWithMember !== NULL ? static::$createWithMember : $author, $ipAddress, $time, $container, $hidden );
}
/**
* Process after the object has been edited on the front-end
*
@@ -3155,11 +3259,17 @@ class _Records extends \IPS\Content\Item implements
{
return TRUE;
}
/* Am I a Moderator with edit permissions ?*/
if( $this->container()->modPermission( 'edit', $member, \get_called_class() ) )
{
return TRUE;
}
if ( parent::canEdit( $member ) )
{
/* Test against specific perms for this category */
return $this->container()->can( 'edit', $member ) or $this->container()->modPermission( 'edit', $member, \get_called_class() );
return $this->container()->can( 'edit', $member );
}
return FALSE;
@@ -3713,7 +3823,7 @@ class _Records extends \IPS\Content\Item implements
$url = NULL;
}
return array(
$return = array(
'id' => $this->primary_id_field,
'title' => $this->_title,
'category' => $this->container() ? $this->container()->apiOutput() : null,
@@ -3735,6 +3845,35 @@ class _Records extends \IPS\Content\Item implements
'image' => $this->record_image ? (string) \IPS\File::get( 'cms_Records', $this->record_image )->url : null,
'topic' => $this->topicid ? $this->topic()->apiOutput( $authorizedMember ) : NULL,
);
if ( \IPS\IPS::classUsesTrait( $this, 'IPS\Content\Reactable' ) )
{
if ( $reactions = $this->reactions() )
{
$enabledReactions = \IPS\Content\Reaction::enabledReactions();
$finalReactions = [];
foreach( $reactions as $memberId => $array )
{
foreach( $array as $reaction )
{
$finalReactions[ $memberId ][] = [
'title' => $enabledReactions[ $reaction ]->_title,
'id' => $reaction,
'value' => $enabledReactions[ $reaction ]->value,
'icon' => (string) $enabledReactions[ $reaction ]->_icon->url
];
}
}
$return['reactions'] = $finalReactions;
}
else
{
$return['reactions'] = [];
}
}
return $return;
}
/**
+8 -2
View File
@@ -96,6 +96,11 @@ class _Review extends \IPS\Content\Review implements \IPS\Content\EditHistory, \
*/
public static $customDatabaseId = NULL;
/**
* @brief Whether to track the sentiment scores in cloud_sentiment_scores for this content
*/
public $trackSentimentScore = true;
/**
* Load Record
*
@@ -133,12 +138,13 @@ class _Review extends \IPS\Content\Review implements \IPS\Content\EditHistory, \
* @param \IPS\DateTime|NULL $time The time
* @param string|NULL $ipAddress The IP address or NULL to detect automatically
* @param int|NULL $hiddenStatus NULL to set automatically or override: 0 = unhidden; 1 = hidden, pending moderator approval; -1 = hidden (as if hidden by a moderator)
* @param int|NULL $anonymous NULL for no value, 0 or 1 for a value (0=no, 1=yes)
* @return static
* @throws \InvalidArgumentException
*/
public static function create( $item, $comment, $first=FALSE, $rating=NULL, $guestName=NULL, $member=NULL, \IPS\DateTime $time=NULL, $ipAddress=NULL, $hiddenStatus=NULL )
public static function create( $item, $comment, $first=FALSE, $rating=NULL, $guestName=NULL, $member=NULL, \IPS\DateTime $time=NULL, $ipAddress=NULL, $hiddenStatus=NULL, $anonymous=NULL )
{
$review = parent::create( $item, $comment, $first, $rating, $guestName, $member, $time, $ipAddress, $hiddenStatus );
$review = parent::create( $item, $comment, $first, $rating, $guestName, $member, $time, $ipAddress, $hiddenStatus, $anonymous );
$review->database_id = static::$customDatabaseId;
$review->save();
@@ -516,7 +516,10 @@ class _Templates extends \IPS\Patterns\ActiveRecord
foreach( $templates as $id => $template )
{
$return[ $template->location ][ $template->group ][ $template->key ] = $template;
if ( ! ( $template->location === 'database' and ! \IPS\Member::loggedIn()->hasAcpRestriction( 'cms', 'databases', 'databases_use' ) ) )
{
$return[$template->location][$template->group][$template->key] = $template;
}
}
return $return;