Version 5.0.13
This commit is contained in:
1 parent
b89858b2ff
commit
5efe744c5f
1407 files changed
+69690
-30177
No files matched your search
+147
-10
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user