Version 5.0.13

This commit is contained in:
Neo committed 2025-12-19 19:04:57 -08:00
1 parent b89858b2ff
commit 5efe744c5f
1407 files changed
+69690 -30177

No files matched your search

+147 -10
View File
@@ -18,6 +18,7 @@ use BadMethodCallException;
use Exception;
use InvalidArgumentException;
use IPS\Application;
use IPS\cms\Records;
use IPS\Content;
use IPS\Data\Store;
use IPS\DateTime;
@@ -27,6 +28,7 @@ use IPS\Helpers\Form;
use IPS\Helpers\Form\Text;
use IPS\Helpers\Form\Translatable;
use IPS\Helpers\Form\Upload;
use IPS\Helpers\Form\YesNo;
use IPS\Http\Url;
use IPS\Http\Url\Friendly;
use IPS\IPS;
@@ -127,6 +129,11 @@ class Tag extends Model
*/
public static string $application = 'core';
/**
* @brief [Node] Sortable?
*/
public static bool $nodeSortable = false;
/**
* [Node] Return the custom badge for each row
*
@@ -222,6 +229,21 @@ class Tag extends Model
$this->_data['totals'] = ( is_array( $val ) and count( $val ) ) ? json_encode( $val ) : null;
}
/**
* [Node] Get content table meta description
*
* @return string|null
*/
public function metaDescription(): ?string
{
if( !Member::loggedIn()->language()->checkKeyExists( static::$titleLangPrefix . $this->id . static::$descriptionLangSuffix ) )
{
return null;
}
return parent::metaDescription();
}
/**
* Is this node currently queued for deleting or moving content OR is it the target of content queued to be moved from another node?
*
@@ -237,6 +259,16 @@ class Tag extends Model
return parent::deleteOrMoveQueued();
}
/**
* [Node] Get the title to store in the log
*
* @return string|null
*/
public function titleForLog(): ?string
{
return $this->text;
}
/**
* Determines if the tag has been flagged for merging.
* We need to flag it because this can take a while if there
@@ -257,7 +289,9 @@ class Tag extends Model
*/
public function form( Form &$form ): void
{
$form->add( new Text( 'tag_text', $this->text, true, [], function( $val ){
$form->add( new Text( 'tag_text', $this->text, true, [
'regex' => '/^[^,]+$/i',
], function( $val ){
try
{
$test = Db::i()->select( '*', static::$databaseTable, [ 'tag_text=? and tag_id <> ?', $val, (int) $this->id ] )->first();
@@ -299,6 +333,8 @@ class Tag extends Model
'multiple' => false,
'allowStockPhotos' => true
] ) );
$form->add( new YesNo( 'tag_recommended', $this->recommended, false ) );
}
/**
@@ -334,6 +370,56 @@ class Tag extends Model
return $values;
}
/**
* [Node] Get buttons to display in tree
* Example code explains return value
*
* @code
* array(
* array(
* 'icon' => 'plus-circle', // Name of FontAwesome icon to use
* 'title' => 'foo', // Language key to use for button's title parameter
* 'link' => \IPS\Http\Url::internal( 'app=foo...' ) // URI to link to
* 'class' => 'modalLink' // CSS Class to use on link (Optional)
* ),
* ... // Additional buttons
* );
* @endcode
* @param Url $url Base URL
* @param bool $subnode Is this a subnode?
* @return array
*/
public function getButtons( Url $url, bool $subnode=FALSE ): array
{
$buttons = [];
if( $this->recommended )
{
$buttons['recommend'] = [
'icon' => 'star',
'title' => 'tag_mark_norecommend',
'link' => $url->setQueryString( [ 'do' => 'recommend', 'id' => $this->id ] )->csrf()
];
}
else
{
$buttons['recommend'] = [
'icon' => 'regular fa-star',
'title' => 'tag_mark_recommend',
'link' => $url->setQueryString( [ 'do' => 'recommend', 'id' => $this->id ] )->csrf()
];
}
$buttons['view'] = [
'icon' => 'search',
'title' => 'tag_view_page',
'link' => $this->url(),
'target' => '_blank'
];
return array_merge( $buttons, parent::getButtons( $url, $subnode ) );
}
/**
* Recount the totals for this content type all affected tags
*
@@ -446,7 +532,7 @@ class Tag extends Model
public static function allTags() : array
{
return iterator_to_array(
Db::i()->select( 'tag_text', static::$databaseTable, null, 'tag_text' )
Db::i()->select( 'tag_text', static::$databaseTable, null, 'tag_recommended desc, tag_text' )
);
}
@@ -462,7 +548,10 @@ class Tag extends Model
{
if( IPS::classUsesTrait( $class, Taggable::class ) )
{
$return[ $class::$title ] = $class;
$bits = explode( "\\", $class );
$tab = $bits[1] . '__' . array_pop( $bits );
$return[ $tab ] = $class;
Member::loggedIn()->language()->words[ $tab . '_pl' ] = Member::loggedIn()->language()->get( $class::$title . '_pl' );
}
}
return $return;
@@ -501,9 +590,11 @@ class Tag extends Model
try
{
$item = $itemClass::load( $row['pinned_item_id'] );
$item->pinnedData = $row;
$items[] = $item;
if( $item->canView() )
{
$item->pinnedData = $row;
$items[] = $item;
}
}
catch( OutOfRangeException ){}
}
@@ -579,14 +670,14 @@ class Tag extends Model
if( !isset( Store::i()->tagSlugs ) )
{
Store::i()->tagSlugs = iterator_to_array(
Db::i()->select( 'tag_text,tag_text_seo', static::$databaseTable, [ 'tag_enabled=?', 1 ] )
Db::i()->select( 'LOWER(tag_text) as tag_text,tag_text_seo', static::$databaseTable, [ 'tag_enabled=?', 1 ] )
->setKeyField( 'tag_text' )
->setValueField( 'tag_text_seo' )
);
}
$cache = Store::i()->tagSlugs;
$slug = $cache[ $tagText ] ?? Friendly::seoTitle( $tagText );
$slug = $cache[ mb_strtolower( $tagText ) ] ?? Friendly::seoTitle( $tagText );
return Url::internal( "app=core&module=discover&controller=tag&tag=" . $slug, "front", "tags" );
}
@@ -652,11 +743,21 @@ class Tag extends Model
if ( !isset( Store::i()->tags ) )
{
/* Cache only the enabled tags */
Store::i()->tags = iterator_to_array(
Db::i()->select( 'tag_id,tag_text', static::$databaseTable, [ 'tag_enabled=?', 1 ], 'tag_text' )
$recommended = iterator_to_array(
Db::i()->select( 'tag_id,tag_text', static::$databaseTable, [ 'tag_enabled=? and tag_recommended=?', 1, 1 ], 'tag_text' )
->setKeyField( 'tag_id' )
->setValueField( 'tag_text' )
);
natcasesort( $recommended );
$other = iterator_to_array(
Db::i()->select( 'tag_id,tag_text', static::$databaseTable, [ 'tag_enabled=? and tag_recommended=?', 1, 0 ], 'tag_text' )
->setKeyField( 'tag_id' )
->setValueField( 'tag_text' )
);
natcasesort( $other );
Store::i()->tags = $recommended + $other;
}
return Store::i()->tags;
@@ -740,4 +841,40 @@ class Tag extends Model
/* Queue the background task to remove the tag from all currently tagged items */
Task::queue( 'core', 'UpdateTaggedItems', [ 'tag' => $this->text, 'delete' => true ], 5, [ 'tag' ] );
}
/**
* Get output for API
*
* @param Member|NULL $authorizedMember The member making the API request or NULL for API Key / client_credentials
* @return array
* @apiresponse int id ID number
* @apiresponse string tag Name
* @apiresponse string text_seo URL Slug
* @apiresponse string headline Headline
* @apiresponse string description description
* @apiresponse string cover_photo Cover Photo Path
* @apiresponse int recommended Recommended
*/
public function apiOutput( Member $authorizedMember = NULL ): array
{
$return = [
'id' => $this->id,
'tag' => $this->_title,
'text-seo' => $this->text_seo,
'headline' => $this->headline,
'url' => (string) $this->url(),
'description' => $this->description,
];
if( $file = $this->coverPhotoFile() )
{
$return[ 'cover_photo' ] = (string) $file;
}else
{
$return[ 'cover_photo' ] = null;
}
$return['recommended'] = $this->recommended;
return $return;
}
}