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\cms\modules\front\database;
/* 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;
@@ -73,21 +73,21 @@ class _record extends \IPS\Content\Controller
$_tabs = array_keys( $tabs );
$tab = isset( \IPS\Request::i()->tab ) ? \IPS\Request::i()->tab : array_shift( $_tabs );
$activeTabContents = $record->commentReviews( $tab );
$comments = count( $tabs ) ? \IPS\cms\Theme::i()->getTemplate( $record->container()->_template_display, 'cms', 'database' )->commentsAndReviewsTabs( \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $tab, $activeTabContents, $record->url(), 'tab', FALSE, TRUE ), md5( $record->url() ) ) : NULL;
$comments = \count( $tabs ) ? \IPS\cms\Theme::i()->getTemplate( $record->container()->_template_display, 'cms', 'database' )->commentsAndReviewsTabs( \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $tab, $activeTabContents, $record->url(), 'tab', FALSE, TRUE ), md5( $record->url() ) ) : NULL;
if ( \IPS\Request::i()->isAjax() and ( isset( \IPS\Request::i()->page ) OR isset( \IPS\Request::i()->tab ) ) )
if ( \IPS\Request::i()->isAjax() and !isset( \IPS\Request::i()->rating_submitted ) and ( isset( \IPS\Request::i()->page ) OR isset( \IPS\Request::i()->tab ) ) and $activeTabContents )
{
\IPS\Output::i()->sendOutput( $activeTabContents, 200, 'text/html', \IPS\Output::i()->httpHeaders );
\IPS\Output::i()->sendOutput( $activeTabContents, 200, 'text/html' );
}
$class = '\IPS\cms\Categories' . $record::$customDatabaseId;
$category = $class::load( $record->category_id );
$FieldsClass = '\\IPS\\cms\\Fields' . $record::$customDatabaseId;
$updateFields = $FieldsClass::fields( $record->fieldValues(), 'edit', $record->container(), $FieldsClass::FIELD_SKIP_TITLE_CONTENT | $FieldsClass::FIELD_DISPLAY_COMMENTFORM );
$updateFields = $FieldsClass::fields( $record->fieldValues(), 'edit', $record->container(), $FieldsClass::FIELD_DISPLAY_COMMENTFORM, $record );
$form = null;
/* We need edit permission to change the record */
if ( count( $updateFields ) and $record->canEdit() )
if ( \count( $updateFields ) and $record->canEdit() )
{
$form = new \IPS\Helpers\Form( 'update_record', 'update', $record->url()->setQueryString( array( 'd' => $record::$customDatabaseId ) ) );
$form->class = 'ipsForm_vertical';
@@ -113,18 +113,29 @@ class _record extends \IPS\Content\Controller
}
}
if ( count( $customValues ) )
if ( \count( $customValues ) )
{
if ( $values['record_display_field_change'] )
{
$record->addCommentWhenFiltersChanged( $values );
}
else
{
/* Set excludes for custom field updates. We'll send the notifications later, once we know the new content of the fields. */
$record->setFieldQuoteAndMentionExcludes();
}
foreach( $fieldsClass::fields( $customValues, 'edit', $record->category_id ? $category : NULL, $FieldsClass::FIELD_SKIP_TITLE_CONTENT | $FieldsClass::FIELD_DISPLAY_COMMENTFORM ) as $key => $field )
foreach( $fieldsClass::fields( $customValues, 'edit', $record->category_id ? $category : NULL, $FieldsClass::FIELD_DISPLAY_COMMENTFORM ) as $key => $field )
{
$key = 'field_' . $key;
$record->$key = $field::stringValue( isset( $values[ $field->name ] ) ? $values[ $field->name ] : NULL );
}
/* Send custom field update notifications */
if ( !$values['record_display_field_change'] )
{
$record->sendFieldQuoteAndMentionNotifications();
}
$record->save();
$record->processAfterEdit( $values );
@@ -146,7 +157,14 @@ class _record extends \IPS\Content\Controller
}
/* Set record URL as canonical tag */
\IPS\Output::i()->linkTags['canonical'] = $record->url();
if ( $record::database()->canonical_flag == 1 and ( isset( \IPS\Request::i()->page ) and \IPS\Request::i()->page > 1 ) )
{
\IPS\Output::i()->linkTags['canonical'] = $record->url()->setPage( 'page', \IPS\Request::i()->page );
}
else
{
\IPS\Output::i()->linkTags['canonical'] = $record->url();
}
/* Update location */
if( $record->database()->use_categories )
@@ -163,7 +181,7 @@ class _record extends \IPS\Content\Controller
/* Next unread */
try
{
$nextUnread = $record->nextUnread();
$nextUnread = $record->containerHasUnread();
}
catch( \Exception $e )
{
@@ -176,6 +194,8 @@ class _record extends \IPS\Content\Controller
}
/* Add Json-LD */
$jsonLdText = $record->truncated( TRUE, NULL );
\IPS\Output::i()->jsonLd['article'] = array(
'@context' => "http://schema.org",
'@type' => "Article",
@@ -184,8 +204,8 @@ class _record extends \IPS\Content\Controller
'mainEntityOfPage' => (string) $record->url(),
'name' => $record->_title,
'headline' => $record->_title,
'text' => strip_tags( $record->truncated() ),
'articleBody' => strip_tags( $record->truncated() ),
'text' => $jsonLdText,
'articleBody' => $jsonLdText,
'dateCreated' => \IPS\DateTime::ts( $record->record_saved )->format( \IPS\DateTime::ISO8601 ),
'datePublished' => \IPS\DateTime::ts( $record->record_publish_date ?: $record->record_saved )->format( \IPS\DateTime::ISO8601 ),
'dateModified' => \IPS\DateTime::ts( $record->record_edit_time ?: ( $record->record_publish_date ?: $record->record_saved ) )->format( \IPS\DateTime::ISO8601 ),
@@ -193,16 +213,15 @@ class _record extends \IPS\Content\Controller
'pageEnd' => $record->commentPageCount(),
'author' => array(
'@type' => 'Person',
'name' => \IPS\Member::load( $record->member_id )->name,
'image' => \IPS\Member::load( $record->member_id )->get_photo()
'name' => (string) \IPS\Member::load( $record->member_id )->name,
'image' => (string) \IPS\Member::load( $record->member_id )->get_photo()
),
'publisher' => array(
'@type' => 'Organization',
'name' => \IPS\Member::load( $record->member_id )->name,
'image' => \IPS\Member::load( $record->member_id )->get_photo(),
'logo' => array(
'@type' => 'ImageObject',
'url' => \IPS\Member::load( $record->member_id )->get_photo(),
'@id' => \IPS\Settings::i()->base_url . '#organization',
'member' => array(
'@type' => "Person",
'name' => \IPS\Member::load( $record->member_id )->name,
'image' => (string) \IPS\Member::load( $record->member_id )->get_photo(),
)
),
'interactionStatistic' => array(
@@ -223,22 +242,35 @@ class _record extends \IPS\Content\Controller
if( $record->member_id )
{
\IPS\Output::i()->jsonLd['article']['author']['url'] = (string) \IPS\Member::load( $record->member_id )->url();
\IPS\Output::i()->jsonLd['article']['publisher']['url'] = (string) \IPS\Member::load( $record->member_id )->url();
\IPS\Output::i()->jsonLd['article']['publisher']['member']['url'] = (string) \IPS\Member::load( $record->member_id )->url();
}
$logo = NULL;
if( \IPS\Theme::i()->logo['front'] )
{
try
{
$logo = \IPS\File::get( 'core_Theme', \IPS\Theme::i()->logo['front']['url'] )->url;
}
/* File doesn't exist */
catch ( \RuntimeException $e ){}
catch ( \DomainException $e ){}
}
\IPS\Output::i()->jsonLd['article']['publisher']['logo'] = array(
'@type' => 'ImageObject',
'url' => $logo ? (string) $logo : (string) \IPS\Member::load( $record->member_id )->get_photo(),
);
/* Image is required */
if( $record->record_image )
{
try
{
$imageObj = \IPS\File::get( 'cms_Records', $record->record_image );
$imageDims = $imageObj->getImageDimensions();
\IPS\Output::i()->jsonLd['article']['image'] = array(
'@type' => 'ImageObject',
'url' => (string) $imageObj->url,
'width' => $imageDims[0],
'height' => $imageDims[1]
'url' => (string) $imageObj->url
);
}
/* File doesn't exist */
@@ -257,26 +289,7 @@ class _record extends \IPS\Content\Controller
);
}
if( $record->averageReviewRating() )
{
\IPS\Output::i()->jsonLd['article']['aggregateRating'] = array(
'@type' => 'AggregateRating',
'ratingValue' => $record->averageReviewRating(),
'reviewCount' => $record->record_reviews,
'bestRating' => \IPS\Settings::i()->reviews_rating_out_of
);
}
elseif( $record->container()->allow_rating AND $record->averageRating() AND $record->numberOfRatings() )
{
\IPS\Output::i()->jsonLd['article']['aggregateRating'] = array(
'@type' => 'AggregateRating',
'ratingValue' => $record->averageRating(),
'ratingCount' => $record->numberOfRatings(),
'bestRating' => \IPS\Settings::i()->reviews_rating_out_of
);
}
if( $record::database()->options['reviews'] )
if( $record::database()->options['reviews'] or $record->container()->allow_rating )
{
\IPS\Output::i()->jsonLd['article']['interactionStatistic'][] = array(
'@type' => 'InteractionCounter',
@@ -296,12 +309,12 @@ class _record extends \IPS\Content\Controller
}
\IPS\Output::i()->contextualSearchOptions = array();
\IPS\Output::i()->contextualSearchOptions[ \IPS\Member::loggedIn()->language()->addToStack( 'search_contextual_item', FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( $record::$title ) ) ) ) ] = array( 'type' => mb_strtolower( str_replace( '\\', '_', mb_substr( get_class( $record ), 4 ) ) ), 'item' => $record->_id );
\IPS\Output::i()->contextualSearchOptions[ \IPS\Member::loggedIn()->language()->addToStack( 'search_contextual_item', FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( $record::$title ) ) ) ) ] = array( 'type' => mb_strtolower( str_replace( '\\', '_', mb_substr( \get_class( $record ), 4 ) ) ), 'item' => $record->_id );
try
{
$container = $record->container();
\IPS\Output::i()->contextualSearchOptions[ \IPS\Member::loggedIn()->language()->addToStack( 'search_contextual_item_categories' ) ] = array( 'type' => mb_strtolower( str_replace( '\\', '_', mb_substr( get_class( $record ), 4 ) ) ), 'nodes' => $container->_id );
\IPS\Output::i()->contextualSearchOptions[ \IPS\Member::loggedIn()->language()->addToStack( 'search_contextual_item_categories' ) ] = array( 'type' => mb_strtolower( str_replace( '\\', '_', mb_substr( \get_class( $record ), 4 ) ) ), 'nodes' => $container->_id );
}
catch ( \BadMethodCallException $e ) { }
@@ -412,14 +425,16 @@ class _record extends \IPS\Content\Controller
);
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'system/diff.css', 'core', 'admin' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'codemirror/diff_match_patch.js', 'core', 'interface' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'codemirror/diff_match_patch.js', 'core', 'interface' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('front_records.js', 'cms' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'codemirror/codemirror.js', 'core', 'interface' ) );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'codemirror/codemirror.css', 'core', 'interface' ) );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'records/record.css', 'cms', 'front' ) );
/* Output */
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( $table ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( $table ), 200, 'text/html' );
}
else
{
@@ -529,12 +544,27 @@ class _record extends \IPS\Content\Controller
$conflicts = array();
$form = new \IPS\Helpers\Form( 'form', 'content_revision_restore' );
/* Add a "cancel" button that will take you back to the previous page */
array_unshift( $form->actionButtons, \IPS\Theme::i()->getTemplate( 'forms', 'core', 'global' )->button( 'cancel', 'link', $record->url()->setQueryString( array( 'do' => 'revisions', 'd' => $record::$customDatabaseId ) ), 'ipsButton ipsButton_link', array( 'tabindex' => '3', 'accesskey' => 'c' ) ) );
/* Build up our data set */
$conflicts = $revision->getDiffHtmlTables( $record::$customDatabaseId, $record, true );
foreach( $conflicts as $conflict )
/* If there is only one change, then clicking restore naturally means to revert that single change, so we don't need a form */
if( \count( $conflicts ) === 1 )
{
$form->add( new \IPS\Helpers\Form\Radio( 'conflict_' . $conflict['field']->id, 'no', false, array( 'options' => array( 'old' => '', 'new' => '' ) ) ) );
foreach( $conflicts as $conflict )
{
$form->hiddenValues[ 'conflict_' . $conflict['field']->id ] = 'old';
}
}
/* Otherwise if multiple fields have changes to compare, let the admin decide what to do */
else
{
foreach( $conflicts as $conflict )
{
$form->add( new \IPS\Helpers\Form\Radio( 'conflict_' . $conflict['field']->id, 'no', false, array( 'options' => array( 'old' => '', 'new' => '' ) ) ) );
}
}
if ( $values = $form->values() )
@@ -553,7 +583,7 @@ class _record extends \IPS\Content\Controller
$record->save();
$revision->delete();
\IPS\Output::i()->redirect( $record->url('revisions') );
\IPS\Output::i()->redirect( $record->url(), 'content_revision_restored' );
}
}
@@ -573,7 +603,8 @@ class _record extends \IPS\Content\Controller
\IPS\Output::i()->title = $title;
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'system/diff.css', 'core', 'admin' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'codemirror/diff_match_patch.js', 'core', 'interface' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'codemirror/diff_match_patch.js', 'core', 'interface' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('front_records.js', 'cms' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'codemirror/codemirror.js', 'core', 'interface' ) );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'codemirror/codemirror.css', 'core', 'interface' ) );
@@ -633,8 +664,8 @@ class _record extends \IPS\Content\Controller
$hasModOptions = FALSE;
if ( $recordClass::modPermission( 'lock', NULL, $category ) or
$recordClass::modPermission( 'pin', NULL, $category ) or
$recordClass::modPermission( 'hide', NULL, $category ) or
$recordClass::modPermission( 'pin', NULL, $category ) or
$record->canHide() or
$recordClass::modPermission( 'feature', NULL, $category ) or
$fieldsClass::fixedFieldFormShow( 'record_allow_comments' ) or
$fieldsClass::fixedFieldFormShow( 'record_expiry_date' ) or
@@ -669,7 +700,7 @@ class _record extends \IPS\Content\Controller
\IPS\Output::i()->allowDefaultWidgets = FALSE;
\IPS\Output::i()->sidebar['enabled'] = FALSE;
\IPS\cms\Pages\Page::$currentPage->getWidgets();
\IPS\cms\Databases\Dispatcher::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\cms\Theme::i(), 'getTemplate' ), array( $database->template_form, 'cms', 'database' ) ), 'recordForm' ), NULL, $category, $database, \IPS\cms\Pages\Page::$currentPage, $title, $hasModOptions );
\IPS\cms\Databases\Dispatcher::i()->output = $form->customTemplate( array( \IPS\cms\Theme::i()->getTemplate( $database->template_form, 'cms', 'database' ), 'recordForm' ), NULL, $category, $database, \IPS\cms\Pages\Page::$currentPage, $title, $hasModOptions );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( $title );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'records/form.css', 'cms', 'front' ) );
@@ -690,7 +721,7 @@ class _record extends \IPS\Content\Controller
}
/**
* Mark Topic Read
* Mark Database Record Read
*
* @return void
*/
@@ -889,16 +920,4 @@ class _record extends \IPS\Content\Controller
\IPS\Output::i()->error( 'node_error', '2T252/F', 403, '' );
}
}
/**
* Moderate
*
* @return void
*/
protected function moderate()
{
parent::moderate();
\IPS\cms\Databases\Dispatcher::i()->output = \IPS\Output::i()->output;
}
}