Version 4.7.8

This commit is contained in:
Neo committed 2025-12-19 16:10:42 -08:00
1 parent 7b7404e741
commit fd22d99e69
688 files changed
+19814 -10890

No files matched your search

+3 -10
View File
@@ -29,7 +29,7 @@ Clipboard
CKEditor CKEditor
Description: Provides the editor functionality for submitting content. Description: Provides the editor functionality for submitting content.
Location: In development: applications/core/dev/ckeditor (custom build with additional plugins) Location: In development: applications/core/dev/ckeditor (custom build with additional plugins)
Included version: 4.19.1 Included version: 4.20.1
Website: http://ckeditor.com Website: http://ckeditor.com
License: http://www.gnu.org/copyleft/lesser.html License: http://www.gnu.org/copyleft/lesser.html
@@ -110,7 +110,7 @@ Howler
HTMLPurifier HTMLPurifier
Description: Validates and cleans submitted HTML for content Description: Validates and cleans submitted HTML for content
Location: system/3rd_party/HTMLPurifier Location: system/3rd_party/HTMLPurifier
Included version: 4.14.0 Included version: 4.15.0
Website: http://htmlpurifier.org Website: http://htmlpurifier.org
License: http://www.gnu.org/copyleft/lesser.html License: http://www.gnu.org/copyleft/lesser.html
@@ -211,13 +211,6 @@ JShrink
Website: https://github.com/tedious/JShrink Website: https://github.com/tedious/JShrink
License: https://github.com/tedious/JShrink/blob/master/LICENSE License: https://github.com/tedious/JShrink/blob/master/LICENSE
jsTimezoneDetect
Description: Provides timezone detection
Location: dev/js/library/jstz
Included version: 1.0.6
Website: https://bitbucket.org/pellepim/jstimezonedetect
License: http://www.opensource.org/licenses/mit-license.php
JwtFramework JwtFramework
Description: Provides JWT signing & encryption support Description: Provides JWT signing & encryption support
Location: system/3rd_party/JwtFramework Location: system/3rd_party/JwtFramework
@@ -336,7 +329,7 @@ success.mp3 Notification Sound by RCP Tones
Twemoji Twemoji
Description: Emoji images Description: Emoji images
Location: Served from CDN Location: Served from CDN
Included version: 2.3 Included version: 14.0.2
Website: http://twitter.github.io/twemoji/ Website: http://twitter.github.io/twemoji/
License: https://github.com/twitter/twemoji/blob/gh-pages/LICENSE License: https://github.com/twitter/twemoji/blob/gh-pages/LICENSE
+1 -1
View File
@@ -1,5 +1,5 @@
=============================[NOTE]============================= =============================[NOTE]=============================
IPS 4.7.6 (107601) IPS 4.7.8 (107643)
=============================[NOTE]============================= =============================[NOTE]=============================
Invision Community End User License Agreement Invision Community End User License Agreement
@@ -0,0 +1,41 @@
<?php
/**
* @brief GraphQL: Blog mutations
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 22 Oct 2022
* @version SVN_VERSION_NUMBER
*/
namespace IPS\blog\api\GraphQL;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\Types;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Blog mutationss GraphQL API
*/
abstract class _Mutation
{
/**
* Get the supported query types in this app
*
* @return array
*/
public static function mutations(): array
{
$return = [
'createEntry' => new \IPS\blog\api\GraphQL\Mutations\CreateEntry(),
'replyEntry' => new \IPS\blog\api\GraphQL\Mutations\ReplyEntry(),
];
return $return;
}
}
@@ -0,0 +1,95 @@
<?php
/**
* @brief GraphQL: Create blog entry mutation
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 22 oct 2022
* @version SVN_VERSION_NUMBER
*/
namespace IPS\blog\api\GraphQL\Mutations;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Create blog entry mutation for GraphQL API
*/
class _CreateEntry extends \IPS\Content\Api\GraphQL\ItemMutator
{
/**
* Class
*/
protected $class = \IPS\blog\Entry::class;
/*
* @brief Query description
*/
public static $description = "Create a new blog entry";
/*
* Mutation arguments
*/
public function args(): array
{
return [
'blog' => TypeRegistry::nonNull( TypeRegistry::id() )
];
}
/**
* Return the mutation return type
*/
public function type()
{
return \IPS\blog\api\GraphQL\TypeRegistry::entry();
}
/**
* Resolves this mutation
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\blog\Blog
*/
public function resolve($val, $args, $context, $info)
{
/* Get blog */
try
{
$blog = \IPS\blog\Blog::loadAndCheckPerms( $args['blogID'] );
}
catch ( \OutOfRangeException $e )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_BLOG', '1B300/1_graphql', 400 );
}
/* Check permission */
if ( !$blog->can( 'add', \IPS\Member::loggedIn() ) )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_PERMISSION', '1B300/A_graphql', 403 );
}
/* Check we have a title and a post */
if ( !$args['title'] )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_TITLE', '1B300/4_graphql', 400 );
}
if ( !$args['content'] )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_POST', '1B300/5_grapqhl', 400 );
}
return $this->_create( $args, $blog, $args['postKey'] ?? NULL );
}
}
@@ -0,0 +1,108 @@
<?php
/**
* @brief GraphQL: Reply to topic mutation
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 10 May 2017
* @version SVN_VERSION_NUMBER
*/
namespace IPS\blog\api\GraphQL\Mutations;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Reply to entry mutation for GraphQL API
*/
class _ReplyEntry extends \IPS\Content\Api\GraphQL\CommentMutator
{
/**
* Class
*/
protected $class = \IPS\blog\Entry\Comment::class;
/*
* @brief Query description
*/
public static $description = "Create a new comment";
/*
* Mutation arguments
*/
public function args(): array
{
return [
'entryID' => TypeRegistry::nonNull( TypeRegistry::id() ),
'content' => TypeRegistry::nonNull( TypeRegistry::string() ),
'replyingTo' => TypeRegistry::id(),
'postKey' => TypeRegistry::string()
];
}
/**
* Return the mutation return type
*/
public function type()
{
return \IPS\blog\api\GraphQL\TypeRegistry::comment();
}
/**
* Resolves this mutation
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\blog\Entry
*/
public function resolve($val, $args, $context, $info)
{
/* Get topic */
try
{
$entry = \IPS\blog\Entry::loadAndCheckPerms( $args['entryID'] );
}
catch ( \OutOfRangeException $e )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_TOPIC', '1F295/1_graphql', 403 );
}
/* Get author */
if ( !$entry->canComment( \IPS\Member::loggedIn() ) )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_PERMISSION', '2F294/A_graphql', 403 );
}
/* Check we have a post */
if ( !$args['content'] )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_POST', '1F295/3_graphql', 403 );
}
$originalPost = NULL;
if( isset( $args['replyingTo'] ) )
{
try
{
$originalPost = \IPS\blog\Entry\Comment::loadAndCheckPerms( $args['replyingTo'] );
}
catch ( \OutOfRangeException $e )
{
// Just ignore it
}
}
/* Do it */
return $this->_createComment( $args, $entry, $args['postKey'] ?? NULL, $originalPost );
}
}
@@ -0,0 +1,69 @@
<?php
/**
* @brief GraphQL: Blog query
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 10 May 2017
* @version SVN_VERSION_NUMBER
*/
namespace IPS\blog\api\GraphQL\Queries;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Blog query for GraphQL API
*/
class _Blog
{
/*
* @brief Query description
*/
public static $description = "Returns a Blog";
/*
* Query arguments
*/
public function args(): array
{
return array(
'id' => TypeRegistry::nonNull( TypeRegistry::id() ),
);
}
/**
* Return the query return type
*/
public function type()
{
return \IPS\blog\api\GraphQL\TypeRegistry::blog();
}
/**
* Resolves this query
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\blog\Blog
*/
public function resolve($val, $args, $context, $info)
{
$blog = \IPS\blog\Blog::load( $args['id'] );
if( !$blog->can( 'view', $context['member'] ) )
{
throw new \OutOfRangeException;
}
return $blog;
}
}
@@ -0,0 +1,64 @@
<?php
/**
* @brief GraphQL: Blog query
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 22 Oct 2022
* @version SVN_VERSION_NUMBER
*/
namespace IPS\blog\api\GraphQL\Queries;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Blogs query for GraphQL API
*/
class _Blogs
{
/*
* @brief Query description
*/
public static $description = "Returns a list of blogs";
/*
* Query arguments
*/
public function args(): array
{
return array(
'id' => TypeRegistry::id()
);
}
/**
* Return the query return type
*/
public function type()
{
return TypeRegistry::listOf( \IPS\blog\api\GraphQL\TypeRegistry::blog() );
}
/**
* Resolves this query
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return array
*/
public function resolve($val, $args, $context, $info)
{
\IPS\blog\Blog::loadIntoMemory('view', $context['member']);
return \IPS\blog\Blog::roots();
}
}
@@ -0,0 +1,143 @@
<?php
/**
* @brief GraphQL: Topics query
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 10 May 2017
* @version SVN_VERSION_NUMBER
*/
namespace IPS\blog\api\GraphQL\Queries;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Topics query for GraphQL API
*/
class _Entries
{
/*
* @brief Query description
*/
public static $description = "Returns a list of blog entries";
/*
* Query arguments
*/
public function args(): array
{
return array(
'blogs' => TypeRegistry::listOf( TypeRegistry::int() ),
'offset' => [
'type' => TypeRegistry::int(),
'defaultValue' => 0
],
'limit' => [
'type' => TypeRegistry::int(),
'defaultValue' => 25
],
'orderBy' => [
'type' => TypeRegistry::eNum([
'name' => 'blog_order_by',
'description' => 'Fields on which event can be sorted',
'values' => \IPS\blog\api\GraphQL\Types\EntryType::getOrderByOptions()
]),
'defaultValue' => NULL // will use default sort option
],
'orderDir' => [
'type' => TypeRegistry::eNum([
'name' => 'entries_order_dir',
'description' => 'Directions in which items can be sorted',
'values' => [ 'ASC', 'DESC' ]
]),
'defaultValue' => 'DESC'
],
'honorPinned' => [
'type' => TypeRegistry::boolean(),
'defaultValue' => true
]
);
}
/**
* Return the query return type
*/
public function type()
{
return TypeRegistry::listOf( \IPS\blog\api\GraphQL\TypeRegistry::entry() );
}
/**
* Resolves this query
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\blog\Entry
*/
public function resolve($val, $args, $context, $info)
{
\IPS\blog\Blog::loadIntoMemory('view', \IPS\Member::loggedIn() );
$blogIds = [];
/* Are we filtering by blogs? */
if( isset( $args['blogs'] ) && \count( $args['blogs'] ) )
{
foreach( $args['blogs'] as $id )
{
$blog = \IPS\blog\Blog::loadAndCheckPerms( $id );
$blogIds[] = $blog->id;
}
if( \count( $blogIds ) )
{
$where['container'][] = array( \IPS\Db::i()->in( 'blog_blogs.blog_id', array_filter( $blogIds ) ) );
}
}
/* Get sorting */
try
{
if( $args['orderBy'] === NULL )
{
$orderBy = 'last_post';
}
else
{
$orderBy = \IPS\blog\Entry::$databaseColumnMap[ $args['orderBy'] ];
}
if( $args['orderBy'] === 'last_comment' )
{
$orderBy = \is_array( $orderBy ) ? array_pop( $orderBy ) : $orderBy;
}
}
catch (\Exception $e)
{
$orderBy = 'last_post';
}
$sortBy = \IPS\blog\Entry::$databaseTable . '.' . \IPS\blog\Entry::$databasePrefix . "{$orderBy} {$args['orderDir']}";
$offset = max( $args['offset'], 0 );
$limit = min( $args['limit'], 50 );
/* Figure out pinned status */
if ( $args['honorPinned'] )
{
$column = \IPS\blog\Entry::$databaseTable . '.' . \IPS\blog\Entry::$databasePrefix . \IPS\blog\Entry::$databaseColumnMap['pinned'];
$sortBy = "{$column} DESC, {$sortBy}";
}
return \IPS\blog\Entry::getItemsWithPermission( $where, $sortBy, array( $offset, $limit ), 'read' );
}
}
@@ -0,0 +1,77 @@
<?php
/**
* @brief GraphQL: Entry query
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 22 Oct 2022
* @version SVN_VERSION_NUMBER
*/
namespace IPS\blog\api\GraphQL\Queries;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Entry query for GraphQL API
*/
class _Entry
{
/*
* @brief Query description
*/
public static $description = "Returns a Blog Entry";
/*
* Query arguments
*/
public function args(): array
{
return array(
'id' => TypeRegistry::nonNull( TypeRegistry::id() )
);
}
/**
* Return the query return type
*/
public function type()
{
return \IPS\blog\api\GraphQL\TypeRegistry::entry();
}
/**
* Resolves this query
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\blog\Entry
*/
public function resolve($val, $args, $context, $info)
{
try
{
$entry = \IPS\blog\Entry::loadAndCheckPerms( $args['id'] );
}
catch ( \OutOfRangeException $e )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_TOPIC', '2B300/A_graphql', 400 );
}
if( !$entry->can('read') )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_PERMISSION', '2B300/9_graphql', 403 );
}
return $entry;
}
}
+42
View File
@@ -0,0 +1,42 @@
<?php
/**
* @brief GraphQL: Blog queries
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 22 Oct 2022
* @version SVN_VERSION_NUMBER
*/
namespace IPS\blog\api\GraphQL;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\Types;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Blog queries for GraphQL API
*/
abstract class _Query
{
/**
* Get the supported query types in this app
*
* @return array
*/
public static function queries(): array
{
return [
'blogs' => new \IPS\blog\api\GraphQL\Queries\Blogs(),
'blog' => new \IPS\blog\api\GraphQL\Queries\Blog(),
'entries' => new \IPS\blog\api\GraphQL\Queries\Entries(),
'entry' => new \IPS\blog\api\GraphQL\Queries\Entry(),
];
}
}
@@ -0,0 +1,76 @@
<?php
/**
* @brief GraphQL: Types registry
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 22 Oct 2022
* @version SVN_VERSION_NUMBER
*/
namespace IPS\blog\api\GraphQL;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\Types;
use IPS\blog\api\GraphQL\Types\_BlogType;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
class _TypeRegistry
{
/**
* The blog type instance
* @var \IPS\blog\api\GraphQL\Types\BlogType
*/
protected static $blog;
/**
* The blog entry type instance
* @var \IPS\blog\api\GraphQL\Types\EntryType
*/
protected static $entry;
/**
* The entry comment instance
* @var \IPS\blog\api\GraphQL\Types\CommentType
*/
protected static $comment;
/**
* Constructor
*/
public function __construct()
{
// Defined to suppress static warnings
}
/**
* @return BlogType
*/
public static function blog(): \IPS\blog\api\GraphQL\Types\BlogType
{
return self::$blog ?: (self::$blog = new \IPS\blog\api\GraphQL\Types\BlogType());
}
/**
* @return EntryType
*/
public static function entry(): \IPS\blog\api\GraphQL\Types\EntryType
{
return self::$entry ?: (self::$entry = new \IPS\blog\api\GraphQL\Types\EntryType());
}
/**
* @return CommentType
*/
public static function comment(): \IPS\blog\api\GraphQL\Types\CommentType
{
return self::$comment ?: (self::$comment = new \IPS\blog\api\GraphQL\Types\CommentType());
}
}
@@ -0,0 +1,58 @@
<?php
/**
* @brief GraphQL: Blog Type
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 22 Oct 2022
* @version SVN_VERSION_NUMBER
*/
namespace IPS\blog\api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* BlogType for GraphQL API
*/
class _BlogType extends \IPS\Node\Api\GraphQL\NodeType
{
/*
* @brief The item classname we use for this type
*/
protected static $nodeClass = \IPS\blog\Blog::class;
/*
* @brief GraphQL type name
*/
protected static $typeName = 'blog_Blog';
/*
* @brief GraphQL type description
*/
protected static $typeDescription = 'A blog';
/*
* @brief Follow data passed in to FollowType resolver
*/
protected static $followData = array('app' => 'blog', 'area' => 'blog');
/**
* Get the item type that goes with this node type
*
* @return ObjectType
*/
public static function getItemType()
{
return \IPS\blog\api\GraphQL\TypeRegistry::entry();
}
}
@@ -0,0 +1,75 @@
<?php
/**
* @brief GraphQL: Post Type
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 10 May 2017
* @version SVN_VERSION_NUMBER
*/
namespace IPS\blog\api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* PostType for GraphQL API
*/
class _CommentType extends \IPS\Content\Api\GraphQL\CommentType
{
/*
* @brief The item classname we use for this type
*/
protected static $commentClass = \IPS\blog\Entry\Comment::class;
/*
* @brief GraphQL type name
*/
protected static $typeName = 'blog_Comment';
/*
* @brief GraphQL type description
*/
protected static $typeDescription = 'A blog comment';
/**
* Get the item type that goes with this item type
*
* @return ObjectType
*/
public static function getItemType()
{
return \IPS\blog\api\GraphQL\TypeRegistry::comment();
}
/**
* Return the fields available in this type
*
* @return array
*/
public function fields()
{
$defaultFields = parent::fields();
$postFields = array(
'entry' => [
'type' => \IPS\blog\api\GraphQL\TypeRegistry::entry(),
'resolve' => function ($comment) {
return $comment->item();
}
],
);
// Remove duplicated fields
unset( $defaultFields['item'] );
return array_merge( $defaultFields, $postFields );
}
}
@@ -0,0 +1,58 @@
<?php
/**
* @brief GraphQL: Topic Type
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 10 May 2017
* @version SVN_VERSION_NUMBER
*/
namespace IPS\blog\api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\_TypeRegistry;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Entry for GraphQL API
*/
class _EntryType extends \IPS\Content\Api\GraphQL\ItemType
{
/*
* @brief The item classname we use for this type
*/
protected static $itemClass = \IPS\blog\Entry::class;
/*
* @brief GraphQL type name
*/
protected static $typeName = 'blog_Entry';
/*
* @brief GraphQL type description
*/
protected static $typeDescription = 'A blog entry';
/*
* @brief Follow data passed in to FollowType resolver
*/
protected static $followData = array('app' => 'blogs', 'area' => 'entry');
/**
* Get the comment type that goes with this item type
*
* @return ObjectType
*/
protected static function getCommentType()
{
return \IPS\blog\api\GraphQL\TypeRegistry::comment();
}
}
+3 -2
View File
@@ -34,6 +34,7 @@ class _blogs extends \IPS\Node\Api\NodeController
* Get list of blogs * Get list of blogs
* *
* @note For requests using an OAuth Access Token for a particular member, only blogs that are not disabled and not belonging to a particular club or social group will be included * @note For requests using an OAuth Access Token for a particular member, only blogs that are not disabled and not belonging to a particular club or social group will be included
* @apiparam string ids Comma-delimited list of blog ids
* @apiparam string owners Comma-delimited list of member IDs - if provided, only blogs owned by those members are returned (can be used in conjection with groups or set to 0 to exclude member-created blogs) * @apiparam string owners Comma-delimited list of member IDs - if provided, only blogs owned by those members are returned (can be used in conjection with groups or set to 0 to exclude member-created blogs)
* @apiparam string groups Comma-delimited list of group IDs - if provided, only blogs owned by those groups are returned (can be used in conjection with members or set to 0 to exclude group blogs) * @apiparam string groups Comma-delimited list of group IDs - if provided, only blogs owned by those groups are returned (can be used in conjection with members or set to 0 to exclude group blogs)
* @apiparam int pinned If 1, only blogs which are pinned are returned, if 0 only not pinned * @apiparam int pinned If 1, only blogs which are pinned are returned, if 0 only not pinned
@@ -46,8 +47,8 @@ class _blogs extends \IPS\Node\Api\NodeController
public function GETindex() public function GETindex()
{ {
/* Where clause */ /* Where clause */
$where = array(); $where = $this->_globalWhere();
/* Owners */ /* Owners */
if ( isset( \IPS\Request::i()->owners ) and isset( \IPS\Request::i()->groups ) ) if ( isset( \IPS\Request::i()->owners ) and isset( \IPS\Request::i()->groups ) )
{ {
+2 -1
View File
@@ -33,6 +33,7 @@ class _categories extends \IPS\Node\Api\NodeController
* GET /blog/categories * GET /blog/categories
* Get list of blog categories * Get list of blog categories
* *
* @apiparam string ids Comma-delimited list of category ids
* @apiparam string sortBy What to sort by. Can be 'count_entries' for number of entries, 'last_edate' for last entry date or do not specify for ID * @apiparam string sortBy What to sort by. Can be 'count_entries' for number of entries, 'last_edate' for last entry date or do not specify for ID
* @apiparam string sortDir Sort direction. Can be 'asc' or 'desc' - defaults to 'asc' * @apiparam string sortDir Sort direction. Can be 'asc' or 'desc' - defaults to 'asc'
* @apiparam int page Page number * @apiparam int page Page number
@@ -42,7 +43,7 @@ class _categories extends \IPS\Node\Api\NodeController
public function GETindex() public function GETindex()
{ {
/* Where clause */ /* Where clause */
$where = array(); $where = $this->_globalWhere();
/* Sort */ /* Sort */
if ( isset( \IPS\Request::i()->sortBy ) and \in_array( \IPS\Request::i()->sortBy, array( 'position' ) ) ) if ( isset( \IPS\Request::i()->sortBy ) and \in_array( \IPS\Request::i()->sortBy, array( 'position' ) ) )
+1
View File
@@ -33,6 +33,7 @@ class _entries extends \IPS\Content\Api\ItemController
* Get list of entries * Get list of entries
* *
* @note For requests using an OAuth Access Token for a particular member, only entries that are published and in blogs that are not disabled and not belonging to a particular club or social group will be included * @note For requests using an OAuth Access Token for a particular member, only entries that are published and in blogs that are not disabled and not belonging to a particular club or social group will be included
* @apiparam string ids Comma-delimited list of entry IDs
* @apiparam string blogs Comma-delimited list of blog IDs * @apiparam string blogs Comma-delimited list of blog IDs
* @apiparam string authors Comma-delimited list of member IDs - if provided, only entries started by those members are returned * @apiparam string authors Comma-delimited list of member IDs - if provided, only entries started by those members are returned
* @apiparam int locked If 1, only entries which are locked are returned, if 0 only unlocked * @apiparam int locked If 1, only entries which are locked are returned, if 0 only unlocked
@@ -45,6 +45,14 @@ class _entrycategories extends \IPS\Node\Api\NodeController
/* Where clause */ /* Where clause */
$where = array(); $where = array();
$class = $this->class;
if ( isset( \IPS\Request::i()->ids ) )
{
$idField = $class::$databaseTable . '.' . $class::$databasePrefix . '.' . $class::$databaseColumnId;
$where[] = array( \IPS\Db::i()->in( $idField, array_map( 'intval', explode( ',', \IPS\Request::i()->ids ) ) ) );
}
/* Blog */ /* Blog */
if ( isset( \IPS\Request::i()->blog ) ) if ( isset( \IPS\Request::i()->blog ) )
{ {
+6 -6
View File
@@ -1,16 +1,16 @@
{ {
"blogs": { "blogs": {
"settings": {
"tab": "community",
"controller": "settings",
"do": "",
"restriction": "settings_manage"
},
"blogs": { "blogs": {
"tab": "community", "tab": "community",
"controller": "blogs", "controller": "blogs",
"do": "", "do": "",
"restriction": "blogs_manage" "restriction": "blogs_manage"
},
"settings": {
"tab": "community",
"controller": "settings",
"do": "",
"restriction": "settings_manage"
} }
} }
} }
+4 -5
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<javascript app="blog"> <javascript app="blog">
<file javascript_app="blog" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.grid.js" javascript_type="controller" javascript_version="107601" javascript_position="1000050"><![CDATA[/** <file javascript_app="blog" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.grid.js" javascript_type="controller" javascript_version="107643" javascript_position="1000050"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -37,7 +37,7 @@
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="blog" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.list.js" javascript_type="controller" javascript_version="107601" javascript_position="1000050">/** <file javascript_app="blog" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.list.js" javascript_type="controller" javascript_version="107643" javascript_position="1000050">/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -66,7 +66,7 @@
} }
}); });
}(jQuery, _));</file> }(jQuery, _));</file>
<file javascript_app="blog" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.manageCategories.js" javascript_type="controller" javascript_version="107601" javascript_position="1000100"><![CDATA[/** <file javascript_app="blog" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.manageCategories.js" javascript_type="controller" javascript_version="107643" javascript_position="1000100"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -343,7 +343,7 @@
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="blog" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.view.js" javascript_type="template" javascript_version="107601" javascript_position="1000150"><![CDATA[/* CLASS LIST TEMPLATES */ <file javascript_app="blog" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.view.js" javascript_type="template" javascript_version="107643" javascript_position="1000150"><![CDATA[/* CLASS LIST TEMPLATES */
ips.templates.set('blog.view.addButton', "\ ips.templates.set('blog.view.addButton', "\
<button type=\"button\" class=\"ipsButton ipsButton_primary ipsHide\" data-action=\"addNew\">{{#lang}}manage_cats_new_row{{/lang}}</button>\ <button type=\"button\" class=\"ipsButton ipsButton_primary ipsHide\" data-action=\"addNew\">{{#lang}}manage_cats_new_row{{/lang}}</button>\
"); ");
@@ -373,7 +373,6 @@ controllers</order>
<order app="global" path="/dev/js//library/">underscore <order app="global" path="/dev/js//library/">underscore
jquery jquery
mustache mustache
jstz
IntersectionObserver IntersectionObserver
Debug.js Debug.js
app.js</order> app.js</order>
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<language> <language>
<app key="blog" version="107601"> <app key="blog" version="107643">
<word key="__app_blog" js="0">Blogs</word> <word key="__app_blog" js="0">Blogs</word>
<word key="frontnavigation_blogs" js="0">Blogs</word> <word key="frontnavigation_blogs" js="0">Blogs</word>
<word key="__indefart_blog_entry_comment" js="0">a comment on a blog entry</word> <word key="__indefart_blog_entry_comment" js="0">a comment on a blog entry</word>
+37 -43
View File
@@ -1270,7 +1270,7 @@
</div> </div>
</div> </div>
<div class='ipsFlex-flex:01 ipsResponsive_hidePhone'> <div class='ipsFlex-flex:01 ipsResponsive_hidePhone'>
<div class='ipsFlex ipsFlex-ai:center ipsFlex-jc:center ipsGap:3 ipsGap_row:0'> <div class='ipsShareLinks'>
{{if \count( $entry->shareLinks() )}} {{if \count( $entry->shareLinks() )}}
{template="shareButton" app="core" group="sharelinks" params="$entry"} {template="shareButton" app="core" group="sharelinks" params="$entry"}
{{endif}} {{endif}}
@@ -1384,18 +1384,12 @@
</article> </article>
<div class='ipsBox ipsPadding ipsResponsive_pull ipsResponsive_showPhone ipsMargin_vertical'> <div class='ipsBox ipsPadding ipsResponsive_pull ipsResponsive_showPhone ipsMargin_vertical'>
<div class='ipsGap:3'> <div class='ipsShareLinks'>
{{if \count( $entry->shareLinks() )}} {{if \count( $entry->shareLinks() )}}
<div> {template="shareButton" app="core" group="sharelinks" params="$entry, 'verySmall', 'light'"}
{template="shareButton" app="core" group="sharelinks" params="$entry, 'verySmall', 'light'"}
</div>
{{endif}} {{endif}}
<div> {template="follow" app="core" group="global" params="'blog', 'entry', $entry->id, $entry->followersCount()"}
{template="follow" app="core" group="global" params="'blog', 'entry', $entry->id, $entry->followersCount()"} {template="promote" app="core" group="global" params="$entry"}
</div>
<div>
{template="promote" app="core" group="global" params="$entry"}
</div>
</div> </div>
</div> </div>
@@ -1588,7 +1582,7 @@
<template template_group="widgets" template_name="blogCommentFeed" template_data="$comments, $title, $orientation='vertical'" template_location="front" template_app="blog"><![CDATA[{{if !empty( $comments ) }} <template template_group="widgets" template_name="blogCommentFeed" template_data="$comments, $title, $orientation='vertical'" template_location="front" template_app="blog"><![CDATA[{{if !empty( $comments ) }}
<h3 class='ipsType_reset ipsWidget_title'>{$title}</h3> <h3 class='ipsType_reset ipsWidget_title'>{$title}</h3>
{{if $orientation == 'vertical'}} {{if $orientation == 'vertical'}}
<div class='ipsWidget_inner ipsPad_half'> <div class='ipsWidget_inner'>
<ul class='ipsDataList ipsDataList_reducedSpacing'> <ul class='ipsDataList ipsDataList_reducedSpacing'>
{{foreach $comments as $comment}} {{foreach $comments as $comment}}
<li class='ipsDataItem'> <li class='ipsDataItem'>
@@ -1596,8 +1590,8 @@
{template="userPhoto" group="global" app="core" params="$comment->author(), 'tiny'"} {template="userPhoto" group="global" app="core" params="$comment->author(), 'tiny'"}
</div> </div>
<div class='ipsDataItem_main'> <div class='ipsDataItem_main'>
<div class='ipsType_break ipsContained'><a href="{$comment->url()}" class='ipsType_medium ipsTruncate ipsTruncate_line'>{$comment->item()->name}</a></div> <div class='ipsType_break ipsContained'><a href="{$comment->url()}" class='ipsDataItem_title'>{$comment->item()->name}</a></div>
<p class='ipsType_reset ipsType_medium ipsType_light ipsType_blendLinks'>{lang="byline_nodate" htmlsprintf="$comment->author()->link()"} &middot; <a href="{$comment->url()}" class='ipsDataItem_title ipsType_break ipsType_blendLinks'>{$comment->dateLine()|raw}</a></p> <p class='ipsType_reset ipsType_medium ipsType_light ipsType_blendLinks'>{lang="byline_nodate" htmlsprintf="$comment->author()->link()"} &middot; <a href="{$comment->url()}" class='ipsType_break ipsType_blendLinks'>{$comment->dateLine()|raw}</a></p>
<div class='ipsType_medium ipsType_textBlock ipsType_richText ipsType_break ipsContained ipsSpacer_top ipsSpacer_half' data-ipsTruncate data-ipsTruncate-type='remove' data-ipsTruncate-size='{{if $orientation == 'vertical'}}6 lines{{else}}2 lines{{endif}}'> <div class='ipsType_medium ipsType_textBlock ipsType_richText ipsType_break ipsContained ipsSpacer_top ipsSpacer_half' data-ipsTruncate data-ipsTruncate-type='remove' data-ipsTruncate-size='{{if $orientation == 'vertical'}}6 lines{{else}}2 lines{{endif}}'>
{$comment->truncated( true )|raw} {$comment->truncated( true )|raw}
</div> </div>
@@ -1680,7 +1674,7 @@
]]></template> ]]></template>
<template template_group="widgets" template_name="blogs" template_data="$blogs, $title, $orientation='vertical'" template_location="front" template_app="blog"><![CDATA[<h3 class='ipsType_reset ipsWidget_title'>{$title}</h3> <template template_group="widgets" template_name="blogs" template_data="$blogs, $title, $orientation='vertical'" template_location="front" template_app="blog"><![CDATA[<h3 class='ipsType_reset ipsWidget_title'>{$title}</h3>
{{if $orientation == 'vertical'}} {{if $orientation == 'vertical'}}
<div class='ipsPad_half ipsWidget_inner'> <div class='ipsWidget_inner ipsPadding:half'>
<ul class='ipsDataList ipsDataList_reducedSpacing'> <ul class='ipsDataList ipsDataList_reducedSpacing'>
{{foreach $blogs as $blog}} {{foreach $blogs as $blog}}
<li class='ipsDataItem'> <li class='ipsDataItem'>
@@ -1797,26 +1791,24 @@
<template template_group="widgets" template_name="blogStatistics" template_data="$stats, $orientation='vertical'" template_location="front" template_app="blog"><![CDATA[<h3 class='ipsType_reset ipsWidget_title'>{lang="block_blogStatistics"}</h3> <template template_group="widgets" template_name="blogStatistics" template_data="$stats, $orientation='vertical'" template_location="front" template_app="blog"><![CDATA[<h3 class='ipsType_reset ipsWidget_title'>{lang="block_blogStatistics"}</h3>
<div class='ipsWidget_inner'> <div class='ipsWidget_inner'>
{{if $orientation == 'vertical'}} {{if $orientation == 'vertical'}}
<div class='ipsPad_half'> <ul class='ipsDataList' id='elBlogStats'>
<ul class='ipsDataList' id='elBlogStats'> <li class='ipsDataItem'>
<li class='ipsDataItem'> <div class='ipsDataItem_main ipsPos_middle'>
<div class='ipsDataItem_main ipsPos_middle'> <strong>{lang="total_blogs"}</strong>
<strong>{lang="total_blogs"}</strong> </div>
</div> <div class='ipsDataItem_stats ipsDataItem_statsLarge'>
<div class='ipsDataItem_stats ipsDataItem_statsLarge'> <span class='ipsDataItem_stats_number'>{number="$stats['total_blogs']"}</span>
<span class='ipsDataItem_stats_number'>{number="$stats['total_blogs']"}</span> </div>
</div> </li>
</li> <li class='ipsDataItem'>
<li class='ipsDataItem'> <div class='ipsDataItem_main ipsPos_middle'>
<div class='ipsDataItem_main ipsPos_middle'> <strong>{lang="total_entries"}</strong>
<strong>{lang="total_entries"}</strong> </div>
</div> <div class='ipsDataItem_stats ipsDataItem_statsLarge'>
<div class='ipsDataItem_stats ipsDataItem_statsLarge'> <span class='ipsDataItem_stats_number'>{number="$stats['total_entries']"}</span>
<span class='ipsDataItem_stats_number'>{number="$stats['total_entries']"}</span> </div>
</div> </li>
</li> </ul>
</ul>
</div>
{{else}} {{else}}
<div class='ipsGrid ipsGrid_collapsePhone ipsWidget_stats'> <div class='ipsGrid ipsGrid_collapsePhone ipsWidget_stats'>
<div class='ipsGrid_span6 ipsType_center'> <div class='ipsGrid_span6 ipsType_center'>
@@ -1832,7 +1824,7 @@
</div>]]></template> </div>]]></template>
<template template_group="widgets" template_name="entryFeed" template_data="$entries, $title, $orientation='vertical'" template_location="front" template_app="blog"><![CDATA[{{if !empty( $entries ) }} <template template_group="widgets" template_name="entryFeed" template_data="$entries, $title, $orientation='vertical'" template_location="front" template_app="blog"><![CDATA[{{if !empty( $entries ) }}
<h3 class='ipsType_reset ipsWidget_title'>{$title}</h3> <h3 class='ipsType_reset ipsWidget_title'>{$title}</h3>
<div class='ipsPad_half ipsWidget_inner'> <div class='ipsWidget_inner'>
<ul class='ipsDataList ipsDataList_reducedSpacing'> <ul class='ipsDataList ipsDataList_reducedSpacing'>
{{foreach $entries as $entry}} {{foreach $entries as $entry}}
{template="entryRow" group="widgets" app="blog" params="$entry, $orientation"} {template="entryRow" group="widgets" app="blog" params="$entry, $orientation"}
@@ -1845,14 +1837,16 @@
{template="userPhoto" app="core" params="$entry->author(), 'tiny'" group="global"} {template="userPhoto" app="core" params="$entry->author(), 'tiny'" group="global"}
</div> </div>
<div class='ipsDataItem_main'> <div class='ipsDataItem_main'>
<div class='ipsContained ipsType_break'><a href="{$entry->url('getLastComment')}" title='{lang="view_this_entry" sprintf="$entry->_title"}' class='ipsType_medium ipsTruncate ipsTruncate_line'>{$entry->name}</a></div> <div class='ipsContained ipsType_break'><a href="{$entry->url('getLastComment')}" title='{lang="view_this_entry" sprintf="$entry->_title"}' class='ipsDataItem_title'>{$entry->name}</a></div>
<span class='ipsType_blendLinks ipsType_light ipsType_medium ipsType_break ipsContained'>{lang="byline_nodate" htmlsprintf="$entry->author()->link()"} {lang="in"} <a href='{$entry->container()->url()}' class='ipsType_blendLinks ipsTruncate ipsTruncate_line'>{$entry->container()->_title}</a></span> <div class='ipsType_blendLinks ipsType_light ipsType_break ipsContained'>{lang="byline_nodate" htmlsprintf="$entry->author()->link()"} {lang="in"} <a href='{$entry->container()->url()}' class='ipsType_blendLinks'>{$entry->container()->_title}</a></div>
{{if \IPS\Settings::i()->blog_enable_rating}} <div class='ipsMargin_top:half'>
{template="rating" group="global" location="front" app="core" params="'small', $entry->averageRating(), 5, $entry->memberRating()"} &nbsp;&nbsp; {{if \IPS\Settings::i()->blog_enable_rating}}
{{endif}} {template="rating" group="global" location="front" app="core" params="'small', $entry->averageRating(), 5, $entry->memberRating()"} &nbsp;&nbsp;
<span class='ipsType_medium ipsType_reset'>{{if !$entry->num_comments}}<span class='ipsType_light'>{{endif}}<i class='fa fa-comment'></i> {number="$entry->num_comments"}{{if !$entry->num_comments}}</span>{{endif}}</span> {{endif}}
<span {{if !$entry->num_comments}}class='ipsType_light'{{endif}}>{number="$entry->num_comments"} {lang="blog_comments" pluralize="$entry->num_comments"}</span>
</div>
{{if $orientation == 'horizontal'}} {{if $orientation == 'horizontal'}}
<div class='ipsType_medium ipsType_richText ipsType_break' data-ipsTruncate data-ipsTruncate-type='remove' data-ipsTruncate-size='2 lines'> <div class='ipsMargin_top:half ipsType_medium ipsType_richText ipsType_break' data-ipsTruncate data-ipsTruncate-type='remove' data-ipsTruncate-size='2 lines'>
{$entry->truncated()|raw} {$entry->truncated()|raw}
</div> </div>
{{endif}} {{endif}}
+15 -1
View File
@@ -535,5 +535,19 @@
"107504": "4.7.5", "107504": "4.7.5",
"107505": "4.7.5", "107505": "4.7.5",
"107600": "4.7.6 Beta 1", "107600": "4.7.6 Beta 1",
"107601": "4.7.6" "107601": "4.7.6",
"107602": "4.7.6",
"107620": "4.7.7 Beta 1",
"107621": "4.7.7 Beta 2",
"107622": "4.7.7 Beta 2",
"107623": "4.7.7 Beta 3",
"107624": "4.7.7 Beta 4",
"107625": "4.7.7",
"107626": "4.7.7",
"107627": "4.7.7",
"107628": "4.7.7",
"107640": "4.7.8 Beta 1",
"107641": "4.7.8 Beta 2",
"107642": "4.7.8 Beta 3",
"107643": "4.7.8"
} }
@@ -0,0 +1,23 @@
{
"id": 107602,
"name": "4.7.6",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107620,
"name": "4.7.7 Beta 1",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": true,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": true,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,14 @@
{
"files": {
"added": [],
"edited": [],
"removed": []
},
"orders": {
"added": [],
"edited": [
"global\/\/dev\/js\/\/library\/"
],
"removed": []
}
}
@@ -0,0 +1,23 @@
{
"id": 107621,
"name": "4.7.7 Beta 2",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107622,
"name": "4.7.7 Beta 2",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107623,
"name": "4.7.7 Beta 3",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107624,
"name": "4.7.7 Beta 4",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107625,
"name": "4.7.7",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107626,
"name": "4.7.7",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107627,
"name": "4.7.7",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107628,
"name": "4.7.7",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107640,
"name": "4.7.8 Beta 1",
"steps": {
"queries": false,
"lang": false,
"theme": true,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"html": {
"added": [],
"edited": [
"front\/view\/entry",
"front\/widgets\/blogCommentFeed",
"front\/widgets\/blogs",
"front\/widgets\/blogStatistics",
"front\/widgets\/entryFeed",
"front\/widgets\/entryRow"
],
"removed": []
},
"css": {
"added": [],
"edited": [],
"removed": []
},
"resources": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,23 @@
{
"id": 107641,
"name": "4.7.8 Beta 2",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107642,
"name": "4.7.8 Beta 3",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107643,
"name": "4.7.8",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
+1 -1
View File
@@ -1322,7 +1322,7 @@ class _Blog extends \IPS\Node\Model implements \IPS\Node\Ratings, \IPS\Content\E
if( $club->type == 'closed' ) if( $club->type == 'closed' )
{ {
$form->add( new \IPS\Helpers\Form\YesNo( 'club_node_public', $this->id ? $this->isPublic() : FALSE ) ); $form->add( new \IPS\Helpers\Form\Radio( 'club_node_public', $this->id ? $this->isPublic() : 0, TRUE, array( 'options' => array( '0' => 'club_node_public_no', '1' => 'club_node_public_view', '2' => 'club_node_public_participate' ) ) ) );
} }
/* Categories */ /* Categories */
@@ -81,11 +81,6 @@ class _Comment extends \IPS\Content\Comment implements \IPS\Content\EditHistory,
* @brief [Content] Key for hide reasons * @brief [Content] Key for hide reasons
*/ */
public static $hideLogKey = 'blog-entries'; public static $hideLogKey = 'blog-entries';
/**
* @brief Whether to track the sentiment scores in cloud_sentiment_scores for this content
*/
public $trackSentimentScore = true;
/** /**
* Get items with permission check * Get items with permission check
+10 -5
View File
@@ -155,11 +155,6 @@ class _Entry extends \IPS\Content\Item implements
* @brief Use a default cover photo * @brief Use a default cover photo
*/ */
public static $coverPhotoDefault = true; public static $coverPhotoDefault = true;
/**
* @brief Whether to track the sentiment scores in cloud_sentiment_scores for this content
*/
public $trackSentimentScore = true;
/** /**
* Set the title * Set the title
@@ -296,6 +291,16 @@ class _Entry extends \IPS\Content\Item implements
return $return; return $return;
} }
/**
* Unclaim attachments
*
* @return void
*/
protected function unclaimAttachments()
{
\IPS\File::unclaimAttachments( 'blog_Entries', $this->id );
}
/** /**
* Get items with permisison check * Get items with permisison check
@@ -0,0 +1,40 @@
<?php
/**
* @brief GraphQL: Calendar mutations
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 22 Oct 2022
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\api\GraphQL;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\Types;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Blog mutationss GraphQL API
*/
abstract class _Mutation
{
/**
* Get the supported query types in this app
*
* @return array
*/
public static function mutations(): array
{
$return = [
'createEvent' => new \IPS\calendar\api\GraphQL\Mutations\CreateEvent(),
];
return $return;
}
}
@@ -0,0 +1,99 @@
<?php
/**
* @brief GraphQL: Create entry mutation
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 22 oct 2022
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\api\GraphQL\Mutations;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Create Event mutation for GraphQL API
*/
class _CreateEvent extends \IPS\Content\Api\GraphQL\ItemMutator
{
/**
* Class
*/
protected $class = \IPS\calendar\Event::class;
/*
* @brief Query description
*/
public static $description = "Create a new calendar event";
/*
* Mutation arguments
*/
public function args(): array
{
$args = parent::args();
$args['calendar'] = TypeRegistry::nonNull( TypeRegistry::id() );
return $args;
}
/**
* Return the mutation return type
*/
public function type()
{
return \IPS\calendar\api\GraphQL\TypeRegistry::event();
}
/**
* Resolves this mutation
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\calendar\Event
*/
public function resolve($val, $args, $context, $info)
{
/* Get calendar */
try
{
$calendar = \IPS\calendar\Calendar::loadAndCheckPerms( $args['calendarID'] );
}
catch ( \OutOfRangeException $e )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_CALENDAR', '1L296/6_graphql', 400 );
}
/* Check permission */
if ( !$calendar->can( 'add', \IPS\Member::loggedIn() ) )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_PERMISSION', '1L296/7_graphql', 403 );
}
/* Check we have a title and a post */
if ( !$args['title'] )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_TITLE', '1L296/8_graphql', 400 );
}
if ( !$args['content'] )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_POST', '1L296/9_grapqhl', 400 );
}
if ( !$args['start'] )
{
throw new \IPS\Api\GraphQL\SafeException( 'INVALID_START', '1L296/A_grapqhl', 400 );
}
return $this->_create( $args, $calendar, $args['postKey'] ?? NULL );
}
}
@@ -0,0 +1,69 @@
<?php
/**
* @brief GraphQL: Forum query
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 10 May 2017
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\api\GraphQL\Queries;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Calendar query for GraphQL API
*/
class _calendar
{
/*
* @brief Query description
*/
public static $description = "Returns a calendar";
/*
* Query arguments
*/
public function args(): array
{
return array(
'id' => TypeRegistry::nonNull( TypeRegistry::id() ),
);
}
/**
* Return the query return type
*/
public function type()
{
return \IPS\calendar\api\GraphQL\TypeRegistry::calendar();
}
/**
* Resolves this query
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\calendar\Calendar
*/
public function resolve($val, $args, $context, $info)
{
$calendar = \IPS\calendar\Calendar::load( $args['id'] );
if( !$calendar->can( 'view', $context['member'] ) )
{
throw new \OutOfRangeException;
}
return $calendar;
}
}
@@ -0,0 +1,64 @@
<?php
/**
* @brief GraphQL: Forums query
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 10 May 2017
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\api\GraphQL\Queries;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Forums query for GraphQL API
*/
class _Calendars
{
/*
* @brief Query description
*/
public static $description = "Returns a list of calendars";
/*
* Query arguments
*/
public function args(): array
{
return array(
'id' => TypeRegistry::id()
);
}
/**
* Return the query return type
*/
public function type()
{
return TypeRegistry::listOf( \IPS\calendar\api\GraphQL\TypeRegistry::calendar() );
}
/**
* Resolves this query
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return array
*/
public function resolve($val, $args, $context, $info)
{
\IPS\calendar\Calendar::loadIntoMemory('view', $context['member']);
return \IPS\calendar\Calendar::roots();
}
}
@@ -0,0 +1,77 @@
<?php
/**
* @brief GraphQL: Topic query
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 10 May 2017
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\api\GraphQL\Queries;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Event query for GraphQL API
*/
class _Event
{
/*
* @brief Query description
*/
public static $description = "Returns an event";
/*
* Query arguments
*/
public function args(): array
{
return array(
'id' => TypeRegistry::nonNull( TypeRegistry::id() )
);
}
/**
* Return the query return type
*/
public function type()
{
return \IPS\calendar\api\GraphQL\TypeRegistry::event();
}
/**
* Resolves this query
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\calendar\Event
*/
public function resolve($val, $args, $context, $info)
{
try
{
$event = \IPS\calendar\Event::loadAndCheckPerms( $args['id'] );
}
catch ( \OutOfRangeException $e )
{
throw new \IPS\Api\GraphQL\SafeException( 'NO_EVENT', '1F294/2_graphql', 400 );
}
if( !$event->can('read') )
{
throw new \IPS\Api\GraphQL\SafeException( 'INVALID_ID', '2F294/9_graphql', 403 );
}
return $event;
}
}
@@ -0,0 +1,127 @@
<?php
/**
* @brief GraphQL: Calender Events query
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 26 January 2023
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\api\GraphQL\Queries;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER[ 'SERVER_PROTOCOL' ] ) ? $_SERVER[ 'SERVER_PROTOCOL' ] : 'HTTP/1.0' ).' 403 Forbidden' );
exit;
}
/**
* Calendar Events query for GraphQL API
*/
class _Events
{
/*
* @brief Query description
*/
public static $description = "Returns a list of events";
/*
* Query arguments
*/
public function args(): array
{
return [
'calendar' => TypeRegistry::listOf( TypeRegistry::int() ),
'offset' => [
'type' => TypeRegistry::int(),
'defaultValue' => 0,
],
'limit' => [
'type' => TypeRegistry::int(),
'defaultValue' => 25,
],
'orderBy' => [
'type' => TypeRegistry::eNum( [
'name' => 'events_order_by',
'description' => 'Fields on which events can be sorted',
'values' => \IPS\calendar\api\GraphQL\Types\EventType::getOrderByOptions(),
] ),
'defaultValue' => NULL, // will use default sort option
],
'orderDir' => [
'type' => TypeRegistry::eNum( [
'name' => 'events_order_dir',
'description' => 'Directions in which items can be sorted',
'values' => [ 'ASC', 'DESC' ],
] ),
'defaultValue' => 'DESC',
],
'honorPinned' => [
'type' => TypeRegistry::boolean(),
'defaultValue' => TRUE,
],
];
}
/**
* Return the query return type
*/
public function type()
{
return TypeRegistry::listOf( \IPS\calendar\api\GraphQL\TypeRegistry::event() );
}
/**
* Resolves this query
*
* @param mixed Value passed into this resolver
* @param array Arguments
* @param array Context values
* @return \IPS\calendar\Event
*/
public function resolve( $val, $args, $context, $info )
{
$where = [];
\IPS\calendar\Calendar::loadIntoMemory( 'view', \IPS\Member::loggedIn() );
$calendarIDs = [];
/* Are we filtering by calendards? */
if( isset( $args[ 'calendars' ] ) && \count( $args[ 'calendars' ] ) )
{
foreach( $args[ 'calendars' ] as $id )
{
$calendar = \IPS\calendar\Calendar::loadAndCheckPerms( $id );
$calendarIDs[] = $calendar->id;
}
if( \count( $calendarIDs ) )
{
$where[ 'container' ][] = [ \IPS\Db::i()->in( 'calendar_events.event_calendar_id', array_filter( $calendarIDs ) ) ];
}
}
/* Get sorting */
if( $args[ 'orderBy' ] === NULL )
{
$orderBy = 'saved';
}
else if( \in_array( $args[ 'orderBy' ], \IPS\calendar\api\GraphQL\Types\EventType::getOrderByOptions() ) )
{
$orderBy = $args[ 'orderBy' ];
}
$sortBy = \IPS\calendar\Event::$databaseTable.'.'.\IPS\calendar\Event::$databasePrefix."{$orderBy} {$args['orderDir']}";
$offset = max( $args[ 'offset' ], 0 );
$limit = min( $args[ 'limit' ], 50 );
return \IPS\calendar\Event::getItemsWithPermission( $where, $sortBy, [ $offset, $limit ], 'read' );
}
}
@@ -0,0 +1,42 @@
<?php
/**
* @brief GraphQL: Calendar queries
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 22 Oct 2022
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\api\GraphQL;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\Types;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Blog queries for GraphQL API
*/
abstract class _Query
{
/**
* Get the supported query types in this app
*
* @return array
*/
public static function queries()
{
return [
'calendar' => new \IPS\calendar\api\GraphQL\Queries\Calendar(),
'calendars' => new \IPS\calendar\api\GraphQL\Queries\Calendars(),
'events' => new \IPS\calendar\api\GraphQL\Queries\Events(),
'event' => new \IPS\calendar\api\GraphQL\Queries\Event(),
];
}
}
@@ -0,0 +1,72 @@
<?php
/**
* @brief GraphQL: Types registry
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 22 Oct 2022
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\api\GraphQL;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\Types;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
class _TypeRegistry
{
/**
* The calendar type instance
* @var \IPS\calendar\api\GraphQL\Types\CalendarType
*/
protected static $calendar;
/**
* The event type instance
* @var \IPS\calendar\api\GraphQL\Types\EventType
*/
protected static $event;
/**
* The event comment instance
* @var \IPS\calendar\api\GraphQL\Types\CalendarType
*/
protected static $comment;
/**
* Constructor
*/
public function __construct()
{
// Defined to suppress static warnings
}
/**
* @return CalendarType
*/
public static function calendar() : \IPS\calendar\api\GraphQL\Types\CalendarType
{
return self::$calendar ?: (self::$calendar = new \IPS\calendar\api\GraphQL\Types\CalendarType());
}
/**
* @return EventType
*/
public static function event() : \IPS\calendar\api\GraphQL\Types\EventType
{
return self::$event ?: (self::$event = new \IPS\calendar\api\GraphQL\Types\EventType());
}
public static function comment() : \IPS\calendar\api\GraphQL\Types\CommentType
{
return self::$comment ?: ( self::$comment = new \IPS\calendar\api\GraphQL\Types\CommentType() );
}
}
@@ -0,0 +1,59 @@
<?php
/**
* @brief GraphQL: Blog Type
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 22 Oct 2022
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* CalendarType for GraphQL API
*/
class _CalendarType extends \IPS\Node\Api\GraphQL\NodeType
{
/*
* @brief The item classname we use for this type
*/
protected static $nodeClass = \IPS\calendar\Calendar::class;
/*
* @brief GraphQL type name
*/
protected static $typeName = 'calendar_Calendar';
/*
* @brief GraphQL type description
*/
protected static $typeDescription = 'A calendar';
/*
* @brief Follow data passed in to FollowType resolver
*/
protected static $followData = array('app' => 'calendar', 'area' => 'calendar');
/**
* Get the item type that goes with this node type
*
* @return ObjectType
*/
public static function getItemType()
{
return \IPS\calendar\api\GraphQL\TypeRegistry::event();
}
}
@@ -0,0 +1,75 @@
<?php
/**
* @brief GraphQL: Post Type
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 10 May 2017
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* PostType for GraphQL API
*/
class _CommentType extends \IPS\Content\Api\GraphQL\CommentType
{
/*
* @brief The item classname we use for this type
*/
protected static $commentClass = \IPS\calendar\Event\Comment::class;
/*
* @brief GraphQL type name
*/
protected static $typeName = 'calendar_Comment';
/*
* @brief GraphQL type description
*/
protected static $typeDescription = 'A calendar event comment';
/**
* Get the item type that goes with this item type
*
* @return ObjectType
*/
public static function getItemType()
{
return \IPS\calendar\api\GraphQL\TypeRegistry::comment();
}
/**
* Return the fields available in this type
*
* @return array
*/
public function fields()
{
$defaultFields = parent::fields();
$postFields = array(
'event' => [
'type' => \IPS\calendar\api\GraphQL\TypeRegistry::event(),
'resolve' => function ($comment) {
return $comment->item();
}
],
);
// Remove duplicated fields
unset( $defaultFields['item'] );
return array_merge( $defaultFields, $postFields );
}
}
@@ -0,0 +1,96 @@
<?php
/**
* @brief GraphQL: Topic Type
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 10 May 2017
* @version SVN_VERSION_NUMBER
*/
namespace IPS\calendar\api\GraphQL\Types;
use GraphQL\Type\Definition\ObjectType;
use IPS\Api\GraphQL\_TypeRegistry;
use IPS\Api\GraphQL\TypeRegistry;
/* To prevent PHP errors (extending class does not exist) revealing path */
if( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER[ 'SERVER_PROTOCOL' ] ) ? $_SERVER[ 'SERVER_PROTOCOL' ] : 'HTTP/1.0' ).' 403 Forbidden' );
exit;
}
/**
* Entry for GraphQL API
*/
class _EventType extends \IPS\Content\Api\GraphQL\ItemType
{
/*
* @brief The item classname we use for this type
*/
protected static $itemClass = \IPS\calendar\Event::class;
/*
* @brief GraphQL type name
*/
protected static $typeName = 'calendar_Event';
/*
* @brief GraphQL type description
*/
protected static $typeDescription = 'A calendar event';
/*
* @brief Follow data passed in to FollowType resolver
*/
protected static $followData = array( 'app' => 'calendar', 'area' => 'event' );
/**
* Get the comment type that goes with this item type
*
* @return ObjectType
*/
protected static function getCommentType()
{
return \IPS\calendar\api\GraphQL\TypeRegistry::comment();
}
/**
* Return the fields available in this type
*
* @return array
*/
public function fields()
{
// Extend our fields with image-specific stuff
$defaultFields = parent::fields();
$imageFields = array(
'start' => [
'type' => TypeRegistry::string(),
'resolve' => function( $event ){
return $event->start_date;
}
]
);
// Remove duplicated fields
unset( $defaultFields[ 'poll' ], $defaultFields[ 'isLocked' ], $defaultFields[ 'isPinned' ], $defaultFields[ 'isFeatured' ] );
return array_merge( $defaultFields, $imageFields );
}
/**
* Return the sort options available for this type
*
* @return array|string[]
*/
public static function getOrderByOptions(): array
{
return array_merge( parent::getOrderByOptions(), array(
'saved','last_comment','start_date'
) );
}
}
+1
View File
@@ -33,6 +33,7 @@ class _events extends \IPS\Content\Api\ItemController
* Get list of events * Get list of events
* *
* @note For requests using an OAuth Access Token for a particular member, only events the authorized user can view will be included * @note For requests using an OAuth Access Token for a particular member, only events the authorized user can view will be included
* @apiparam string ids Comma-delimited list of event IDs
* @apiparam string calendars Comma-delimited list of calendar IDs * @apiparam string calendars Comma-delimited list of calendar IDs
* @apiparam string authors Comma-delimited list of member IDs - if provided, only events started by those members are returned * @apiparam string authors Comma-delimited list of member IDs - if provided, only events started by those members are returned
* @apiparam int locked If 1, only events which are locked are returned, if 0 only unlocked * @apiparam int locked If 1, only events which are locked are returned, if 0 only unlocked
+95 -25
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<javascript app="calendar"> <javascript app="calendar">
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.main.js" javascript_type="controller" javascript_version="107601" javascript_position="1000050"><![CDATA[/** <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.main.js" javascript_type="controller" javascript_version="107643" javascript_position="1000050"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -112,7 +112,7 @@
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.monthView.js" javascript_type="controller" javascript_version="107601" javascript_position="1000050"><![CDATA[/** <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.monthView.js" javascript_type="controller" javascript_version="107643" javascript_position="1000050"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -231,7 +231,7 @@
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/overview" javascript_name="ips.overview.carousel.js" javascript_type="controller" javascript_version="107601" javascript_position="1000100"><![CDATA[/** <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/overview" javascript_name="ips.overview.carousel.js" javascript_type="controller" javascript_version="107643" javascript_position="1000100"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -291,7 +291,7 @@
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/overview" javascript_name="ips.overview.eventList.js" javascript_type="controller" javascript_version="107601" javascript_position="1000100"><![CDATA[/** <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/overview" javascript_name="ips.overview.eventList.js" javascript_type="controller" javascript_version="107643" javascript_position="1000100"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -409,7 +409,7 @@ var PER_PAGE = 16;
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/overview" javascript_name="ips.overview.nearMe.js" javascript_type="controller" javascript_version="107601" javascript_position="1000100"><![CDATA[/** <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/overview" javascript_name="ips.overview.nearMe.js" javascript_type="controller" javascript_version="107643" javascript_position="1000100"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -776,7 +776,7 @@ var PER_PAGE = 16;
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/overview" javascript_name="ips.overview.search.js" javascript_type="controller" javascript_version="107601" javascript_position="1000100"><![CDATA[/** <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/overview" javascript_name="ips.overview.search.js" javascript_type="controller" javascript_version="107643" javascript_position="1000100"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -808,8 +808,6 @@ var PER_PAGE = 16;
*/ */
setup: function () { setup: function () {
var self = this;
// Other setup // Other setup
this._gotCoords = false; this._gotCoords = false;
this._offset = 0; this._offset = 0;
@@ -837,6 +835,34 @@ var PER_PAGE = 16;
// Get map ready to show // Get map ready to show
if( ips.getSetting( 'mapProvider' ) === 'google' ){
this.setupGoogle();
} else {
this.setupMapbox();
}
},
setupGoogle: function(){
var self = this;
self._mapReady = true;
Debug.log( self._resultsContainer.find('[data-eventid]') );
Debug.log( self._mapContainer.attr('data-markers') );
if( self._resultsContainer.find('[data-eventid]').length && self._mapContainer.attr('data-markers') ){
Debug.log('here');
try {
var markers = JSON.parse( self._mapContainer.attr('data-markers') );
Debug.log( markers );
self._updateGoogleMap( markers );
} catch (err) {
Debug.log("Invalid marker JSON");
Debug.log(err);
}
}
},
setupMapbox: function(){
var self = this;
$('head').append( "<link rel='stylesheet' type='text/css' media='all' href='https://api.mapbox.com/mapbox.js/v3.3.1/mapbox.css'><link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v1.0.0/MarkerCluster.css' rel='stylesheet' /><link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v1.0.0/MarkerCluster.Default.css' rel='stylesheet' /><link rel='stylesheet' type='text/css' media='all' href='https://api.mapbox.com/mapbox.js/plugins/leaflet-fullscreen/v1.0.1/leaflet.fullscreen.css' />" ); $('head').append( "<link rel='stylesheet' type='text/css' media='all' href='https://api.mapbox.com/mapbox.js/v3.3.1/mapbox.css'><link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v1.0.0/MarkerCluster.css' rel='stylesheet' /><link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v1.0.0/MarkerCluster.Default.css' rel='stylesheet' /><link rel='stylesheet' type='text/css' media='all' href='https://api.mapbox.com/mapbox.js/plugins/leaflet-fullscreen/v1.0.1/leaflet.fullscreen.css' />" );
ips.loader.get( [ 'https://api.mapbox.com/mapbox.js/v3.3.1/mapbox.js' ] ).then( function () { ips.loader.get( [ 'https://api.mapbox.com/mapbox.js/v3.3.1/mapbox.js' ] ).then( function () {
@@ -844,17 +870,12 @@ var PER_PAGE = 16;
'https://api.mapbox.com/mapbox.js/plugins/leaflet-fullscreen/v1.0.1/Leaflet.fullscreen.min.js' ] ).then( function () { 'https://api.mapbox.com/mapbox.js/plugins/leaflet-fullscreen/v1.0.1/Leaflet.fullscreen.min.js' ] ).then( function () {
self._mapReady = true; self._mapReady = true;
Debug.log( self._resultsContainer.find('[data-eventid]') );
Debug.log( self._mapContainer.attr('data-markers') );
if( self._resultsContainer.find('[data-eventid]').length && self._mapContainer.attr('data-markers') ){ if( self._resultsContainer.find('[data-eventid]').length && self._mapContainer.attr('data-markers') ){
Debug.log('here');
try { try {
var markers = JSON.parse( self._mapContainer.attr('data-markers') ); var markers = JSON.parse( self._mapContainer.attr('data-markers') );
Debug.log( markers ); self._updateMapboxMap( markers );
self._updateMap( markers );
} catch (err) { } catch (err) {
Debug.log("Invalid marker JSON"); Debug.log("Invalid marker JSON");
Debug.log(err); Debug.log(err);
@@ -862,7 +883,6 @@ var PER_PAGE = 16;
} }
}); });
}); });
}, },
getInitialLocation: function () { getInitialLocation: function () {
@@ -1076,7 +1096,57 @@ var PER_PAGE = 16;
}); });
}, },
_updateMap: function (markers) { _updateMap: function ( markers ){
if( ips.getSetting( 'mapProvider' ) === 'google' ){
this._updateGoogleMap( markers );
} else {
this._updateMapboxMap( markers );
}
},
_updateGoogleMap: function (markers){
if( !this._map ){
this._map = new window.google.maps.Map( document.querySelector( '[data-role="searchResultsMap"]' ) );
this._mapMarkers = [];
}
this._mapContainer.removeClass('cEvents__searchMap--loading');
/* Clear existing markers before we rebuild */
if( this._mapMarkers.length ){
for ( let marker of Object.values(this._mapMarkers) ) {
marker.setMap(null);
}
this._mapMarkers = [];
}
var bounds = new google.maps.LatLngBounds();
for ( let marker of Object.values(markers) ) {
let mapMarker = new window.google.maps.Marker({
position: {lat: marker.lat, lng: marker.long},
map: this._map,
title: marker.title
});
this._mapMarkers.push( mapMarker );
var coords = new google.maps.LatLng( marker.lat, marker.long );
if( !( bounds.contains( coords ) ) ){
bounds.extend( coords );
}
}
/* If we have only one marker in here, fitting to the bounds zooms in way too much */
if( this._mapMarkers.length === 1 ){
this._map.setZoom(15);
this._map.setCenter(bounds.getCenter());
} else {
this._map.fitBounds( bounds );
}
this._mapContainer.show();
},
_updateMapboxMap: function (markers) {
if( !this._map ){ if( !this._map ){
L.mapbox.accessToken = ips.getSetting('mapApiKey'); L.mapbox.accessToken = ips.getSetting('mapApiKey');
this._map = L.mapbox this._map = L.mapbox
@@ -1270,8 +1340,9 @@ var PER_PAGE = 16;
this._page.find('[data-role="searchResultsWrapper"]').hide(); this._page.find('[data-role="searchResultsWrapper"]').hide();
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.dates.js" javascript_type="controller" javascript_version="107601" javascript_position="1000150"><![CDATA[/** ]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.dates.js" javascript_type="controller" javascript_version="107643" javascript_position="1000150"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -1844,7 +1915,7 @@ var PER_PAGE = 16;
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/venue" javascript_name="ips.venue.main.js" javascript_type="controller" javascript_version="107601" javascript_position="1000200"><![CDATA[/** <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/venue" javascript_name="ips.venue.main.js" javascript_type="controller" javascript_version="107643" javascript_position="1000200"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -1956,7 +2027,7 @@ var PER_PAGE = 16;
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.reminderButton.js" javascript_type="controller" javascript_version="107601" javascript_position="1000250"><![CDATA[/** <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.reminderButton.js" javascript_type="controller" javascript_version="107643" javascript_position="1000250"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -2039,7 +2110,7 @@ var PER_PAGE = 16;
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.reminderForm.js" javascript_type="controller" javascript_version="107601" javascript_position="1000250">/** <file javascript_app="calendar" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.reminderForm.js" javascript_type="controller" javascript_version="107643" javascript_position="1000250">/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -2149,7 +2220,7 @@ var PER_PAGE = 16;
}); });
}(jQuery, _)); }(jQuery, _));
</file> </file>
<file javascript_app="calendar" javascript_location="front" javascript_path="templates" javascript_name="ips.calendar.templates.js" javascript_type="framework" javascript_version="107601" javascript_position="1000300"><![CDATA[/** <file javascript_app="calendar" javascript_location="front" javascript_path="templates" javascript_name="ips.calendar.templates.js" javascript_type="framework" javascript_version="107643" javascript_position="1000300"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*/ */
@@ -2158,7 +2229,7 @@ var PER_PAGE = 16;
ips.templates.set('calendar.reminder.loading', " \ ips.templates.set('calendar.reminder.loading', " \
<div class='ipsLoading ipsLoading_tiny'></div>\ <div class='ipsLoading ipsLoading_tiny'></div>\
");]]></file> ");]]></file>
<file javascript_app="calendar" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.overview.js" javascript_type="template" javascript_version="107601" javascript_position="1000300"><![CDATA[ips.templates.set("eventLoading", "\ <file javascript_app="calendar" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.overview.js" javascript_type="template" javascript_version="107643" javascript_position="1000300"><![CDATA[ips.templates.set("eventLoading", "\
<li class='ipsBox ipsBox--child event event--withImage event--loading'>\ <li class='ipsBox ipsBox--child event event--withImage event--loading'>\
<div class='cEvents__skeleton cEvents__skeleton--eventImage'></div>\ <div class='cEvents__skeleton cEvents__skeleton--eventImage'></div>\
<div class='cEvents__details'>\ <div class='cEvents__details'>\
@@ -2184,7 +2255,6 @@ controllers</order>
<order app="global" path="/dev/js//library/">underscore <order app="global" path="/dev/js//library/">underscore
jquery jquery
mustache mustache
jstz
IntersectionObserver IntersectionObserver
Debug.js Debug.js
app.js</order> app.js</order>
+2 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<language> <language>
<app key="calendar" version="107601"> <app key="calendar" version="107643">
<word key="__app_calendar" js="0">Events</word> <word key="__app_calendar" js="0">Events</word>
<word key="frontnavigation_calendar" js="0">Events</word> <word key="frontnavigation_calendar" js="0">Events</word>
<word key="__indefart_calendar_event_comment" js="0">a comment on an event</word> <word key="__indefart_calendar_event_comment" js="0">a comment on an event</word>
@@ -480,6 +480,7 @@
<word key="AchievementAction__Rsvp_log" js="0">RSVP'd to %s</word> <word key="AchievementAction__Rsvp_log" js="0">RSVP'd to %s</word>
<word key="AchievementAction__Rsvp_title" js="0">Event RSVP</word> <word key="AchievementAction__Rsvp_title" js="0">Event RSVP</word>
<word key="menu__calendar_stats" js="0">Calendar</word> <word key="menu__calendar_stats" js="0">Calendar</word>
<word key="emailstats__notification_event_reminder" js="0">Event Reminders</word>
<word key="menu__calendar_stats_rsvp" js="0">RSVP</word> <word key="menu__calendar_stats_rsvp" js="0">RSVP</word>
<word key="calendar_stats_rsvp_title" js="0">RSVPs over time</word> <word key="calendar_stats_rsvp_title" js="0">RSVPs over time</word>
<word key="calendar_stats_rsvp_response_0" js="0">Not Going</word> <word key="calendar_stats_rsvp_response_0" js="0">Not Going</word>
+74 -50
View File
@@ -624,7 +624,7 @@
"comment": "", "comment": "",
"decimals": null, "decimals": null,
"default": "0", "default": "0",
"length": 4, "length": 1,
"name": "event_rsvp", "name": "event_rsvp",
"type": "TINYINT", "type": "TINYINT",
"unsigned": false, "unsigned": false,
@@ -636,7 +636,7 @@
"comment": "", "comment": "",
"decimals": null, "decimals": null,
"default": "0", "default": "0",
"length": 4, "length": 1,
"name": "event_approved", "name": "event_approved",
"type": "TINYINT", "type": "TINYINT",
"unsigned": false, "unsigned": false,
@@ -792,7 +792,7 @@
"comment": "Whether the event is locked (for new comments\/reviews) or not", "comment": "Whether the event is locked (for new comments\/reviews) or not",
"decimals": null, "decimals": null,
"default": "0", "default": "0",
"length": 3, "length": 1,
"name": "event_locked", "name": "event_locked",
"type": "TINYINT", "type": "TINYINT",
"unsigned": true, "unsigned": true,
@@ -804,7 +804,7 @@
"comment": "Whether the event is featured or not", "comment": "Whether the event is featured or not",
"decimals": null, "decimals": null,
"default": "0", "default": "0",
"length": 3, "length": 1,
"name": "event_featured", "name": "event_featured",
"type": "TINYINT", "type": "TINYINT",
"unsigned": true, "unsigned": true,
@@ -876,7 +876,7 @@
"comment": "Maximum number of attendees allowed for the event", "comment": "Maximum number of attendees allowed for the event",
"decimals": null, "decimals": null,
"default": null, "default": null,
"length": 11, "length": 10,
"name": "event_rsvp_limit", "name": "event_rsvp_limit",
"type": "INT", "type": "INT",
"unsigned": false, "unsigned": false,
@@ -1020,7 +1020,7 @@
"comment": "", "comment": "",
"decimals": null, "decimals": null,
"default": null, "default": null,
"length": 11, "length": 10,
"name": "event_edit_time", "name": "event_edit_time",
"type": "INT", "type": "INT",
"unsigned": false, "unsigned": false,
@@ -1044,7 +1044,7 @@
"comment": "", "comment": "",
"decimals": null, "decimals": null,
"default": "0", "default": "0",
"length": 4, "length": 1,
"name": "event_append_edit", "name": "event_append_edit",
"type": "TINYINT", "type": "TINYINT",
"unsigned": false, "unsigned": false,
@@ -1062,6 +1062,42 @@
"unsigned": false, "unsigned": false,
"values": [] "values": []
}, },
"event_author_name": {
"allow_null": true,
"auto_increment": false,
"comment": "",
"decimals": null,
"default": null,
"length": 255,
"name": "event_author_name",
"type": "VARCHAR",
"unsigned": false,
"values": []
},
"event_is_anon": {
"allow_null": false,
"auto_increment": false,
"comment": "",
"decimals": null,
"default": "0",
"length": 10,
"name": "event_is_anon",
"type": "INT",
"unsigned": true,
"values": []
},
"event_external_url": {
"allow_null": true,
"auto_increment": false,
"comment": "",
"decimals": null,
"default": null,
"length": 255,
"name": "event_external_url",
"type": "VARCHAR",
"unsigned": false,
"values": []
},
"event_latitude": { "event_latitude": {
"allow_null": true, "allow_null": true,
"auto_increment": false, "auto_increment": false,
@@ -1086,33 +1122,45 @@
"unsigned": false, "unsigned": false,
"values": [] "values": []
}, },
"event_author_name": { "event_online": {
"allow_null": true,
"auto_increment": false,
"comment": "",
"decimals": null,
"default": null,
"length": 255,
"name": "event_author_name",
"type": "VARCHAR",
"unsigned": false,
"values": []
},
"event_is_anon": {
"allow_null": false, "allow_null": false,
"auto_increment": false, "auto_increment": false,
"comment": "", "comment": "",
"decimals": null, "decimals": null,
"default": "0", "default": "0",
"length": 10, "length": 3,
"name": "event_is_anon", "name": "event_online",
"type": "INT", "type": "TINYINT",
"unsigned": true, "unsigned": true,
"values": [] "values": []
}, },
"event_online": { "event_url": {
"name": "event_online", "allow_null": true,
"type": "TINYINT", "auto_increment": false,
"comment": "",
"decimals": null,
"default": null,
"length": 250,
"name": "event_url",
"type": "VARCHAR",
"unsigned": false,
"values": []
},
"event_online_type": {
"allow_null": true,
"auto_increment": false,
"comment": "",
"decimals": null,
"default": null,
"length": 250,
"name": "event_online_type",
"type": "VARCHAR",
"unsigned": false,
"values": []
},
"event_livetopic_id": {
"name": "event_livetopic_id",
"type": "INT",
"length": null, "length": null,
"decimals": null, "decimals": null,
"values": null, "values": null,
@@ -1121,30 +1169,6 @@
"comment": "", "comment": "",
"unsigned": true, "unsigned": true,
"auto_increment": false "auto_increment": false
},
"event_url": {
"name": "event_url",
"type": "VARCHAR",
"length": 250,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": false,
"auto_increment": false
},
"event_online_type": {
"name": "event_online_type",
"type": "VARCHAR",
"length": 250,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": false,
"auto_increment": false
} }
}, },
"indexes": { "indexes": {
+77 -65
View File
@@ -340,7 +340,7 @@
</ul> </ul>
</form> </form>
</div>]]></template> </div>]]></template>
<template template_group="events" template_name="event" template_data="$event, $size='normal'" template_location="front" template_app="calendar"><![CDATA[ <template template_group="events" template_name="event" template_data="$event, $size='normal', $date=NULL" template_location="front" template_app="calendar"><![CDATA[{{$date = $date ?: \IPS\calendar\Date::getDate();}}
{{$sameDay = FALSE;}} {{$sameDay = FALSE;}}
{{if $event->_end_date}} {{if $event->_end_date}}
{{$sameDay = !( ($event->_start_date->mday != $event->_end_date->mday) or ($event->_start_date->mon != $event->_end_date->mon) or ($event->_start_date->year != $event->_end_date->year) );}} {{$sameDay = !( ($event->_start_date->mday != $event->_end_date->mday) or ($event->_start_date->mon != $event->_end_date->mon) or ($event->_start_date->year != $event->_end_date->year) );}}
@@ -364,8 +364,8 @@
</a> </a>
<div class='cEvent__dateAside'> <div class='cEvent__dateAside'>
{{if $event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )}} {{if $event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )}}
<span class='cEvent__dateAside__month'>{lang="_date_month_short" pluralize="$event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )->format( 'n' )"}</span> <span class='cEvent__dateAside__month'>{lang="_date_month_short" pluralize="$event->nextOccurrence( $date, 'startDate' )->format( 'n' )"}</span>
<span class='cEvent__dateAside__day'>{$event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )->format( 'd' )}</span> <span class='cEvent__dateAside__day'>{$event->nextOccurrence( $date, 'startDate' )->format( 'd' )}</span>
{{else}} {{else}}
<span class='cEvent__dateAside__month'>{lang="_date_month_short" pluralize="$event->lastOccurrence( 'startDate' )->format( 'n' )"}</span> <span class='cEvent__dateAside__month'>{lang="_date_month_short" pluralize="$event->lastOccurrence( 'startDate' )->format( 'n' )"}</span>
<span class='cEvent__dateAside__day'>{$event->lastOccurrence( 'startDate' )->format('d')}</span> <span class='cEvent__dateAside__day'>{$event->lastOccurrence( 'startDate' )->format('d')}</span>
@@ -431,9 +431,9 @@
" data-ipsTooltip>{$event->_happening}</span> " data-ipsTooltip>{$event->_happening}</span>
{{else}} {{else}}
<time datetime='{expression="$event->_start_date->format( 'Y-m-d' )"}'> <time datetime='{expression="$event->_start_date->format( 'Y-m-d' )"}'>
{{if $event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )}} {{if $event->nextOccurrence( $date, 'startDate' )}}
<span data-controller="core.global.core.datetime" data-time="{$event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )->format('c')}" data-format="{expression="\IPS\calendar\Date::calendarDateFormat()"}{{if !$event->all_day}}, {{endif}}"> <span data-controller="core.global.core.datetime" data-time="{$event->nextOccurrence( $date, 'startDate' )->format('c')}" data-format="{expression="\IPS\calendar\Date::calendarDateFormat()"}{{if !$event->all_day}}, {{endif}}">
{$event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )->calendarDate()}{{if !$event->all_day}}, {{endif}} {$event->nextOccurrence( $date, 'startDate' )->calendarDate()}{{if !$event->all_day}}, {{endif}}
</span> </span>
{{if !$event->all_day}} {{if !$event->all_day}}
<span data-controller="core.global.core.datetime" data-time="{$event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )->format('c')}" data-format="{expression="\IPS\calendar\Date::localeTimeFormat( FALSE )"}"> <span data-controller="core.global.core.datetime" data-time="{$event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )->format('c')}" data-format="{expression="\IPS\calendar\Date::localeTimeFormat( FALSE )"}">
@@ -537,7 +537,7 @@
<div data-item="{$idx + 1}" class='cFeaturedEvents__event cFeaturedEvents__event--{$idx + 1}'> <div data-item="{$idx + 1}" class='cFeaturedEvents__event cFeaturedEvents__event--{$idx + 1}'>
{{if $image}} {{if $image}}
<img class='cFeaturedEvents__image' src='{backgroundimage="$image->url"}' alt=''> <img class='cFeaturedEvents__image' src='{$image->url}' alt=''>
{{endif}} {{endif}}
<div class='cFeaturedEvents__event-details'> <div class='cFeaturedEvents__event-details'>
@@ -714,9 +714,7 @@
</li> </li>
</ul> </ul>
</div> </div>
{{if $mapMarkers and $mapMarkers !== '[]'}} <div class='cEvents__searchMap cEvents__searchMap--loading event ipsAreaBackground ipsPad ipsSpacer_bottom ipsSpacer_double' data-role='searchResultsMap' {{if $mapMarkers}}data-markers="{$mapMarkers}"{{endif}}></div>
<div class='cEvents__searchMap cEvents__searchMap--loading event ipsAreaBackground ipsPad ipsSpacer_bottom ipsSpacer_double' data-role='searchResultsMap' {{if $mapMarkers}}data-markers="{$mapMarkers}"{{endif}}></div>
{{endif}}
<ul class='eventList {{if !\count( $results )}}ipsHide{{endif}}' data-role='searchResults'> <ul class='eventList {{if !\count( $results )}}ipsHide{{endif}}' data-role='searchResults'>
{template="searchResults" app="calendar" group="events" params="$results"} {template="searchResults" app="calendar" group="events" params="$results"}
</ul> </ul>
@@ -1327,8 +1325,7 @@
<p class='ipsType_light'>{$reason}</p> <p class='ipsType_light'>{$reason}</p>
</div> </div>
{{endif}}]]></template> {{endif}}]]></template>
<template template_group="overview" template_name="byMonth" template_data="$calendars, $date, $featured, $events, $thisCalendar, $months=array()" template_location="front" template_app="calendar"><![CDATA[ <template template_group="overview" template_name="byMonth" template_data="$calendars, $date, $featured, $events, $thisCalendar, $months=array()" template_location="front" template_app="calendar"><![CDATA[<section class='ipsBox' data-controller="calendar.front.overview.eventList">
<section class='ipsBox' data-controller="calendar.front.overview.eventList">
<h2 class='ipsType_sectionTitle'>{lang="events_browse_by_month"}</h2> <h2 class='ipsType_sectionTitle'>{lang="events_browse_by_month"}</h2>
<div class='ipsPadding ipsAreaBackground_light ipsRadius:bl ipsRadius:br'> <div class='ipsPadding ipsAreaBackground_light ipsRadius:bl ipsRadius:br'>
<div class='cEvents__monthNav' data-role='monthNav'> <div class='cEvents__monthNav' data-role='monthNav'>
@@ -1344,7 +1341,7 @@
{{if \count($events) }} {{if \count($events) }}
<ul class='eventList' data-role='eventList'> <ul class='eventList' data-role='eventList'>
{{foreach $events as $event}} {{foreach $events as $event}}
{template="event" app="calendar" group="events" params="$event"} {template="event" app="calendar" group="events" params="$event, 'normal', \IPS\calendar\Date::getDate( $date->firstDayOfMonth('year'), $date->firstDayOfMonth('mon'), $date->firstDayOfMonth('mday') )"}
{{endforeach}} {{endforeach}}
</ul> </ul>
<div class='ipsPadding_top ipsType_center'> <div class='ipsPadding_top ipsType_center'>
@@ -1366,12 +1363,36 @@
<ul class="ipsToolList ipsToolList_horizontal ipsClearfix"> <ul class="ipsToolList ipsToolList_horizontal ipsClearfix">
<li class="ipsToolList_primaryAction"> <li class="ipsToolList_primaryAction">
{{if !\IPS\Settings::i()->club_nodes_in_apps and $theOnlyNode = \IPS\calendar\Calendar::theOnlyNode() }} {{if \IPS\Application::appIsEnabled('cloud') and \IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( 'cloud', 'livetopics' ) ) and \IPS\cloud\LiveTopic::canCreate( \IPS\Member::loggedIn() )}}
<a class="ipsButton ipsButton_medium ipsButton_important" href="{url="app=calendar&module=calendar&controller=submit&do=submit&id={$theOnlyNode->_id}" seoTemplate="calendar_submit"}">{lang="create_event"}</a> <a href="#elEventCreate_menu" id="elEventCreate" class="ipsButton ipsButton_medium ipsButton_important" data-ipsMenu>{lang="livetopic_create_event"} <i class="fa fa-caret-down"></i></a>
{{elseif ( $thisCalendar AND $thisCalendar->can('add') )}} <ul id="elEventCreate_menu" class="ipsMenu ipsMenu_normal ipsHide">
<a class="ipsButton ipsButton_medium ipsButton_important" href='{url="app=calendar&module=calendar&controller=submit&do=submit&id={$thisCalendar->_id}" seoTemplate="calendar_submit"}' data-ipsTooltip title='{lang="add_event"}'>{lang="create_event"}</a> <li class="ipsMenu_item" data-menuItem="livetopic">
{{elseif \IPS\calendar\Calendar::canOnAny('add')}} {{if !\IPS\Settings::i()->club_nodes_in_apps and $theOnlyNode = \IPS\calendar\Calendar::theOnlyNode() }}
<a class="ipsButton ipsButton_medium ipsButton_important" href="{url="app=calendar&module=calendar&controller=submit" seoTemplate="calendar_submit"}" data-ipsdialog="" data-ipsdialog-size="narrow" data-ipsdialog-title="{lang="select_calendar"}">{lang="create_event"}</a> <a class="ipsMenu_link" href="{url="app=calendar&module=calendar&controller=submit&do=livetopic&id={$theOnlyNode->_id}" seoTemplate="calendar_submit"}">{lang="event_create_livetopic"}</a>
{{elseif ( $thisCalendar AND $thisCalendar->can('add') )}}
<a class="ipsMenu_link" href='{url="app=calendar&module=calendar&controller=submit&do=livetopic&id={$thisCalendar->_id}" seoTemplate="calendar_submit"}' data-ipsTooltip title='{lang="add_event"}'>{lang="event_create_livetopic"}</a>
{{elseif \IPS\calendar\Calendar::canOnAny('add')}}
<a class="ipsMenu_link" href="{url="app=calendar&module=calendar&controller=submit&do=livetopic" seoTemplate="calendar_submit"}">{lang="event_create_livetopic"}</a>
{{endif}}
</li>
<li class="ipsMenu_item" data-menuItem="event">
{{if !\IPS\Settings::i()->club_nodes_in_apps and $theOnlyNode = \IPS\calendar\Calendar::theOnlyNode() }}
<a class="ipsMenu_link" href="{url="app=calendar&module=calendar&controller=submit&do=submit&id={$theOnlyNode->_id}" seoTemplate="calendar_submit"}">{lang="event_create_normal"}</a>
{{elseif ( $thisCalendar AND $thisCalendar->can('add') )}}
<a class="ipsMenu_link" href='{url="app=calendar&module=calendar&controller=submit&do=submit&id={$thisCalendar->_id}" seoTemplate="calendar_submit"}' data-ipsTooltip title='{lang="add_event"}'>{lang="event_create_normal"}</a>
{{elseif \IPS\calendar\Calendar::canOnAny('add')}}
<a class="ipsMenu_link" href="{url="app=calendar&module=calendar&controller=submit" seoTemplate="calendar_submit"}" data-ipsdialog="" data-ipsdialog-size="narrow" data-ipsdialog-title="{lang="select_calendar"}">{lang="event_create_normal"}</a>
{{endif}}
</li>
</ul>
{{else}}
{{if !\IPS\Settings::i()->club_nodes_in_apps and $theOnlyNode = \IPS\calendar\Calendar::theOnlyNode() }}
<a class="ipsButton ipsButton_medium ipsButton_important" href="{url="app=calendar&module=calendar&controller=submit&do=submit&id={$theOnlyNode->_id}" seoTemplate="calendar_submit"}">{lang="create_event"}</a>
{{elseif ( $thisCalendar AND $thisCalendar->can('add') )}}
<a class="ipsButton ipsButton_medium ipsButton_important" href='{url="app=calendar&module=calendar&controller=submit&do=submit&id={$thisCalendar->_id}" seoTemplate="calendar_submit"}' data-ipsTooltip title='{lang="add_event"}'>{lang="create_event"}</a>
{{elseif \IPS\calendar\Calendar::canOnAny('add')}}
<a class="ipsButton ipsButton_medium ipsButton_important" href="{url="app=calendar&module=calendar&controller=submit" seoTemplate="calendar_submit"}" data-ipsdialog="" data-ipsdialog-size="narrow" data-ipsdialog-title="{lang="select_calendar"}">{lang="create_event"}</a>
{{endif}}
{{endif}} {{endif}}
</li> </li>
<li> <li>
@@ -1723,6 +1744,10 @@
{template="pageHeader" group="global" app="core" params="$pageHeader"} {template="pageHeader" group="global" app="core" params="$pageHeader"}
{{if isset( \IPS\Request::i()->do ) and \IPS\Request::i()->do === 'livetopic'}}
<div class="ipsMargin_top ipsMargin_bottom">{lang="ai_service_livetopics_desc"}</div>
{{endif}}
{$output|raw}]]></template> {$output|raw}]]></template>
<template template_group="venue" template_name="upcomingStream" template_data="$date, $events, $venue" template_location="front" template_app="calendar"><![CDATA[ <template template_group="venue" template_name="upcomingStream" template_data="$date, $events, $venue" template_location="front" template_app="calendar"><![CDATA[
<div class='ipsPager cCalendarNav ipsSpacer_bottom lg:ipsPos_sticky'> <div class='ipsPager cCalendarNav ipsSpacer_bottom lg:ipsPos_sticky'>
@@ -2168,6 +2193,11 @@
</div> </div>
{{endif}} {{endif}}
{{endif}} {{endif}}
{{if $livetopic = $event->_livetopic_id}}
<div class='ipsBox ipsResponsive_pull ipsMargin_bottom ipsPadding'>
<a href='{$livetopic->url()}' target='_blank' class='ipsButton ipsButton_important ipsButton_fullWidth ipsMargin_bottom:half'>{lang="open_event"} <i class="fa fa-external-link" aria-hidden="true" style='margin-inline:.4em'></i></a>
</div>
{{endif}}
{{if $event->rsvp }} {{if $event->rsvp }}
<div class='ipsBox ipsResponsive_pull'> <div class='ipsBox ipsResponsive_pull'>
@@ -2483,7 +2513,7 @@
{{endif}} {{endif}}
</div>]]></template> </div>]]></template>
<template template_group="view" template_name="rsvpControls" template_data="$event, $attendees" template_location="front" template_app="calendar"><![CDATA[<!-- Don't use IDs here, this template is called twice in view --> <template template_group="view" template_name="rsvpControls" template_data="$event, $attendees" template_location="front" template_app="calendar"><![CDATA[<!-- Don't use IDs here, this template is called twice in view -->
{{if \IPS\Member::loggedIn()->member_id AND ( isset( $attendees[0][ \IPS\Member::loggedIn()->member_id ] ) OR isset( $attendees[1][ \IPS\Member::loggedIn()->member_id ] ) OR isset( $attendees[2][ \IPS\Member::loggedIn()->member_id ] ) )}} {{if \IPS\Member::loggedIn()->member_id AND ( isset( $attendees[0][ \IPS\Member::loggedIn()->member_id ] ) OR isset( $attendees[1][ \IPS\Member::loggedIn()->member_id ] ) OR ( isset( $attendees[2][ \IPS\Member::loggedIn()->member_id ] ) ) AND \count( $attendees[1] ) < $event->rsvp_limit )}}
<div class='{{if isset( $attendees[1][ \IPS\Member::loggedIn()->member_id ] )}}ipsAreaBackground_positive{{elseif isset( $attendees[0][ \IPS\Member::loggedIn()->member_id ] )}}ipsAreaBackground_negative{{else}}ipsAreaBackground_reset{{endif}} ipsPadding'> <div class='{{if isset( $attendees[1][ \IPS\Member::loggedIn()->member_id ] )}}ipsAreaBackground_positive{{elseif isset( $attendees[0][ \IPS\Member::loggedIn()->member_id ] )}}ipsAreaBackground_negative{{else}}ipsAreaBackground_reset{{endif}} ipsPadding'>
<p class='ipsType_large ipsType_center ipsType_reset'> <p class='ipsType_large ipsType_center ipsType_reset'>
<strong> <strong>
@@ -2592,7 +2622,7 @@
{template="contentItemMessages" group="global" app="core" params="$event->getMessages(), $event"} {template="contentItemMessages" group="global" app="core" params="$event->getMessages(), $event"}
<div id="sidebarWrapper"> <div id="sidebarWrapper">
{{if $event->rsvp || $address || $event->map( 270, 270 ) || $event->online }} {{if $event->rsvp || $address || $event->map( 270, 270 ) || $event->online || $event->_livetopic_id }}
<div class='ipsColumns ipsColumns_collapsePhone'> <div class='ipsColumns ipsColumns_collapsePhone'>
<div class='ipsColumn ipsColumn_fluid'> <div class='ipsColumn ipsColumn_fluid'>
{{endif}} {{endif}}
@@ -2608,7 +2638,7 @@
{{endif}} {{endif}}
</div> </div>
<div class='ipsFlex-flex:01 ipsResponsive_hidePhone'> <div class='ipsFlex-flex:01 ipsResponsive_hidePhone'>
<div class='ipsFlex ipsFlex-ai:center ipsFlex-fw:wrap ipsGap:2'> <div class='ipsShareLinks'>
{{if \count( $event->shareLinks() )}} {{if \count( $event->shareLinks() )}}
{template="shareButton" app="core" group="sharelinks" params="$event"} {template="shareButton" app="core" group="sharelinks" params="$event"}
{{endif}} {{endif}}
@@ -2715,7 +2745,7 @@
</ul> </ul>
</div> </div>
</div> </div>
{{if $event->rsvp || $address || $event->map( 270, 270 ) || ( $event->online and $event->url and !$event->hasPassed() ) }} {{if $event->rsvp || $address || $event->map( 270, 270 ) || ( $event->online and $event->url and !$event->hasPassed() ) || $event->_livetopic_id}}
</div> </div>
<aside class='ipsColumn ipsColumn_veryWide'> <aside class='ipsColumn ipsColumn_veryWide'>
<div> <div>
@@ -2728,23 +2758,15 @@
</section> </section>
<div class='ipsBox ipsPadding ipsResponsive_pull ipsResponsive_showPhone ipsMargin_top'> <div class='ipsBox ipsPadding ipsResponsive_pull ipsResponsive_showPhone ipsMargin_top'>
<div class='ipsGap_row:3'> <div class='ipsShareLinks'>
{{if \count( $event->shareLinks() )}} {{if \count( $event->shareLinks() )}}
<div> {template="shareButton" app="core" group="sharelinks" params="$event, 'verySmall', 'light'"}
{template="shareButton" app="core" group="sharelinks" params="$event, 'verySmall', 'light'"}
</div>
{{endif}} {{endif}}
{{if $event->canRemind()}} {{if $event->canRemind()}}
<div> {template="reminder" app="calendar" group="view" params="$event, $reminder, 'ipsButton_fullWidth'"}
{template="reminder" app="calendar" group="view" params="$event, $reminder, 'ipsButton_fullWidth'"}
</div>
{{endif}} {{endif}}
<div> {template="follow" app="core" group="global" params="'calendar', 'event', $event->id, $event->followersCount()"}
{template="follow" app="core" group="global" params="'calendar', 'event', $event->id, $event->followersCount()"} {template="promote" app="core" group="global" params="$event"}
</div>
<div>
{template="promote" app="core" group="global" params="$event"}
</div>
</div> </div>
</div> </div>
@@ -2766,27 +2788,25 @@
<template template_group="widgets" template_name="recentReviews" template_data="$reviews, $orientation='vertical'" template_location="front" template_app="calendar"><![CDATA[<h3 class='ipsType_reset ipsWidget_title'>{lang="block_recentReviews"}</h3> <template template_group="widgets" template_name="recentReviews" template_data="$reviews, $orientation='vertical'" template_location="front" template_app="calendar"><![CDATA[<h3 class='ipsType_reset ipsWidget_title'>{lang="block_recentReviews"}</h3>
<div class='ipsWidget_inner'> <div class='ipsWidget_inner'>
{{if $orientation == 'vertical'}} {{if $orientation == 'vertical'}}
<div class='ipsPad_half'> {{if !empty( $reviews ) }}
{{if !empty( $reviews ) }} <ul class='ipsDataList ipsDataList_reducedSpacing'>
<ul class='ipsDataList ipsDataList_reducedSpacing'> {{foreach $reviews as $review}}
{{foreach $reviews as $review}} <li class='ipsDataItem'>
<li class='ipsDataItem'> <div class='ipsDataItem_icon'>
<div class='ipsDataItem_icon'> {template="userPhoto" app="core" group="global" params="$review->author(), 'tiny'"}
{template="userPhoto" app="core" group="global" params="$review->author(), 'tiny'"} </div>
</div> <div class='ipsDataItem_main ipsType_break ipsContained'>
<div class='ipsDataItem_main ipsType_break ipsContained'> <a href="{$review->item()->url( "getPrefComment" )}" title='{lang="view_this_event" sprintf="$review->item()->title"}' class='ipsTruncate ipsTruncate_line'>{$review->item()->title}</a><br>
<a href="{$review->item()->url( "getPrefComment" )}" title='{lang="view_this_event" sprintf="$review->item()->title"}' class='ipsTruncate ipsTruncate_line'>{$review->item()->title}</a><br> <span class='ipsType_light ipsType_medium'>{lang="byline_nodate" htmlsprintf="$review->author()->link()"}</span><br>
<span class='ipsType_light ipsType_medium'>{lang="byline_nodate" htmlsprintf="$review->author()->link()"}</span><br> {template="rating" group="global" location="front" app="core" params="'small', $review->rating, \IPS\Settings::i()->reviews_rating_out_of"} &nbsp;&nbsp;
{template="rating" group="global" location="front" app="core" params="'small', $review->rating, \IPS\Settings::i()->reviews_rating_out_of"} &nbsp;&nbsp; <span class='ipsType_small ipsType_reset'><time datetime="{$review->mapped('date')}">{datetime="$review->mapped('date')" norelative="true"}</time></span>
<span class='ipsType_small ipsType_reset'><time datetime="{$review->mapped('date')}">{datetime="$review->mapped('date')" norelative="true"}</time></span> </div>
</div> </li>
</li> {{endforeach}}
{{endforeach}} </ul>
</ul> {{else}}
{{else}} <div class='ipsType_light ipsPadding:half ipsType_center'>{lang="no_recent_reviews"}</div>
<div class='ipsType_light ipsPad_half ipsType_center'>{lang="no_recent_reviews"}</div> {{endif}}
{{endif}}
</div>
{{else}} {{else}}
{{if !empty( $reviews ) }} {{if !empty( $reviews ) }}
<ul class='ipsDataList ipsDataList_reducedSpacing'> <ul class='ipsDataList ipsDataList_reducedSpacing'>
@@ -2813,10 +2833,6 @@
<template template_group="widgets" template_name="upcomingEvents" template_data="$events, $today, $orientation='vertical'" template_location="front" template_app="calendar"><![CDATA[<h3 class='ipsType_reset ipsWidget_title'>{lang="block_upcomingEvents"}</h3> <template template_group="widgets" template_name="upcomingEvents" template_data="$events, $today, $orientation='vertical'" template_location="front" template_app="calendar"><![CDATA[<h3 class='ipsType_reset ipsWidget_title'>{lang="block_upcomingEvents"}</h3>
<div class='ipsWidget_inner'> <div class='ipsWidget_inner'>
{{if $orientation == 'vertical'}}
<div class='ipsPad_half'>
{{endif}}
{{if !empty( $events ) }} {{if !empty( $events ) }}
<ul class='ipsDataList ipsDataList_reducedSpacing'> <ul class='ipsDataList ipsDataList_reducedSpacing'>
@@ -2889,10 +2905,6 @@
<div class='ipsType_light ipsPad_half ipsType_center'>{lang="no_upcoming_events"}</div> <div class='ipsType_light ipsPad_half ipsType_center'>{lang="no_upcoming_events"}</div>
{{endif}} {{endif}}
{{if $orientation == 'vertical'}}
</div>
{{endif}}
</div>]]></template> </div>]]></template>
<css css_location="front" css_app="calendar" css_attributes="" css_path="." css_name="calendar_responsive.css"><![CDATA[/* BOTH */ <css css_location="front" css_app="calendar" css_attributes="" css_path="." css_name="calendar_responsive.css"><![CDATA[/* BOTH */
@media screen and (max-width: 979px) { @media screen and (max-width: 979px) {
+15 -1
View File
@@ -507,5 +507,19 @@
"107504": "4.7.5", "107504": "4.7.5",
"107505": "4.7.5", "107505": "4.7.5",
"107600": "4.7.6 Beta 1", "107600": "4.7.6 Beta 1",
"107601": "4.7.6" "107601": "4.7.6",
"107602": "4.7.6",
"107620": "4.7.7 Beta 1",
"107621": "4.7.7 Beta 2",
"107622": "4.7.7 Beta 2",
"107623": "4.7.7 Beta 3",
"107624": "4.7.7 Beta 4",
"107625": "4.7.7",
"107626": "4.7.7",
"107627": "4.7.7",
"107628": "4.7.7",
"107640": "4.7.8 Beta 1",
"107641": "4.7.8 Beta 2",
"107642": "4.7.8 Beta 3",
"107643": "4.7.8"
} }
@@ -369,6 +369,18 @@ class _event extends \IPS\Content\Controller
*/ */
protected function edit() protected function edit()
{ {
if ( \IPS\Application::appIsEnabled('cloud') and $this->event->livetopic_id )
{
/* Allow live topic edit form to handle this */
try
{
/* Make sure it's a valid topic */
$liveTopic = \IPS\cloud\LiveTopic::load( $this->event->livetopic_id );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=modcp&controller=modcp&tab=livetopics&action=create&fromEvent=1&id=' . $liveTopic->id, 'front', 'modcp_livetopics' ) );
}
catch( \Exception ) { }
}
/* Are we blocking changes to past events? */ /* Are we blocking changes to past events? */
if( $this->event->hasPassed() AND \IPS\Settings::i()->calendar_block_past_changes ) if( $this->event->hasPassed() AND \IPS\Settings::i()->calendar_block_past_changes )
{ {
@@ -648,7 +648,7 @@ class _view extends \IPS\Dispatcher\Controller
/* Build an array of month objects for the nav */ /* Build an array of month objects for the nav */
$months = new \DatePeriod( (new \DateTime)->setDate( date('Y'), date('m'), 1 ), new \DateInterval( 'P1M' ), 11 ); $months = new \DatePeriod( (new \DateTime)->setDate( date('Y'), date('m'), 1 ), new \DateInterval( 'P1M' ), 11 );
$stream = \IPS\Theme::i()->getTemplate( 'overview', 'calendar' )->byMonth( $calendars, $date, $featured, $events, NULL, $months ); $stream = \IPS\Theme::i()->getTemplate( 'overview', 'calendar' )->byMonth( $calendars, \IPS\calendar\Date::getDate( $date->firstDayOfMonth('year'), $date->firstDayOfMonth('mon'), $date->firstDayOfMonth('mday') ), $featured, $events, NULL, $months );
$form = $this->getForm(); $form = $this->getForm();
@@ -762,16 +762,14 @@ class _view extends \IPS\Dispatcher\Controller
{ {
$having[] = 'distance < 500'; $having[] = 'distance < 500';
} }
if( isset( \IPS\Request::i()->sortBy ) && \IPS\Request::i()->sortBy == 'nearest' )
{
$sort = 'distance asc';
}
} }
} }
$sort = 'event_start_date asc';
if( isset( \IPS\Request::i()->sortBy ) && \IPS\Request::i()->sortBy == 'nearest' && $location )
{
$sort = 'distance asc';
}
/* Filter? */ /* Filter? */
if( isset( \IPS\Request::i()->show ) && \IPS\Request::i()->show !== 'all' ) if( isset( \IPS\Request::i()->show ) && \IPS\Request::i()->show !== 'all' )
{ {
@@ -109,7 +109,7 @@
"params": [ "params": [
"calendar_events", "calendar_events",
{ {
"name": "event_appened_edit", "name": "event_append_edit",
"type": "TINYINT", "type": "TINYINT",
"length": 1, "length": 1,
"decimals": null, "decimals": null,
@@ -128,7 +128,7 @@
"method": "changeColumn", "method": "changeColumn",
"params": [ "params": [
"calendar_events", "calendar_events",
"event_appened_edit", "event_append_edit",
{ {
"name": "event_append_edit", "name": "event_append_edit",
"type": "TINYINT", "type": "TINYINT",
@@ -0,0 +1,23 @@
{
"id": 107602,
"name": "4.7.6",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107620,
"name": "4.7.7 Beta 1",
"steps": {
"queries": false,
"lang": true,
"theme": true,
"themeSettings": false,
"javascript": true,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": true,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,14 @@
{
"files": {
"added": [],
"edited": [],
"removed": []
},
"orders": {
"added": [],
"edited": [
"global\/\/dev\/js\/\/library\/"
],
"removed": []
}
}
@@ -0,0 +1,14 @@
{
"normal": {
"added": [
"emailstats__notification_event_reminder"
],
"edited": [],
"removed": []
},
"js": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,20 @@
{
"html": {
"added": [],
"edited": [
"front\/events\/event",
"front\/overview\/byMonth"
],
"removed": []
},
"css": {
"added": [],
"edited": [],
"removed": []
},
"resources": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,23 @@
{
"id": 107621,
"name": "4.7.7 Beta 2",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107622,
"name": "4.7.7 Beta 2",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107623,
"name": "4.7.7 Beta 3",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107624,
"name": "4.7.7 Beta 4",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107625,
"name": "4.7.7",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107626,
"name": "4.7.7",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107627,
"name": "4.7.7",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107628,
"name": "4.7.7",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107640,
"name": "4.7.8 Beta 1",
"steps": {
"queries": true,
"lang": false,
"theme": true,
"themeSettings": false,
"javascript": true,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,14 @@
{
"files": {
"added": [],
"edited": [
"calendar\/front\/controllers\/overview\/ips.overview.search.js"
],
"removed": []
},
"orders": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,20 @@
{
"1": {
"method": "addColumn",
"params": [
"calendar_events",
{
"name": "event_livetopic_id",
"type": "INT",
"length": null,
"decimals": null,
"values": null,
"allow_null": false,
"default": 0,
"comment": "",
"unsigned": true,
"auto_increment": false
}
]
}
}
@@ -0,0 +1,27 @@
{
"html": {
"added": [],
"edited": [
"front\/events\/featuredEvent",
"front\/events\/searchResultsWrapper",
"front\/overview\/header",
"front\/submit\/submitPage",
"front\/view\/eventSidebar",
"front\/view\/rsvpControls",
"front\/view\/view",
"front\/widgets\/recentReviews",
"front\/widgets\/upcomingEvents"
],
"removed": []
},
"css": {
"added": [],
"edited": [],
"removed": []
},
"resources": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,23 @@
{
"id": 107641,
"name": "4.7.8 Beta 2",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107642,
"name": "4.7.8 Beta 3",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,23 @@
{
"id": 107643,
"name": "4.7.8",
"steps": {
"queries": false,
"lang": false,
"theme": false,
"themeSettings": false,
"javascript": false,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": false,
"settings": false,
"tasks": false,
"modules": false,
"widgets": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -332,7 +332,7 @@ class _Calendar extends \IPS\Node\Model implements \IPS\Node\Permissions
$form->add( new \IPS\Helpers\Form\YesNo( 'cal_allow_reviews', $this->id ? $this->allow_reviews : FALSE, FALSE, array( 'togglesOn' => array( 'cal_review_moderate' ) ) ) ); $form->add( new \IPS\Helpers\Form\YesNo( 'cal_allow_reviews', $this->id ? $this->allow_reviews : FALSE, FALSE, array( 'togglesOn' => array( 'cal_review_moderate' ) ) ) );
if( $club->type == 'closed' ) if( $club->type == 'closed' )
{ {
$form->add( new \IPS\Helpers\Form\YesNo( 'club_node_public', $this->id ? $this->isPublic() : FALSE ) ); $form->add( new \IPS\Helpers\Form\Radio( 'club_node_public', $this->id ? $this->isPublic() : 0, TRUE, array( 'options' => array( '0' => 'club_node_public_no', '1' => 'club_node_public_view', '2' => 'club_node_public_participate' ) ) ) );
} }
} }
+7 -1
View File
@@ -334,7 +334,13 @@ class _Date extends \IPS\DateTime
public function adjust( $adjustment ) public function adjust( $adjustment )
{ {
$datetime = \IPS\DateTime::ts( $this->dateInformation[0] )->setTimezone( new \DateTimeZone( "UTC" ) ); $datetime = \IPS\DateTime::ts( $this->dateInformation[0] )->setTimezone( new \DateTimeZone( "UTC" ) );
$datetime->add( \DateInterval::createFromDateString( $adjustment ) ); $dateInterval=\DateInterval::createFromDateString( $adjustment );
if( $dateInterval )
{
$datetime->add( $dateInterval );
}
return static::getDate( gmdate( 'Y', $datetime->getTimestamp() ), gmdate( 'm', $datetime->getTimestamp() ), gmdate( 'd', $datetime->getTimestamp() ), gmdate( 'H', $datetime->getTimestamp() ), gmdate( 'i', $datetime->getTimestamp() ), gmdate( 's', $datetime->getTimestamp() ) ); return static::getDate( gmdate( 'Y', $datetime->getTimestamp() ), gmdate( 'm', $datetime->getTimestamp() ), gmdate( 'd', $datetime->getTimestamp() ), gmdate( 'H', $datetime->getTimestamp() ), gmdate( 'i', $datetime->getTimestamp() ), gmdate( 's', $datetime->getTimestamp() ) );
} }
@@ -81,11 +81,6 @@ class _Comment extends \IPS\Content\Comment implements \IPS\Content\EditHistory,
* @brief [Content] Key for hide reasons * @brief [Content] Key for hide reasons
*/ */
public static $hideLogKey = 'calendar-events'; public static $hideLogKey = 'calendar-events';
/**
* @brief Whether to track the sentiment scores in cloud_sentiment_scores for this content
*/
public $trackSentimentScore = true;
/** /**
* Get URL for doing stuff * Get URL for doing stuff
+28 -3
View File
@@ -472,7 +472,7 @@ class _Event extends \IPS\Content\Item implements
$results[] = array( 'startDate' => $date, 'endDate' => $eDate ); $results[] = array( 'startDate' => $date, 'endDate' => $eDate );
} }
/* Figure out which of teh days is next. For example, if the start date is a Wednesday, and the /* Figure out which of the days is next. For example, if the start date is a Wednesday, and the
event repeats every Monday and Friday, we need to start with Friday (not Monday) because that's event repeats every Monday and Friday, we need to start with Friday (not Monday) because that's
when the first occurance is */ when the first occurance is */
$nextTimes = array(); $nextTimes = array();
@@ -1053,6 +1053,28 @@ class _Event extends \IPS\Content\Item implements
return $this->dateObjects['end']; return $this->dateObjects['end'];
} }
/**
* Get the live topic, or NULL if one not available
*
* @return \IPS\cloud\LiveTopic|null
*/
public function get__livetopic_id(): ?\IPS\cloud\LiveTopic
{
if ( ! \IPS\Application::appIsEnabled('cloud') )
{
return NULL;
}
try
{
return \IPS\cloud\LiveTopic::load( $this->livetopic_id );
}
catch( \Exception )
{
return NULL;
}
}
/** /**
* Get a string with the event date/times in the timezone of the user who created the event * Get a string with the event date/times in the timezone of the user who created the event
@@ -2304,8 +2326,11 @@ class _Event extends \IPS\Content\Item implements
public function hasPassed() public function hasPassed()
{ {
// Get the end date. If none is available use the start date plus an hour so that online event join links show for a short while after the start // Get the end date. If none is available use the start date plus an hour so that online event join links show for a short while after the start
$lastOccurrence = $this->lastOccurrence( 'endDate' ) ?? $this->lastOccurrence( 'startDate' )->add( new \DateInterval("PT1H") ); $lastOccurrence = $this->lastOccurrence( 'endDate' ) ?? $this->lastOccurrence( 'startDate' );
if ( $lastOccurrence < \IPS\DateTime::ts( time() ) )
$lastOccurrenceClone = clone $lastOccurrence;
$lastOccurrenceClone = $lastOccurrenceClone->add( new \DateInterval("PT1H") );
if ( $lastOccurrenceClone < \IPS\DateTime::ts( time() ) )
{ {
return true; return true;
} }
@@ -85,11 +85,6 @@ class _Review extends \IPS\Content\Review implements \IPS\Content\EditHistory, \
* @brief [Content] Key for hide reasons * @brief [Content] Key for hide reasons
*/ */
public static $hideLogKey = 'calendar-events-rev'; public static $hideLogKey = 'calendar-events-rev';
/**
* @brief Whether to track the sentiment scores in cloud_sentiment_scores for this content
*/
public $trackSentimentScore = true;
/** /**
* Get URL for doing stuff * Get URL for doing stuff
+2 -1
View File
@@ -48,7 +48,7 @@ spl_autoload_register( function( $class )
public static \$databaseColumnMap = array( public static \$databaseColumnMap = array(
'author' => 'member_id', 'author' => 'member_id',
'container' => 'category_id', 'container' => 'category_id',
'date' => 'record_publish_date', 'date' => 'record_saved',
'is_future_entry' => 'record_future_date', 'is_future_entry' => 'record_future_date',
'future_date' => 'record_publish_date', 'future_date' => 'record_publish_date',
'title' => 'field_{$titleField}', 'title' => 'field_{$titleField}',
@@ -76,6 +76,7 @@ spl_autoload_register( function( $class )
'meta_data' => 'record_meta_data', 'meta_data' => 'record_meta_data',
'author_name' => 'record_author_name', 'author_name' => 'record_author_name',
'is_anon' => 'record_is_anon', 'is_anon' => 'record_is_anon',
'last_comment_anon' => 'record_last_comment_anon'
); );
public static \$pagePath; public static \$pagePath;
} }
+1
View File
@@ -71,6 +71,7 @@ class _records extends \IPS\Content\Api\ItemController
* *
* @note For requests using an OAuth Access Token for a particular member, only records the authorized user can view will be included * @note For requests using an OAuth Access Token for a particular member, only records the authorized user can view will be included
* @param int $database Database ID * @param int $database Database ID
* @apiparam string ids Comma-delimited list of record IDs
* @apiparam string categories Comma-delimited list of category IDs * @apiparam string categories Comma-delimited list of category IDs
* @apiparam string authors Comma-delimited list of member IDs - if provided, only records started by those members are returned * @apiparam string authors Comma-delimited list of member IDs - if provided, only records started by those members are returned
* @apiparam int locked If 1, only records which are locked are returned, if 0 only unlocked * @apiparam int locked If 1, only records which are locked are returned, if 0 only unlocked
+19 -19
View File
@@ -36,7 +36,7 @@
</span> </span>
</h2> </h2>
<p class='ipsType_light ipsType_reset cmsInformation'> <p class='ipsType_light ipsType_reset cmsInformation'>
{lang="cms_byline" htmlsprintf="$record->author()->link( NULL, NULL, $record->isAnonymous() ), $record->container()->url(), $record->container()->_title"}{datetime="$record->record_publish_date"} {lang="cms_byline" htmlsprintf="$record->author()->link( NULL, NULL, $record->isAnonymous() ), $record->container()->url(), $record->container()->_title"}{datetime="$record->mapped( 'date' )"}
</p> </p>
</div> </div>
</header> </header>
@@ -221,7 +221,7 @@
{{endif}} {{endif}}
</h2> </h2>
<p class='ipsType_light ipsType_reset cmsInformation'> <p class='ipsType_light ipsType_reset cmsInformation'>
{lang="cms_byline" htmlsprintf="$record->author()->link( NULL, NULL, $record->isAnonymous() ), $record->container()->url(), $record->container()->_title"}{datetime="$record->record_publish_date"} {lang="cms_byline" htmlsprintf="$record->author()->link( NULL, NULL, $record->isAnonymous() ), $record->container()->url(), $record->container()->_title"}{datetime="$record->mapped( 'date' )"}
</p> </p>
</div> </div>
</header> </header>
@@ -406,7 +406,7 @@
</span> </span>
</h2> </h2>
<p class='ipsType_light ipsType_reset'> <p class='ipsType_light ipsType_reset'>
{lang="cms_byline" htmlsprintf="$record->author()->link( NULL, NULL, $record->isAnonymous() ), $record->container()->url(), $record->container()->_title"}{datetime="$record->record_publish_date"} {lang="cms_byline" htmlsprintf="$record->author()->link( NULL, NULL, $record->isAnonymous() ), $record->container()->url(), $record->container()->_title"}{datetime="$record->mapped( 'date' )"}
</p> </p>
</div> </div>
</header> </header>
@@ -536,7 +536,11 @@
{{if $lastPost}} {{if $lastPost}}
<li>{template="userPhoto" app="core" group="global" params="$lastPost['author'], 'tiny'"}</li> <li>{template="userPhoto" app="core" group="global" params="$lastPost['author'], 'tiny'"}</li>
<li><div class='ipsType_break ipsContained'><a href="{$lastPost['record_url']}" class='ipsTruncate ipsTruncate_line' title='{$lastPost['record_title']}'>{$lastPost['record_title']}</a></div></li> <li><div class='ipsType_break ipsContained'><a href="{$lastPost['record_url']}" class='ipsTruncate ipsTruncate_line' title='{$lastPost['record_title']}'>{$lastPost['record_title']}</a></div></li>
<li class='ipsType_blendLinks'>{lang="byline_nodate" htmlsprintf="$lastPost['author']->link()"}</li> {{if $category->last_poster_anon}}
<li class='ipsType_blendLinks'>{lang="byline_nodate" htmlsprintf="$lastPost['author']->link( NULL, NULL, TRUE )"}</li>
{{else}}
<li class='ipsType_blendLinks'>{lang="byline_nodate" htmlsprintf="$lastPost['author']->link()"}</li>
{{endif}}
<li data-short="1 dy" class="ipsType_light"><a href='{$lastPost['record_url']->setQueryString( 'do', 'getLastComment' )}' title='{lang="get_last_post"}' class='ipsType_blendLinks'>{datetime="$lastPost['date']"}</a></li> <li data-short="1 dy" class="ipsType_light"><a href='{$lastPost['record_url']->setQueryString( 'do', 'getLastComment' )}' title='{lang="get_last_post"}' class='ipsType_blendLinks'>{datetime="$lastPost['date']"}</a></li>
{{else}} {{else}}
<li class='ipsType_light ipsResponsive_showDesktop'>{lang="content_categories_index_no_records" sprintf="\IPS\cms\Databases::load( $category->database_id )->recordWord()"}</li> <li class='ipsType_light ipsResponsive_showDesktop'>{lang="content_categories_index_no_records" sprintf="\IPS\cms\Databases::load( $category->database_id )->recordWord()"}</li>
@@ -936,7 +940,7 @@
{{endif}} {{endif}}
</p> </p>
<ul class='ipsList_inline'> <ul class='ipsList_inline'>
<li>{datetime="$record->record_publish_date"}</li> <li>{datetime="$record->mapped( 'date' )"}</li>
{{foreach $record->customFieldsForDisplay('display_top') as $fieldId => $fieldValue}} {{foreach $record->customFieldsForDisplay('display_top') as $fieldId => $fieldValue}}
{{if $fieldValue}} {{if $fieldValue}}
{$fieldValue|raw} {$fieldValue|raw}
@@ -947,7 +951,7 @@
</div> </div>
</div> </div>
<div class='ipsFlex-flex:00 ipsResponsive_hidePhone'> <div class='ipsFlex-flex:00 ipsResponsive_hidePhone'>
<div class='ipsFlex ipsFlex-ai:center ipsGap:3 ipsGap_row:0'> <div class='ipsShareLinks'>
{{if !$record->container()->disable_sharelinks}} {{if !$record->container()->disable_sharelinks}}
{template="shareButton" app="core" group="sharelinks" params="$record"} {template="shareButton" app="core" group="sharelinks" params="$record"}
{{endif}} {{endif}}
@@ -1081,19 +1085,15 @@
</article> </article>
<div class='ipsBox ipsPadding ipsResponsive_pull ipsResponsive_showPhone ipsMargin_top'> <div class='ipsBox ipsPadding ipsResponsive_pull ipsResponsive_showPhone ipsMargin_top'>
{{if !$record->container()->disable_sharelinks}} <div class='ipsShareLinks'>
<div class='ipsResponsive_noFloat ipsResponsive_block ipsMargin_bottom:half'> {{if !$record->container()->disable_sharelinks}}
{template="shareButton" app="core" group="sharelinks" params="$record, 'verySmall', 'light'"} {template="shareButton" app="core" group="sharelinks" params="$record, 'verySmall', 'light'"}
</div> {{endif}}
{{endif}}
<div class='ipsResponsive_noFloat ipsResponsive_block'>
{template="follow" app="core" group="global" params="'cms', 'records'.$record::$customDatabaseId, $record->primary_id_field, $record->followersCount()"} {template="follow" app="core" group="global" params="'cms', 'records'.$record::$customDatabaseId, $record->primary_id_field, $record->followersCount()"}
</div> {{if $record->canPromoteToSocialMedia() and ( $record instanceof \IPS\Content or $record instanceof \IPS\Node\Model )}}
{{if $record->canPromoteToSocialMedia() and ( $record instanceof \IPS\Content or $record instanceof \IPS\Node\Model )}}
<div class='ipsResponsive_noFloat ipsResponsive_block ipsMargin_top:half'>
{template="promote" app="core" group="global" params="$record"} {template="promote" app="core" group="global" params="$record"}
</div> {{endif}}
{{endif}} </div>
</div> </div>
<div class='ipsPager ipsSpacer_top'> <div class='ipsPager ipsSpacer_top'>
@@ -2032,7 +2032,7 @@
</div> </div>
{{endif}} {{endif}}
<div class='ipsDataItem_meta ipsType_reset ipsType_light ipsType_blendLinks'> <div class='ipsDataItem_meta ipsType_reset ipsType_light ipsType_blendLinks'>
<span>{lang="byline" htmlsprintf="$row->author()->link( $row->warningRef(), NULL, $row->isAnonymous() )"}{datetime="$row->_publishDate"}</span> <span>{lang="byline" htmlsprintf="$row->author()->link( $row->warningRef(), NULL, $row->isAnonymous() )"}{datetime="$row->mapped( 'date' )"}</span>
{{if \count( $row->tags() )}} {{if \count( $row->tags() )}}
&nbsp;&nbsp; &nbsp;&nbsp;
{template="tags" group="global" app="core" params="$row->tags(), true"} {template="tags" group="global" app="core" params="$row->tags(), true"}
@@ -2090,13 +2090,13 @@
{{if $row->record_edit_time > 0}} {{if $row->record_edit_time > 0}}
{lang="cms_row_updated_by" htmlsprintf="\IPS\Member::load( $row->record_edit_member_id )->link()"} {lang="cms_row_updated_by" htmlsprintf="\IPS\Member::load( $row->record_edit_member_id )->link()"}
{{else}} {{else}}
{lang="cms_row_added_by" htmlsprintf="$row->author()->link()"} {lang="cms_row_added_by" htmlsprintf="$row->author()->link( NULL, NULL, $row->isAnonymous() )"}
{{endif}} {{endif}}
{{else}} {{else}}
{{if $row->record_edit_time > 0}} {{if $row->record_edit_time > 0}}
{lang="cms_row_updated_by" htmlsprintf="$row->lastCommenter()->link()"} {lang="cms_row_updated_by" htmlsprintf="$row->lastCommenter()->link()"}
{{else}} {{else}}
{lang="cms_row_added_by" htmlsprintf="$row->author()->link()"} {lang="cms_row_added_by" htmlsprintf="$row->author()->link( NULL, NULL, $row->isAnonymous() )"}
{{endif}} {{endif}}
{{endif}} {{endif}}
</li> </li>
+16
View File
@@ -777,6 +777,22 @@
"unsigned": true, "unsigned": true,
"values": [ "values": [
],
"zerofill": false
},
"record_last_comment_anon": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "0",
"length": 1,
"name": "record_last_comment_anon",
"type": "TINYINT",
"unsigned": true,
"values": [
], ],
"zerofill": false "zerofill": false
} }
+21 -22
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<javascript app="cms"> <javascript app="cms">
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/blocks" javascript_name="ips.blocks.form.js" javascript_type="controller" javascript_version="107601" javascript_position="1000050"><![CDATA[/** <file javascript_app="cms" javascript_location="admin" javascript_path="controllers/blocks" javascript_name="ips.blocks.form.js" javascript_type="controller" javascript_version="107643" javascript_position="1000050"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -76,7 +76,7 @@
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/databases" javascript_name="ips.databases.download.js" javascript_type="controller" javascript_version="107601" javascript_position="1000100">/** <file javascript_app="cms" javascript_location="admin" javascript_path="controllers/databases" javascript_name="ips.databases.download.js" javascript_type="controller" javascript_version="107643" javascript_position="1000100">/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -121,7 +121,7 @@
} }
}); });
}(jQuery, _));</file> }(jQuery, _));</file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/databases" javascript_name="ips.databases.form.js" javascript_type="controller" javascript_version="107601" javascript_position="1000100"><![CDATA[/** <file javascript_app="cms" javascript_location="admin" javascript_path="controllers/databases" javascript_name="ips.databases.form.js" javascript_type="controller" javascript_version="107643" javascript_position="1000100"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -197,7 +197,7 @@
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="front" javascript_path="controllers/external" javascript_name="ips.external.communication.js" javascript_type="controller" javascript_version="107601" javascript_position="1000050"><![CDATA[/** <file javascript_app="cms" javascript_location="front" javascript_path="controllers/external" javascript_name="ips.external.communication.js" javascript_type="controller" javascript_version="107643" javascript_position="1000050"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -332,7 +332,7 @@
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/fields" javascript_name="ips.fields.form.js" javascript_type="controller" javascript_version="107601" javascript_position="1000150">/** <file javascript_app="cms" javascript_location="admin" javascript_path="controllers/fields" javascript_name="ips.fields.form.js" javascript_type="controller" javascript_version="107643" javascript_position="1000150">/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -369,7 +369,7 @@
} }
}); });
}(jQuery, _));</file> }(jQuery, _));</file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/media" javascript_name="ips.media.main.js" javascript_type="controller" javascript_version="107601" javascript_position="1000200"><![CDATA[/** <file javascript_app="cms" javascript_location="admin" javascript_path="controllers/media" javascript_name="ips.media.main.js" javascript_type="controller" javascript_version="107643" javascript_position="1000200"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -1009,7 +1009,7 @@
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/pages" javascript_name="ips.pages.embed.js" javascript_type="controller" javascript_version="107601" javascript_position="1000250"><![CDATA[/** <file javascript_app="cms" javascript_location="admin" javascript_path="controllers/pages" javascript_name="ips.pages.embed.js" javascript_type="controller" javascript_version="107643" javascript_position="1000250"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -1055,7 +1055,7 @@
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/pages" javascript_name="ips.pages.form.js" javascript_type="controller" javascript_version="107601" javascript_position="1000250"><![CDATA[/** <file javascript_app="cms" javascript_location="admin" javascript_path="controllers/pages" javascript_name="ips.pages.form.js" javascript_type="controller" javascript_version="107643" javascript_position="1000250"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -1177,7 +1177,7 @@
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="front" javascript_path="controllers/records" javascript_name="ips.records.form.js" javascript_type="controller" javascript_version="107601" javascript_position="1000100"><![CDATA[/** <file javascript_app="cms" javascript_location="front" javascript_path="controllers/records" javascript_name="ips.records.form.js" javascript_type="controller" javascript_version="107643" javascript_position="1000100"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -1289,7 +1289,7 @@
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="front" javascript_path="controllers/records" javascript_name="ips.records.revisions.js" javascript_type="controller" javascript_version="107601" javascript_position="1000100">/** <file javascript_app="cms" javascript_location="front" javascript_path="controllers/records" javascript_name="ips.records.revisions.js" javascript_type="controller" javascript_version="107643" javascript_position="1000100">/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -1344,7 +1344,7 @@
} }
}); });
}(jQuery, _));</file> }(jQuery, _));</file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.addForm.js" javascript_type="controller" javascript_version="107601" javascript_position="1000300">/** <file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.addForm.js" javascript_type="controller" javascript_version="107643" javascript_position="1000300">/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -1394,7 +1394,7 @@
} }
}); });
}(jQuery, _));</file> }(jQuery, _));</file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.conflict.js" javascript_type="controller" javascript_version="107601" javascript_position="1000300">/** <file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.conflict.js" javascript_type="controller" javascript_version="107643" javascript_position="1000300">/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -1466,7 +1466,7 @@
} }
}); });
}(jQuery, _));</file> }(jQuery, _));</file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.fileEditor.js" javascript_type="controller" javascript_version="107601" javascript_position="1000300"><![CDATA[/** <file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.fileEditor.js" javascript_type="controller" javascript_version="107643" javascript_position="1000300"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -2422,7 +2422,7 @@
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.fileList.js" javascript_type="controller" javascript_version="107601" javascript_position="1000300"><![CDATA[/** <file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.fileList.js" javascript_type="controller" javascript_version="107643" javascript_position="1000300"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -2765,7 +2765,7 @@
} }
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.main.js" javascript_type="controller" javascript_version="107601" javascript_position="1000300"><![CDATA[/** <file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.main.js" javascript_type="controller" javascript_version="107643" javascript_position="1000300"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -2934,7 +2934,7 @@
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.variablesDialog.js" javascript_type="controller" javascript_version="107601" javascript_position="1000300">/** <file javascript_app="cms" javascript_location="admin" javascript_path="controllers/templates" javascript_name="ips.templates.variablesDialog.js" javascript_type="controller" javascript_version="107643" javascript_position="1000300">/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -2979,7 +2979,7 @@
} }
}); });
}(jQuery, _));</file> }(jQuery, _));</file>
<file javascript_app="cms" javascript_location="front" javascript_path="mixins" javascript_name="ips.cms.builder.area.js" javascript_type="mixins" javascript_version="107601" javascript_position="1000150"><![CDATA[/** <file javascript_app="cms" javascript_location="front" javascript_path="mixins" javascript_name="ips.cms.builder.area.js" javascript_type="mixins" javascript_version="107643" javascript_position="1000150"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -3049,7 +3049,7 @@
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="front" javascript_path="mixins" javascript_name="ips.cms.builder.block.js" javascript_type="mixins" javascript_version="107601" javascript_position="1000150"><![CDATA[/** <file javascript_app="cms" javascript_location="front" javascript_path="mixins" javascript_name="ips.cms.builder.block.js" javascript_type="mixins" javascript_version="107643" javascript_position="1000150"><![CDATA[/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -3157,7 +3157,7 @@
}); });
}(jQuery, _));]]></file> }(jQuery, _));]]></file>
<file javascript_app="cms" javascript_location="front" javascript_path="mixins" javascript_name="ips.cms.comment.js" javascript_type="mixins" javascript_version="107601" javascript_position="1000150">/** <file javascript_app="cms" javascript_location="front" javascript_path="mixins" javascript_name="ips.cms.comment.js" javascript_type="mixins" javascript_version="107643" javascript_position="1000150">/**
* Invision Community * Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com * (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
* *
@@ -3184,7 +3184,7 @@
}); });
}); });
}(jQuery, _));</file> }(jQuery, _));</file>
<file javascript_app="cms" javascript_location="admin" javascript_path="templates" javascript_name="ips.templates.media.js" javascript_type="template" javascript_version="107601" javascript_position="1000300"><![CDATA[ips.templates.set( 'templates.media.grid', "\ <file javascript_app="cms" javascript_location="admin" javascript_path="templates" javascript_name="ips.templates.media.js" javascript_type="template" javascript_version="107643" javascript_position="1000300"><![CDATA[ips.templates.set( 'templates.media.grid', "\
<ul class='ipsGrid' data-ipsGrid data-ipsGrid-minItemSize='100' data-ipsGrid-maxItemSize='200'>\ <ul class='ipsGrid' data-ipsGrid data-ipsGrid-minItemSize='100' data-ipsGrid-maxItemSize='200'>\
{{{contents}}}\ {{{contents}}}\
</ul>\ </ul>\
@@ -3201,7 +3201,7 @@ ips.templates.set( 'templates.media.noSearchResults', "\
{{#lang}}mediaNoResults{{/lang}}\ {{#lang}}mediaNoResults{{/lang}}\
</div>\ </div>\
");]]></file> ");]]></file>
<file javascript_app="cms" javascript_location="admin" javascript_path="templates" javascript_name="ips.templates.templates.js" javascript_type="template" javascript_version="107601" javascript_position="1000300"><![CDATA[/* TEMPLATE EDITOR TEMPLATES */ <file javascript_app="cms" javascript_location="admin" javascript_path="templates" javascript_name="ips.templates.templates.js" javascript_type="template" javascript_version="107643" javascript_position="1000300"><![CDATA[/* TEMPLATE EDITOR TEMPLATES */
/* TEMPLATECEPTION */ /* TEMPLATECEPTION */
ips.templates.set('templates.editor.newTab', " \ ips.templates.set('templates.editor.newTab', " \
<li data-fileid='{{fileid}}' data-location='{{location}}'>\ <li data-fileid='{{fileid}}' data-location='{{location}}'>\
@@ -3250,7 +3250,6 @@ controllers</order>
<order app="global" path="/dev/js//library/">underscore <order app="global" path="/dev/js//library/">underscore
jquery jquery
mustache mustache
jstz
IntersectionObserver IntersectionObserver
Debug.js Debug.js
app.js</order> app.js</order>
+4 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<language> <language>
<app key="cms" version="107601"> <app key="cms" version="107643">
<word key="__app_cms" js="0">Pages</word> <word key="__app_cms" js="0">Pages</word>
<word key="menutab__cms" js="0">Pages</word> <word key="menutab__cms" js="0">Pages</word>
<word key="menutab__cms_icon" js="0">files-o</word> <word key="menutab__cms_icon" js="0">files-o</word>
@@ -285,6 +285,9 @@
<word key="page_folder_id" js="0">Page Folder</word> <word key="page_folder_id" js="0">Page Folder</word>
<word key="page_meta_keywords" js="0">Meta Keywords</word> <word key="page_meta_keywords" js="0">Meta Keywords</word>
<word key="page_meta_description" js="0">Meta Description</word> <word key="page_meta_description" js="0">Meta Description</word>
<word key="page_meta_index" js="0">Index</word>
<word key="page_meta_index_desc" js="0">Allow Search Engines to index this page.</word>
<word key="page_meta_index_desc_disabled" js="0">The page is not visible to guests, so it cannot be indexed.</word>
<word key="page_show_sidebar" js="0">Show the suite sidebar on this page</word> <word key="page_show_sidebar" js="0">Show the suite sidebar on this page</word>
<word key="page_type" js="0">Content Editor</word> <word key="page_type" js="0">Content Editor</word>
<word key="page_type_builder" js="0">Page Builder</word> <word key="page_type_builder" js="0">Page Builder</word>
+24
View File
@@ -1683,6 +1683,18 @@
"comment": "", "comment": "",
"unsigned": true, "unsigned": true,
"auto_increment": false "auto_increment": false
},
"category_last_poster_anon": {
"name": "category_last_poster_anon",
"type": "TINYINT",
"length": null,
"decimals": null,
"values": null,
"allow_null": true,
"default": "0",
"comment": "",
"unsigned": true,
"auto_increment": false
} }
}, },
"indexes": { "indexes": {
@@ -2939,6 +2951,18 @@
"unsigned": true, "unsigned": true,
"values": [], "values": [],
"zerofill": false "zerofill": false
},
"page_meta_index": {
"name": "page_meta_index",
"type": "TINYINT",
"length": null,
"decimals": null,
"values": null,
"allow_null": false,
"default": "1",
"comment": "",
"unsigned": false,
"auto_increment": false
} }
}, },
"indexes": { "indexes": {
+2 -2
View File
@@ -1191,7 +1191,7 @@
<template template_group="widgets" template_name="RecordFeed" template_data="$records, $title, $orientation='vertical'" template_location="front" template_app="cms"><![CDATA[{{if !empty( $records ) }} <template template_group="widgets" template_name="RecordFeed" template_data="$records, $title, $orientation='vertical'" template_location="front" template_app="cms"><![CDATA[{{if !empty( $records ) }}
<h3 class='ipsWidget_title ipsType_reset'>{$title}</h3> <h3 class='ipsWidget_title ipsType_reset'>{$title}</h3>
{{if $orientation == 'vertical'}} {{if $orientation == 'vertical'}}
<div class='ipsPad_half ipsWidget_inner'> <div class='ipsWidget_inner'>
<ul class='ipsDataList ipsDataList_reducedSpacing ipsContained_container'> <ul class='ipsDataList ipsDataList_reducedSpacing ipsContained_container'>
{{foreach $records as $record}} {{foreach $records as $record}}
<li class='ipsDataItem {{if $record->hidden()}} ipsModerated{{endif}}'> <li class='ipsDataItem {{if $record->hidden()}} ipsModerated{{endif}}'>
@@ -1241,7 +1241,7 @@
{{endif}}]]></template> {{endif}}]]></template>
<template template_group="widgets" template_name="Rss" template_data="$items, $title, $orientation='vertical'" template_location="front" template_app="cms"><![CDATA[{{if !empty( $items ) }} <template template_group="widgets" template_name="Rss" template_data="$items, $title, $orientation='vertical'" template_location="front" template_app="cms"><![CDATA[{{if !empty( $items ) }}
<h3 class='ipsWidget_title ipsType_reset'>{$title}</h3> <h3 class='ipsWidget_title ipsType_reset'>{$title}</h3>
<div class='ipsPad_half ipsWidget_inner'> <div class='ipsWidget_inner'>
<ul class='ipsDataList ipsDataList_reducedSpacing'> <ul class='ipsDataList ipsDataList_reducedSpacing'>
{{foreach $items as $item}} {{foreach $items as $item}}
<li class='ipsDataItem'> <li class='ipsDataItem'>
+15 -1
View File
@@ -543,5 +543,19 @@
"107504": "4.7.5", "107504": "4.7.5",
"107505": "4.7.5", "107505": "4.7.5",
"107600": "4.7.6 Beta 1", "107600": "4.7.6 Beta 1",
"107601": "4.7.6" "107601": "4.7.6",
"107602": "4.7.6",
"107620": "4.7.7 Beta 1",
"107621": "4.7.7 Beta 2",
"107622": "4.7.7 Beta 2",
"107623": "4.7.7 Beta 3",
"107624": "4.7.7 Beta 4",
"107625": "4.7.7",
"107626": "4.7.7",
"107627": "4.7.7",
"107628": "4.7.7",
"107640": "4.7.8 Beta 1",
"107641": "4.7.8 Beta 2",
"107642": "4.7.8 Beta 3",
"107643": "4.7.8"
} }
@@ -122,7 +122,7 @@ class _Databases
} }
/* And however many for the content items */ /* And however many for the content items */
$count = ceil( max( (int) $class::getItemsWithPermission( $class::sitemapWhere(), NULL, 10, 'read', \IPS\Content\Hideable::FILTER_PUBLIC_ONLY, 0, new \IPS\Member, FALSE, FALSE, FALSE, TRUE ), \IPS\Settings::i()->sitemap_databases_count ) / \IPS\Sitemap::MAX_PER_FILE ); $count = ceil( max( (int) $class::getItemsWithPermission( $class::sitemapWhere(), NULL, 10, 'read', \IPS\Content\Hideable::FILTER_PUBLIC_ONLY, 0, new \IPS\Member, FALSE, FALSE, FALSE, TRUE ), \IPS\Settings::i()->sitemap_databases_count ) / \IPS\SITEMAP_MAX_PER_FILE );
for( $i=1; $i <= $count; $i++ ) for( $i=1; $i <= $count; $i++ )
{ {
$files[] = $database->id . '_sitemap_database_records_' . $i; $files[] = $database->id . '_sitemap_database_records_' . $i;
@@ -193,8 +193,8 @@ class _Databases
$exploded = explode( '_', $filename ); $exploded = explode( '_', $filename );
$block = (int) array_pop( $exploded ); $block = (int) array_pop( $exploded );
$offset = ( $block - 1 ) * \IPS\Sitemap::MAX_PER_FILE; $offset = ( $block - 1 ) * \IPS\SITEMAP_MAX_PER_FILE;
$limit = \IPS\Sitemap::MAX_PER_FILE; $limit = \IPS\SITEMAP_MAX_PER_FILE;
$totalLimit = \IPS\Settings::i()->sitemap_databases_count; $totalLimit = \IPS\Settings::i()->sitemap_databases_count;
if ( $totalLimit > -1 and ( $offset + $limit ) > $totalLimit ) if ( $totalLimit > -1 and ( $offset + $limit ) > $totalLimit )
@@ -84,12 +84,13 @@ class _Pages
$permissionCheck = 'view'; $permissionCheck = 'view';
$where = array( array( '(' . \IPS\Db::i()->findInSet( 'perm_' . $class::$permissionMap[ $permissionCheck ], $member->groups ) . ' OR ' . 'perm_' . $class::$permissionMap[ $permissionCheck ] . '=? )', '*' ) ); $where = array( array( '(' . \IPS\Db::i()->findInSet( 'perm_' . $class::$permissionMap[ $permissionCheck ], $member->groups ) . ' OR ' . 'perm_' . $class::$permissionMap[ $permissionCheck ] . '=? )', '*' ) );
$where[] = [ 'page_meta_index=?', 1 ];
$count = \IPS\Db::i()->select( '*', $class::$databaseTable, $where ) $count = \IPS\Db::i()->select( '*', $class::$databaseTable, $where )
->join( 'core_permission_index', array( "core_permission_index.app=? AND core_permission_index.perm_type=? AND core_permission_index.perm_type_id=" . $class::$databaseTable . "." . $class::$databasePrefix . $class::$databaseColumnId, $class::$permApp, $class::$permType ) ) ->join( 'core_permission_index', array( "core_permission_index.app=? AND core_permission_index.perm_type=? AND core_permission_index.perm_type_id=" . $class::$databaseTable . "." . $class::$databasePrefix . $class::$databaseColumnId, $class::$permApp, $class::$permType ) )
->count(); ->count();
$count = ceil( max( $count, \IPS\Settings::i()->sitemap_pages_count ) / \IPS\Sitemap::MAX_PER_FILE ); $count = ceil( max( $count, \IPS\Settings::i()->sitemap_pages_count ) / \IPS\SITEMAP_MAX_PER_FILE );
for( $i=1; $i <= $count; $i++ ) for( $i=1; $i <= $count; $i++ )
{ {
@@ -123,8 +124,8 @@ class _Pages
$exploded = explode( '_', $filename ); $exploded = explode( '_', $filename );
$block = (int) array_pop( $exploded ); $block = (int) array_pop( $exploded );
$offset = ( $block - 1 ) * \IPS\Sitemap::MAX_PER_FILE; $offset = ( $block - 1 ) * \IPS\SITEMAP_MAX_PER_FILE;
$limit = \IPS\Sitemap::MAX_PER_FILE; $limit = \IPS\SITEMAP_MAX_PER_FILE;
$totalLimit = \IPS\Settings::i()->sitemap_pages_count; $totalLimit = \IPS\Settings::i()->sitemap_pages_count;
if ( $totalLimit > -1 and ( $offset + $limit ) > $totalLimit ) if ( $totalLimit > -1 and ( $offset + $limit ) > $totalLimit )
@@ -140,8 +141,8 @@ class _Pages
} }
$where = array( array( '(' . \IPS\Db::i()->findInSet( 'perm_' . $class::$permissionMap[ $permissionCheck ], $member->groups ) . ' OR ' . 'perm_' . $class::$permissionMap[ $permissionCheck ] . '=? )', '*' ) ); $where = array( array( '(' . \IPS\Db::i()->findInSet( 'perm_' . $class::$permissionMap[ $permissionCheck ], $member->groups ) . ' OR ' . 'perm_' . $class::$permissionMap[ $permissionCheck ] . '=? )', '*' ) );
$where[] = [ 'page_meta_index=?', 1 ];
$direction = ( $totalLimit > \IPS\Sitemap::MAX_PER_FILE ) ? ' ASC' : ' DESC'; $direction = ( $totalLimit > \IPS\SITEMAP_MAX_PER_FILE ) ? ' ASC' : ' DESC';
$select = \IPS\Db::i()->select( '*', $class::$databaseTable, $where, 'page_id' . $direction, array( $offset, $limit ) ) $select = \IPS\Db::i()->select( '*', $class::$databaseTable, $where, 'page_id' . $direction, array( $offset, $limit ) )
->join( 'core_permission_index', array( "core_permission_index.app=? AND core_permission_index.perm_type=? AND core_permission_index.perm_type_id=" . $class::$databaseTable . "." . $class::$databasePrefix . $class::$databaseColumnId, $class::$permApp, $class::$permType ) ); ->join( 'core_permission_index', array( "core_permission_index.app=? AND core_permission_index.perm_type=? AND core_permission_index.perm_type_id=" . $class::$databaseTable . "." . $class::$databasePrefix . $class::$databaseColumnId, $class::$permApp, $class::$permType ) );
+14 -11
View File
@@ -362,23 +362,26 @@ FILE;
*/ */
protected function _afterSave( ?\IPS\Node\Model $old, \IPS\Node\Model $new, $lastUsedTab = FALSE ) protected function _afterSave( ?\IPS\Node\Model $old, \IPS\Node\Model $new, $lastUsedTab = FALSE )
{ {
/* If this page was the default in a folder, and it was moved to a new folder that already has a default, we need to unset the /* Is there a default page in the folder? */
default page flag or there will be two defaults in the destination folder */ try
if( $old !== NULL AND $old->folder_id != $new->folder_id AND $old->default )
{ {
/* Is there already a default page in the new folder? */ $existingDefault = \IPS\Db::i()->select( 'page_id', 'cms_pages', array( 'page_folder_id=? and page_default=? and page_id <> ?', $new->folder_id, 1, $new->id ) )->first();
try
{
$existingDefault = \IPS\Db::i()->select( 'page_id', 'cms_pages', array( 'page_folder_id=? and page_default=?', $new->folder_id, 1 ) )->first();
/* If this page was the default in a folder, and it was moved to a new folder that already has a default, we need to unset the
default page flag or there will be two defaults in the destination folder */
if( $old !== NULL AND $old->folder_id != $new->folder_id AND $old->default )
{
\IPS\Db::i()->update( 'cms_pages', array( 'page_default' => 0 ), array( 'page_id=?', $new->id ) ); \IPS\Db::i()->update( 'cms_pages', array( 'page_default' => 0 ), array( 'page_id=?', $new->id ) );
\IPS\cms\Pages\Page::buildPageUrlStore(); \IPS\cms\Pages\Page::buildPageUrlStore();
} }
catch( \UnderflowException $e ) }
{ catch( \UnderflowException $e )
/* No default found in destination folder, do nothing */ {
} /* No default found in destination folder, make this the default */
\IPS\Db::i()->update( 'cms_pages', array( 'page_default' => 1 ), array( 'page_id=?', $new->id ) );
\IPS\cms\Pages\Page::buildPageUrlStore();
} }
/* If page filename changes or the folder ID changes, we need to clear front navigation cache*/ /* If page filename changes or the folder ID changes, we need to clear front navigation cache*/
@@ -276,6 +276,11 @@ class _category extends \IPS\cms\Databases\Controller
$table->hover = TRUE; $table->hover = TRUE;
$table->sortBy = ( isset( \IPS\Request::i()->sortby ) ) ? \IPS\Request::i()->sortby : ( $database->field_sort ? $RecordsClass::$databaseTable . '.' . $RecordsClass::$databasePrefix . $database->field_sort : 'record_last_comment' ); $table->sortBy = ( isset( \IPS\Request::i()->sortby ) ) ? \IPS\Request::i()->sortby : ( $database->field_sort ? $RecordsClass::$databaseTable . '.' . $RecordsClass::$databasePrefix . $database->field_sort : 'record_last_comment' );
$table->sortDirection = ( isset( \IPS\Request::i()->sortdirection ) ) ? \IPS\Request::i()->sortdirection : ( $database->field_direction ? $database->field_direction : 'desc' ); $table->sortDirection = ( isset( \IPS\Request::i()->sortdirection ) ) ? \IPS\Request::i()->sortdirection : ( $database->field_direction ? $database->field_direction : 'desc' );
if ( $database->field_sort )
{
$table->defaultSortBy = $RecordsClass::$databasePrefix . $database->field_sort;
$table->defaultSortDirection = $database->field_direction;
}
$table->limit = $database->field_perpage ? $database->field_perpage : 25; $table->limit = $database->field_perpage ? $database->field_perpage : 25;
$table->title = \IPS\Member::loggedIn()->language()->addToStack( $database->use_categories ? 'x_records_in_this_category' : 'x_records' , FALSE, array( 'sprintf' => array( $category->_items, $database->recordWord( $category->_items ) ) ) ); $table->title = \IPS\Member::loggedIn()->language()->addToStack( $database->use_categories ? 'x_records_in_this_category' : 'x_records' , FALSE, array( 'sprintf' => array( $category->_items, $database->recordWord( $category->_items ) ) ) );
Loaded 100 of 688 files, more files were not shown because too many files have changed in this diff. Show more