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

+97 -33
View File
@@ -443,9 +443,8 @@ class _Application extends \IPS\Node\Model
{
$update = array();
if( $this->update_version )
if( ( $versions = json_decode( $this->update_version, TRUE ) ) AND is_iterable( $versions ) )
{
$versions = json_decode( $this->update_version, TRUE );
if ( \is_array( $versions ) and !isset( $versions[0] ) and isset( $versions['longversion'] ) )
{
$versions = array( $versions );
@@ -810,7 +809,7 @@ EOF;
{
$classes[ $name ] = new $classname( $checkAccess === TRUE ? \IPS\Member::loggedIn() : ( $checkAccess === FALSE ? NULL : $checkAccess ) );
}
catch( \RuntimeException $e ){}
catch( \RuntimeException | \OutOfRangeException $e ){}
}
}
}
@@ -1019,7 +1018,7 @@ EOF;
);
/* Upgrade */
if( !$this->protected AND !\IPS\DEMO_MODE AND $this->marketplace_id === NULL AND \IPS\IPS::canManageResources() )
if( !$this->protected AND !\IPS\DEMO_MODE AND $this->marketplace_id === NULL AND \IPS\IPS::canManageResources() AND \IPS\IPS::checkThirdParty() )
{
$buttons['upgrade'] = array(
'icon' => 'upload',
@@ -1084,6 +1083,15 @@ EOF;
'link' => \IPS\Http\Url::internal( "app=core&module=applications&controller=developer&appKey={$this->_id}" ),
);
}
if( !\IPS\IN_DEV ) {
$buttons['export'] = array(
'icon' => 'download',
'title' => 'download',
'link' => \IPS\Http\Url::internal("app=core&module=applications&controller=applications&appKey={$this->_id}&do=downloadMafia")
);
}
return $buttons;
}
@@ -1100,6 +1108,7 @@ EOF;
{
return TRUE;
}
return $this->enabled and ( !\in_array( $this->directory, \IPS\IPS::$ipsApps ) or $this->version == \IPS\Application::load('core')->version );
}
@@ -1174,7 +1183,7 @@ EOF;
*/
public function get__disabledMessage()
{
if ( $this->_locked and $this->directory != 'core' )
if ( $this->_locked and $this->directory != 'core' AND \in_array( $this->directory, \IPS\IPS::$ipsApps ) )
{
return \IPS\Member::loggedIn()->language()->addToStack('app_force_disabled');
}
@@ -1204,16 +1213,6 @@ EOF;
}
}
/**
* Return an array of specific links to add to the sitemap
*
* @return array
*/
public function sitemapLinks()
{
return array();
}
/**
* Get the authors website
*
@@ -1235,6 +1234,11 @@ EOF;
*/
public function get__badge()
{
if ( \IPS\CIC AND \IPS\IPS::isManaged() AND \in_array( $this->directory, \IPS\IPS::$ipsApps ) )
{
return NULL;
}
if ( $availableUpgrade = $this->availableUpgrade( TRUE ) )
{
return array(
@@ -2689,13 +2693,11 @@ EOF;
{
if( file_exists( $this->getApplicationPath() . "/data/widgets.json" ) )
{
$currentWidgets = iterator_to_array( \IPS\Db::i()->select( '`key`', 'core_widgets', array( 'app=?', $this->directory ) ) );
\IPS\Db::i()->delete( 'core_widgets', array( 'app=?', $this->directory ) );
$inserts = array();
foreach ( json_decode( file_get_contents( $this->getApplicationPath() . "/data/widgets.json" ), TRUE ) as $key => $json )
{
if ( ! \in_array( $key, $currentWidgets ) )
{
$inserts[] = array(
'app' => $this->directory,
'key' => $key,
@@ -2705,8 +2707,7 @@ EOF;
'allow_reuse' => ( isset( $json['allow_reuse'] ) ? $json['allow_reuse'] : 0 ),
'menu_style' => ( isset( $json['menu_style'] ) ? $json['menu_style'] : 'menu' ),
'embeddable' => ( isset( $json['embeddable'] ) ? $json['embeddable'] : 0 ),
);
}
);
}
if( \count( $inserts ) )
@@ -3472,7 +3473,11 @@ EOF;
{
if ( $data = @json_decode( \file_get_contents( \IPS\Application::load( $appKey )->getApplicationPath() . "/setup/upg_{$versionId}/whatsnew.json" ), TRUE ) )
{
\IPS\Db::i()->insert( 'core_members_features', $data );
try
{
\IPS\Db::i()->insert( 'core_members_features', $data );
}
catch ( \IPS\Db\Exception $e) {}
}
}
}
@@ -4144,6 +4149,12 @@ EOF;
/* Strip the params tag */
$html = str_replace( $params[0], '', $html );
/* Enforce \n line endings */
if( mb_strtolower( mb_substr( PHP_OS, 0, 3 ) ) === 'win' )
{
$html = str_replace( "\r\n", "\n", $html );
}
/* Figure out some details */
$extension = mb_substr( $file->getFilename(), mb_strrpos( $file->getFilename(), '.' ) + 1 );
@@ -4631,7 +4642,7 @@ EOF;
}
/* If we are in the AdminCP, and we have permission to manage applications, then we have access */
if( \IPS\Dispatcher::hasInstance() AND \IPS\Dispatcher::i()->controllerLocation === 'admin' AND \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'applications', 'app_manage' ) )
if( \IPS\Dispatcher::hasInstance() AND \IPS\Dispatcher::i()->controllerLocation === 'admin' AND ( !$memberOrGroup AND \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'applications', 'app_manage' ) ) )
{
return TRUE;
}
@@ -4780,12 +4791,18 @@ EOF;
\IPS\Db::i()->delete( 'core_sys_conf_settings', array( 'conf_app=?', $this->directory ) );
\IPS\Db::i()->delete( 'core_queue', array( 'app=?', $this->directory ) );
\IPS\Db::i()->delete( 'core_follow', array( 'follow_app=?', $this->directory ) );
\IPS\Db::i()->delete( 'core_follow_count_cache', array( "class LIKE CONCAT( ?, '%' )", "IPS\\\\{$this->directory}" ) );
\IPS\Db::i()->delete( 'core_view_updates', array( "classname LIKE CONCAT( ?, '%' )", "IPS\\\\{$this->directory}" ) );
\IPS\Db::i()->delete( 'core_moderator_logs', array( 'appcomponent=?', $this->directory ) );
\IPS\Db::i()->delete( 'core_member_history', array( 'log_app=?', $this->directory ) );
\IPS\Db::i()->delete( 'core_acp_notifications', array( 'app=?', $this->directory ) );
\IPS\Db::i()->delete( 'core_solved_index', array( 'app=?', $this->directory ) );
\IPS\Db::i()->delete( 'core_notifications', array( 'notification_app=?', $this->directory ) );
$rulesToDelete = iterator_to_array( \IPS\Db::i()->select( 'id', 'core_achievements_rules', [ "action LIKE CONCAT( ?, '_%' )", $this->directory ] ) );
\IPS\Db::i()->delete( 'core_achievements_rules', \IPS\Db::i()->in( 'id', $rulesToDelete ) );
\IPS\Db::i()->delete( 'core_achievements_log_milestones', \IPS\Db::i()->in( 'milestone_rule', $rulesToDelete ) );
foreach( $this->extensions( 'core', 'AdminNotifications', FALSE ) AS $adminNotificationExtension )
{
$exploded = explode( '\\', $adminNotificationExtension );
@@ -5139,15 +5156,8 @@ EOF;
\IPS\Settings::i()->clearCache();
/* Remove the files and folders, if possible (if not IN_DEV and not in DEMO_MODE) */
if ( \IPS\CIC2 )
{
if ( !\in_array( $this->directory, \IPS\IPS::$ipsApps ) )
{
\IPS\Cicloud\folderDelete( "applications/{$this->directory}" );
}
}
elseif ( !\IPS\IN_DEV AND !\IPS\DEMO_MODE AND file_exists( \IPS\ROOT_PATH . '/applications/' . $this->directory ) )
/* Remove the files and folders, if possible (if not IN_DEV and not in DEMO_MODE and not on platform) */
if ( !\IPS\CIC2 AND !\IPS\IN_DEV AND !\IPS\DEMO_MODE AND file_exists( \IPS\ROOT_PATH . '/applications/' . $this->directory ) )
{
try
{
@@ -5396,4 +5406,58 @@ EOF;
return \IPS\SITE_FILES_PATH;
}
}
}
/**
* Returns a list of all existing webhooks and their payload in this app.
*
* @return array
*/
public function getWebhooks() : array
{
// Fetch all the content classes
$classes = [];
$hooks = [];
foreach ( $this->extensions( 'core', 'ContentRouter' ) as $router )
{
foreach ( $router->classes as $class )
{
$classes[] = $class;
if ( isset( $class::$commentClass ) )
{
$commentClass = $class::$commentClass;
$classes[] = $commentClass;
}
if ( isset( $class::$reviewClass ) )
{
$reviewClass = $class::$reviewClass;
$classes[] = $reviewClass;
}
}
}
foreach( $classes as $class )
{
$key = str_replace( '\\', '', \substr( $class, 3 ) );
$hooks[$key .'_create'] = $class;
$hooks[$key .'_delete'] = $class;
\IPS\Member::loggedIn()->language()->words[ 'webhook_' . $key .'_create' ] = \IPS\Member::loggedIn()->language()->addToStack('webhook_contentitem_created', FALSE, ['sprintf' => [ $class::_indefiniteArticle() ]]);
\IPS\Member::loggedIn()->language()->words[ 'webhook_' . $key .'_delete' ] = \IPS\Member::loggedIn()->language()->addToStack('webhook_contentitem_deleted', FALSE, ['sprintf' => [ $class::_indefiniteArticle() ]]);
}
return $hooks;
}
/**
* Do Member Check
*
* @return \IPS\Http\Url|NULL
*/
public function doMemberCheck(): ?\IPS\Http\Url
{
return NULL;
}
}