Version 4.1.19

This commit is contained in:
Neo committed 2025-12-19 05:38:56 -08:00
1 parent 28bd025b35
commit 2bd5025018
2674 files changed
+233518 -77766

No files matched your search

+204 -42
View File
@@ -2,9 +2,10 @@
/**
* @brief Databases Model
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @subpackage Content
* @since 31 March 2014
* @version SVN_VERSION_NUMBER
*/
@@ -48,6 +49,11 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
*/
protected static $databaseIdFields = array( 'database_key', 'database_page_id' );
/**
* @brief [ActiveRecord] Multiton Map
*/
protected static $multitonMap = array();
/**
* @brief [Node] Parent ID Database Column
*/
@@ -147,6 +153,11 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
)
);
/**
* @brief Page title
*/
protected static $pageTitle = NULL;
/**
* Return all databases
*
@@ -156,15 +167,10 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
{
if ( ! static::$gotAll )
{
if ( ! isset( \IPS\Data\Store::i()->cms_databases ) )
{
\IPS\Data\Store::i()->cms_databases = iterator_to_array( \IPS\Db::i()->select( '*', static::$databaseTable )->setKeyField('database_id') );
}
/* Avoid using SHOW TABLES LIKE / checkForTable() */
try
{
foreach( \IPS\Data\Store::i()->cms_databases as $db )
foreach( static::getDatabaseDataFromStore() as $db )
{
$id = $db[ static::$databasePrefix . static::$databaseColumnId ];
static::$multitons[ $id ] = static::constructFromData( $db );
@@ -177,7 +183,31 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
return static::$multitons;
}
/**
* Returns database data from the store
*
* @return array
*/
public static function getDatabaseDataFromStore()
{
if ( ! isset( \IPS\Data\Store::i()->cms_databases ) )
{
\IPS\Data\Store::i()->cms_databases = iterator_to_array(
\IPS\Db::i()->select(
static::$databaseTable . '.*, core_permission_index.perm_id, core_permission_index.perm_view, core_permission_index.perm_2, core_permission_index.perm_3, core_permission_index.perm_4, core_permission_index.perm_5, core_permission_index.perm_6, core_permission_index.perm_7',
static::$databaseTable
)->join(
'core_permission_index',
array( "core_permission_index.app=? AND core_permission_index.perm_type=? AND core_permission_index.perm_type_id=" . static::$databaseTable . "." . static::$databasePrefix . static::$databaseColumnId, static::$permApp, static::$permType )
)
->setKeyField('database_id')
);
}
return \IPS\Data\Store::i()->cms_databases;
}
/**
* Can we promote stuff to Pages?
*
@@ -652,7 +682,33 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
{
$this->_data['featured_settings'] = ( is_array( $value ) ? json_encode( $value ) : $value );
}
/**
* Get the title of the page when using a database
*
* @return string
*/
public function pageTitle()
{
if ( static::$pageTitle === NULL )
{
if ( $this->use_as_page_title )
{
static::$pageTitle = $this->_title;
}
else
{
try
{
static::$pageTitle = \IPS\cms\Pages\Page::load( $this->page_id )->getHtmlTitle();
}
catch( \Exception $e ) { }
}
}
return static::$pageTitle;
}
/**
* Check permissions
*
@@ -692,39 +748,22 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
$this->langLoaded = TRUE;
return;
}
if ( ! $this->langLoaded )
{
\IPS\Member::loggedIn()->language()->words['__indefart_content_record_comments_title_' . $this->id ] = \IPS\Member::loggedIn()->language()->addToStack( '__indefart_content_record_comments_title' );
\IPS\Member::loggedIn()->language()->words['__indefart_content_record_reviews_title_' . $this->id ] = \IPS\Member::loggedIn()->language()->addToStack( '__indefart_content_record_reviews_title' );
\IPS\Member::loggedIn()->language()->words['content_record_comments_title_' . $this->id ] = \IPS\Member::loggedIn()->language()->addToStack( 'content_record_comment_title', FALSE, array( 'sprintf' => array( $this->recordWord( 1, TRUE ) ) ) );
\IPS\Member::loggedIn()->language()->words['content_record_reviews_title_' . $this->id ] = \IPS\Member::loggedIn()->language()->addToStack( 'content_record_review_title', FALSE, array( 'sprintf' => array( $this->recordWord( 1, TRUE ) ) ) );
\IPS\Member::loggedIn()->language()->words['content_record_comments_title_' . $this->id . '_pl' ] = \IPS\Member::loggedIn()->language()->addToStack( 'content_record_comments_title', FALSE, array( 'sprintf' => array( $this->recordWord( 1, TRUE ) ) ) );
\IPS\Member::loggedIn()->language()->words['content_record_reviews_title_' . $this->id . '_pl' ] = \IPS\Member::loggedIn()->language()->addToStack( 'content_record_reviews_title', FALSE, array( 'sprintf' => array( $this->recordWord( 1, TRUE ) ) ) );
\IPS\Member::loggedIn()->language()->words['content_db_lang_su_' . $this->id . '_pl' ] = \IPS\Member::loggedIn()->language()->addToStack( 'content_db_lang_pu_' . $this->id );
\IPS\Member::loggedIn()->language()->words['content_db_lang_sl_' . $this->id . '_pl_lc' ] = \IPS\Member::loggedIn()->language()->addToStack( 'content_db_lang_pl_' . $this->id );
$fieldsClass = '\IPS\cms\Fields' . $this->id;
$customFields = $fieldsClass::databaseFieldIds();
foreach ( $customFields AS $id )
{
\IPS\Member::loggedIn()->language()->words['sort_field_' . $id] = \IPS\Member::loggedIn()->language()->addToStack( 'content_field_' . $id );
}
if ( \IPS\Dispatcher::i()->controllerLocation === 'admin' )
{
/* Moderator tools */
\IPS\Member::loggedIn()->language()->words['modperms__core_Content_cms_Records' . $this->id ] = $this->_title;
\IPS\Member::loggedIn()->language()->words['cms' . $this->id ] = \IPS\Member::loggedIn()->language()->addToStack('categories');
/* Editor Areas */
\IPS\Member::loggedIn()->language()->words['editor__cms_Records' . $this->id ] = $this->_title;
foreach( array( 'pin', 'unpin', 'feature', 'unfeature', 'edit', 'hide', 'unhide', 'view_hidden', 'future_publish', 'view_future', 'move', 'lock', 'unlock', 'reply_to_locked', 'delete' ) as $lang )
{
\IPS\Member::loggedIn()->language()->words['can_' . $lang . '_content_db_lang_sl_' . $this->id ] = \IPS\Member::loggedIn()->language()->addToStack( 'can_' . $lang . '_record', FALSE, array( 'sprintf' => array( $this->recordWord( 1 ) ) ) );
\IPS\Member::loggedIn()->language()->words['can_' . $lang . '_content_db_lang_su_' . $this->id ] = \IPS\Member::loggedIn()->language()->addToStack( 'can_' . $lang . '_record', FALSE, array( 'sprintf' => array( $this->recordWord( 1, TRUE ) ) ) );
if ( in_array( $lang, array( 'edit', 'hide', 'unhide', 'view_hidden', 'delete' ) ) )
{
@@ -748,8 +787,16 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
*/
public function recordWord( $number = 2, $upper = FALSE )
{
$case = $upper ? 'u' : 'l';
return $number == 1 ? \IPS\Member::loggedIn()->language()->addToStack("content_db_lang_s{$case}_{$this->id}") : \IPS\Member::loggedIn()->language()->addToStack("content_db_lang_p{$case}_{$this->id}");
if ( \IPS\Application::appIsEnabled('cms') )
{
return \IPS\Member::loggedIn()->language()->recordWord( $number, $upper, $this->id );
}
else
{
/* If the Pages app is disabled, just load a generic phrase */
$key = "content_database_noun_" . ( $number > 1 ? "p" : "s" ) . ( $upper ? "u" : "l" );
return \IPS\Member::loggedIn()->language()->addToStack( $key );
}
}
/**
@@ -759,12 +806,39 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
*/
public function save()
{
/* If we are enabling search, we will need to index that content */
$rebuildSearchIndex = ( !$this->_new AND isset( $this->changed['search'] ) AND $this->changed['search'] );
parent::save();
/* Clear cache */
if ( isset( \IPS\Data\Store::i()->cms_databases ) )
{
unset( \IPS\Data\Store::i()->cms_databases );
}
parent::save();
/* If this database isn't searchable, make sure its content is not in the search index */
if( !$this->search AND !$this->_new )
{
\IPS\Content\Search\Index::i()->removeClassFromSearchIndex( 'IPS\cms\Records' . $this->id );
\IPS\Content\Search\Index::i()->removeClassFromSearchIndex( 'IPS\cms\Records\Comment' . $this->id );
\IPS\Content\Search\Index::i()->removeClassFromSearchIndex( 'IPS\cms\Records\Review' . $this->id );
/* If there are any bg tasks to rebuild index, clear them */
foreach( \IPS\Db::i()->select( '*', 'core_queue', array( '`key`=?', 'RebuildSearchIndex' ) ) as $queue )
{
$details = json_decode( $queue['data'], true );
if( isset( $details['class'] ) AND $details['class'] == 'IPS\cms\Records' . $this->id )
{
\IPS\Db::i()->delete( 'core_queue', array( 'id=?', $queue['id'] ) );
}
}
}
elseif( $rebuildSearchIndex )
{
\IPS\Task::queue( 'core', 'RebuildSearchIndex', array( 'class' => 'IPS\cms\Records' . $this->id ), 5, TRUE );
}
}
/**
@@ -795,20 +869,22 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
/* Delete comments */
\IPS\Db::i()->delete( 'cms_database_comments', array( 'comment_database_id=?', $this->id ) );
/* Delete from search index */
\IPS\Db::i()->delete( 'core_search_index', array( 'index_class=?', "IPS\cms\Records\Comment" . $this->id ) );
\IPS\Db::i()->delete( 'core_search_index', array( 'index_class=?', "IPS\cms\Records\Review" . $this->id ) );
/* Delete from view counter */
\IPS\Db::i()->delete( 'core_view_updates', array( 'classname=? ', 'IPS\cms\Records' . $this->id ) );
/* Delete records */
\IPS\Db::i()->dropTable( 'cms_custom_database_' . $this->id, TRUE );
/* Delete revisions */
\IPS\Db::i()->delete( 'cms_database_revisions', array( 'revision_database_id=?', $this->id ) );
/* Remove any reciprocal linking */
\IPS\Db::i()->delete( 'cms_database_fields_reciprocal_map', array( 'map_foreign_database_id=? or map_origin_database_id=?', $this->id, $this->id ) );
/* Delete notifications */
$memberIds = array();
foreach( \IPS\DB::i()->select( 'member', 'core_notifications', array( 'item_class=? ', 'IPS\cms\Records' . $this->id ) ) as $member )
foreach( \IPS\Db::i()->select( 'member', 'core_notifications', array( 'item_class=? ', 'IPS\cms\Records' . $this->id ) ) as $member )
{
$memberIds[ $member ] = $member;
}
@@ -823,6 +899,8 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
/* Remove from search */
\IPS\Content\Search\Index::i()->removeClassFromSearchIndex( 'IPS\cms\Records' . $this->id );
\IPS\Content\Search\Index::i()->removeClassFromSearchIndex( 'IPS\cms\Records\Comment' . $this->id );
\IPS\Content\Search\Index::i()->removeClassFromSearchIndex( 'IPS\cms\Records\Review' . $this->id );
/* Delete custom languages */
\IPS\Lang::deleteCustom( 'cms', "content_db_" . $this->id );
@@ -834,16 +912,20 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
\IPS\Lang::deleteCustom( 'cms', "content_db_lang_ia_" . $this->id );
\IPS\Lang::deleteCustom( 'cms', "content_db_lang_sl_" . $this->id . '_pl' );
\IPS\Lang::deleteCustom( 'cms', "__indefart_content_db_lang_sl_" . $this->id );
\IPS\Lang::deleteCustom( 'cms', "__defart_content_db_lang_sl_" . $this->id );
\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 );
/* Unclaim attachments */
\IPS\File::unclaimAttachments( 'content_Records_' . $this->id );
\IPS\File::unclaimAttachments( 'cms_Records_' . $this->id );
/* Remove widgets */
$this->removeWidgets();
/* Best remove the stored data */
unset( \IPS\Data\Store::i()->database_reciprocal_links );
parent::delete();
}
@@ -890,6 +972,12 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
{
parent::setPermissions( $insert, $matrix );
/* Clear cache */
if ( isset( \IPS\Data\Store::i()->cms_databases ) )
{
unset( \IPS\Data\Store::i()->cms_databases );
}
/* Clone these permissions to all categories that do not have permissions */
$class = '\IPS\cms\Categories' . $this->id;
foreach( $class::roots( NULL, NULL, array(), $this->id ) as $category )
@@ -936,5 +1024,79 @@ class _Databases extends \IPS\Node\Model implements \IPS\Node\Permissions
}
return $this->_numberOfCategories;
}
/**
* Determines if any fields from other databases are linking to items in this database via the Relational field
*
* @param int $databaseId The ID of the database
* @return boolean
*/
public static function hasReciprocalLinking( $databaseId )
{
if ( isset( \IPS\Data\Store::i()->database_reciprocal_links ) )
{
$values = \IPS\Data\Store::i()->database_reciprocal_links;
}
else
{
$values = array();
foreach( static::databases() as $database )
{
$fieldsClass = 'IPS\cms\Fields' . $database->_id;
foreach( $fieldsClass::data() as $field )
{
if ( $field->type === 'Item' )
{
$extra = $field->extra;
if ( ! empty( $extra['database'] ) )
{
$values[ $database->_id ] = $extra;
}
}
}
\IPS\Data\Store::i()->database_reciprocal_links = $values;
}
}
if ( is_array( $values ) )
{
foreach( $values as $id => $data )
{
if ( $data['database'] == $databaseId and $data['crosslink'] )
{
return TRUE;
}
}
}
return FALSE;
}
/**
* Rebuild the reciprocal linking maps across all databases
*
* @return void
*/
public static function rebuildReciprocalLinkMaps()
{
/* Ensure the SPL are loaded from /cms/Application.php as this may be called by a task or upgrade module */
\IPS\Application::load('cms');
\IPS\Db::i()->delete( 'cms_database_fields_reciprocal_map' );
foreach( static::databases() as $database )
{
$fieldsClass = 'IPS\cms\Fields' . $database->_id;
foreach( $fieldsClass::data() as $field )
{
if ( $field->type === 'Item' )
{
\IPS\Task::queue( 'cms', 'RebuildReciprocalMaps', array( 'database' => $database->_id, 'field' => $field->id ), 2, array( 'field' ) );
}
}
}
}
}