211 lines
4.5 KiB
PHP
211 lines
4.5 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @brief Revision
|
|
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
|
* @copyright (c) Invision Power Services, Inc.
|
|
* @license https://www.invisioncommunity.com/legal/standards/
|
|
* @package Invision Community
|
|
* @subpackage
|
|
* @since 6/25/2025
|
|
*/
|
|
|
|
namespace IPS\cms\Pages;
|
|
|
|
/* To prevent PHP errors (extending class does not exist) revealing path */
|
|
|
|
use IPS\Db;
|
|
use IPS\Lang;
|
|
use IPS\Member;
|
|
use IPS\Patterns\ActiveRecord;
|
|
use IPS\Widget\Area;
|
|
use UnderflowException;
|
|
use function count;
|
|
use function is_array;
|
|
|
|
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
|
{
|
|
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
|
exit;
|
|
}
|
|
|
|
class Revision extends ActiveRecord
|
|
{
|
|
/**
|
|
* @brief Database Table
|
|
*/
|
|
public static ?string $databaseTable = 'cms_page_revisions';
|
|
|
|
/**
|
|
* @brief Database Prefix
|
|
*/
|
|
public static string $databasePrefix = 'revision_';
|
|
|
|
/**
|
|
* @brief Multiton Store
|
|
*/
|
|
protected static array $multitons;
|
|
|
|
/**
|
|
* @return Page
|
|
*/
|
|
public function get_page() : Page
|
|
{
|
|
return Page::load( $this->page_id );
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function get_data() : array
|
|
{
|
|
return isset( $this->_data['data'] ) ? json_decode( $this->_data['data'], true ) : [];
|
|
}
|
|
|
|
/**
|
|
* @param mixed $val
|
|
* @return void
|
|
*/
|
|
public function set_data( mixed $val ) : void
|
|
{
|
|
$this->_data['data'] = ( is_array( $val ) and count( $val ) ) ? json_encode( $val ) : null;
|
|
}
|
|
|
|
/**
|
|
* @return Member
|
|
*/
|
|
public function author() : Member
|
|
{
|
|
return Member::load( $this->member_id );
|
|
}
|
|
|
|
/**
|
|
* Store a version of the page history
|
|
*
|
|
* @param Page $page
|
|
* @param bool $manualSave Whether this is being called manually (e.g. from finish editing)
|
|
* @return void
|
|
*/
|
|
public static function store( Page $page, bool $manualSave=false ) : void
|
|
{
|
|
$data = [
|
|
'settings' => [
|
|
'name' => Member::loggedIn()->language()->get( Page::$titleLangPrefix . $page->id ),
|
|
'js_css_ids' => $page->js_css_ids,
|
|
'wrapper_template' => $page->wrapper_template,
|
|
'theme' => $page->theme,
|
|
'template' => $page->template,
|
|
'ipb_wrapper' => $page->ipb_wrapper,
|
|
'default' => $page->default
|
|
],
|
|
'areas' => []
|
|
];
|
|
|
|
if( $page->type == 'html' )
|
|
{
|
|
$data['settings']['content'] = $page->content;
|
|
}
|
|
|
|
/* Now handle all the areas */
|
|
foreach( $page->getAreasFromDatabase() as $area )
|
|
{
|
|
$data['areas'][ $area->id ] = $area->toArray();
|
|
}
|
|
|
|
/* Get the latest revision; if nothing has changed, don't store it */
|
|
if( $previous = static::previousVersion( $page ) )
|
|
{
|
|
if( ! $manualSave and ( $previous->data === $data ) )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
$obj = new static;
|
|
$obj->page_id = $page->id;
|
|
$obj->data = $data;
|
|
$obj->manual_save = (int) $manualSave;
|
|
$obj->save();
|
|
}
|
|
|
|
/**
|
|
* Make this the latest version.
|
|
* If no version is specified, just use the latest
|
|
*
|
|
* @return void
|
|
*/
|
|
public function revert() : void
|
|
{
|
|
/* @var Page $page */
|
|
$page = $this->page;
|
|
|
|
/* First, store the current page as is */
|
|
static::store( $page );
|
|
|
|
/* Now loop through the page configuration and set all properties */
|
|
foreach( $this->data['settings'] as $k => $v )
|
|
{
|
|
$page->$k = $v;
|
|
if( $k == 'name' )
|
|
{
|
|
Lang::saveCustom( 'cms', Page::$titleLangPrefix . $page->id, $v );
|
|
}
|
|
}
|
|
$page->save();
|
|
|
|
/* Load the current areas, in case we need to remove one */
|
|
$currentAreas = $page->getAreasFromDatabase();
|
|
|
|
/* Now the areas */
|
|
$newAreas = [];
|
|
foreach( $this->data['areas'] as $id => $tree )
|
|
{
|
|
$newAreas[] = $id;
|
|
$area = new Area( $tree, $id );
|
|
$page->saveArea( $area, false );
|
|
}
|
|
|
|
/* Remove any areas that we no longer need */
|
|
foreach( $currentAreas as $area )
|
|
{
|
|
if( !in_array( $area->id, $newAreas ) )
|
|
{
|
|
Db::i()->delete( 'cms_page_widget_areas', [ 'area_area=? and area_page_id=?', $area->id, $page->id ] );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the previously saved version
|
|
*
|
|
* @param Page $page
|
|
* @return static|null
|
|
*/
|
|
public static function previousVersion( Page $page ) : static|null
|
|
{
|
|
try
|
|
{
|
|
$row = Db::i()->select( '*', static::$databaseTable, [ 'revision_page_id=?', $page->id ], 'revision_date desc', [ 0, 1 ] )->first();
|
|
return static::constructFromData( $row );
|
|
}
|
|
catch( UnderflowException ){}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Save Changed Columns
|
|
*
|
|
* @return void
|
|
*/
|
|
public function save() : void
|
|
{
|
|
if( $this->_new )
|
|
{
|
|
$this->member_id = Member::loggedIn()->member_id;
|
|
$this->date = time();
|
|
}
|
|
|
|
parent::save();
|
|
}
|
|
} |