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

+150 -10
View File
@@ -511,6 +511,38 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
throw new \BadMethodCallException;
}
/**
* @brief Cached AdminCP urls
*/
protected $_acpUrls = array();
/**
* @brief The class of the ACP \IPS\Node\Controller that manages this node type
*/
protected static $acpController = NULL;
/**
* Get the URL of the AdminCP page for this node
*
* @param string|NULL $do The "do" query parameter of the url (e.g. 'form', 'permissions', etc).
*
* @return \IPS\Http\Url | NULL
*/
public function acpUrl( $do="form" )
{
if ( !isset( $this->acpUrls[$do] ) AND static::$acpController !== NULL )
{
/* Does the method exist? */
if ( method_exists( static::$acpController, $do ) )
{
$bits = explode( "\\", static::$acpController );
$acpUrlBase = "app={$bits[1]}&module={$bits[4]}&controller={$bits[5]}";
$this->_acpUrls[$do] = \IPS\Http\Url::internal( $acpUrlBase )->setQueryString( array( 'do' => $do, 'id' => $this->_id ) );
}
}
return $this->_acpUrls[$do] ?? NULL;
}
/**
* Columns needed to query for search result / stream view
*
@@ -738,7 +770,7 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
{
if ( static::$titleLangPrefix and static::$descriptionLangSuffix )
{
return \IPS\Member::loggedIn()->language()->addToStack( static::$titleLangPrefix . $this->id . static::$descriptionLangSuffix, FALSE, array( 'striptags' => TRUE, 'escape' => TRUE ) );
return \IPS\Member::loggedIn()->language()->addToStack( static::$titleLangPrefix . $this->id . static::$descriptionLangSuffix, FALSE, array( 'striptags' => TRUE, 'escape' => TRUE, 'removeNewlines' => TRUE ) );
}
return NULL;
}
@@ -1610,24 +1642,39 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
* @brief Constant allow anonymous comments
*/
const ANON_COMMENTS = 2;
/**
* [Node] Does the currently logged in user have permission to post anonymously in this node?
*
* @return bool
* @param int $where What are we checking, 0 => means don't check it, 2 means comments only
* @param \IPS\Member|NULL $member The member posting anonymously or NULL for logged in member
* @return bool
*/
public function canPostAnonymously( $where = 0 )
public function canPostAnonymously( $where = 0, \IPS\Member $member = NULL ): bool
{
if ( ! isset( static::$contentItemClass ) or ! \in_array( 'IPS\Content\Anonymous', class_implements( static::$contentItemClass ) ) )
{
return FALSE;
return FALSE;
}
if( ! \IPS\Member::loggedIn()->member_id or ! \IPS\Member::loggedIn()->group['gbw_can_post_anonymously'] )
$member = $member ?: \IPS\Member::loggedIn();
if( ! $member->member_id or ! $member->group['gbw_can_post_anonymously'] )
{
return FALSE;
}
return $this->isAnonymousContentSupported( $where );
}
/**
* Does the current node support anonymous content?
*
* @param int $where What are we checking, 0 => means don't check it, 2 means comments only
* @return bool
*/
public function isAnonymousContentSupported( int $where = 0 ) : bool
{
/* 1 means both items and comments */
if ( $this->allow_anonymous === 1 )
{
@@ -1639,13 +1686,12 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
{
return TRUE;
}
/* 2 means comments only */
if ( $where === static::ANON_COMMENTS and $this->allow_anonymous === 2 )
{
return TRUE;
}
return FALSE;
}
@@ -2206,6 +2252,16 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
return $this->can( 'view', $member );
}
/**
* Return if this node has custom permissions
*
* @return null|array
*/
public static function customPermissionNodes()
{
return NULL;
}
/**
* @brief Cached permission checks
*/
@@ -3472,7 +3528,7 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
protected static $deleteOrMoveQueue = NULL;
/**
* Is this node currently queued for deleting or moving content?
* Is this node currently queued for deleting or moving content OR is it the target of content queued to be moved from another node?
*
* @return bool
*/
@@ -3500,6 +3556,15 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
{
$this->queued = TRUE;
}
elseif ( isset( $data['moveTo'] ) )
{
$moveToClass = $data['moveToClass'] ?? \get_class( $this );
if ( $moveToClass === \get_class( $this ) AND $data['moveTo'] == $this->_id )
{
$this->queued = TRUE;
}
}
}
}
@@ -3687,6 +3752,11 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
{
$return['permissions'] = \in_array( 'IPS\Node\Permissions', class_implements( \get_class( $this ) ) ) ? $this->permissions() : NULL;
}
if ( \IPS\IPS::classUsesTrait( \get_called_class(), 'IPS\Content\ClubContainer' ) AND $this->club() )
{
$return['public'] = ( $this->isPublic() ) ? 1 : 0;
}
return $return;
}
@@ -3710,4 +3780,74 @@ abstract class _Model extends \IPS\Patterns\ActiveRecord
{
return static::$nodeTitle . '_sg';
}
/**
* @brief Field cache for getDataLayerProperties
*/
protected $_dataLayerProperties = array();
/**
* Get the properties that can be added to the datalayer for this key
*
* @return array
*/
public function getDataLayerProperties()
{
if ( empty( $this->_dataLayerProperties ) )
{
try
{
$url = (string) $this->url();
}
catch ( \BadMethodCallException $e )
{
$url = null;
}
/* Try to figure out the Node's app, its lang key will be the area */
$area = "System";
if ( static::$permApp )
{
$app = static::$permApp;
}
elseif ( !empty( static::$restrictions['app'] ) )
{
$app = static::$restrictions['app'];
}
else
{
$class = \get_called_class();
$matches = array();
preg_match( '/IPS\\\\([a-z]+)\\\\/', $class, $matches );
$app = $matches[1] ?? null;
}
/* If we got a valid app (directory) name, try its language key */
if ( $app )
{
$area = \IPS\Lang::load( \IPS\Lang::defaultLanguage() )->addToStack( "__app_$app" );
}
/* Get the path */
$type = static::$nodeTitle ?? 'container';
$path = [
array( 'type' => $type, 'id' => $this->_id, 'name' => $this->_title )
];
foreach ( $this->parents() as $parent )
{
$path[] = array( 'type' => $parent::$nodeTitle ?? 'container', 'id' => $parent->_id, 'name' => $parent->_title );
}
$this->_dataLayerProperties = array(
'content_area' => $area,
'content_container_id' => $this->_id,
'content_container_name' => $this->_title,
'content_container_type' => $type,
'content_container_url' => $url,
'content_container_path' => array_reverse( $path ),
);
}
return $this->_dataLayerProperties;
}
}