Invision Power Services, Inc. * @copyright (c) Invision Power Services, Inc. * @license https://www.invisioncommunity.com/legal/standards/ * @package Invision Community * @since 31 Jan 2024 */ namespace IPS\core\modules\admin\developer; use IPS\Developer\Controller; use IPS\Helpers\Form; use IPS\Helpers\Form\Text; use IPS\Helpers\Tree\Tree; use IPS\Http\Url; use IPS\Member; use IPS\Output; use IPS\Request; use IPS\Session; use IPS\Theme; use function defined; use const IPS\ROOT_PATH; /* To prevent PHP errors (extending class does not exist) revealing path */ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) ) { header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' ); exit; } /** * acprestrictions */ class acprestrictions extends Controller { /** * @var bool */ public static bool $csrfProtected = true; /** * @var array|null */ protected ?array $modules = null; /** * @var array|null */ protected ?array $restrictions = null; /** * ... * * @return void */ protected function manage() : void { $this->modules = $this->_getModules(); $this->url = Url::internal( "app=core&module=developer&controller=acprestrictions&appKey={$this->application->directory}" ); $this->restrictions = $this->_getJson( ROOT_PATH . "/applications/{$this->application->directory}/data/acprestrictions.json" ); $appKey = $this->application->directory; /* Display the table */ $tree = new Tree( $this->url, 'dev_acprestrictions', array( $this, 'restrictionsGetRoots' ), array( $this, 'restrictionsGetRow' ), function ( $k ) { if ( mb_substr( $k, 0, 1 ) === 'M' ) { return NULL; } else { return 'M' . mb_substr( $k, 1, mb_strpos( $k, '-' ) - 1 ); } }, array( $this, 'restrictionsGetchildren' ), NULL, FALSE, TRUE, TRUE ); Output::i()->output = (string) $tree; } /** * @return void */ protected function reorder() : void { Session::i()->csrfCheck(); $this->restrictions = $this->_getJson( ROOT_PATH . "/applications/{$this->application->directory}/data/acprestrictions.json" ); /* Figure out the items we are reordering, we would only be reordering a single group */ $newOrder = array(); $position = 1; foreach( Request::i()->ajax_order as $i => $parent ) { if( strpos( $i, '~' ) !== FALSE ) { if( !isset( $newOrder[ $parent ] ) ) { $newOrder[ $parent ] = array(); } $newOrder[ $parent ][ $i ] = $position++; } } foreach( $newOrder as $groupKey => $order ) { if( isset( Request::i()->ajax_order[ $groupKey ] ) ) { $moduleKey = Request::i()->ajax_order[ $groupKey ]; /* Sort */ uasort( $this->restrictions[ $moduleKey ][ $groupKey ], function( $a, $b ) use ( $order ) { return ( isset( $order[ str_replace( '_', '~', $a ) ] ) ? $order[ str_replace( '_', '~', $a ) ] : 0 ) - ( isset( $order[ str_replace( '_', '~', $b ) ] ) ? $order[ str_replace( '_', '~', $b ) ] : 0 ); }); } } /* Write */ $this->_writeJson( ROOT_PATH . "/applications/{$this->application->directory}/data/acprestrictions.json", $this->restrictions ); } /** * Restrictions: Get Root Rows * * @return array */ public function restrictionsGetRoots() : array { $rows = array(); if( !empty( $this->modules['admin'] ) ) { foreach ( $this->modules['admin'] as $k => $module ) { if ( empty( $module['protected'] ) ) { $rows[ $k ] = $this->_restrictionsModuleRow( $this->url, $k, $this->restrictions, FALSE ); } } } return $rows; } /** * Restrictions: Get Individual Row * * @param string $k ID * @param bool $root Is root row? * @return string */ public function restrictionsGetRow( string $k, bool $root ) : string { if ( mb_substr( $k, 0, 1 ) === 'M' ) { return $this->_restrictionsModuleRow( $this->url, mb_substr( $k, 1 ), $this->restrictions, $root ); } else { $moduleKey = mb_substr( $k, 1, mb_strpos( $k, '-' ) - 1 ); $groupKey = mb_substr( $k, mb_strpos( $k, '-' ) + 1 ); return $this->_restrictionsGroupRow( $this->url, $groupKey, $moduleKey, $this->restrictions[ $moduleKey ][ $groupKey ], $root ); } } /** * Restrictions: Get Child Rows * * @param string $k ID * @return array */ public function restrictionsGetChildren( string $k ) : array { $rows = array(); if ( mb_substr( $k, 0, 1 ) === 'M' ) { $k = mb_substr( $k, 1 ); foreach ( $this->restrictions[ $k ] as $groupKey => $r ) { $rows[ $groupKey ] = $this->_restrictionsGroupRow( $this->url, $groupKey, $k, $r, FALSE ); } } else { $moduleKey = mb_substr( $k, 1, mb_strpos( $k, '-' ) - 1 ); $groupKey = mb_substr( $k, mb_strpos( $k, '-' ) + 1 ); $pos = 0; foreach ( $this->restrictions[ $moduleKey ][ $groupKey ] as $rKey ) { $lang = "r__{$rKey}"; $rows[ str_replace( '_', '~', $rKey ) ] = Theme::i()->getTemplate( 'trees' )->row( $this->url, $rKey, Member::loggedIn()->language()->addToStack( $lang ), FALSE, array( 'delete' => array( 'icon' => 'times-circle', 'title' => 'delete', 'link' => Url::internal( "app=core&module=developer&controller=acprestrictions&appKey={$this->application->directory}&do=restrictionRowDelete&module_key={$moduleKey}&group={$groupKey}&id={$rKey}" ), 'data' => array( 'delete' => '' ) ) ), $rKey, NULL, ++$pos ); } } return $rows; } /** * Get Module Row * * @param string|Url $url URL * @param string $k Key * @param array $restrictions Restrictions JSON * @param bool $root As root? * @return string */ protected function _restrictionsModuleRow( string|Url $url, string $k, array $restrictions, bool $root ) : string { return Theme::i()->getTemplate( 'trees' )->row( $url, 'M'.$k, $k, isset( $restrictions[ $k ] ), array( 'add' => array( 'icon' => 'plus-circle', 'title' => 'acprestrictions_addgroup', 'link' => Url::internal( "app=core&module=developer&controller=acprestrictions&appKey={$this->application->directory}&do=restrictionGroupForm&module_key={$k}&id=0" ), 'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => Member::loggedIn()->language()->addToStack('acprestrictions_addgroup') ) ) ), '', NULL, NULL, $root ); } /** * Get Group Row * * @param string|Url $url URL * @param string $groupKey Key * @param string $moduleKey Module Key * @param array $r Rows in this group * @param bool $root As root? * @return string */ protected function _restrictionsGroupRow( string|Url $url, string $groupKey, string $moduleKey, array $r, bool $root ) : string { $lang = "r__{$groupKey}"; return Theme::i()->getTemplate( 'trees' )->row( $url, "G{$moduleKey}-{$groupKey}", Member::loggedIn()->language()->addToStack( $lang ), !empty( $r ), array( 'add' => array( 'icon' => 'plus-circle', 'title' => 'acprestrictions_addrow', 'link' => Url::internal( "app=core&module=developer&controller=acprestrictions&appKey={$this->application->directory}&do=restrictionRowForm&module_key={$moduleKey}&group={$groupKey}" ), 'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => Member::loggedIn()->language()->addToStack('acprestrictions_addrow') ) ), 'edit' => array( 'icon' => 'pencil', 'title' => 'edit', 'link' => Url::internal( "app=core&module=developer&controller=acprestrictions&appKey={$this->application->directory}&do=restrictionGroupForm&module_key={$moduleKey}&id={$groupKey}" ), 'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => Member::loggedIn()->language()->addToStack('edit') ), 'hotkey'=> 'e' ), 'delete'=> array( 'icon' => 'times-circle', 'title' => 'delete', 'link' => Url::internal( "app=core&module=developer&controller=acprestrictions&appKey={$this->application->directory}&do=restrictionGroupDelete&module_key={$moduleKey}&id={$groupKey}" ), 'data' => array( 'delete' => '' ) ) ), '', NULL, NULL, $root ); } /** * Restriction Group Form * * @return void */ public function restrictionGroupForm() : void { /* Get restriction data */ $restrictions = $this->_getJson( ROOT_PATH . "/applications/{$this->application->directory}/data/acprestrictions.json" ); /* Load module */ $module = $this->_loadModule(); /* Do we have a default value? */ $current = NULL; if ( Request::i()->id and isset( $restrictions[ $module->key ][ Request::i()->id ] ) ) { $current = Request::i()->id; } /* Build Form */ $form = new Form(); $form->add( new Text( 'acprestrictions_groupkey', $current ?: '', TRUE ) ); /* Handle submissions */ if ( $values = $form->values() ) { $rows = array(); if ( $current !== NULL ) { $rows = $restrictions[ $module->key ][ $current ]; unset( $restrictions[ $module->key ][ $current ] ); } $restrictions[ $module->key ][ $values['acprestrictions_groupkey'] ] = $rows; $this->_writeJson( ROOT_PATH . "/applications/{$this->application->directory}/data/acprestrictions.json", $restrictions ); Output::i()->redirect( Url::internal( "app=core&module=developer&controller=acprestrictions&appKey={$this->application->directory}&root=M{$module->key}" ) ); } /* Display */ Output::i()->output = Theme::i()->getTemplate( 'global' )->block( 'acprestrictions_addgroup', $form, FALSE ); } /** * Delete Restriction Group * * @return void */ public function restrictionGroupDelete() : void { /* Make sure the user confirmed the deletion */ Request::i()->confirmedDelete(); $restrictions = $this->_getJson( ROOT_PATH . "/applications/{$this->application->directory}/data/acprestrictions.json" ); $module = $this->_loadModule(); if( isset( $restrictions[ $module->key ][ Request::i()->id ] ) ) { unset( $restrictions[ $module->key ][ Request::i()->id ] ); $this->_writeJson( ROOT_PATH . "/applications/{$this->application->directory}/data/acprestrictions.json", $restrictions ); } Output::i()->redirect( Url::internal( "app=core&module=developer&controller=acprestrictions&appKey={$this->application->directory}&root=M{$module->key}" ) ); } /** * Restriction Row Form * * @return void */ protected function restrictionRowForm() : void { $module = $this->_loadModule(); $group = Request::i()->group; $form = new Form(); $form->add( new Text( 'acprestrictions_rowkey', NULL, TRUE ) ); if ( $values = $form->values() ) { $restrictions = $this->_getJson( ROOT_PATH . "/applications/{$this->application->directory}/data/acprestrictions.json" ); $restrictions[ $module->key ][ $group ][ $values['acprestrictions_rowkey'] ] = $values['acprestrictions_rowkey']; $this->_writeJson( ROOT_PATH . "/applications/{$this->application->directory}/data/acprestrictions.json", $restrictions ); Output::i()->redirect( Url::internal( "app=core&module=developer&controller=acprestrictions&appKey={$this->application->directory}&root=G{$module->key}-{$group}" ) ); } Output::i()->output = Theme::i()->getTemplate( 'global' )->block( 'acprestrictions_addrow', $form, FALSE ); } /** * Delete Restriction Row * * @return void */ public function restrictionRowDelete() : void { /* Make sure the user confirmed the deletion */ Request::i()->confirmedDelete(); $restrictions = $this->_getJson( ROOT_PATH . "/applications/{$this->application->directory}/data/acprestrictions.json" ); $module = $this->_loadModule(); $group = Request::i()->group; $id = Request::i()->id; if( isset( $restrictions[ $module->key ][ $group ][ $id ] ) ) { unset( $restrictions[ $module->key ][ $group ][ $id ] ); $this->_writeJson( ROOT_PATH . "/applications/{$this->application->directory}/data/acprestrictions.json", $restrictions ); } Output::i()->redirect( Url::internal( "app=core&module=developer&controller=acprestrictions&appKey={$this->application->directory}&root=G{$module->key}-{$group}" ) ); } }