Version 5.0.6
This commit is contained in:
1 parent
a3a4a9ccbd
commit
b89858b2ff
1214 files changed
+92828
-14859
No files matched your search
@@ -297,7 +297,7 @@ class Controller extends DispatcherController
|
||||
$this->_titleHtml,
|
||||
$this->_descriptionHtml,
|
||||
$node->canAdd(),
|
||||
( $node instanceof $nodeClass ),
|
||||
$this->_canBeRoot( $node ),
|
||||
$this->_getRowHtml( $node ) . $node->ui( 'rowHtml' ),
|
||||
isset( $node->_lockedLang ) ? $node->_lockedLang : null,
|
||||
isset( $class::$featureColumnName ),
|
||||
@@ -354,6 +354,17 @@ class Controller extends DispatcherController
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the node can be a root-level
|
||||
*
|
||||
* @param Model $node
|
||||
* @return bool
|
||||
*/
|
||||
public function _canBeRoot( Model $node ) : bool
|
||||
{
|
||||
return $node instanceof $this->nodeClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add/Edit Form
|
||||
*
|
||||
@@ -1198,7 +1209,7 @@ class Controller extends DispatcherController
|
||||
}
|
||||
catch ( OutOfRangeException $e ) { }
|
||||
|
||||
return Theme::i()->getTemplate( 'global', 'core', 'global' )->titleWithLink( $value, $groupLink, 'all_permissions', Member::loggedIn()->language()->addToStack( "all_permissions_group_hovertitle", FALSE, array( 'sprintf' => [ $value ] ) ) );
|
||||
return Theme::i()->getTemplate( 'global', 'core', 'global' )->titleWithLink( $value, $groupLink, 'all_permissions', Member::loggedIn()->language()->addToStack( "all_permissions_group_hovertitle", FALSE, array( 'htmlsprintf' => [ $value ] ) ) );
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @brief CustomBadge
|
||||
* @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 3/6/2025
|
||||
*/
|
||||
|
||||
namespace IPS\Node;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
|
||||
use IPS\core\CustomBadge as CustomBadgeClass;
|
||||
use IPS\Db;
|
||||
use IPS\Helpers\Form;
|
||||
use IPS\Helpers\Form\Color;
|
||||
use IPS\Helpers\Form\Icon;
|
||||
use IPS\Helpers\Form\Number;
|
||||
use IPS\Helpers\Form\Radio;
|
||||
use IPS\Helpers\Form\YesNo;
|
||||
use IPS\Output;
|
||||
use IPS\Theme;
|
||||
use UnderflowException;
|
||||
use function get_called_class;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
trait CustomBadge
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static array $customBadgeStore = array();
|
||||
|
||||
/**
|
||||
* Get the custom badge linked to this class
|
||||
*
|
||||
* @return CustomBadgeClass|null
|
||||
*/
|
||||
public function getRecordBadge() : CustomBadgeClass|null
|
||||
{
|
||||
$class = get_called_class();
|
||||
$idColumn = static::$databaseColumnId;
|
||||
|
||||
if( !isset( static::$customBadgeStore[ $class ][ $this->$idColumn ] ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$row = Db::i()->select( '*', 'core_custom_badges', [ 'class=? and active_record_id=?', $class, $this->$idColumn ] )->first();
|
||||
static::$customBadgeStore[ $class ][ $this->$idColumn ] = CustomBadgeClass::constructFromData( $row );
|
||||
}
|
||||
catch( UnderflowException )
|
||||
{
|
||||
static::$customBadgeStore[ $class ][ $this->$idColumn ] = false;
|
||||
}
|
||||
}
|
||||
|
||||
return static::$customBadgeStore[ $class ][ $this->$idColumn ] ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add elements to the form which are responsible for creating custom badges, and loads the JS and CSS that forms the interactive and grid-style UI
|
||||
*
|
||||
* @param Form $form
|
||||
* @param CustomBadgeClass|null $badge
|
||||
* @return void
|
||||
*/
|
||||
public function addBadgeFieldsToForm( Form $form, ?CustomBadgeClass $badge=null ) : void
|
||||
{
|
||||
$form->class .= " ipsBadgePicker--form";
|
||||
|
||||
$shapeToggles = ["custombadge_background", "custombadge_border"];
|
||||
$dynamicShapeToggles = [ "custombadge_sides", "custombadge_rotation" ];
|
||||
$form->add( new YesNo(
|
||||
"custombadge_use_custom",
|
||||
(bool) $badge,
|
||||
true,
|
||||
[
|
||||
'togglesOff' => static::$customBadgeToggles ?? [],
|
||||
'togglesOn' => [
|
||||
"{$form->id}_header_badge_preview",
|
||||
"custombadge_border",
|
||||
"custombadge_foreground",
|
||||
"custombadge_background",
|
||||
"custombadge_shape",
|
||||
"custombadge_icon",
|
||||
"custombadge_sides",
|
||||
"custombadge_rotation",
|
||||
"custombadge_number_overlay",
|
||||
"custombadge_icon_size",
|
||||
'preview'
|
||||
]
|
||||
]
|
||||
));
|
||||
|
||||
$form->addHeader( 'custombadge_preview' );
|
||||
|
||||
Output::i()->jsFiles = array_merge( Output::i()->jsFiles, Output::i()->js( 'admin_badgepreview.js', 'core', 'admin' ) );
|
||||
$form->addHtml( Theme::i()->getTemplate( 'achievements', 'core', 'admin' )->badgePreview( $badge ? $badge->raw : '' ) );
|
||||
|
||||
$form->add( new Radio( "custombadge_shape", $badge ? $badge->shape : 'circle', null, ['options' => [
|
||||
'square' => 'custombadge_square',
|
||||
'circle' => 'custombadge_circle',
|
||||
'ngon' => 'custombadge_n_gon',
|
||||
'star' => 'custombadge_star',
|
||||
'flower' => 'custombadge_flower',
|
||||
"no_shape" => "custombadge_no_shape",
|
||||
], 'toggles' => [
|
||||
'ngon' => [...$dynamicShapeToggles, ...$shapeToggles],
|
||||
'star' => [...$dynamicShapeToggles, ...$shapeToggles],
|
||||
'flower' => [...$dynamicShapeToggles, ...$shapeToggles],
|
||||
"square" => $shapeToggles,
|
||||
"circle" => $shapeToggles
|
||||
], 'rowClasses' => ['ipsFieldRow--badge-creator ipsFieldRow--badge-creator-shape']], null, null, null, "custombadge_shape") );
|
||||
|
||||
$form->add( new Icon( "custombadge_icon", ( $badge and $badge->icon ) ? [ $badge->icon ] : null, false, ['useSvgIcon' => true, 'rowClasses' => ['ipsFieldRow--badge-creator ipsFieldRow--badge-creator-icon']], null, null, null, "custombadge_icon" ) );
|
||||
|
||||
/* The overlay is optional */
|
||||
if ( !isset( static::$customBadgeNumberOverlay ) or static::$customBadgeNumberOverlay )
|
||||
{
|
||||
$form->add( new Number( "custombadge_number_overlay", ( $badge and $badge->number_overlay ) ? $badge->number_overlay : 0, false, [ 'step' => 1, 'min' => 1, 'max' => 999, 'unlimited' => 0, 'unlimitedLang' => 'none', 'rowClasses' => ['ipsFieldRow--badge-creator'] ], null, null, null, "custombadge_number_overlay" ) );
|
||||
}
|
||||
|
||||
$form->add( new Color( "custombadge_background", $badge ? $badge->background : '#eeb95f', null, ['rowClasses' => ['ipsFieldRow--badge-creator ipsFieldRow--badge-creator-background']], null, null, null, "custombadge_background" ) );
|
||||
$form->add( new Color( "custombadge_border", $badge ? $badge->border : '#f7d36f', null, ['rowClasses' => ['ipsFieldRow--badge-creator ipsFieldRow--badge-creator-border']], null, null, null, "custombadge_border" ) );
|
||||
$form->add( new Color( "custombadge_foreground", $badge ? $badge->foreground : '#ffffff', null, ['rgba' => true, 'swatches' => true, 'rowClasses' => ['ipsFieldRow--badge-creator ipsFieldRow--badge-creator-foreground']], null, null, null, "custombadge_foreground" ) );
|
||||
|
||||
$form->add( new Form\Number( "custombadge_icon_size", $badge ? $badge->icon_size : 3, null, ["min" => 1, "max" => 5, "step" => 1, "range" => true, "rowClasses" => ['ipsFieldRow--badge-creator', 'ipsFieldRow--badge-creator-icon-size']], id: "custombadge_icon_size" ) );
|
||||
|
||||
$form->add( new Number( "custombadge_sides", $badge ? $badge->sides : 5, null, ['step' => 1, 'min' => 4, 'max' => 12, 'range' => true, 'rowClasses' => ['ipsFieldRow--badge-creator']], null, null, null, "custombadge_sides" ) );
|
||||
$form->add( new Number( "custombadge_rotation", $badge?->rotation, null, ['step' => 1, 'min' => 0, 'max' => 90, 'range' => true, 'rowClasses' => ['ipsFieldRow--badge-creator']], null, null, null, "custombadge_rotation" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $values
|
||||
* @return void
|
||||
*/
|
||||
public function saveRecordBadge( array &$values ) : void
|
||||
{
|
||||
$badge = $this->getRecordBadge();
|
||||
|
||||
/* Are we using a badge? */
|
||||
if( $values['custombadge_use_custom'] )
|
||||
{
|
||||
if( $badge === null )
|
||||
{
|
||||
$badge = new CustomBadgeClass;
|
||||
$badge->class = get_called_class();
|
||||
|
||||
$idColumn = static::$databaseColumnId;
|
||||
$badge->active_record_id = $this->$idColumn;
|
||||
}
|
||||
|
||||
$badge->shape = $values['custombadge_shape'];
|
||||
$badge->foreground = $values['custombadge_foreground'];
|
||||
$badge->background = $values['custombadge_background'];
|
||||
$badge->border = $values['custombadge_border'];
|
||||
$badge->icon = $values['custombadge_icon'][0] ?? null;
|
||||
$badge->rotation = $values['custombadge_rotation'];
|
||||
$badge->sides = $values['custombadge_sides'];
|
||||
$badge->number_overlay = $values['custombadge_number_overlay'] ?? 0;
|
||||
$badge->icon_size = $values['custombadge_icon_size'] ?? 3;
|
||||
$badge->save();
|
||||
}
|
||||
elseif( $badge !== null )
|
||||
{
|
||||
/* If we are not using a custom badge, and we already have one, delete it */
|
||||
$badge->delete();
|
||||
}
|
||||
|
||||
/* Clear the form fields */
|
||||
foreach ( ['shape', 'foreground', 'background', 'border', 'icon', 'rotation', 'sides', 'number_overlay', 'use_custom', 'icon_size'] as $key )
|
||||
{
|
||||
unset( $values["custombadge_{$key}"] );
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
-8
@@ -14,7 +14,6 @@ namespace IPS\Node;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use IPS\Application\Module;
|
||||
use IPS\Content\ClubContainer;
|
||||
use IPS\Content\Comment;
|
||||
@@ -79,6 +78,7 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
* @mixin Colorize
|
||||
* @mixin Permissions
|
||||
* @mixin Icon
|
||||
* @mixin CustomBadge
|
||||
*/
|
||||
abstract class Model extends ActiveRecord
|
||||
{
|
||||
@@ -2747,7 +2747,7 @@ abstract class Model extends ActiveRecord
|
||||
{
|
||||
$canView = true;
|
||||
}
|
||||
elseif( $container !== null AND in_array( $containerId, $perms[ static::$modPerm ] ) )
|
||||
elseif( $container !== null and !empty( $perms[ static::$modPerm ] ) and in_array( $containerId, $perms[ static::$modPerm ] ) )
|
||||
{
|
||||
$canView = true;
|
||||
}
|
||||
@@ -2817,6 +2817,15 @@ abstract class Model extends ActiveRecord
|
||||
*/
|
||||
public function save(): void
|
||||
{
|
||||
/* Validate the counts, sometimes we inadvertently end up with a count less than 0 */
|
||||
foreach( [ '_items', '_comments', '_reviews', '_unapprovedItems', '_unapprovedComments', '_unapprovedReviews', '_futureItems' ] as $column )
|
||||
{
|
||||
if( $this->$column !== null and $this->$column < 0 )
|
||||
{
|
||||
$this->$column = 0;
|
||||
}
|
||||
}
|
||||
|
||||
parent::save();
|
||||
|
||||
if ( in_array( Permissions::class, class_implements( $this ) ) and $this->_permissions !== NULL and $this->_permissions != $this->_originalPermissions )
|
||||
@@ -3529,6 +3538,15 @@ abstract class Model extends ActiveRecord
|
||||
}
|
||||
catch( OutOfRangeException ){}
|
||||
|
||||
/* Delete custom badges */
|
||||
if( IPS::classUsesTrait( $this, CustomBadge::class ) )
|
||||
{
|
||||
if( $badge = $this->getRecordBadge() )
|
||||
{
|
||||
$badge->delete();
|
||||
}
|
||||
}
|
||||
|
||||
parent::delete();
|
||||
|
||||
Event::fire( 'onDelete', $this );
|
||||
@@ -3644,10 +3662,25 @@ abstract class Model extends ActiveRecord
|
||||
public function form( Form &$form ) : void
|
||||
{
|
||||
/* Now loop through and add all the elements to the form */
|
||||
foreach( UiExtension::i()->run( $this, 'formElements' ) as $element )
|
||||
{
|
||||
$form->add( $element );
|
||||
}
|
||||
if( static::$canBeExtended )
|
||||
{
|
||||
foreach( UiExtension::i()->run( $this, 'formElements' ) as $element )
|
||||
{
|
||||
if( is_object( $element ) )
|
||||
{
|
||||
$form->add( $element );
|
||||
}
|
||||
else
|
||||
{
|
||||
$form->addHtml( $element );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( IPS::classUsesTrait( $this, CustomBadge::class ) )
|
||||
{
|
||||
$this->addBadgeFieldsToForm( $form, $this->getRecordBadge() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3670,9 +3703,17 @@ abstract class Model extends ActiveRecord
|
||||
public function saveForm( array $values ): mixed
|
||||
{
|
||||
/* Loop through each extension and update the values */
|
||||
foreach( UiExtension::i()->getObjectExtensions( $this ) as $extension )
|
||||
if( static::$canBeExtended )
|
||||
{
|
||||
$values = $extension->processForm( $this, $values );
|
||||
foreach( UiExtension::i()->getObjectExtensions( $this ) as $extension )
|
||||
{
|
||||
$values = $extension->processForm( $this, $values );
|
||||
}
|
||||
}
|
||||
|
||||
if( IPS::classUsesTrait( $this, CustomBadge::class ) )
|
||||
{
|
||||
$this->saveRecordBadge( $values );
|
||||
}
|
||||
|
||||
foreach ( $values as $k => $v )
|
||||
|
||||
Reference in new issue
Block a user