Version 4.5.0

This commit is contained in:
Neo committed 2025-12-19 05:51:58 -08:00
1 parent 1a0c7fd3c2
commit f79dcf067a
3791 files changed
+248032 -76372

No files matched your search

+84 -3
View File
@@ -23,13 +23,75 @@ class _Application extends \IPS\Application
*/
public function init()
{
/* If the viewing member cannot view the board (ex: guests must login first), then send a 404 Not Found header here, before the Login page shows in the dispatcher */
if ( !\IPS\Member::loggedIn()->group['g_view_board'] and ( \IPS\Request::i()->module == 'blogs' and \IPS\Request::i()->controller == 'view' and \IPS\Request::i()->do == 'rss' ) )
/* Handle RSS requests */
if ( \IPS\Request::i()->module == 'blogs' and \IPS\Request::i()->controller == 'view' and \IPS\Request::i()->do == 'rss' )
{
\IPS\Output::i()->error( 'node_error', '2B221/1', 404, '' );
$member = NULL;
if( \IPS\Request::i()->member AND \IPS\Request::i()->key )
{
$member = \IPS\Member::load( \IPS\Request::i()->member );
if( !\IPS\Login::compareHashes( md5( ( $member->members_pass_hash ?: $member->email ) . $member->members_pass_salt ), (string) \IPS\Request::i()->key ) )
{
$member = NULL;
}
}
$this->sendBlogRss( $member ?? new \IPS\Member );
if( !\IPS\Member::loggedIn()->group['g_view_board'] )
{
\IPS\Output::i()->error( 'node_error', '2B221/1', 404, '' );
}
}
}
/**
* Send the blog's RSS feed for the indicated member
*
* @param \IPS\Member $member Member
* @return void
*/
protected function sendBlogRss( $member )
{
try
{
$blog = \IPS\blog\Blog::load( \IPS\Request::i()->id );
if( !$blog->can( 'view', $member ) )
{
throw new \OutOfRangeException;
}
}
catch ( \OutOfRangeException $e )
{
/* We'll let the regular controller handle the error */
return;
}
if( !\IPS\Settings::i()->blog_allow_rss or !$blog->settings['allowrss'] )
{
\IPS\Output::i()->error( 'blog_rss_offline', '2B201/5', 403, 'blog_rss_offline_admin' );
}
/* We have to use get() to ensure CDATA tags wrap the blog title properly */
$title = $blog->member_id ? $blog->name : $member->language()->get( "blogs_blog_{$blog->id}" );
$document = \IPS\Xml\Rss::newDocument( $blog->url(), $title, $blog->description );
foreach ( \IPS\blog\Entry::getItemsWithPermission( array( array( 'entry_blog_id=?', $blog->id ), array( 'entry_status!=?', 'draft' ) ), 'entry_date DESC', 25, 'read', \IPS\Content\Hideable::FILTER_PUBLIC_ONLY, 0, $member, FALSE, FALSE, FALSE, FALSE, NULL, $blog ) as $entry )
{
$document->addItem( $entry->name, $entry->url(), $entry->content, \IPS\DateTime::ts( $entry->date ), $entry->id );
}
/* @note application/rss+xml is not a registered IANA mime-type so we need to stick with text/xml for RSS */
\IPS\Output::i()->sendOutput( $document->asXML(), 200, 'text/xml', array(), TRUE );
}
/**
* Perform any additional installation needs
*
* @return void
*/
public function installOther()
{
/* Allow non guests to create and comment on Blogs */
@@ -39,6 +101,13 @@ class _Application extends \IPS\Application
$group->g_blog_allowcomment = TRUE;
$group->save();
}
/* Create new default category */
$category = new \IPS\blog\Category;
$category->seo_name = 'general';
$category->save();
\IPS\Lang::saveCustom( 'blog', "blog_category_{$category->id}", "General" );
}
/**
@@ -84,4 +153,16 @@ class _Application extends \IPS\Application
'activityTabs' => array()
);
}
/**
* Return an array of specific links to add to the sitemap
*
* @return array
*/
public function sitemapLinks()
{
return array(
\IPS\Http\Url::internal( 'app=blog&module=blogs&controller=browse', 'front', 'blogs' ),
);
}
}
+5 -5
View File
@@ -12,7 +12,7 @@
namespace IPS\blog\api;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -27,7 +27,7 @@ class _blogs extends \IPS\Node\Api\NodeController
/**
* Class
*/
protected $class = 'IPS\blogs\Blog';
protected $class = 'IPS\blog\Blog';
/**
* GET /blog/blogs
@@ -65,7 +65,7 @@ class _blogs extends \IPS\Node\Api\NodeController
/* Pinned */
if ( isset( \IPS\Request::i()->pinned ) )
{
$where[] = array( 'blog_pinned=?', intval( \IPS\Request::i()->pinned ) );
$where[] = array( 'blog_pinned=?', \intval( \IPS\Request::i()->pinned ) );
}
/* Permission */
@@ -75,7 +75,7 @@ class _blogs extends \IPS\Node\Api\NodeController
}
/* Sort */
if ( isset( \IPS\Request::i()->sortBy ) and in_array( \IPS\Request::i()->sortBy, array( 'count_entries', 'last_edate' ) ) )
if ( isset( \IPS\Request::i()->sortBy ) and \in_array( \IPS\Request::i()->sortBy, array( 'count_entries', 'last_edate' ) ) )
{
$sortBy = 'blog_' . \IPS\Request::i()->sortBy;
}
@@ -83,7 +83,7 @@ class _blogs extends \IPS\Node\Api\NodeController
{
$sortBy = 'blog_id';
}
$sortDir = ( isset( \IPS\Request::i()->sortDir ) and in_array( mb_strtolower( \IPS\Request::i()->sortDir ), array( 'asc', 'desc' ) ) ) ? \IPS\Request::i()->sortDir : 'asc';
$sortDir = ( isset( \IPS\Request::i()->sortDir ) and \in_array( mb_strtolower( \IPS\Request::i()->sortDir ), array( 'asc', 'desc' ) ) ) ? \IPS\Request::i()->sortDir : 'asc';
/* Return */
return new \IPS\Api\PaginatedResponse(
+167
View File
@@ -0,0 +1,167 @@
<?php
/**
* @brief Blog Categories API
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @subpackage Blog
* @since 4 Sep 2019
*/
namespace IPS\blog\api;
/* 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;
}
/**
* @brief Blog Blogs API
*/
class _categories extends \IPS\Node\Api\NodeController
{
/**
* Class
*/
protected $class = 'IPS\blog\Category';
/**
* GET /blog/categories
* Get list of blog categories
*
* @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 int page Page number
* @apiparam int perPage Number of results per page - defaults to 25
* @return \IPS\Api\PaginatedResponse<IPS\blog\Entry>
*/
public function GETindex()
{
/* Where clause */
$where = array();
/* Sort */
if ( isset( \IPS\Request::i()->sortBy ) and \in_array( \IPS\Request::i()->sortBy, array( 'position' ) ) )
{
$sortBy = 'category_' . \IPS\Request::i()->sortBy;
}
else
{
$sortBy = 'category_id';
}
$sortDir = ( isset( \IPS\Request::i()->sortDir ) and \in_array( mb_strtolower( \IPS\Request::i()->sortDir ), array( 'asc', 'desc' ) ) ) ? \IPS\Request::i()->sortDir : 'asc';
/* Return */
return new \IPS\Api\PaginatedResponse(
200,
\IPS\Db::i()->select( '*', 'blog_categories', $where, "{$sortBy} {$sortDir}" ),
isset( \IPS\Request::i()->page ) ? \IPS\Request::i()->page : 1,
'IPS\blog\Category',
\IPS\Db::i()->select( 'COUNT(*)', 'blog_categories', $where )->first(),
$this->member,
isset( \IPS\Request::i()->perPage ) ? \IPS\Request::i()->perPage : NULL
);
}
/**
* GET /blog/categories/{id}
* Get information about a specific blog category
*
* @param int $id ID Number
* @return \IPS\blog\Blog
*/
public function GETitem( $id )
{
return $this->_view( $id );
}
/**
* POST /blog/categories
* Create a blog category
*
* @apiclientonly
* @reqapiparam string name The category name
* @apiparam int|null parent The ID number of the parent the category should be created in. NULL for root.
* @apiparam int position The category position
* @return \IPS\blog\Category
* @throws 1B408/1 NO_TITLE A name for the category must be supplied
*/
public function POSTindex()
{
if ( !\IPS\Request::i()->name )
{
throw new \IPS\Api\Exception( 'NO_TITLE', '1B408/1', 400 );
}
return new \IPS\Api\Response( 201, $this->_create()->apiOutput( $this->member ) );
}
/**
* POST /blog/categories/{id}
* Edit a blog category
*
* @apiclientonly
* @reqapiparam string name The category name
* @apiparam int|null parent The ID number of the parent the category should be created in. NULL for root.
* @apiparam int position The category position
* @param int $id ID Number
* @return \IPS\blog\Category
*/
public function POSTitem( $id )
{
$class = $this->class;
$category = $class::load( $id );
return new \IPS\Api\Response( 200, $this->_createOrUpdate( $category )->apiOutput( $this->member ) );
}
/**
* DELETE /blog/categories/{id}
* Delete a blog category
*
* @apiclientonly
* @param int $id ID Number
* @return void
* @throws 2B408/3 INVALID_ID The blog category ID does not exist or the authorized user does not have permission to delete it
*/
public function DELETEitem( $id )
{
$class = $this->class;
try
{
$category = $class::load( $id );
$category->delete();
return new \IPS\Api\Response( 200, NULL );
}
catch ( \OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2B408/3', 404 );
}
}
/**
* Create or update node
*
* @param \IPS\Node\Model $category The node
* @return \IPS\Node\Model
*/
protected function _createOrUpdate( \IPS\Node\Model $category )
{
if ( isset( \IPS\Request::i()->name ) )
{
\IPS\Lang::saveCustom( 'blog', "blog_category_{$category->id}", \IPS\Request::i()->name );
$category->seo_name = \IPS\Http\Url\Friendly::seoTitle( \IPS\Request::i()->name );
}
$category->parent = (int) \IPS\Request::i()->parent?: \IPS\blog\Category::$databaseColumnParentRootValue;
return parent::_createOrUpdate( $category );
}
}
+3 -3
View File
@@ -12,7 +12,7 @@
namespace IPS\blog\api;
/* To prentry PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -98,7 +98,7 @@ class _comments extends \IPS\Content\Api\CommentController
* POST /blog/comments
* Create a comment
*
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, hidden will only be honoured if the authentictaed user has permission to hide content).
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, hidden will only be honoured if the authenticated user has permission to hide content).
* @reqapiparam int entry The ID number of the entry the comment is for
* @reqapiparam int author The ID number of the member making the comment (0 for guest). Required for requests made using an API Key or the Client Credentials Grant Type. For requests using an OAuth Access Token for a particular member, that member will always be the author
* @apiparam string author_name If author is 0, the guest name that should be used
@@ -164,7 +164,7 @@ class _comments extends \IPS\Content\Api\CommentController
* POST /blog/comments/{id}
* Edit a comment
*
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, hidden will only be honoured if the authentictaed user has permission to hide content).
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, hidden will only be honoured if the authenticated user has permission to hide content).
* @param int $id ID Number
* @apiparam int author The ID number of the member making the comment (0 for guest). Ignored for requests using an OAuth Access Token for a particular member.
* @apiparam string author_name If author is 0, the guest name that should be used
+25 -6
View File
@@ -12,7 +12,7 @@
namespace IPS\blog\api;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -40,7 +40,7 @@ class _entries extends \IPS\Content\Api\ItemController
* @apiparam int pinned If 1, only entries which are pinned are returned, if 0 only not pinned
* @apiparam int featured If 1, only entries which are featured are returned, if 0 only not featured
* @apiparam int draft If 1, only draft entries are returned, if 0 only published
* @apiparam string sortBy What to sort by. Can be 'date' for creation date, 'title' or leave unspecified for ID
* @apiparam string sortBy What to sort by. Can be 'date' for creation date, 'title', 'updated' or leave unspecified for ID
* @apiparam string sortDir Sort direction. Can be 'asc' or 'desc' - defaults to 'asc'
* @apiparam int page Page number
* @apiparam int perPage Number of results per page - defaults to 25
@@ -111,7 +111,7 @@ class _entries extends \IPS\Content\Api\ItemController
* POST /blog/entries
* Create an entry
*
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, locked will only be honoured if the authentictaed user has permission to lock topics).
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, locked will only be honoured if the authenticated user has permission to lock topics).
* @reqapiparam int blog The ID number of the blog the entry should be created in
* @reqapiparam int author The ID number of the member creating the entry (0 for guest). Required for requests made using an API Key or the Client Credentials Grant Type. For requests using an OAuth Access Token for a particular member, that member will always be the author
* @reqapiparam string title The entry title
@@ -125,6 +125,11 @@ class _entries extends \IPS\Content\Api\ItemController
* @apiparam int hidden 0 = unhidden; 1 = hidden, pending moderator approval; -1 = hidden (as if hidden by a moderator)
* @apiparam int pinned 1/0 indicating if the entry should be pinned
* @apiparam int featured 1/0 indicating if the entry should be featured
* @apiparam int category The blog entry category
* @apiparam string poll_title Poll title (to create a poll)
* @apiparam bool poll_public Make the poll public
* @apiparam bool poll_only Make this a poll-only topic
* @apiparam array poll_options Array of objects with keys 'title' (string), 'answers' (array of objects with key 'value' set to the choice) and 'multichoice' (bool)
* @throws 1B300/2 NO_BLOG The blog ID does not exist
* @throws 1B300/3 NO_AUTHOR The author ID does not exist
* @throws 1B300/4 NO_TITLE No title was supplied
@@ -133,7 +138,7 @@ class _entries extends \IPS\Content\Api\ItemController
* @return \IPS\blog\Entry
*/
public function POSTindex()
{
{
/* Get blog */
try
{
@@ -187,7 +192,7 @@ class _entries extends \IPS\Content\Api\ItemController
* POST /blog/entries/{id}
* Edit a blog entry
*
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, locked will only be honoured if the authentictaed user has permission to lock topics).
* @note For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, locked will only be honoured if the authenticated user has permission to lock topics).
* @reqapiparam int blog The ID number of the blog the entry should be created in
* @reqapiparam int author The ID number of the member creating the entry (0 for guest). Ignored for requests using an OAuth Access Token for a particular member.
* @reqapiparam string title The entry title
@@ -195,12 +200,17 @@ class _entries extends \IPS\Content\Api\ItemController
* @apiparam bool draft If this is a draft
* @apiparam string prefix Prefix tag
* @apiparam string tags Comma-separated list of tags (do not include prefix)
* @apiparam datetime date The date/time that should be used for the entry date. If not provided, will use the current date/time. Ignored for requests using an OAuth Access Token for a particular member.
* @apiparam string ip_address The IP address that should be stored for the entry/post. If not provided, will use the IP address from the API request. Ignored for requests using an OAuth Access Token for a particular member.
* @apiparam int locked 1/0 indicating if the entry should be locked
* @apiparam int hidden 0 = unhidden; 1 = hidden, pending moderator approval; -1 = hidden (as if hidden by a moderator)
* @apiparam int pinned 1/0 indicating if the entry should be pinned
* @apiparam int featured 1/0 indicating if the entry should be featured
* @apiparam int category The blog entry category
* @apiparam string poll_title Poll title (to create a poll)
* @apiparam bool poll_public Make the poll public
* @apiparam bool poll_only Make this a poll-only topic
* @apiparam array poll_options Array of objects with keys 'title' (string), 'answers' (array of objects with key 'value' set to the choice) and 'multichoice' (bool)
* @param int $id ID Number
* @throws 2B300/6 INVALID_ID The entry ID is invalid or the authorized user does not have permission to view it
* @throws 1B300/7 NO_BLOG The blog ID does not exist or the authorized user does not have permission to post in it
* @throws 1B300/8 NO_AUTHOR The author ID does not exist
@@ -297,6 +307,15 @@ class _entries extends \IPS\Content\Api\ItemController
}
$item->content = $entryContents;
}
/* Do we have a poll to attach? */
$this->_createOrUpdatePoll( $item, $type );
/* Category */
if ( isset( \IPS\Request::i()->category ) )
{
$item->category_id = \IPS\Request::i()->category;
}
/* Pass up */
return parent::_createOrUpdate( $item, $type );
+118
View File
@@ -0,0 +1,118 @@
<?php
/**
* @brief Blog Entry Category API
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @subpackage Blog
* @since 4 Sep 2019
*/
namespace IPS\blog\api;
/* 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;
}
/**
* @brief Blog Categories API
*/
class _entrycategories extends \IPS\Node\Api\NodeController
{
/**
* Class
*/
protected $class = 'IPS\blog\Entry\Category';
/**
* GET /blog/entrycategories
* Get list of entry categories
*
* @apiparam int blog ID of blog. Null for all.
* @apiparam string sortBy What to sort by. Can be 'position' for category position or do not specify for ID
* @apiparam string sortDir Sort direction. Can be 'asc' or 'desc' - defaults to 'asc'
* @apiparam int page Page number
* @apiparam int perPage Number of results per page - defaults to 25
* @return \IPS\Api\PaginatedResponse<IPS\blog\Entry\Category>
*/
public function GETindex()
{
/* Where clause */
$where = array();
/* Blog */
if ( isset( \IPS\Request::i()->blog ) )
{
$where[] = array( 'entry_category_blog_id=?', \intval( \IPS\Request::i()->blog ) );
}
/* Sort */
if ( isset( \IPS\Request::i()->sortBy ) and \in_array( \IPS\Request::i()->sortBy, array( 'position' ) ) )
{
$sortBy = 'entry_category_' . \IPS\Request::i()->sortBy;
}
else
{
$sortBy = 'entry_category_id';
}
$sortDir = ( isset( \IPS\Request::i()->sortDir ) and \in_array( mb_strtolower( \IPS\Request::i()->sortDir ), array( 'asc', 'desc' ) ) ) ? \IPS\Request::i()->sortDir : 'asc';
/* Return */
return new \IPS\Api\PaginatedResponse(
200,
\IPS\Db::i()->select( '*', 'blog_entry_categories', $where, "{$sortBy} {$sortDir}" ),
isset( \IPS\Request::i()->page ) ? \IPS\Request::i()->page : 1,
'IPS\blog\Entry\Category',
\IPS\Db::i()->select( 'COUNT(*)', 'blog_entry_categories', $where )->first(),
$this->member,
isset( \IPS\Request::i()->perPage ) ? \IPS\Request::i()->perPage : NULL
);
}
/**
* GET /blog/entrycategories/{id}
* Get information about a specific entry category
*
* @param int $id ID Number
* @return \IPS\blog\Entry\Category
*/
public function GETitem( $id )
{
return $this->_view( $id );
}
/**
* DELETE /blog/entrycategories/{id}
* Delete an entry category
*
* @param int $id ID Number
* @return void
* @throws 2B408/5 INVALID_ID The category ID does not exist or the authorized user does not have permission to delete it
*/
public function DELETEitem( $id )
{
$class = $this->class;
try
{
$category = $class::load( $id );
if ( !$category->canDelete( $this->member ) )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2B408/5', 404 );
}
$category->delete();
return new \IPS\Api\Response( 200, NULL );
}
catch ( \OutOfRangeException $e )
{
throw new \IPS\Api\Exception( 'INVALID_ID', '2B408/6', 404 );
}
}
}
View File
Whitespace-only changes.
+1 -16
View File
@@ -9,7 +9,7 @@
]
},
"app=blog&module=blogs&controller=blogs&do=form": {
"lang_key": "menu__blog_blogs_blogs",
"lang_key": "add_category",
"restriction": "blogs_manage",
"keywords": [
"add blog"
@@ -36,21 +36,6 @@
"blog name"
]
},
"app=blog&module=blogs&controller=blogs&searchResult=form_1_blog_enable_rss": {
"lang_key": "blog_enable_rss",
"restriction": "blogs_manage",
"keywords": [
"blog rss feed"
]
},
"app=blog&module=blogs&controller=blogs&searchResult=form_1_blog_type": {
"lang_key": "blog_type",
"restriction": "blogs_manage",
"keywords": [
"blog author",
"group blog"
]
},
"app=blog&module=blogs&controller=blogs&searchResult=form_new_blog_enable_rss": {
"lang_key": "blog_enable_rss",
"restriction": "blogs_manage",
+30
View File
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<build>
<module key="admin/blogs"><![CDATA[{"default_controller":"","protected":0,"default":1}]]></module>
<module key="front/blogs"><![CDATA[{"default_controller":"browse","protected":0,"default":1}]]></module>
<setting key="blog_allow_grid"><![CDATA[{"key":"blog_allow_grid","default":"1","report":"full"}]]></setting>
<setting key="blog_allow_rss"><![CDATA[{"key":"blog_allow_rss","default":"1","report":"full"}]]></setting>
<setting key="blog_allow_rssimport"><![CDATA[{"key":"blog_allow_rssimport","default":"1","report":"full"}]]></setting>
<setting key="blog_enable_rating"><![CDATA[{"key":"blog_enable_rating","default":"0","report":"full"}]]></setting>
<setting key="blog_enable_sidebar"><![CDATA[{"key":"blog_enable_sidebar","default":"0","report":"full"}]]></setting>
<setting key="blog_view_mode"><![CDATA[{"key":"blog_view_mode","default":"grid","report":"bool"}]]></setting>
<widget key="blogStatistics"><![CDATA[{"class":"\\IPS\\Widget\\StaticCache","restrict":[],"default_area":"","allow_reuse":false,"menu_style":"menu","embeddable":true}]]></widget>
<widget key="entryFeed"><![CDATA[{"class":"\\IPS\\Widget\\PermissionCache","restrict":["sidebar","cms"],"default_area":"","allow_reuse":true,"menu_style":"modal","embeddable":true}]]></widget>
<widget key="blogCommentFeed"><![CDATA[{"class":"\\IPS\\Widget\\PermissionCache","restrict":["sidebar","cms"],"default_area":"","allow_reuse":true,"menu_style":"modal","embeddable":true}]]></widget>
<widget key="blogs"><![CDATA[{"class":"\\IPS\\Widget\\PermissionCache","restrict":["sidebar","cms"],"default_area":"","allow_reuse":true,"menu_style":"menu","embeddable":true}]]></widget>
<acpsearch key="app=blog&amp;module=blogs&amp;controller=blogs"><![CDATA[{"lang_key":"menu__blog_blogs_blogs","restriction":"blogs_manage","keywords":["blogs","group blogs","manage blogs"]}]]></acpsearch>
<acpsearch key="app=blog&amp;module=blogs&amp;controller=blogs&amp;do=form"><![CDATA[{"lang_key":"add_category","restriction":"blogs_manage","keywords":["add blog"]}]]></acpsearch>
<acpsearch key="app=blog&amp;module=blogs&amp;controller=blogs&amp;searchResult=blog_desc_wrap"><![CDATA[{"lang_key":"blog_desc","restriction":"blogs_manage","keywords":["blog description"]}]]></acpsearch>
<acpsearch key="app=blog&amp;module=blogs&amp;controller=blogs&amp;searchResult=blog_member_id"><![CDATA[{"lang_key":"blog_member_id","restriction":"blogs_manage","keywords":["blog author"]}]]></acpsearch>
<acpsearch key="app=blog&amp;module=blogs&amp;controller=blogs&amp;searchResult=blog_name"><![CDATA[{"lang_key":"blog_name","restriction":"blogs_manage","keywords":["blog name"]}]]></acpsearch>
<acpsearch key="app=blog&amp;module=blogs&amp;controller=blogs&amp;searchResult=form_new_blog_enable_rss"><![CDATA[{"lang_key":"blog_enable_rss","restriction":"blogs_manage","keywords":["blog rss feed","rss feed"]}]]></acpsearch>
<acpsearch key="app=blog&amp;module=blogs&amp;controller=blogs&amp;searchResult=form_new_blog_type"><![CDATA[{"lang_key":"blog_type","restriction":"blogs_manage","keywords":["blog type","group blog"]}]]></acpsearch>
<acpsearch key="app=blog&amp;module=blogs&amp;controller=settings"><![CDATA[{"lang_key":"menu__blog_blogs_settings","restriction":"settings_manage","keywords":["blog settings"]}]]></acpsearch>
<acpsearch key="app=blog&amp;module=blogs&amp;controller=settings&amp;searchResult=form_blog_allow_rss"><![CDATA[{"lang_key":"blog_allow_rss","restriction":"settings_manage","keywords":["blog rss export","rss export"]}]]></acpsearch>
<acpsearch key="app=blog&amp;module=blogs&amp;controller=settings&amp;searchResult=form_blog_allow_rssimport"><![CDATA[{"lang_key":"blog_allow_rssimport","restriction":"settings_manage","keywords":["blog rss import","rss import"]}]]></acpsearch>
<acpsearch key="app=blog&amp;module=blogs&amp;controller=settings&amp;searchResult=form_blog_enable_rating"><![CDATA[{"lang_key":"blog_enable_rating","restriction":"settings_manage","keywords":["blog ratings","ratings"]}]]></acpsearch>
<acpsearch key="app=blog&amp;module=blogs&amp;controller=settings&amp;searchResult=form_blog_enable_sidebar"><![CDATA[{"lang_key":"blog_enable_sidebar","restriction":"settings_manage","keywords":["sidebar","social"]}]]></acpsearch>
<acpsearch key="app=core&amp;module=members&amp;controller=groups&amp;searchResult=4_g_blog_allowlocal"><![CDATA[{"lang_key":"g_blog_allowlocal","restriction":"groups_manage","keywords":["blogs","blogs permission","create blogs","post blogs"]}]]></acpsearch>
<acpsearch key="app=core&amp;module=members&amp;controller=groups&amp;searchResult=g_blog_allowdelete"><![CDATA[{"lang_key":"g_blog_allowdelete","restriction":"groups_manage","keywords":["delete blogs","delete own blogs"]}]]></acpsearch>
<acpsearch key="app=core&amp;module=members&amp;controller=groups&amp;searchResult=g_blog_allowprivate"><![CDATA[{"lang_key":"g_blog_allowprivate","restriction":"groups_manage","keywords":["private blogs"]}]]></acpsearch>
</build>
+3 -3
View File
@@ -5,7 +5,7 @@
</td>
<td dir='{dir}' align='left'>
<p style='font-family: "Helvetica Neue", helvetica, sans-serif; margin: 0; font-size: 13px; font-weight: bold'>
{$email->language->addToStack("x_created_entry_in", FALSE, array( 'sprintf' => array( $entry->author()->name, $entry->container()->_title ) ) )}
{$email->language->addToStack("x_created_entry_in", FALSE, array( 'sprintf' => array( $entry->author()->name, $entry->container()->getTitleForLanguage( $email->language ) ) ) )}
</p>
<h2 style="font-family: 'Helvetica Neue', helvetica, sans-serif; font-size: 18px; font-weight: 500 !important; margin: 0">
<a href='{$entry->url()}' style='text-decoration: none;'>{$entry->title}</a>
@@ -25,7 +25,7 @@
</strong>
</p>
</td>
</tr>]]></template_content_html><template_data>$entry, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("x_created_entry_in", FALSE, array( 'sprintf' => array( $entry->author()->name, $entry->container()->_title ) ) )}: {$entry->title} ({$entry->url()})
</tr>]]></template_content_html><template_data>$entry, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("x_created_entry_in", FALSE, array( 'htmlsprintf' => array( $entry->author()->name, $entry->container()->getTitleForLanguage( $email->language ) ) ) )}: {$entry->title} ({$entry->url()})
]]></template_content_plaintext><template_pinned>0</template_pinned></template><template><template_app>blog</template_app><template_name>digests__comment</template_name><template_content_html><![CDATA[<tr style='border-bottom: 1px solid #eeeeee'>
<td dir='{dir}' width='40' align='center' valign='top' class=' '>
<img src='{$comment->author()->get_photo( true, true )}' width='32' height='32' style='border: 1px solid #000; vertical-align: middle;'>
@@ -41,5 +41,5 @@
{$email->parseTextForEmail( $comment->content(), $email->language )|raw}
</div>
</td>
</tr>]]></template_content_html><template_data>$comment, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("x_commented_entry", FALSE, array( 'sprintf' => array( $comment->author()->name ) ) )}: {$comment->item()->name} ({$comment->url()})
</tr>]]></template_content_html><template_data>$comment, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("x_commented_entry", FALSE, array( 'htmlsprintf' => array( $comment->author()->name ) ) )}: {$comment->item()->name} ({$comment->url()})
]]></template_content_plaintext><template_pinned>0</template_pinned></template></emails>
+56
View File
@@ -0,0 +1,56 @@
{
"core": {
"BBCode": {
"blog": "IPS\\blog\\extensions\\core\\BBCode\\blog",
"entry": "IPS\\blog\\extensions\\core\\BBCode\\entry"
},
"ContentRouter": {
"Blog": "IPS\\blog\\extensions\\core\\ContentRouter\\Blog"
},
"CreateMenu": {
"Entry": "IPS\\blog\\extensions\\core\\CreateMenu\\Entry"
},
"Dashboard": {
"Overview": "IPS\\blog\\extensions\\core\\Dashboard\\Overview"
},
"EditorLocations": {
"Blogs": "IPS\\blog\\extensions\\core\\EditorLocations\\Blogs",
"Categories": "IPS\\blog\\extensions\\core\\EditorLocations\\Categories",
"Entries": "IPS\\blog\\extensions\\core\\EditorLocations\\Entries"
},
"FileStorage": {
"Blogs": "IPS\\blog\\extensions\\core\\FileStorage\\Blogs",
"Entries": "IPS\\blog\\extensions\\core\\FileStorage\\Entries"
},
"FrontNavigation": {
"Blogs": "IPS\\blog\\extensions\\core\\FrontNavigation\\Blogs"
},
"GroupForm": {
"Blog": "IPS\\blog\\extensions\\core\\GroupForm\\Blog"
},
"LiveSearch": {
"Blogs": "IPS\\blog\\extensions\\core\\LiveSearch\\Blogs"
},
"MemberFilter": {
"Blog": "IPS\\blog\\extensions\\core\\MemberFilter\\Blog"
},
"MemberSync": {
"Blog": "IPS\\blog\\extensions\\core\\MemberSync\\Blog"
},
"ModeratorPermissions": {
"Blogs": "IPS\\blog\\extensions\\core\\ModeratorPermissions\\Blogs"
},
"OverviewStatistics": {
"Blogs": "IPS\\blog\\extensions\\core\\OverviewStatistics\\Blogs"
},
"Profile": {
"blog": "IPS\\blog\\extensions\\core\\Profile\\blog"
},
"Queue": {
"RebuildEntryImages": "IPS\\blog\\extensions\\core\\Queue\\RebuildEntryImages"
},
"RssImport": {
"RssImport": "IPS\\blog\\extensions\\core\\RssImport\\RssImport"
}
}
}
+14 -2
View File
@@ -29,16 +29,23 @@
"real": "app=blog&module=blogs&controller=view&do=rss",
"alias": "blog/entry-{#id}-{?}"
},
"blogs_blog_cat": {
"friendly": "blog/{#id}-{?0}/{#cat}-{?1}",
"real": "app=blog&module=blogs&controller=view",
"seoPagination": true
},
"blogs_blog": {
"friendly": "blog/{#id}-{?}",
"real": "app=blog&module=blogs&controller=view",
"verify": "\\IPS\\blog\\Blog"
"verify": "\\IPS\\blog\\Blog",
"seoPagination": true
},
"blog_entry": {
"friendly": "entry/{#id}-{?}",
"real": "app=blog&module=blogs&controller=entry",
"verify": "\\IPS\\blog\\Entry",
"alias": "blog/{!}/entry-{#id}-{?}"
"alias": "blog/{!}/entry-{#id}-{?}",
"seoPagination": true
},
"blog_submit": {
"friendly": "submit",
@@ -48,6 +55,11 @@
"friendly": "create",
"real": "app=blog&module=blogs&controller=create"
},
"blog_category": {
"friendly": "category/{#id}-{?}",
"real": "app=blog&module=blogs&controller=browse",
"verify": "\\IPS\\blog\\Category"
},
"blogs": {
"friendly": "",
"real": "app=blog&module=blogs&controller=browse",
+3
View File
@@ -0,0 +1,3 @@
{
"blog_category_1": "General"
}
+295 -2
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<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="103038" 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="105100" javascript_position="1000150"><![CDATA[/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
@@ -37,7 +37,7 @@
}
});
}(jQuery, _));]]></file>
<file javascript_app="blog" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.list.js" javascript_type="controller" javascript_version="103038" 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="105100" javascript_position="1000150">/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
@@ -66,6 +66,297 @@
}
});
}(jQuery, _));</file>
<file javascript_app="blog" javascript_location="front" javascript_path="controllers/view" javascript_name="ips.view.manageCategories.js" javascript_type="controller" javascript_version="105100" javascript_position="1000100"><![CDATA[/**
* Invision Community
* (c) Invision Power Services, Inc. - https://www.invisioncommunity.com
*
* ips.view.manageCategories.js - Blog manage categories controller
*
* Author: Matt Mecham
*/
;( function($, _, undefined){
"use strict";
ips.controller.register('blog.front.view.manageCategories', {
_sortableElem: null,
initialize: function () {
this.on( 'click', '[data-action="delete"]', this.delete );
this.on( 'click', '[data-action="edit"]', this.edit );
this.on( 'click', '[data-role="saveChanges"]', this.saveChanges );
this.on( 'click', '[data-role="cancelChanges"]', this.cancelEditing );
/* Cancel edits */
var _this = this;
$( document )
.on( 'keydown', function (e) {
if( e.keyCode == ips.ui.key.ESCAPE ){
_this.cancelEditing();
}
});
/* Save button changes */
$('.ipsTabs ul[role="tablist"] a').on( 'click', this.tabChange );
$('.ipsForm .ipsToolList').append( ips.templates.render('blog.view.addButton') );
$('[data-action="addNew"]').on( 'click', _.bind( this.newRow, this ) );
this.renderList();
this.setup();
},
setup: function () {
var self = this;
ips.loader.get( ['core/interface/jquery/jquery-ui.js'] ).then( function () {
self.scope.find('[data-role="tableRows"]')
.sortable({
placeholder: 'sortable-placeholder',
handle: '[data-role="sortHandle"]',
items: '> li',
forcePlaceholderSize: true,
update: function () {
var data = self.scope.find('[data-role="tableRows"]').sortable( 'toArray', { attribute: 'data-category-id' } )
var url = '?app=blog&module=blogs&controller=view&do=categoriesReorder&id=' + self.scope.attr('data-blog-id');
ips.getAjax()( url, {
data: {
ajax_order: data
},
method: 'POST'
})
.done( function() {
ips.ui.flashMsg.show( ips.getString('entry_cat_order_saved') );
})
.fail( function () {
window.location = url + "&ajax_order=" + data + "&csrfKey=" + ips.getSetting('csrfKey');
});
}
});
Debug.log( "Sortable categories initialized" );
});
},
/**
* Cancel all editing
*
* @param {event} e Event object
* @returns {void}
*/
cancelEditing: function (e) {
e.preventDefault();
var _this = this;
this.scope.find('input[type="text"][name^="blog_name_"]').each( function( i ) {
if ( ! $(this).hasClass('ipsHide') ) {
var id = $(this).attr('data-role').replace( /^input_/, '' );
if( id == 'new' )
{
_this.renderList();
}
else
{
_this._cancelEditingRow( id );
}
}
} );
},
/**
* Cancel the text box editing
*
* @param {int} id Category ID
* @returns {void}
*/
_cancelEditingRow: function( id ) {
this.scope.find('[data-role="title_' + id + '"]').removeClass('ipsHide');
this.scope.find('[data-role="input_' + id + '"]').addClass('ipsHide');
this.scope.find('[data-role="saveChanges"][data-category-id="' + id + '"]').addClass('ipsHide');
this.scope.find('[data-role="cancelChanges"][data-category-id="' + id + '"]').addClass('ipsHide');
},
/**
* Event handler for clicking the edit button
*
* @param {event} e Event object
* @returns {void}
*/
newRow: function (e) {
var listContainer = this.scope.find('[data-role="tableRows"]');
listContainer.append( ips.templates.render( 'blog.view.categoryRow', {
cat: 'new',
name: ''
} ) );
$('[data-action="addNew"]').attr('disabled', true );
$('[data-action="delete"][data-category-id="new"],[data-action="edit"][data-category-id="new"]').hide();
$('body').find('[data-action="edit"][data-category-id="new"]').click();
},
/**
* Re-draws the list of categories
*
*/
renderList: function() {
var _this = this;
ips.getAjax()( '?app=blog&module=blogs&controller=view&do=categoriesJson&id=' + this.scope.attr('data-blog-id') )
.done( function (response) {
if( response.categories.length ){
var listContainer = _this.scope.find('[data-role="tableRows"]');
listContainer.html('');
var json = response.categories;
for( var i = 0; i < json.length; i++ ){
listContainer.append( ips.templates.render( 'blog.view.categoryRow', {
cat: json[i].id,
name: json[i].name
} ) );
}
}
} );
$('[data-action="addNew"]').attr('disabled', false );
},
/**
* Event handler for clicking the edit button
*
* @param {event} e Event object
* @returns {void}
*/
tabChange: function (e) {
if ( ! $('#form_tab_blog_entry_categories').hasClass('ipsTabs_activeItem') ) { // This looks back to front but the tab status is changed after this has fired
$('button[type="submit"]').addClass('ipsHide');
$('button[data-action="addNew"]').removeClass('ipsHide');
} else {
$('button[type="submit"]').removeClass('ipsHide');
$('button[data-action="addNew"]').addClass('ipsHide');
}
},
/**
* Event handler for clicking the edit button
*
* @param {event} e Event object
* @returns {void}
*/
edit: function (e) {
e.preventDefault();
var a = $( e.currentTarget );
var id = a.attr('data-category-id');
var title = this.scope.find('[data-role="title_' + id + '"]');
var input = this.scope.find('[data-role="input_' + id + '"]');
var saveButton = this.scope.find('[data-role="saveChanges"][data-category-id="' + id + '"]');
var cancelLink = this.scope.find('[data-role="cancelChanges"][data-category-id="' + id + '"]');
/* Are we already editing? */
if ( ! input.hasClass('ipsHide') ) {
this._cancelEditingRow( id );
return;
}
title.addClass('ipsHide');
input.val( title.html() );
input.removeClass('ipsHide');
saveButton.removeClass('ipsHide');
cancelLink.removeClass('ipsHide');
},
/**
* Event handler for clicking a save changes button
*
* @param {event} e Event object
* @returns {void}
*/
saveChanges: function (e) {
e.preventDefault();
var a = $( e.currentTarget );
var id = a.attr('data-category-id');
var title = this.scope.find('[data-role="title_' + id + '"]');
var input = this.scope.find('[data-role="input_' + id + '"]');
var _this = this;
var langBit = a.html();
a.html('&nbsp;&nbsp;').addClass('ipsField_loading');
ips.getAjax()( '?app=blog&module=blogs&controller=view&do=editCategoryName&id=' + this.scope.attr('data-blog-id') + '&cat=' + id, {
data: {
name: input.val()
},
type: 'post'
} )
.done( function (response) {
_this.renderList();
} )
.fail( function (response) {
a.html( langBit ).removeClass('ipsField_loading');
ips.ui.flashMsg.show( response.responseJSON );
} );
},
/**
* Event handler for clicking a delete button
*
* @param {event} e Event object
* @returns {void}
*/
delete: function (e) {
e.preventDefault();
var a = $( e.currentTarget );
var id = a.attr('data-category-id');
var _this = this;
ips.ui.alert.show({
type: 'confirm',
message: ips.getString('blog_category_confirm_delete'),
subText: ips.getString('blog_category_confirm_delete_desc'),
icon: 'info',
callbacks: {
ok: function () {
if ( a.attr('data-category-id') == 'new' ) {
_this.renderList();
} else {
ips.getAjax()( '?app=blog&module=blogs&controller=view&do=deleteCategory&id=' + _this.scope.attr('data-blog-id') + '&cat=' + id )
.done( function (response) {
_this.renderList();
} )
.fail( function (response) {
ips.ui.flashMsg.show( response.responseJSON );
} );
}
}
}
});
return false;
}
});
}(jQuery, _));]]></file>
<file javascript_app="blog" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.view.js" javascript_type="template" javascript_version="105100" javascript_position="1000050"><![CDATA[/* CLASS LIST TEMPLATES */
ips.templates.set('blog.view.addButton', "\
<button type=\"button\" class=\"ipsButton ipsButton_primary ipsHide\" data-action=\"addNew\">{{#lang}}manage_cats_new_row{{/lang}}</button>\
");
ips.templates.set('blog.view.categoryRow', "\
<li class=\"ipsDataItem ipsClearfix\" itemprop=\"itemListElement\" data-category-id=\"{{cat}}\">\
<div class=\"ipsDataItem_main\">\
<span data-role=\"sortHandle\" class=\"ipsCursor_drag\"><i class=\"fa fa-bars\"></i></span>&nbsp;\
<span class=\"ipsDataItem_title\" data-role=\"title_{{cat}}\">{{name}}</span>\
<input type=\"text\" name=\"blog_name_{{cat}}\" value=\"\" data-role=\"input_{{cat}}\" class=\"ipsHide\">\
<a href=\"#\" data-role=\"saveChanges\" data-category-id=\"{{cat}}\" class=\"ipsHide ipsButton ipsButton_verySmall ipsButton_light ipsButton_narrow\" data-ipstooltip=\"\" title=\"{{#lang}}save{{/lang}}\">{{#lang}}save{{/lang}}</a>\
<a href=\"#\" data-role=\"cancelChanges\" data-category-id=\"{{cat}}\" class=\"ipsHide\" data-ipstooltip=\"\" title=\"{{#lang}}cancel{{/lang}}\">{{#lang}}cancel{{/lang}}</a>\
</div>\
<div class=\"ipsDataItem_generic ipsDataItem_size3 cBlog_manage_edit ipsPos_top ipsType_right\">\
<a href=\"#\" data-action=\"delete\" data-category-id=\"{{cat}}\" class=\"ipsButton ipsButton_verySmall ipsButton_light ipsButton_narrow ipsPos_right\" data-ipstooltip title=\"{{#lang}}delete{{/lang}}\"><i class=\"fa fa-times-circle\"></i></a>\
<a href=\"#\" data-action=\"edit\" data-category-id=\"{{cat}}\" class=\"ipsButton ipsButton_verySmall ipsButton_light ipsButton_narrow ipsPos_right\" data-ipstooltip title=\"{{#lang}}edit{{/lang}}\"><i class\=\"fa fa-pencil\"></i></a>\
</div>\
</li>\
");
]]></file>
<order app="global" path="/dev/js//framework/">templates
common/ips.loader.js
common/ui
@@ -76,9 +367,11 @@ controllers</order>
jquery
mustache
jstz
IntersectionObserver
Debug.js
app.js</order>
<order app="global" path="/dev/js//library//jquery">jquery.js
jquery-migrate.js
jquery.history.js
jquery.transform.js</order>
<order app="global" path="/dev/js//library//linkify">linkify.min.js
+49 -6
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<language>
<app key="blog" version="103038">
<app key="blog" version="105100">
<word key="__app_blog" 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>
@@ -32,8 +32,8 @@
<word key="blog_enable_rating" js="0">Enable blog ratings?</word>
<word key="blog_settings_rss" js="0">RSS Settings</word>
<word key="blog_allow_rssimport" js="0">Allow RSS imports</word>
<word key="blog_allow_rssimport_desc" js="0"><![CDATA[Allowing users to import RSS feeds will make your site susceptible to <a href='https://owasp.org/www-community/attacks/Server_Side_Request_Forgery' target='_blank' rel='noopener'>SSRF attacks</a>. You should not allow RSS imports to Blog if untrusted users are permitted to create blogs, and you should only import RSS feeds from sources that are trusted and that do not allow user-submitted content to be included in the feed.]]></word>
<word key="blog_allow_rss" js="0">Allow RSS exports</word>
<word key="blog_allow_rss_desc" js="0"><![CDATA[Only content that is available to guests will be shown. For more options, create a <a href='{internal.app=core&module=discovery&controller=rss}'>Custom RSS Feed</a>]]></word>
<word key="blog_allow_grid" js="0">Enable grid view</word>
<word key="blog_allow_grid_desc" js="0">Grid view showcases blog entries as cards with space for a feature photo</word>
<word key="blog_view_mode" js="0">Default view</word>
@@ -90,7 +90,7 @@
<word key="blog_entry_title" js="0">Title</word>
<word key="blog_entry_tags" js="0">Tags</word>
<word key="blog_entry_auto_follow" js="0"></word>
<word key="blog_entry_auto_follow_suffix" js="0">Notify me when other comments are posted</word>
<word key="blog_entry_auto_follow_suffix" js="0">Follow this entry</word>
<word key="blog_entry_content" js="0">Content</word>
<word key="blog_entry_date" js="0">Publish Time</word>
<word key="blog_entry_publish" js="0">Publish</word>
@@ -104,6 +104,9 @@
<word key="entry_ip_address" js="0">IP Address</word>
<word key="entry_gallery_album" js="0">Album</word>
<word key="entry_gallery_album_desc" js="0">You can associate an album from the Gallery with this entry to display images alongside the entry content</word>
<word key="entry_category_choice" js="0">Entry Category</word>
<word key="entry_category_choice_new" js="0">Create a new entry category</word>
<word key="entry_category_choice_existing" js="0">Use an existing entry category</word>
<word key="block_entryFeed" js="0">Blog Entry Feed</word>
<word key="block_entryFeed_desc" js="0">Create a feed of blog entries</word>
<word key="widget_feed_container_blog_entry" js="0">Blogs</word>
@@ -112,6 +115,8 @@
<word key="view_this_entry" js="0">View the entry %s</word>
<word key="block_blogStatistics" js="0">Blog Statistics</word>
<word key="block_blogStatistics_desc" js="0">Shows general blog statistics</word>
<word key="stats_overview_blogs" js="0">Blogs</word>
<word key="stats_overview_blogs_desc" js="0">Blog creation date is not tracked so this is a total count and not limited by any date range restrictions applied</word>
<word key="total_blogs" js="0">Total Blogs</word>
<word key="total_entries" js="0">Total Entries</word>
<word key="block_recentEntries" js="0">Recent Entries</word>
@@ -140,6 +145,8 @@
<word key="entry_posted" js="0">Entry posted by %s</word>
<word key="entry_future_posted" js="0">Entry by %s publishes on</word>
<word key="entry_images" js="0">Images</word>
<word key="entry_posted_with_cat" js="0">Entry posted by %s in %s</word>
<word key="entry_future_posted_with_cat" js="0">Entry by %s in %s publishes on</word>
<word key="blog_comments" js="0">{!#[1:comment][?:comments]}</word>
<word key="blog_entries" js="0">{!#[1:entry][?:entries]}</word>
<word key="blog_views" js="0">{!#[1:view][?:views]}</word>
@@ -161,16 +168,19 @@
<word key="read_blog" js="0">You've read this entry</word>
<word key="go_to_blog" js="0">Go to the blog %s</word>
<word key="latest_entry" js="0">Latest Entry</word>
<word key="entry_name_with_cat" js="0">%s in %s</word>
<word key="no_entries" js="0">No blog entries have been created</word>
<word key="pin_blog" js="0">Pin</word>
<word key="unpin_blog" js="0">Unpin</word>
<word key="blog_by" js="0">A blog by %s</word>
<word key="group_blog_by" js="0">A group blog by %s</word>
<word key="blog_by" js="0">A blog by %s in %s</word>
<word key="group_blog_by" js="0">A group blog by %s in %s</word>
<word key="club_blog_for" js="0">A club blog for %s</word>
<word key="contributors_to_this" js="0">Contributors to this blog</word>
<word key="num_contributors_to_this" js="0">{# [1:contributor][?:contributors]} to this blog</word>
<word key="about_this_blog" js="0">About this blog</word>
<word key="entries_in_this_blog" js="0">Entries in this blog</word>
<word key="blog_category_viewing" js="0">Viewing category %s</word>
<word key="blog_category_select" js="0">View a category</word>
<word key="blog_rss_offline" js="0">RSS feed disabled</word>
<word key="blog_rss_offline_admin" js="0">This RSS feed is disabled either because the setting &quot;Allow RSS exports&quot; is currently disabled in the ACP or it is disabled in the individual blog settings.</word>
<word key="blog_enable_rss" js="0">Enable RSS Feed</word>
@@ -212,7 +222,13 @@
<word key="loc_blog_viewing_blog" js="0">Viewing Blog: %s</word>
<word key="loc_blog_adding_entry" js="0">Adding a Blog Entry in: %s</word>
<word key="loc_blog_viewing_entry" js="0">Viewing Entry: %s</word>
<word key="modperms__core_Content_blog_Entry" js="0">Blogs</word>
<word key="loc_blog_viewing_index_action" js="0">%s is browsing blogs</word>
<word key="loc_blog_creating_action" js="0">%s is creating a blog</word>
<word key="loc_blog_viewing_blog_action" js="0">%s is viewing a blog</word>
<word key="loc_blog_adding_entry_action" js="0">%s is adding a blog entry</word>
<word key="loc_blog_viewing_entry_action" js="0">%s is reading a blog entry</word>
<word key="modperms__core_Content_blog_Entry" js="0">Blog Entries</word>
<word key="modperms__blog_Blogs" js="0">Blogs</word>
<word key="can_pin_blog_entry" js="0">Can pin entries?</word>
<word key="can_unpin_blog_entry" js="0">Can unpin entries?</word>
<word key="can_feature_blog_entry" js="0">Can feature entries?</word>
@@ -221,6 +237,7 @@
<word key="can_hide_blog_entry" js="0">Can hide entries?</word>
<word key="can_unhide_blog_entry" js="0">Can unhide entries?</word>
<word key="can_view_hidden_blog_entry" js="0">Can view hidden entries?</word>
<word key="can_mod_blogs" js="0">Can move blogs?</word>
<word key="can_move_blog_entry" js="0">Can move entries?</word>
<word key="can_move_blog_entry_desc" js="0">Will be able to move entries only between the blogs they can create new content within.</word>
<word key="can_lock_blog_entry" js="0">Can lock entries?</word>
@@ -246,6 +263,7 @@
<word key="g_blog_allowprivate_desc" js="0">Private blogs can only be seen by the members that the creator chooses.</word>
<word key="g_blog_allowpoll" js="0">Can add polls to blog entries?</word>
<word key="g_blog_allowcomment" js="0">Can comment on blog entries?</word>
<word key="g_blog_allowcomment_guestreg" js="0"><![CDATA[<a href='{internal.admin.app=core&module=settings&controller=posting&searchResult=post_before_registering}'>Post Before Registering</a> is enabled, but will be bypassed when you enable this setting.]]></word>
<word key="g_blog_allowownmod" js="0">Can moderate own blog entries?</word>
<word key="g_blog_allowownmod_desc" js="0">The user will be able to: edit comments and entries, delete comments and entries, and lock entries from further comments.</word>
<word key="g_blog_allowdelete" js="0">Can delete own blogs?</word>
@@ -268,5 +286,30 @@
<word key="blog_bm_filters" js="0">Blog</word>
<word key="mf_has_blog" js="0">Member has a Blog?</word>
<word key="blog_entry_cover_photo" js="0">Feature Photo</word>
<word key="menu__blog_blogs_categories" js="0">Blogs</word>
<word key="blog_categories" js="0">Blogs</word>
<word key="blog_create_category" js="0">Create New Category</word>
<word key="blog_categories_add_child" js="0">Add Blog</word>
<word key="blog_category_id" js="0">Category</word>
<word key="category_basic_settings" js="0">Basic Settings</word>
<word key="blog_category_desc" js="0">Description</word>
<word key="category_parent" js="0">Parent</word>
<word key="category_desc_placeholder" js="0">Add a description...</word>
<word key="__api_blog_categories" js="0">Categories</word>
<word key="entry_category_id" js="0">Select Entry Category</word>
<word key="blog_entry_new_category" js="0">Entry Category Name</word>
<word key="blog_entry_category_new" js="0"> - Choose New - </word>
<word key="blog_category_heading" js="0">Viewing entries in %s</word>
<word key="blog_manage_entry_categories" js="0">Manage Categories</word>
<word key="blog_entry_categories" js="0">Entry Categories</word>
<word key="blog_error_missing_name" js="0">You need to enter a name for this category</word>
<word key="blog_error_not_find_category" js="0">Could not locate that category</word>
<word key="blog_categories_all" js="0">Show All</word>
<word key="no_entries_in_cat" js="0">There are no entries in this category</word>
<word key="__api_blog_entrycategories" js="0">Entry Categories</word>
<word key="blog_category_confirm_delete" js="1">Are you sure you want to delete this category?</word>
<word key="blog_category_confirm_delete_desc" js="1">Existing entries in this category will be updated so that they are no longer in a category.</word>
<word key="manage_cats_new_row" js="1">Add New Category</word>
<word key="entry_cat_order_saved" js="1">Category order saved</word>
</app>
</language>
+4 -2
View File
@@ -2,13 +2,15 @@
"admin": {
"blogs": {
"default_controller": "",
"protected": 0
"protected": 0,
"default": 1
}
},
"front": {
"blogs": {
"default_controller": "browse",
"protected": 0
"protected": 0,
"default": 1
}
}
}
+214 -201
View File
@@ -379,6 +379,20 @@
"zerofill": false,
"auto_increment": false,
"binary": false
},
"blog_category_id": {
"name": "blog_category_id",
"type": "BIGINT",
"length": 20,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
}
},
"indexes": {
@@ -447,6 +461,16 @@
"blog_allowguests",
"blog_last_edate"
]
},
"blog_category_id": {
"type": "key",
"name": "blog_category_id",
"columns": [
"blog_category_id"
],
"length": [
null
]
}
},
"collation": "utf8mb4_unicode_ci",
@@ -878,13 +902,53 @@
},
"entry_meta_data": {
"name": "entry_meta_data",
"type": "BIT",
"type": "TINYINT",
"length": 1,
"decimals": null,
"values": null,
"allow_null": false,
"default": "0",
"comment": "",
"unsigned": true,
"auto_increment": false
},
"entry_category_id": {
"name": "entry_category_id",
"type": "INT",
"length": 10,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
},
"entry_append_edit": {
"name": "entry_append_edit",
"type": "TINYINT",
"length": 1,
"decimals": null,
"values": null,
"allow_null": false,
"default": "0",
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
},
"entry_edit_reason": {
"name": "entry_edit_reason",
"type": "VARCHAR",
"length": 255,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
@@ -930,16 +994,6 @@
"entry_last_update"
]
},
"entry_category_id": {
"type": "key",
"name": "entry_category_id",
"length": [
null
],
"columns": [
"entry_blog_id"
]
},
"entry_featured": {
"type": "key",
"name": "entry_featured",
@@ -1112,18 +1166,16 @@
"zerofill": false
},
"comment_text": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 0,
"name": "comment_text",
"type": "TEXT",
"unsigned": false,
"type": "MEDIUMTEXT",
"length": 0,
"decimals": null,
"values": [],
"zerofill": false
"allow_null": true,
"default": null,
"comment": "",
"unsigned": false,
"auto_increment": false
},
"comment_approved": {
"allow_null": true,
@@ -1239,10 +1291,105 @@
"comment": "",
"reporting": "count"
},
"blog_rss_import": {
"name": "blog_rss_import",
"blog_categories": {
"name": "blog_categories",
"columns": {
"rss_id": {
"category_id": {
"allow_null": false,
"auto_increment": true,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 5,
"name": "category_id",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
},
"category_seo_name": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 255,
"name": "category_seo_name",
"type": "VARCHAR",
"unsigned": false,
"values": [],
"zerofill": false
},
"category_position": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "0",
"length": 5,
"name": "category_position",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
},
"category_parent": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "0",
"length": 5,
"name": "category_parent",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
}
},
"indexes": {
"PRIMARY": {
"type": "primary",
"name": "PRIMARY",
"length": [
null
],
"columns": [
"category_id"
]
},
"pg_position": {
"type": "key",
"name": "pg_position",
"length": [
null
],
"columns": [
"category_position"
]
},
"pg_parent": {
"type": "key",
"name": "pg_parent",
"length": [
null
],
"columns": [
"category_parent"
]
}
},
"collation": "utf8mb4_unicode_ci",
"engine": "InnoDB"
},
"blog_entry_categories": {
"name": "blog_entry_categories",
"columns": {
"entry_category_id": {
"allow_null": false,
"auto_increment": true,
"binary": false,
@@ -1250,204 +1397,69 @@
"decimals": null,
"default": null,
"length": 10,
"name": "rss_id",
"name": "entry_category_id",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
},
"rss_blog_id": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "0",
"length": 10,
"name": "rss_blog_id",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
},
"rss_url": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "",
"length": 255,
"name": "rss_url",
"type": "VARCHAR",
"unsigned": false,
"values": [],
"zerofill": false
},
"rss_auth_user": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "",
"length": 255,
"name": "rss_auth_user",
"type": "VARCHAR",
"unsigned": false,
"values": [],
"zerofill": false
},
"rss_auth_pass": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "",
"length": 255,
"name": "rss_auth_pass",
"type": "VARCHAR",
"unsigned": false,
"values": [],
"zerofill": false
},
"rss_last_import": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "0",
"length": 10,
"name": "rss_last_import",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
},
"rss_tags": {
"entry_category_name": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 0,
"name": "rss_tags",
"type": "TEXT",
"unsigned": false,
"values": [],
"zerofill": false
},
"rss_member": {
"name": "rss_member",
"type": "BIGINT",
"length": 20,
"decimals": null,
"values": [],
"allow_null": false,
"default": "0",
"comment": "",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
},
"rss_import_show_link": {
"name": "rss_import_show_link",
"type": "VARCHAR",
"length": 255,
"decimals": null,
"values": [],
"allow_null": true,
"default": null,
"comment": "Text to show for link to full article",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
},
"indexes": {
"PRIMARY": {
"type": "primary",
"name": "PRIMARY",
"length": [
null
],
"columns": [
"rss_id"
]
},
"blog_time": {
"type": "key",
"name": "blog_time",
"length": [
null,
null
],
"columns": [
"rss_blog_id",
"rss_last_import"
]
},
"rss_blog_id": {
"type": "key",
"name": "rss_blog_id",
"length": [
null
],
"columns": [
"rss_blog_id"
]
},
"rss_last_import": {
"type": "key",
"name": "rss_last_import",
"length": [
null
],
"columns": [
"rss_last_import"
]
}
},
"comment": "",
"reporting": "count"
},
"blog_rss_imported": {
"name": "blog_rss_imported",
"columns": {
"rss_imported_guid": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "0",
"length": 32,
"name": "rss_imported_guid",
"type": "CHAR",
"name": "entry_category_name",
"type": "VARCHAR",
"unsigned": false,
"values": [],
"zerofill": false
},
"rss_imported_entry_id": {
"entry_category_seo_name": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 255,
"name": "entry_category_seo_name",
"type": "VARCHAR",
"unsigned": false,
"values": [],
"zerofill": false
},
"entry_category_position": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "0",
"length": 10,
"name": "rss_imported_entry_id",
"length": 5,
"name": "entry_category_position",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
},
"rss_imported_impid": {
"entry_category_blog_id": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "",
"length": 10,
"name": "entry_category_blog_id",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
},
"entry_category_count": {
"allow_null": false,
"auto_increment": false,
"binary": false,
@@ -1455,7 +1467,7 @@
"decimals": null,
"default": "0",
"length": 10,
"name": "rss_imported_impid",
"name": "entry_category_count",
"type": "INT",
"unsigned": false,
"values": [],
@@ -1470,20 +1482,21 @@
null
],
"columns": [
"rss_imported_guid"
"entry_category_id"
]
},
"rss_imported_impid": {
"pg_position": {
"type": "key",
"name": "rss_imported_impid",
"name": "pg_position",
"length": [
null
],
"columns": [
"rss_imported_impid"
"entry_category_position"
]
}
},
"comment": ""
"collation": "utf8mb4_unicode_ci",
"engine": "InnoDB"
}
}
+1 -1
View File
@@ -1 +1 @@
{"blogrssimport":"P0Y0M0DT0H30M0S"}
[]
File diff suppressed because it is too large. Load diff
+93 -1
View File
@@ -283,5 +283,97 @@
"103035": "4.3.6",
"103036": "4.3.6",
"103037": "4.3.6",
"103038": "4.3.6"
"103038": "4.3.6",
"103039": "4.3.6",
"104000": "4.4.0 Beta 1",
"104001": "4.4.0 Beta 2",
"104002": "4.4.0 Beta 3",
"104004": "4.4.0 Beta 4",
"104003": "4.4.0 Beta 4",
"104005": "4.4.0",
"104006": "4.4.0",
"104007": "4.4.0",
"104008": "4.4.0",
"104009": "4.4.1",
"104010": "4.4.1 Beta 2",
"104011": "4.4.1",
"104012": "4.4.1",
"104013": "4.4.1",
"104014": "4.4.1",
"104015": "4.4.2 Beta 1",
"104016": "4.4.2",
"104017": "4.4.2",
"104018": "4.4.2",
"104019": "4.4.2",
"104020": "4.4.2",
"104021": "4.4.3 Beta 1",
"104022": "4.4.3 Beta 2",
"104023": "4.4.3",
"104024": "4.4.3",
"104025": "4.4.3",
"104026": "4.4.4 Beta 1",
"104027": "4.4.4",
"104028": "4.4.4",
"104029": "4.4.4",
"104030": "4.4.5 Beta 1",
"104031": "4.4.5 Beta 2",
"104032": "4.4.5 Beta 2",
"104033": "4.4.5",
"104034": "4.4.5",
"104035": "4.4.5",
"104036": "4.4.5",
"104037": "4.4.5",
"104038": "4.4.6",
"104039": "4.4.6",
"104040": "4.4.6",
"104041": "4.4.7 Beta 1",
"104042": "4.4.7 Beta 2",
"104043": "4.4.7 Beta 3",
"104044": "4.4.7",
"104045": "4.4.8 Beta 1",
"104046": "4.4.8 Beta 2",
"104047": "4.4.8",
"104048": "4.4.9 Beta 1",
"104049": "4.4.9",
"104050": "4.4.9",
"104051": "4.4.9",
"104052": "4.4.9",
"104053": "4.4.9.1",
"104054": "4.4.9.1",
"104055": "4.4.9.2",
"104056": "4.4.9.2",
"104057": "4.4.10 Beta 1",
"104058": "4.4.10 Beta 2",
"104059": "4.4.10 Beta 3",
"104060": "4.4.10 Beta 4",
"104061": "4.4.10",
"104062": "4.4.10",
"104063": "4.4.10",
"104064": "4.4.10",
"104065": "4.4.10",
"104066": "4.4.10",
"104067": "4.4.10",
"104068": "4.4.10",
"104069": "4.4.10",
"105013": "4.5.0 Beta 1",
"105014": "4.5.0 Beta 1",
"105015": "4.5.0 Beta 2",
"105016": "4.5.0 Beta 3",
"105017": "4.5.0 Beta 4",
"105018": "4.5.0 Beta 4",
"105019": "4.5.0 Beta 4",
"105020": "4.5.0 Beta 4",
"105021": "4.5.0 Beta 5",
"105022": "4.5.0 Beta 6",
"105023": "4.5.0 Beta 6",
"105024": "4.5.0 Beta 7",
"105025": "4.5.0 Beta 8",
"105026": "4.5.0 Beta 8",
"105027": "4.5.0 Beta 8",
"105028": "4.5.0 Beta 9",
"105029": "4.5.0 Beta 10",
"105030": "4.5.0 Beta 11",
"105031": "4.5.0 Beta 11",
"105032": "4.5.0 Beta 12",
"105100": "4.5.0"
}
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\BBCode;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -60,7 +60,7 @@ class _blog
{
try
{
$node->setAttribute( 'href', (string) \IPS\blog\Blog::load( intval( $matches[2] ) )->url() );
$node->setAttribute( 'href', (string) \IPS\blog\Blog::load( \intval( $matches[2] ) )->url() );
}
catch ( \Exception $e ) {}
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\BBCode;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -60,7 +60,7 @@ class _entry
{
try
{
$node->setAttribute( 'href', (string) \IPS\blog\Entry::load( intval( $matches[2] ) )->url() );
$node->setAttribute( 'href', (string) \IPS\blog\Entry::load( \intval( $matches[2] ) )->url() );
}
catch ( \Exception $e ) {}
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\ContentRouter;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\CreateMenu;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -30,13 +30,19 @@ class _Entry
*/
public function getItems()
{
/* Posting limits */
if ( \IPS\Member::loggedIn()->checkPostsPerDay() === FALSE )
{
return array();
}
$blogs = \IPS\blog\Blog::loadByOwner( \IPS\Member::loggedIn(), array( array( 'blog_disabled=?', 0 ) ) );
if (
count( $blogs )
\count( $blogs )
or
( \IPS\Settings::i()->club_nodes_in_apps and count( \IPS\blog\Blog::clubNodes( 'add' ) ) )
( \IPS\Settings::i()->club_nodes_in_apps and \count( \IPS\blog\Blog::clubNodes( 'add' ) ) )
) {
if ( !\IPS\Settings::i()->club_nodes_in_apps AND count( $blogs ) === 1 )
if ( !\IPS\Settings::i()->club_nodes_in_apps AND \count( $blogs ) === 1 )
{
$ourBlog = array_shift( $blogs );
return array(
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\Dashboard;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\EditorLocations;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -84,7 +84,7 @@ class _Blogs
/* The attachment is attached to a comment */
if ( $id2 )
{
return \IPS\blog\Entry\Comment::load( $id2 )->canView( $member );
return \IPS\blog\Entry\Comment::load( $id2 );
}
else
{
@@ -119,26 +119,46 @@ class _Blogs
}
/**
* @brief Store image proxy status ( true = enabled )
* @brief Use the cached image URL instead of the original URL
*/
protected $_imageProxyStatus = null;
protected $proxyUrl = FALSE;
/**
* Rebuild content to add or remove image proxy
*
* @param int|null $offset Offset to start from
* @param int|null $max Maximum to parse
* @param bool $status Enable/Disable Image Proxy
* @param bool $proxyUrl Use the cached image URL instead of the original URL
* @return int Number completed
* @note This method is optional and will only be called if it exists
*/
public function rebuildImageProxy( $offset, $max, $status=TRUE )
public function rebuildImageProxy( $offset, $max, $proxyUrl = FALSE )
{
$this->_imageProxyStatus = $status;
$this->proxyUrl = $proxyUrl;
return $this->performRebuild( $offset, $max, 'parseImageProxy' );
}
/**
* @brief Store lazy loading status ( true = enabled )
*/
protected $_lazyLoadStatus = null;
/**
* Rebuild content to add or remove lazy loading
*
* @param int|null $offset Offset to start from
* @param int|null $max Maximum to parse
* @param bool $status Enable/Disable lazy loading
* @return int Number completed
* @note This method is optional and will only be called if it exists
*/
public function rebuildLazyLoad( $offset, $max, $status=TRUE )
{
$this->_lazyLoadStatus = $status;
return $this->performRebuild( $offset, $max, 'parseLazyLoad' );
}
/**
* Perform rebuild - abstracted as the call for rebuildContent() and rebuildAttachmentImages() is nearly identical
*
@@ -160,11 +180,15 @@ class _Blogs
{
if( $callback == 'parseImageProxy' )
{
$rebuilt = \IPS\Text\Parser::parseImageProxy( $word['word_custom'], $this->_imageProxyStatus );
$rebuilt = \IPS\Text\Parser::removeImageProxy( $word['word_custom'], $this->proxyUrl );
}
elseif( $callback == 'parseLazyLoad' )
{
$rebuilt = \IPS\Text\Parser::parseLazyLoad( $word['word_custom'], $this->_lazyLoadStatus );
}
else
{
$rebuilt = call_user_func( $callback, $word['word_custom'] );
$rebuilt = $callback( $word['word_custom'] );
}
}
catch( \InvalidArgumentException $e )
@@ -0,0 +1,199 @@
<?php
/**
* @brief Editor Extension: Categories
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @subpackage Blogs
* @since 30 Jul 2019
*/
namespace IPS\blog\extensions\core\EditorLocations;
/* 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;
}
/**
* Editor Extension: Categories
*/
class _Categories
{
/**
* Can we use HTML in this editor?
*
* @param \IPS\Member $member The member
* @return bool|null NULL will cause the default value (based on the member's permissions) to be used, and is recommended in most cases. A boolean value will override that.
*/
public function canUseHtml( $member )
{
return NULL;
}
/**
* Can we use attachments in this editor?
*
* @param \IPS\Member $member The member
* @param \IPS\Helpers\Form\Editor $field The editor field
* @return bool|null NULL will cause the default value (based on the member's permissions) to be used, and is recommended in most cases. A boolean value will override that.
*/
public function canAttach( $member, $field )
{
return NULL;
}
/**
* Permission check for attachments
*
* @param \IPS\Member $member The member
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @param array $attachment The attachment data
* @param bool $viewOnly If true, just check if the user can see the attachment rather than download it
* @return bool
*/
public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment, $viewOnly=FALSE )
{
return TRUE;
}
/**
* Attachment lookup
*
* @param int|null $id1 Primary ID
* @param int|null $id2 Secondary ID
* @param string|null $id3 Arbitrary data
* @return \IPS\Http\Url|\IPS\Content|\IPS\Node\Model
* @throws \LogicException
*/
public function attachmentLookup( $id1, $id2, $id3 )
{
switch ( $id3 )
{
case 'bcategory':
return \IPS\Http\Url::internal( "app=blog&module=blogs&controller=categories&do=form&id={$id1}", 'admin' );
break;
};
}
/**
* Rebuild attachment images in non-content item areas
*
* @param int|null $offset Offset to start from
* @param int|null $max Maximum to parse
* @return int Number completed
* @note This method is optional and will only be called if it exists
*/
public function rebuildAttachmentImages( $offset, $max )
{
return $this->performRebuild( $offset, $max, array( 'IPS\Text\Parser', 'rebuildAttachmentUrls' ) );
}
/**
* @brief Use the cached image URL instead of the original URL
*/
protected $proxyUrl = FALSE;
/**
* Rebuild content to add or remove image proxy
*
* @param int|null $offset Offset to start from
* @param int|null $max Maximum to parse
* @param bool $proxyUrl Use the cached image URL instead of the original URL
* @return int Number completed
* @note This method is optional and will only be called if it exists
*/
public function rebuildImageProxy( $offset, $max, $proxyUrl = FALSE )
{
$this->proxyUrl = $proxyUrl;
return $this->performRebuild( $offset, $max, 'parseImageProxy' );
}
/**
* @brief Store lazy loading status ( true = enabled )
*/
protected $_lazyLoadStatus = null;
/**
* Rebuild content to add or remove lazy loading
*
* @param int|null $offset Offset to start from
* @param int|null $max Maximum to parse
* @param bool $status Enable/Disable lazy loading
* @return int Number completed
* @note This method is optional and will only be called if it exists
*/
public function rebuildLazyLoad( $offset, $max, $status=TRUE )
{
$this->_lazyLoadStatus = $status;
return $this->performRebuild( $offset, $max, 'parseLazyLoad' );
}
/**
* Perform rebuild - abstracted as the call for rebuildContent() and rebuildAttachmentImages() is nearly identical
*
* @param int|null $offset Offset to start from
* @param int|null $max Maximum to parse
* @param callable $callback Method to call to rebuild content
* @return int Number completed
*/
protected function performRebuild( $offset, $max, $callback )
{
/* We will do everything except pages first */
if( !$offset )
{
/* Language bits */
foreach( \IPS\Db::i()->select( '*', 'core_sys_lang_words', "word_key LIKE 'blog_category_%_desc'", 'word_id ASC', array( $offset, $max ) ) as $word )
{
try
{
if( $callback == 'parseImageProxy' )
{
$rebuilt = \IPS\Text\Parser::removeImageProxy( $word['word_custom'], $this->proxyUrl );
}
elseif( $callback == 'parseLazyLoad' )
{
$rebuilt = \IPS\Text\Parser::parseLazyLoad( $word['word_custom'], $this->_lazyLoadStatus );
}
else
{
$rebuilt = $callback( $word['word_custom'] );
}
}
catch( \InvalidArgumentException $e )
{
if( $callback[1] == 'parseStatic' AND $e->getcode() == 103014 )
{
$rebuilt = preg_replace( "#\[/?([^\]]+?)\]#", '', $word['word_custom'] );
}
else
{
throw $e;
}
}
if( $rebuilt !== FALSE )
{
\IPS\Db::i()->update( 'core_sys_lang_words', array( 'word_custom' => $rebuilt ), 'word_id=' . $word['word_id'] );
}
}
}
}
/**
* Total content count to be used in progress indicator
*
* @return int Total Count
*/
public function contentCount()
{
return \IPS\Db::i()->select( 'COUNT(*) as count', 'core_sys_lang_words', "word_key LIKE 'blog_category_%_desc'" )->first();
}
}
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\EditorLocations;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\FileStorage;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\FileStorage;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\FrontNavigation;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\GroupForm;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -42,6 +42,10 @@ class _Blog
}
$form->add(new \IPS\Helpers\Form\YesNo('g_blog_allowcomment', $group->g_blog_allowcomment));
if( $group->g_id == \IPS\Settings::i()->guest_group AND \IPS\Settings::i()->post_before_registering )
{
\IPS\Member::loggedIn()->language()->words['g_blog_allowcomment_desc'] = \IPS\Member::loggedIn()->language()->addToStack('g_blog_allowcomment_guestreg');
}
}
/**
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\LiveSearch;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -26,7 +26,7 @@ class _Blogs
/**
* Check we have access
*
* @return void
* @return bool
*/
public function hasAccess()
{
@@ -37,7 +37,7 @@ class _Blogs
/**
* Get the search results
*
* @param string Search Term
* @param string $searchTerm Search Term
* @return array Array of results
*/
public function getResults( $searchTerm )
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\MemberFilter;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -31,7 +31,7 @@ class _Blog
*/
public function availableIn( $area )
{
return in_array( $area, array( 'bulkmail', 'group_promotions' ) );
return \in_array( $area, array( 'bulkmail', 'group_promotions' ) );
}
/**
@@ -58,7 +58,7 @@ class _Blog
*/
public function save( $post )
{
if( isset( $post['mf_has_blog'] ) and in_array( $post['mf_has_blog'], array( 'yes', 'no' ) ) )
if( isset( $post['mf_has_blog'] ) and \in_array( $post['mf_has_blog'], array( 'yes', 'no' ) ) )
{
return array( 'has_blog' => $post['mf_has_blog'] );
}
@@ -70,7 +70,7 @@ class _Blog
* Get where clause to add to the member retrieval database query
*
* @param mixed $data The array returned from the save() method
* @return array|NULL Where clause - must be a single array( "clause", ...binds )
* @return array|NULL Where clause - must be a single array( "clause" )
*/
public function getQueryWhereClause( $data )
{
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\MemberSync;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -33,7 +33,6 @@ class _Blog
public function onMerge( $member, $member2 )
{
\IPS\Db::i()->update( 'blog_blogs', array( 'blog_member_id' => $member->member_id ), array( 'blog_member_id=?', $member2->member_id ) );
\IPS\Db::i()->update( 'blog_rss_import', array( 'rss_member' => $member->member_id ), array( 'rss_member=?', $member2->member_id ) );
foreach( \IPS\blog\Blog::loadByOwner( $member2 ) as $blog )
{
@@ -50,8 +49,6 @@ class _Blog
*/
public function onDelete( $member )
{
\IPS\Db::i()->update( 'blog_rss_import', array( 'rss_member' => 0 ), array( 'rss_member=?', $member->member_id ) );
foreach( \IPS\blog\Blog::loadByOwner( $member ) as $blog )
{
/* We only want to do this if the blog is owned by the member - loadByOwner() also returns Blogs that are assigned to member groups */
@@ -62,4 +59,30 @@ class _Blog
}
}
}
/**
* Member is flagged as spammer
*
* @param $member \IPS\Member The member
* @return void
*/
public function onSetAsSpammer( $member )
{
$actions = explode( ',', \IPS\Settings::i()->spm_option );
/* Hide or delete */
if ( \in_array( 'unapprove', $actions ) or \in_array( 'delete', $actions ) )
{
foreach( \IPS\blog\Blog::loadByOwner( $member ) as $blog )
{
$blog->disabled = TRUE;
$blog->save();
if( \in_array( 'delete', $actions ) )
{
\IPS\Task::queue( 'core', 'DeleteOrMoveContent', array( 'class' => 'IPS\blog\Blog', 'id' => $blog->id, 'deleteWhenDone' => TRUE ), 3 );
}
}
}
}
}
@@ -0,0 +1,70 @@
<?php
/**
* @brief Moderator Permissions
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @subpackage Blogs
* @since 14 Aug 2019
*/
namespace IPS\blog\extensions\core\ModeratorPermissions;
/* 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;
}
/**
* Moderator Permissions
*/
class _Blogs
{
/**
* Get Permissions
*
* @code
return array(
'key' => 'YesNo', // Can just return a string with type
'key' => array( // Or an array for more options
'YesNo', // Type
array( ... ), // Options (as defined by type's class)
'prefix', // Prefix
'suffix', // Suffix
),
...
);
* @endcode
* @return array
*/
public function getPermissions()
{
return array( 'can_mod_blogs' => 'YesNo' );
}
/**
* After change
*
* @param array $moderator The moderator
* @param array $changed Values that were changed
* @return void
*/
public function onChange( $moderator, $changed )
{
}
/**
* After delete
*
* @param array $moderator The moderator
* @return void
*/
public function onDelete( $moderator )
{
}
}
@@ -0,0 +1,67 @@
<?php
/**
* @brief Overview statistics extension: Blogs
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @subpackage Blogs
* @since 28 Jan 2020
*/
namespace IPS\blog\extensions\core\OverviewStatistics;
/* 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;
}
/**
* @brief Overview statistics extension: Blogs
*/
class _Blogs
{
/**
* @brief Which statistics page (activity or user)
*/
public $page = 'activity';
/**
* Return the sub-block keys
*
* @note This is designed to allow one class to support multiple blocks, for instance using the ContentRouter to generate blocks.
* @return array
*/
public function getBlocks()
{
return array( 'blogs' );
}
/**
* Return block details (title and description)
*
* @param string|NULL $subBlock The subblock we are loading as returned by getBlocks()
* @return array
*/
public function getBlockDetails( $subBlock = NULL )
{
/* Description can be null and will not be shown if so */
return array( 'app' => 'blog', 'title' => 'stats_overview_blogs', 'description' => \IPS\Member::loggedIn()->language()->addToStack( 'stats_overview_blogs_desc' ), 'refresh' => 120 );
}
/**
* Return the block HTML to show
*
* @param array|NULL $dateRange NULL for all time, or an array with 'start' and 'end' \IPS\DateTime objects to restrict to
* @param string|NULL $subBlock The subblock we are loading as returned by getBlocks()
* @return string
*/
public function getBlock( $dateRange = NULL, $subBlock = NULL )
{
$total = \IPS\Db::i()->select( 'COUNT(*)', 'blog_blogs' )->first();
return \IPS\Theme::i()->getTemplate( 'stats' )->overviewComparisonCount( $total, NULL, NULL );
}
}
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\Profile;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\blog\extensions\core\Queue;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -26,7 +26,7 @@ class _RebuildEntryImages
/**
* @brief Number of entry images to rebuild per cycle
*/
public $rebuild = 10;
public $rebuild = \IPS\REBUILD_SLOW;
/**
* Parse data before queuing
@@ -56,12 +56,8 @@ class _RebuildEntryImages
*/
public function run( $data, $offset )
{
$select = \IPS\Db::i()->select( '*', 'blog_entries', "entry_image<>''", 'entry_id ASC', array( $offset, $this->rebuild ) );
if ( !$select->count() )
{
throw new \IPS\Task\Queue\OutOfRangeException;
}
$select = \IPS\Db::i()->select( '*', 'blog_entries', array( "entry_image<>? AND entry_id > ?", '', $offset ), 'entry_id ASC', array( 0, $this->rebuild ) );
$last = NULL;
foreach ( $select as $entry )
{
@@ -102,9 +98,16 @@ IMAGE;
\IPS\Db::i()->replace( 'core_attachments_map', $map );
}
catch ( \Exception $e ) {}
$last = $entry['entry_id'];
}
return $offset + $this->rebuild;
if( $last === NULL )
{
throw new \IPS\Task\Queue\OutOfRangeException;
}
return $last;
}
/**
Whitespace-only changes.
@@ -0,0 +1,129 @@
<?php
/**
* @brief RSS Import extension: RssImport
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @subpackage Forums
* @since 09 Oct 2019
*/
namespace IPS\blog\extensions\core\RssImport;
/* 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;
}
/**
* @brief RSS Import extension: RssImport
*/
class _RssImport
{
/**
* @brief RSSImport Class
*/
public $classes = array();
public $fileStorage = 'blog_Blogs';
/**
* Constructor
*
* @return void
*/
public function __construct()
{
$this->classes = array( 'IPS\\blog\\Entry' );
}
/**
* Return available options for a Form\Select
*
* @return array
*/
public function availableOptions()
{
/* We don't want to set up Blog feeds in the ACP */
return array();
}
/**
* Show in the Admin CP?
*
* @param Object $class The class to check
* @return boolean
*/
public function showInAdminCp( $class ): bool
{
return false;
}
/**
* Node selector options
*
* @param \IPS\core\Rss\Import|null $rss Existing RSS object if editing|NULL if not
* @return array
*/
public function nodeSelectorOptions( $rss )
{
return array( 'class' => 'IPS\blog\Blog', 'permissionCheck' => 'view' );
}
/**
* @param \IPS\core\Rss\Import $rss RSS object
* @param array $article RSS feed article importing
* @param \IPS\Node\Model $container Container object
* @param string $content Post content with read more link if set
* @return \IPS\Content
*/
public function create( \IPS\core\Rss\Import $rss, $article, \IPS\Node\Model $container, $content )
{
$settings = $rss->settings;
$class = $rss->_class;
$member = \IPS\Member::load( $rss->member );
$entry = $class::createItem( $member, NULL, $article['date'], $container );
$entry->name = $article['title'];
$entry->content = $content;
$entry->status = 'published';
$entry->save();
/* Add to search index */
\IPS\Content\Search\Index::i()->index( $entry );
/* Send notifications */
$entry->sendNotifications();
$entry->setTags( $settings['tags'] );
return $entry;
}
/**
* Addition Form elements
*
* @param \IPS\Helpers\Form $form The form
* @param \IPS\core\Rss\Import|null $rss Existing RSS object if editing|NULL if not
* @return void
*/
public function form( &$form, $rss=NULL )
{
/* Blogs has it's own front end controller */
}
/**
* Process additional fields unique to this extension
*
* @param array $values Values from form
* @param \IPS\core\Rss\Import $rss Existing RSS object
* @return array
*/
public function saveForm( &$values, $rss )
{
/* Blogs has it's own front end controller */
return array( $values );
}
}
+10 -123
View File
@@ -12,7 +12,7 @@
namespace IPS\blog\modules\admin\blogs;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,10 +23,15 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _blogs extends \IPS\Node\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Node Class
*/
protected $nodeClass = '\IPS\blog\Blog';
protected $nodeClass = '\IPS\blog\Category';
/**
* Execute
@@ -45,134 +50,16 @@ class _blogs extends \IPS\Node\Controller
* @return void
*/
protected function manage()
{
/* Create the table */
$table = new \IPS\Helpers\Table\Db( 'blog_blogs', \IPS\Http\Url::internal( 'app=blog&module=blogs&controller=blogs' ), array( array( 'blog_club_id IS NULL' ) ) );
$table->langPrefix = 'blog_';
/* Column stuff */
$table->include = array( 'word_custom' );
$table->mainColumn = 'word_custom';
$table->joins = array(
array( 'select' => 'w.word_custom', 'from' => array( 'core_sys_lang_words', 'w' ), 'where' => "w.word_key=CONCAT( 'blogs_blog_', blog_blogs.blog_id ) AND w.lang_id=" . \IPS\Member::loggedIn()->language()->id )
);
/* Sort stuff */
$table->sortBy = $table->sortBy ?: 'word_custom';
$table->sortDirection = $table->sortDirection ?: 'asc';
/* Search */
$table->quickSearch = 'word_custom';
$table->advancedSearch = array(
'word_custom' => \IPS\Helpers\Table\SEARCH_CONTAINS_TEXT,
'blog_member_id' => \IPS\Helpers\Table\SEARCH_MEMBER,
);
$table->parsers = array(
'blog_member_id' => function( $val, $row )
{
$member = \IPS\Member::load( $val );
if( $member->member_id )
{
return $member->link();
}
else
{
return NULL;
}
},
'word_custom' => function( $val, $row )
{
if ( ! $val )
{
return \IPS\Member::loggedIn()->language()->addToStack('blog_member_deleted');
}
return htmlspecialchars( $val, ENT_QUOTES | ENT_DISALLOWED, 'UTF-8', FALSE );
}
);
/* Row buttons */
$table->rowButtons = function( $row )
{
$blog = \IPS\blog\Blog::constructFromData( $row );
$return = array();
if ( $blog->canEdit() )
{
$return['edit'] = array(
'icon' => 'pencil',
'title' => 'edit',
'link' => \IPS\Http\Url::internal( 'app=blog&module=blogs&controller=blogs&do=form&id=' ) . $row['blog_id'],
'data' => array(),
'hotkey'=> 'e return'
);
}
$return['copy'] = array(
'icon' => 'files-o',
'title' => 'copy',
'link' => \IPS\Http\Url::internal( 'app=blog&module=blogs&controller=blogs&do=copy&id=' ) . $row['blog_id'],
'data' => array()
);
$return['content'] =
array(
'icon' => 'arrow-right',
'title' => 'mass_manage_content',
'link' => \IPS\Http\Url::internal( 'app=blog&module=blogs&controller=blogs&do=massManageContent&id=' ) . $row['blog_id'],
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('empty') ),
'hotkey'=> 'm'
);
if ( $blog->canDelete() )
{
$return['delete'] = array(
'icon' => 'times-circle',
'title' => 'delete',
'link' => \IPS\Http\Url::internal( 'app=blog&module=blogs&controller=blogs&do=delete&id=' ) . $row['blog_id'],
'data' => ( $blog->getContentItemCount() ) ? array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('delete') ) : array( 'delete' => '' ),
'hotkey'=> 'd'
);
}
return $return;
};
{
parent::manage();
/* Root buttons */
\IPS\Output::i()->sidebar['actions']['add'] = array(
'primary' => true,
'icon' => 'plus',
'title' => 'add_blog',
'title' => 'blog_create_category',
'link' => \IPS\Http\Url::internal( 'app=blog&module=blogs&controller=blogs&do=form' ),
'data' => array()
);
/* Display */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('blogs');
\IPS\Output::i()->output = (string) $table;
}
/**
* Add/Edit Form
*
* @return void
*/
protected function form()
{
parent::form();
if ( \IPS\Request::i()->id )
{
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('edit_blog') . ': ' . \IPS\Output::i()->title;
}
else
{
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('add_blog');
}
}
}
@@ -12,7 +12,7 @@
namespace IPS\blog\modules\admin\blogs;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,6 +23,11 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _settings extends \IPS\Dispatcher\Controller
{
/**
* @brief Has been CSRF-protected
*/
public static $csrfProtected = TRUE;
/**
* Execute
*
@@ -12,7 +12,7 @@
namespace IPS\blog\modules\front\blogs;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -30,6 +30,16 @@ class _browse extends \IPS\Dispatcher\Controller
*/
protected function manage()
{
/* Category */
try
{
$category = \IPS\blog\Category::loadAndCheckPerms( \IPS\Request::i()->id );
}
catch ( \OutOfRangeException $e )
{
$category = NULL;
}
/* Featured stuff */
$featured = iterator_to_array( \IPS\blog\Entry::featured( 5, '_rand' ) );
$blogs = \IPS\blog\Blog::loadByOwner( \IPS\Member::loggedIn(), array( array( 'blog_disabled=?', 0 ) ) );
@@ -45,6 +55,7 @@ class _browse extends \IPS\Dispatcher\Controller
if ( isset( \IPS\Request::i()->view ) )
{
\IPS\Session::i()->csrfCheck();
\IPS\Request::i()->setCookie( 'blog_view', \IPS\Request::i()->view, ( new \IPS\DateTime )->add( new \DateInterval( 'P1Y' ) ) );
}
@@ -56,7 +67,7 @@ class _browse extends \IPS\Dispatcher\Controller
if ( \IPS\Request::i()->page )
{
$page = intval( \IPS\Request::i()->page );
$page = \intval( \IPS\Request::i()->page );
if ( !$page OR $page < 1 )
{
$page = 1;
@@ -64,8 +75,20 @@ class _browse extends \IPS\Dispatcher\Controller
}
/* @note We cannot check individual member permissions here, so entries in draft status are excluded. */
$count = \IPS\blog\Entry::getItemsWithPermission( array( array( "entry_status!=?", 'draft' ) ), 'entry_date desc', NULL, 'read', \IPS\Content\Hideable::FILTER_AUTOMATIC, 0, NULL, FALSE, FALSE, FALSE, TRUE );
$entries = \IPS\blog\Entry::getItemsWithPermission( array( array( "entry_status!=?", 'draft' ) ), 'entry_date desc', array( ( $perpage * ( $page - 1 ) ), $perpage ) );
$where = array();
$where[] = array( "blog_entries.entry_status!=?", 'draft' );
if ( !\IPS\Settings::i()->club_nodes_in_apps )
{
$where[] = array( "blog_blogs.blog_club_id IS NULL" );
}
if( $category )
{
$where[] = array( 'blog_blogs.blog_category_id=?', $category->_id );
}
$count = \IPS\blog\Entry::getItemsWithPermission( $where, 'entry_date desc', NULL, 'read', \IPS\Content\Hideable::FILTER_AUTOMATIC, 0, NULL, TRUE, FALSE, FALSE, TRUE );
$entries = \IPS\blog\Entry::getItemsWithPermission( $where, 'entry_date desc', array( ( $perpage * ( $page - 1 ) ), $perpage ), 'read', \IPS\Content\Hideable::FILTER_AUTOMATIC, 0, NULL, TRUE );
$pagination = array(
'page' => $page,
'pages' => ceil( $count / $perpage ),
@@ -74,12 +97,16 @@ class _browse extends \IPS\Dispatcher\Controller
);
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'grid.css', 'blog', 'front' ) );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'browse' )->indexGrid( $entries, $featured, $blogs, $pagination, $viewMode );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'browse' )->indexGrid( $entries, $featured, $blogs, $pagination, $viewMode, $category );
}
else
{
/* Blogs table */
$table = new \IPS\blog\Blog\Table( \IPS\Http\Url::internal( 'app=blog&module=blogs&controller=browse', 'front', 'blogs' ) );
if( $category )
{
$table->where[] = array( 'blog_category_id=?', $category->_id );
}
$table->title = 'our_community_blogs';
$table->classes = array( 'cBlogList', 'ipsAreaBackground', 'ipsDataList_large' );
@@ -89,12 +116,25 @@ class _browse extends \IPS\Dispatcher\Controller
'blogs_with_content' => array( 'blog_count_entries>0' )
);
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'browse' )->index( $table, $featured, $blogs, $viewMode );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'browse' )->index( $table, $featured, $blogs, $viewMode, $category );
}
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=blog', 'front', 'blogs' ), array(), 'loc_blog_viewing_index' );
/* Display */
if( \count( \IPS\blog\Category::roots() ) > 1 )
{
\IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate( 'browse' )->categories( $category );
}
if( $category )
{
foreach( $category->parents() as $parent )
{
\IPS\Output::i()->breadcrumb[] = array( $parent->url(), $parent->_title );
}
\IPS\Output::i()->breadcrumb[] = array( $category->url(), $category->_title );
}
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_browse.js', 'blog', 'front' ) );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('blogs');
@@ -12,7 +12,7 @@
namespace IPS\blog\modules\front\blogs;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -61,12 +61,13 @@ class _create extends \IPS\Dispatcher\Controller
}
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=blog', 'front', 'blogs' ), array(), 'loc_blog_creating' );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_view.js', 'blog', 'front' ) );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('create_blog');
if( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
}
else
{
+61 -28
View File
@@ -12,7 +12,7 @@
namespace IPS\blog\modules\front\blogs;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -72,42 +72,47 @@ class _entry extends \IPS\Content\Controller
protected function manage()
{
parent::manage();
$this->entry->container()->clubCheckRules();
$previous = NULL;
$next = NULL;
/* Prev */
try
{
$previous = \IPS\Db::i()->select(
'*',
'blog_entries',
array( 'entry_blog_id=? AND entry_date<? AND entry_status=? AND entry_is_future_entry=0', $this->entry->blog_id, $this->entry->date, "published" ),
'entry_date DESC'
,1
)->first();
$previous = \IPS\Db::i()->select(
'*',
'blog_entries',
array( 'entry_blog_id=? AND entry_date<? AND entry_status=? AND entry_is_future_entry=0 AND entry_hidden=?', $this->entry->blog_id, $this->entry->date, "published", 1 ),
'entry_date DESC'
,1
)->first();
$previous = \IPS\blog\Entry::constructFromData( $previous );
}
catch ( \UnderflowException $e ) {}
/* Next */
try
{
$next = \IPS\Db::i()->select(
'*',
'blog_entries',
array( 'entry_blog_id=? AND entry_date>? AND entry_status=? AND entry_is_future_entry=0', $this->entry->blog_id, $this->entry->date, "published" ),
'entry_date ASC'
,1
)->first();
$next = \IPS\Db::i()->select(
'*',
'blog_entries',
array( 'entry_blog_id=? AND entry_date>? AND entry_status=? AND entry_is_future_entry=0 AND entry_hidden=?', $this->entry->blog_id, $this->entry->date, "published", 1 ),
'entry_date ASC'
,1
)->first();
$next = \IPS\blog\Entry::constructFromData( $next );
}
catch ( \UnderflowException $e ) {}
/* Online User Location */
\IPS\Session::i()->setLocation( $this->entry->url(), $this->entry->onlineListPermissions(), 'loc_blog_viewing_entry', array( $this->entry->name => FALSE ) );
if( !$this->entry->container()->social_group )
{
\IPS\Session::i()->setLocation( $this->entry->url(), $this->entry->onlineListPermissions(), 'loc_blog_viewing_entry', array( $this->entry->name => FALSE ) );
}
/* Add JSON-ld output */
\IPS\Output::i()->jsonLd['blog'] = array(
@@ -146,7 +151,7 @@ class _entry extends \IPS\Content\Controller
'mainEntityOfPage' => (string) $this->entry->url(),
'name' => $this->entry->mapped('title'),
'headline' => $this->entry->mapped('title'),
'articleBody' => strip_tags( $this->entry->truncated() ),
'articleBody' => $this->entry->truncated( TRUE, NULL ),
'commentCount' => $this->entry->mapped('num_comments'),
'dateCreated' => \IPS\DateTime::ts( $this->entry->date )->format( \IPS\DateTime::ISO8601 ),
'datePublished' => \IPS\DateTime::ts( $this->entry->publish_date )->format( \IPS\DateTime::ISO8601 ),
@@ -157,13 +162,12 @@ class _entry extends \IPS\Content\Controller
'image' => \IPS\Member::load( $this->entry->mapped('author') )->get_photo()
),
'publisher' => array(
'@type' => 'Organization',
'name' => \IPS\Member::load( $this->entry->mapped('author') )->name,
'url' => (string) \IPS\Member::load( $this->entry->mapped('author') )->url(),
'image' => \IPS\Member::load( $this->entry->mapped('author') )->get_photo(),
'logo' => array(
'@type' => 'ImageObject',
'url' => \IPS\Member::load( $this->entry->mapped('author') )->get_photo(),
'@id' => \IPS\Settings::i()->base_url . '#organization',
'member' => array(
'@type' => 'Person',
'name' => \IPS\Member::load( $this->entry->mapped('author') )->name,
'url' => (string) \IPS\Member::load( $this->entry->mapped('author') )->url(),
'image' => \IPS\Member::load( $this->entry->mapped('author') )->get_photo()
)
),
'interactionStatistic' => array(
@@ -257,6 +261,35 @@ class _entry extends \IPS\Content\Controller
{
\IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate('view')->blogSidebar( $this->entry->container()->sidebar );
}
/* Breadcrumb */
\IPS\Output::i()->breadcrumb = array();
\IPS\Output::i()->breadcrumb['module'] = array( \IPS\Http\Url::internal( 'app=blog', 'front' ), \IPS\Member::loggedIn()->language()->addToStack( '__app_blog' ) );
try
{
foreach( $this->entry->container()->category()->parents() as $parent )
{
\IPS\Output::i()->breadcrumb[] = array( $parent->url(), $parent->_title );
}
\IPS\Output::i()->breadcrumb[] = array( $this->entry->container()->category()->url(), $this->entry->container()->category()->_title );
}
catch ( \OutOfRangeException $e ) {}
\IPS\Output::i()->breadcrumb[] = array( $this->entry->container()->url(), $this->entry->container()->_title );
\IPS\Output::i()->breadcrumb[] = array( NULL, $this->entry->name );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'view' )->entry( $this->entry, $previous, $next );
}
/**
* Return the form for editing. Abstracted so controllers can define a custom template if desired.
*
* @param \IPS\Helpers\Form $form The form
* @return string
*/
protected function getEditForm( $form )
{
return $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'submit', 'blog' ), 'submitFormTemplate' ) );
}
}
@@ -12,7 +12,7 @@
namespace IPS\blog\modules\front\blogs;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -68,7 +68,7 @@ class _submit extends \IPS\Dispatcher\Controller
\IPS\blog\Entry::canCreate( \IPS\Member::loggedIn(), $this->blog, TRUE );
$form = \IPS\blog\Entry::create( $this->blog );
$formTemplate = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'submit', 'blog' ) ), 'submitFormTemplate' ) );
$formTemplate = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'submit', 'blog' ), 'submitFormTemplate' ) );
if ( $club = $this->blog->club() )
{
@@ -83,8 +83,12 @@ class _submit extends \IPS\Dispatcher\Controller
}
}
\IPS\Output::i()->breadcrumb[] = array( $this->blog->url(), $this->blog->_title );
\IPS\Session::i()->setLocation( $this->blog->url(), array(), 'loc_blog_adding_entry', array( $this->blog->_title => FALSE ) );
if( !$this->blog->social_group )
{
\IPS\Session::i()->setLocation( $this->blog->url(), array(), 'loc_blog_adding_entry', array( $this->blog->_title => FALSE ) );
}
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'submit' )->submit( $formTemplate, $this->blog );
}
catch ( \OutOfRangeException $e )
+257 -53
View File
@@ -12,14 +12,14 @@
namespace IPS\blog\modules\front\blogs;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* View Blog Entry Controller
* View Blog Controller
*/
class _view extends \IPS\Helpers\CoverPhoto\Controller
{
@@ -61,11 +61,31 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
*/
protected function manage()
{
$this->blog->clubCheckRules();
/* Build table */
$where = array();
if ( !in_array( $this->blog->id, array_keys( \IPS\blog\Blog::loadByOwner( \IPS\Member::loggedIn() ) ) ) AND !\IPS\blog\Entry::canViewHiddenItems( \IPS\Member::loggedIn(), $this->blog ) )
if ( !\in_array( $this->blog->id, array_keys( \IPS\blog\Blog::loadByOwner( \IPS\Member::loggedIn() ) ) ) AND !\IPS\blog\Entry::canViewHiddenItems( \IPS\Member::loggedIn(), $this->blog ) )
{
$where[] = array( "entry_status!='draft'" );
if ( !( $club = $this->blog->club() AND \in_array( $club->memberStatus( \IPS\Member::loggedIn() ), array( \IPS\Member\Club::STATUS_LEADER, \IPS\Member\Club::STATUS_MODERATOR ) ) ) )
{
$where[] = array( "entry_status!='draft'" );
}
}
/* Are we limiting by category? */
try
{
$category = \IPS\blog\Entry\Category::load( \IPS\Request::i()->cat );
}
catch( \OutOfRangeException $e )
{
$category = NULL;
}
if( $category )
{
$where[] = array( "entry_category_id=?", $category->id );
}
$table = new \IPS\Helpers\Table\Content( 'IPS\blog\Entry', $this->blog->url(), $where, $this->blog );
@@ -95,14 +115,21 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
);
/* Online User Location */
\IPS\Session::i()->setLocation( $this->blog->url(), array(), 'loc_blog_viewing_blog', array( "blogs_blog_{$this->blog->id}" => TRUE ) );
/* Output */
\IPS\Output::i()->title = $this->blog->_title;
if( !$this->blog->social_group )
{
\IPS\Session::i()->setLocation( $this->blog->url(), array(), 'loc_blog_viewing_blog', array( "blogs_blog_{$this->blog->id}" => TRUE ) );
}
if( \IPS\Settings::i()->blog_allow_rss and $this->blog->settings['allowrss'] )
{
\IPS\Output::i()->rssFeeds['blog_rss_title'] = \IPS\Http\Url::internal( "app=blog&module=blogs&controller=view&id={$this->blog->_id}", 'front', 'blogs_rss', array( $this->blog->seo_name ) );
if ( \IPS\Member::loggedIn()->member_id )
{
$key = md5( ( \IPS\Member::loggedIn()->members_pass_hash ?: \IPS\Member::loggedIn()->email ) . \IPS\Member::loggedIn()->members_pass_salt );
\IPS\Output::i()->rssFeeds['blog_rss_title'] = \IPS\Output::i()->rssFeeds['blog_rss_title']->setQueryString( array( 'member' => \IPS\Member::loggedIn()->member_id , 'key' => $key ) );
}
}
/* Add JSON-ld */
@@ -157,8 +184,26 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
\IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate('view')->blogSidebar( $this->blog->sidebar );
}
\IPS\Output::i()->breadcrumb = array();
\IPS\Output::i()->breadcrumb['module'] = array( \IPS\Http\Url::internal( 'app=blog', 'front' ), \IPS\Member::loggedIn()->language()->addToStack( '__app_blog' ) );
try
{
foreach( $this->blog->category()->parents() as $parent )
{
\IPS\Output::i()->breadcrumb[] = array( $parent->url(), $parent->_title );
}
\IPS\Output::i()->breadcrumb[] = array( $this->blog->category()->url(), $this->blog->category()->_title );
}
catch (\OutOfRangeException $e) {}
\IPS\Output::i()->breadcrumb[] = array( $this->blog->url(), $this->blog->_title );
/* Categories */
$categories = \IPS\blog\Entry\Category::roots( NULL, NULL, array( 'entry_category_blog_id=?', $this->blog->id ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_browse.js', 'blog', 'front' ) );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'view' )->view( $this->blog, (string) $table );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'view' )->view( $this->blog, (string) $table, $category );
\IPS\Output::i()->contextualSearchOptions[ \IPS\Member::loggedIn()->language()->addToStack( 'search_contextual_item_blogs' ) ] = array( 'type' => 'blog_entry', 'nodes' => $this->blog->_id );
}
@@ -189,7 +234,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
{
$form->elements['']['blog_name']->error = \IPS\Member::loggedIn()->language()->addToStack('form_required');
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
return;
}
@@ -201,7 +246,8 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
/* Display form */
\IPS\Output::i()->title = $this->blog->_title;
\IPS\Output::i()->breadcrumb[] = array( $this->blog->url(), $this->blog->_title );
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_view.js', 'blog', 'front' ) );
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) );
}
/**
@@ -259,33 +305,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
\IPS\Output::i()->redirect( $this->blog->url() );
}
}
/**
* RSS feed
*
* @return void
*/
protected function rss()
{
if( !\IPS\Settings::i()->blog_allow_rss or !$this->blog->settings['allowrss'] )
{
\IPS\Output::i()->error( 'blog_rss_offline', '2B201/5', 403, 'blog_rss_offline_admin' );
}
/* We have to use get() to ensure CDATA tags wrap the blog title properly */
$title = $this->blog->member_id ? $this->blog->name : \IPS\Member::loggedIn()->language()->get( "blogs_blog_{$this->blog->id}" );
$document = \IPS\Xml\Rss::newDocument( $this->blog->url(), $title, $this->blog->description );
foreach ( \IPS\blog\Entry::getItemsWithPermission( array( array( 'entry_blog_id=?', $this->blog->id ), array( 'entry_status!=?', 'draft' ) ), 'entry_date DESC', 25, 'read', \IPS\Content\Hideable::FILTER_PUBLIC_ONLY, 0, new \IPS\Member ) as $entry )
{
$document->addItem( $entry->name, $entry->url(), $entry->content, \IPS\DateTime::ts( $entry->date ), $entry->id );
}
/* @note application/rss+xml is not a registered IANA mime-type so we need to stick with text/xml for RSS */
\IPS\Output::i()->sendOutput( $document->asXML(), 200, 'text/xml' );
}
/**
* RSS imports
*
@@ -306,12 +326,13 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
/* Check for existing feed */
try
{
$existing = \IPS\Db::i()->select( '*', 'blog_rss_import', array( 'rss_blog_id=?', $this->blog->id ) )->first();
$feed = \IPS\blog\Blog\Feed::constructFromData( $existing );
$existing = \IPS\Db::i()->select( '*', 'core_rss_import', array( 'rss_import_class=? AND rss_import_node_id=?', 'IPS\\blog\\Entry', $this->blog->id ) )->first();
$feed = \IPS\core\Rss\Import::constructFromData( $existing );
}
catch ( \UnderflowException $e )
{
$feed = new \IPS\blog\Blog\Feed;
$feed = new \IPS\core\Rss\Import;
$feed->class = 'IPS\\blog\\Entry';
}
$form = new \IPS\Helpers\Form;
@@ -321,7 +342,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
$form->add( new \IPS\Helpers\Form\Url( 'blog_rss_import_url', $feed ? $feed->url : NULL, TRUE, array(), NULL, NULL, NULL, 'blog_rss_import_url' ) );
$form->add( new \IPS\Helpers\Form\Text( 'blog_rss_import_auth_user', $feed ? $feed->auth_user : NULL, FALSE, array(), NULL, NULL, NULL, 'blog_rss_import_auth_user' ) );
$form->add( new \IPS\Helpers\Form\Text( 'blog_rss_import_auth_pass', $feed ? $feed->auth_pass : NULL, FALSE, array(), NULL, NULL, NULL, 'blog_rss_import_auth_pass' ) );
$form->add( new \IPS\Helpers\Form\Text( 'blog_rss_import_show_link', $feed->import_show_link ?: \IPS\Member::loggedIn()->language()->addToStack('blog_rss_import_show_link_default' ), FALSE, array(), NULL, NULL, NULL, 'blog_rss_import_show_link' ) );
$form->add( new \IPS\Helpers\Form\Text( 'blog_rss_import_show_link', $feed->showlink ?: \IPS\Member::loggedIn()->language()->addToStack('blog_rss_import_show_link_default' ), FALSE, array(), NULL, NULL, NULL, 'blog_rss_import_show_link' ) );
$options = array( 'autocomplete' => array( 'unique' => TRUE, 'minimized' => FALSE, 'source' => \IPS\Content\Item::definedTags( $this->blog ), 'freeChoice' => ( \IPS\Settings::i()->tags_open_system ? TRUE : FALSE ) ) );
if ( \IPS\Settings::i()->tags_force_lower )
@@ -383,7 +404,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
$extralang[] = \IPS\Member::loggedIn()->language()->addToStack( 'tags_desc_len_max', FALSE, array( 'sprintf' => array( \IPS\Settings::i()->tags_len_max ) ) );
}
$options['autocomplete']['desc'] = \IPS\Member::loggedIn()->language()->addToStack('tags_desc') . ( ( count( $extralang ) ) ? '<br>' . implode( $extralang, ' ' ) : '' );
$options['autocomplete']['desc'] = \IPS\Member::loggedIn()->language()->addToStack('tags_desc') . ( ( \count( $extralang ) ) ? '<br>' . implode( ' ', $extralang ) : '' );
}
$form->add( new \IPS\Helpers\Form\Text( 'blog_rss_import_tags', $feed ? json_decode( $feed->tags, TRUE ) : array(), \IPS\Settings::i()->tags_min and \IPS\Settings::i()->tags_min_req, $options, NULL, NULL, NULL, 'blog_rss_import_tags' ) );
@@ -409,6 +430,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
}
$response = $response->decodeXml();
if ( !( $response instanceof \IPS\Xml\Rss ) and !( $response instanceof \IPS\Xml\Atom ) )
{
$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'rss_import_invalid' );
@@ -416,19 +438,21 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
if( !$form->error )
{
$feed->blog_id = $this->blog->id;
$feed->node_id = $this->blog->id;
$feed->url = $values['blog_rss_import_url'];
$feed->import_show_link = $values['blog_rss_import_show_link'];
$feed->showlink = $values['blog_rss_import_show_link'];
$feed->auth_user = $values['blog_rss_import_auth_user'];
$feed->auth_pass = $values['blog_rss_import_auth_pass'];
$feed->tags = json_encode( $values['blog_rss_import_tags'] );
$feed->member = $this->blog->owner() ? $this->blog->owner()->member_id : \IPS\Member::loggedIn()->member_id;
$feed->settings = json_encode( array( 'tags' => $values['blog_rss_import_tags'] ) );
$feed->save();
$feed->run();
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 1 ), array( '`key`=?', 'blogrssimport' ) );
try
{
$feed->run();
}
catch ( \Exception $e ) { }
/* Redirect */
\IPS\Output::i()->redirect( $this->blog->url() );
}
@@ -445,7 +469,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
}
else
{
\IPS\Db::i()->delete( 'blog_rss_import', array( 'rss_blog_id=?', $this->blog->id ) );
\IPS\Db::i()->delete( 'core_rss_import', array( 'rss_import_class=? AND rss_import_node_id=?', 'IPS\\blog\\Entry', $this->blog->id ) );
/* Redirect */
\IPS\Output::i()->redirect( $this->blog->url() );
@@ -453,7 +477,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
}
/* Display */
\IPS\Output::i()->output = $form->error ? $form : \IPS\Theme::i()->getTemplate( 'view', 'blog', 'front' )->rssImport( $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) ) );
\IPS\Output::i()->output = $form->error ? $form : \IPS\Theme::i()->getTemplate( 'view', 'blog', 'front' )->rssImport( $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'forms', 'core' ), 'popupTemplate' ) ) );
}
/**
@@ -488,4 +512,184 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
{
return $this->blog->coverPhoto();
}
/**
* Return categories as JSON
*
* @return void
*/
protected function categoriesJson()
{
$cats = array();
foreach( \IPS\blog\Entry\Category::roots( NULL, NULL, array( 'entry_category_blog_id=?', $this->blog->id ) ) as $meow )
{
$cats[] = array(
'id' => $meow->id,
'name' => $meow->name
);
}
\IPS\Output::i()->json( array( 'categories' => $cats ) );
}
/**
* Manage
*
* @return void
*/
protected function manageCategories()
{
if( !$this->blog->canEdit() )
{
\IPS\Output::i()->error( 'no_module_permission', '2B201/A', 403, '' );
}
/* Display */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('blog_manage_entry_categories');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'view', 'blog', 'front' )->manageCategories( \IPS\blog\Entry\Category::roots( NULL, NULL, array( 'entry_category_blog_id=?', $this->blog->id ) ), $this->blog );
}
/**
* Edit a category name
*
* @return string
*/
protected function editCategoryName()
{
\IPS\Session::i()->csrfCheck();
if( !$this->blog->canEdit() )
{
\IPS\Output::i()->error( 'no_module_permission', '2B201/C', 403, '' );
}
if( ! \IPS\Request::i()->name )
{
\IPS\Output::i()->error( 'blog_error_missing_name', '1B201/B', 403, '' );
}
/* New category? */
if ( \IPS\Request::i()->cat === 'new' )
{
$newCategory = new \IPS\blog\Entry\Category;
$newCategory->name = \IPS\Request::i()->name;
$newCategory->seo_name = \IPS\Http\Url\Friendly::seoTitle( \IPS\Request::i()->name );
$newCategory->blog_id = $this->blog->id;
$newCategory->save();
}
else
{
try
{
$category = \IPS\blog\Entry\Category::load( \IPS\Request::i()->cat );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'blog_error_not_find_category', '2B201/D', 403, '' );
}
if( $category->blog_id !== $this->blog->id )
{
\IPS\Output::i()->error( 'blog_error_not_find_category', '2B201/E', 403, '' );
}
$category->name = \IPS\Request::i()->name;
$category->save();
}
\IPS\Output::i()->json( 'OK' );
}
/**
* Delete Category
*
* @return void
*/
protected function deleteCategory()
{
\IPS\Session::i()->csrfCheck();
if( !$this->blog->canEdit() )
{
\IPS\Output::i()->error( 'no_module_permission', '2B201/8', 403, '' );
}
try
{
$category = \IPS\blog\Entry\Category::load( \IPS\Request::i()->cat );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->redirect( $this->blog->url() );
}
if( $category->blog_id !== $this->blog->id )
{
\IPS\Output::i()->error( 'no_module_permission', '2B201/9', 403, '' );
}
/* Update Entries */
\IPS\Db::i()->update( 'blog_entries', array( 'entry_category_id' => NULL ), array( 'entry_category_id=?', $category->id ) );
$category->delete();
/* Redirect */
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->json( 'OK' );
}
else
{
\IPS\Output::i()->redirect( $this->blog->url(), 'deleted' );
}
}
/**
* Reorder blog entry categories
*
* @return void
*/
public function categoriesReorder()
{
\IPS\Session::i()->csrfCheck();
if( !$this->blog->canEdit() )
{
\IPS\Output::i()->error( 'no_module_permission', '2B201/F', 403, '' );
}
/* Set order */
$position = 1;
if( !\IPS\Request::i()->isAjax() )
{
\IPS\Request::i()->ajax_order = explode( ',', \IPS\Request::i()->ajax_order );
}
foreach( \IPS\Request::i()->ajax_order as $category )
{
$node = \IPS\blog\Entry\Category::load( $category );
/* No funny business trying to reorder another blog's categories */
if( $node->blog_id !== $this->blog->id )
{
continue;
}
$node->position = $position;
$node->save();
$position++;
}
if( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->json( 'ok' );
}
else
{
\IPS\Output::i()->redirect( $this->blog->url(), 'saved' );
}
}
}
+14 -14
View File
@@ -12,7 +12,7 @@
namespace IPS\blog\setup\upg_100002;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -53,7 +53,7 @@ class _Upgrade
*/
public function step2()
{
$limit = isset( \IPS\Request::i()->extra ) ? intval( \IPS\Request::i()->extra ) : 0;
$limit = isset( \IPS\Request::i()->extra ) ? \intval( \IPS\Request::i()->extra ) : 0;
$select = \IPS\Db::i()->select( '*', 'blog_polls', NULL, 'poll_id ASC', array( $limit, 1000 ) );
@@ -67,7 +67,7 @@ class _Upgrade
/* Sometimes data from 3.4.x isn't always as well formed as we'd like, especially when non-latin chars are involved */
$data = unserialize( $poll['choices'] );
if( !is_array( $data ) )
if( !\is_array( $data ) )
{
$poll['choices'] = str_replace( '\\"', '"', $poll['choices'] );
$data = unserialize( $poll['choices'] );
@@ -75,23 +75,23 @@ class _Upgrade
$_decoded = FALSE;
if( !is_array( $data ) )
if( !\is_array( $data ) )
{
$data = unserialize( utf8_decode( $poll['choices'] ) );
if( is_array( $data ) )
if( \is_array( $data ) )
{
$_decoded = TRUE;
}
}
if( is_array( $data ) AND $_decoded )
if( \is_array( $data ) AND $_decoded )
{
foreach( $data as $_key => $_data )
{
$data[ $_key ]['question'] = utf8_encode( $_data[ $_key ]['question'] );
if( is_array( $_data['choice'] ) )
if( \is_array( $_data['choice'] ) )
{
foreach( $_data['choice'] as $_idx => $_choice )
{
@@ -108,24 +108,24 @@ class _Upgrade
{
$data = unserialize( $poll['choices'] );
if( !is_array( $data ) )
if( !\is_array( $data ) )
{
$poll['choices'] = str_replace( '\\"', '"', $poll['choices'] );
$data = unserialize( $poll['choices'] );
}
if( !is_array( $data ) )
if( !\is_array( $data ) )
{
$data = unserialize( utf8_decode( $poll['choices'] ) );
}
if( is_array( $data ) )
if( \is_array( $data ) )
{
foreach( $data as $_key => $_data )
{
$data[ $_key ]['question'] = utf8_encode( $_data['question'] );
if( is_array( $_data['choice'] ) )
if( \is_array( $_data['choice'] ) )
{
foreach( $_data['choice'] as $_idx => $_choice )
{
@@ -166,7 +166,7 @@ class _Upgrade
*/
public function step2CustomTitle()
{
return "Upgrading polls...";
return "Upgrading polls";
}
/**
@@ -176,7 +176,7 @@ class _Upgrade
*/
public function step3()
{
$limit = isset( \IPS\Request::i()->extra ) ? intval( \IPS\Request::i()->extra ) : 0;
$limit = isset( \IPS\Request::i()->extra ) ? \intval( \IPS\Request::i()->extra ) : 0;
$select = \IPS\Db::i()->select( '*', 'blog_voters', NULL, 'vote_id ASC', array( $limit, 1000 ) );
@@ -211,6 +211,6 @@ class _Upgrade
*/
public function step3CustomTitle()
{
return "Upgrading polls...";
return "Upgrading poll voters";
}
}
@@ -12,7 +12,7 @@
namespace IPS\blog\setup\upg_100015;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\blog\setup\upg_100016;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\blog\setup\upg_100018;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -12,7 +12,7 @@
namespace IPS\blog\setup\upg_100021;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
Whitespace-only changes.
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\blog\setup\upg_100027;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\blog\setup\upg_100028;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\blog\setup\upg_100035;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
Whitespace-only changes.
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\blog\setup\upg_100038;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
Whitespace-only changes.
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\blog\setup\upg_101016;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\blog\setup\upg_101021;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -32,7 +32,7 @@ class _Upgrade
{
$perCycle = 1000;
$did = 0;
$limit = intval( \IPS\Request::i()->extra );
$limit = \intval( \IPS\Request::i()->extra );
/* Try to prevent timeouts to the extent possible */
$cutOff = \IPS\core\Setup\Upgrade::determineCutoff();
@@ -81,6 +81,6 @@ class _Upgrade
$_SESSION['_step1Count'] = \IPS\Db::i()->select( 'COUNT(*)', 'blog_rss_import', array( "rss_member=?", 0 ) )->first();
}
return "Fixing Blog RSS Imports (Upgraded so far: " . ( ( $limit > $_SESSION['_step1Count'] ) ? $_SESSION['_step1Count'] : $limit ) . ' out of ' . $_SESSION['_step1Count'] . ')';
return "Fixing blog RSS imports (Upgraded so far: " . ( ( $limit > $_SESSION['_step1Count'] ) ? $_SESSION['_step1Count'] : $limit ) . ' out of ' . $_SESSION['_step1Count'] . ')';
}
}
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
@@ -12,7 +12,7 @@
namespace IPS\blog\setup\upg_103000;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -0,0 +1,32 @@
{
"1": {
"method": "dropIndex",
"params": [
"blog_entries",
"entry_category_id"
]
},
"2": {
"method": "dropIndex",
"params": [
"blog_rss_import",
"rss_blog_id"
]
},
"3": {
"method": "addIndex",
"params": [
"blog_rss_import",
{
"type": "key",
"name": "member",
"columns": [
"rss_member"
],
"length": [
null
]
}
]
}
}
@@ -0,0 +1,21 @@
{
"added": [
"app=blog&module=blogs&controller=blogs",
"app=blog&module=blogs&controller=blogs&do=form",
"app=blog&module=blogs&controller=blogs&searchResult=blog_desc_wrap",
"app=blog&module=blogs&controller=blogs&searchResult=blog_member_id",
"app=blog&module=blogs&controller=blogs&searchResult=blog_name",
"app=blog&module=blogs&controller=blogs&searchResult=form_new_blog_enable_rss",
"app=blog&module=blogs&controller=blogs&searchResult=form_new_blog_type",
"app=blog&module=blogs&controller=settings",
"app=blog&module=blogs&controller=settings&searchResult=form_blog_allow_rss",
"app=blog&module=blogs&controller=settings&searchResult=form_blog_allow_rssimport",
"app=blog&module=blogs&controller=settings&searchResult=form_blog_enable_rating",
"app=blog&module=blogs&controller=settings&searchResult=form_blog_enable_sidebar",
"app=core&module=members&controller=groups&searchResult=4_g_blog_allowlocal",
"app=core&module=members&controller=groups&searchResult=g_blog_allowdelete",
"app=core&module=members&controller=groups&searchResult=g_blog_allowprivate"
],
"edited": [],
"removed": []
}
@@ -0,0 +1,24 @@
{
"id": 105013,
"name": "4.5.0 Beta 1",
"steps": {
"queries": true,
"lang": true,
"theme": true,
"themeSettings": false,
"javascript": true,
"emailTemplates": false,
"hooks": false,
"acpSearchKeywords": true,
"settings": true,
"tasks": false,
"modules": true,
"widgets": true,
"whatsnew": false,
"customOptions": false,
"customRoutines": true
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,17 @@
{
"files": {
"added": [
"blog\/front\/controllers\/view\/ips.view.manageCategories.js",
"blog\/front\/templates\/ips.templates.view.js"
],
"edited": [],
"removed": []
},
"orders": {
"added": [],
"edited": [
"global\/\/dev\/js\/\/library\/\/jquery"
],
"removed": []
}
}
@@ -0,0 +1,59 @@
{
"normal": {
"added": [
"blog_allow_rssimport_desc",
"entry_category_choice",
"entry_category_choice_new",
"entry_category_choice_existing",
"stats_overview_blogs",
"stats_overview_blogs_desc",
"entry_posted_with_cat",
"entry_future_posted_with_cat",
"entry_name_with_cat",
"blog_category_viewing",
"blog_category_select",
"modperms__blog_Blogs",
"can_mod_blogs",
"menu__blog_blogs_categories",
"blog_categories",
"blog_create_category",
"blog_categories_add_child",
"blog_category_id",
"category_basic_settings",
"blog_category_desc",
"category_parent",
"category_desc_placeholder",
"__api_blog_categories",
"entry_category_id",
"blog_entry_new_category",
"blog_entry_category_new",
"blog_category_heading",
"blog_manage_entry_categories",
"blog_entry_categories",
"blog_error_missing_name",
"blog_error_not_find_category",
"blog_categories_all",
"no_entries_in_cat",
"__api_blog_entrycategories"
],
"edited": [
"blog_entry_auto_follow_suffix",
"blog_by",
"group_blog_by",
"modperms__core_Content_blog_Entry"
],
"removed": [
"blog_allow_rss_desc"
]
},
"js": {
"added": [
"blog_category_confirm_delete",
"blog_category_confirm_delete_desc",
"manage_cats_new_row",
"entry_cat_order_saved"
],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,8 @@
{
"added": [
"admin\/blogs",
"front\/blogs"
],
"edited": [],
"removed": []
}
@@ -0,0 +1,396 @@
{
"1": {
"method": "createTable",
"params": [
{
"name": "blog_categories",
"columns": {
"category_id": {
"allow_null": false,
"auto_increment": true,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 5,
"name": "category_id",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
},
"category_seo_name": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 255,
"name": "category_seo_name",
"type": "VARCHAR",
"unsigned": false,
"values": [],
"zerofill": false
},
"category_position": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "0",
"length": 5,
"name": "category_position",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
},
"category_parent": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "0",
"length": 5,
"name": "category_parent",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
}
},
"indexes": {
"PRIMARY": {
"type": "primary",
"name": "PRIMARY",
"length": [
null
],
"columns": [
"category_id"
]
},
"pg_position": {
"type": "key",
"name": "pg_position",
"length": [
null
],
"columns": [
"category_position"
]
},
"pg_parent": {
"type": "key",
"name": "pg_parent",
"length": [
null
],
"columns": [
"category_parent"
]
}
}
}
]
},
"2": {
"method": "createTable",
"params": [
{
"name": "blog_entry_categories",
"columns": {
"entry_category_id": {
"allow_null": false,
"auto_increment": true,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 10,
"name": "entry_category_id",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
},
"entry_category_name": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 255,
"name": "entry_category_name",
"type": "VARCHAR",
"unsigned": false,
"values": [],
"zerofill": false
},
"entry_category_seo_name": {
"allow_null": true,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": null,
"length": 255,
"name": "entry_category_seo_name",
"type": "VARCHAR",
"unsigned": false,
"values": [],
"zerofill": false
},
"entry_category_position": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "0",
"length": 5,
"name": "entry_category_position",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
},
"entry_category_blog_id": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "",
"length": 10,
"name": "entry_category_blog_id",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
},
"entry_category_count": {
"allow_null": false,
"auto_increment": false,
"binary": false,
"comment": "",
"decimals": null,
"default": "0",
"length": 10,
"name": "entry_category_count",
"type": "INT",
"unsigned": false,
"values": [],
"zerofill": false
}
},
"indexes": {
"PRIMARY": {
"type": "primary",
"name": "PRIMARY",
"length": [
null
],
"columns": [
"entry_category_id"
]
},
"pg_position": {
"type": "key",
"name": "pg_position",
"length": [
null
],
"columns": [
"entry_category_position"
]
}
}
}
]
},
"3": {
"method": "addColumn",
"params": [
"blog_blogs",
{
"name": "blog_category_id",
"type": "BIGINT",
"length": 20,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"4": {
"method": "update",
"params": [
"blog_blogs",
{
"blog_category_id": 1
}
]
},
"5": {
"method": "addColumn",
"params": [
"blog_entries",
{
"name": "entry_category_id",
"type": "INT",
"length": 10,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": true,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"6": {
"method": "addIndex",
"params": [
"blog_blogs",
{
"type": "key",
"name": "blog_category_id",
"columns": [
"blog_category_id"
],
"length": [
null
]
}
]
},
"7": {
"method": "addColumn",
"params": [
"blog_entries",
{
"name": "entry_append_edit",
"type": "TINYINT",
"length": 1,
"decimals": null,
"values": null,
"allow_null": false,
"default": "0",
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"8": {
"method": "addColumn",
"params": [
"blog_entries",
{
"name": "entry_edit_show",
"type": "TINYINT",
"length": 1,
"decimals": null,
"values": null,
"allow_null": false,
"default": "0",
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"9": {
"method": "dropColumn",
"params": [
"blog_entries",
"entry_edit_show"
]
},
"10": {
"method": "addColumn",
"params": [
"blog_entries",
{
"name": "entry_edit_reason",
"type": "VARCHAR",
"length": 255,
"decimals": null,
"values": null,
"allow_null": true,
"default": null,
"comment": "",
"unsigned": false,
"zerofill": false,
"auto_increment": false,
"binary": false
}
]
},
"11": {
"method": "delete",
"params": [
"core_sys_lang_words",
[
"word_key=?",
"blog_allow_rss_desc"
]
]
},
"12": {
"method": "changeColumn",
"params": [
"blog_comments",
"comment_text",
{
"name": "comment_text",
"type": "MEDIUMTEXT",
"length": 0,
"decimals": null,
"values": [],
"allow_null": true,
"default": null,
"comment": "",
"unsigned": false,
"auto_increment": false
}
]
},
"13": {
"method": "changeColumn",
"params": [
"blog_entries",
"entry_meta_data",
{
"name": "entry_meta_data",
"type": "TINYINT",
"length": 1,
"decimals": null,
"values": null,
"allow_null": false,
"default": "0",
"comment": "",
"unsigned": true,
"auto_increment": false
}
]
}
}
@@ -0,0 +1,12 @@
{
"added": [
"blog_allow_grid",
"blog_allow_rss",
"blog_allow_rssimport",
"blog_enable_rating",
"blog_enable_sidebar",
"blog_view_mode"
],
"edited": [],
"removed": []
}
@@ -0,0 +1,49 @@
{
"html": {
"added": [
"front\/browse\/categories",
"front\/global\/blogCategoryLink",
"front\/global\/categoryLink",
"front\/view\/categories",
"front\/view\/manageCategories"
],
"edited": [
"front\/browse\/featuredEntries",
"front\/browse\/index",
"front\/browse\/indexButtons",
"front\/browse\/indexGrid",
"front\/browse\/indexGridEntry",
"front\/browse\/rows",
"front\/global\/commentTableHeader",
"front\/global\/embedBlogs",
"front\/global\/embedEntry",
"front\/global\/embedEntryComment",
"front\/global\/profileBlogRows",
"front\/submit\/submitFormTemplate",
"front\/view\/blogViewLarge",
"front\/view\/blogViewMedium",
"front\/view\/comments",
"front\/view\/coverPhotoOverlay",
"front\/view\/entry",
"front\/view\/noEntries",
"front\/view\/view",
"front\/widgets\/blogCommentFeed",
"front\/widgets\/blogs"
],
"removed": []
},
"css": {
"added": [],
"edited": [
"front\/blog.css",
"front\/grid.css",
"front\/profile.css"
],
"removed": []
},
"resources": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,110 @@
<?php
/**
* @brief 4.5.0 Beta 1 Upgrade Code
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @subpackage Blogs
* @since 01 Aug 2019
*/
namespace IPS\blog\setup\upg_105013;
/* 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;
}
/**
* 4.5.0 Beta 1 Upgrade Code
*/
class _Upgrade
{
/**
* Set up categories
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step1()
{
$category = new \IPS\blog\Category;
$category->seo_name = 'general';
$category->save();
\IPS\Lang::saveCustom( 'blog', "blog_category_{$category->id}", "General" );
return TRUE;
}
/**
* Convert RSS imports over
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function step2()
{
/* Move over blog_rss_import to core_rss_import */
foreach( \IPS\Db::i()->select( '*', 'blog_rss_import' ) as $rss )
{
try
{
$blog = \IPS\blog\Blog::load( $rss['rss_blog_id'] );
}
catch( \Exception $e )
{
continue;
}
$newImportId = \IPS\Db::i()->insert( 'core_rss_import', array(
'rss_import_enabled' => 1,
'rss_import_title' => $blog->titleForLog(),
'rss_import_url' => $rss['rss_url'],
'rss_import_auth_user' => $rss['rss_auth_user'],
'rss_import_auth_pass' => $rss['rss_auth_pass'],
'rss_import_class' => 'IPS\\blog\\Entry',
'rss_import_node_id' => $rss['rss_blog_id'],
'rss_import_member' => $rss['rss_member'],
'rss_import_time' => 0,
'rss_import_last_import' => $rss['rss_last_import'],
'rss_import_showlink' => $rss['rss_import_show_link'],
'rss_import_topic_pre' => '',
'rss_import_auto_follow' => 0,
'rss_import_settings' => json_encode( array(
'tags' => $rss['rss_tags']
) )
) );
/* Prevent multiple runs from breaking */
try
{
\IPS\Db::i()->delete( 'core_rss_imported', array( 'rss_imported_import_id=?', $newImportId ) );
\IPS\Db::i()->query( "INSERT INTO " . \IPS\Db::i()->prefix . "core_rss_imported
(rss_imported_guid, rss_imported_content_id, rss_imported_import_id )
( SELECT a.rss_imported_guid, a.rss_imported_entry_id, {$newImportId} FROM " . \IPS\Db::i()->prefix . "blog_rss_imported a)" );
}
catch( \Exception $e ) { }
}
return TRUE;
}
/**
* Finish
*
* @return array If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
*/
public function finish()
{
/* Delete old language strings */
\IPS\Db::i()->delete( 'core_tasks', array( '`key`=?', 'blogrssimport' ) );
/* Delete old RSS Table */
\IPS\Db::i()->dropTable( array( 'blog_rss_import', 'blog_rss_imported' ) );
return TRUE;
}
}
@@ -0,0 +1,10 @@
{
"added": [
"blogStatistics",
"entryFeed",
"blogCommentFeed",
"blogs"
],
"edited": [],
"removed": []
}
@@ -0,0 +1,24 @@
{
"id": 105014,
"name": "4.5.0 Beta 1",
"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,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105015,
"name": "4.5.0 Beta 2",
"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,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,14 @@
{
"files": {
"added": [],
"edited": [],
"removed": []
},
"orders": {
"added": [],
"edited": [
"global\/\/dev\/js\/\/library\/\/jquery"
],
"removed": []
}
}
@@ -0,0 +1,14 @@
{
"normal": {
"added": [],
"edited": [],
"removed": []
},
"js": {
"added": [],
"edited": [
"blog_category_confirm_delete"
],
"removed": []
}
}
@@ -0,0 +1,20 @@
{
"html": {
"added": [],
"edited": [
"front\/view\/entry",
"front\/view\/view"
],
"removed": []
},
"css": {
"added": [],
"edited": [],
"removed": []
},
"resources": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,24 @@
{
"id": 105016,
"name": "4.5.0 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,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105017,
"name": "4.5.0 Beta 4",
"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,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,19 @@
{
"html": {
"added": [],
"edited": [
"front\/global\/commentTableHeader"
],
"removed": []
},
"css": {
"added": [],
"edited": [],
"removed": []
},
"resources": {
"added": [],
"edited": [],
"removed": []
}
}
@@ -0,0 +1,24 @@
{
"id": 105018,
"name": "4.5.0 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,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105019,
"name": "4.5.0 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,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105020,
"name": "4.5.0 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,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,24 @@
{
"id": 105021,
"name": "4.5.0 Beta 5",
"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,
"whatsnew": false,
"customOptions": false,
"customRoutines": false
},
"forceMainUpgrader": false,
"forceManualDownloadNoCiC": false,
"forceManualDownloadCiC": false
}
@@ -0,0 +1,20 @@
{
"html": {
"added": [],
"edited": [
"front\/browse\/index",
"front\/browse\/indexGrid"
],
"removed": []
},
"css": {
"added": [],
"edited": [],
"removed": []
},
"resources": {
"added": [],
"edited": [],
"removed": []
}
}
Loaded 100 of 3791 files, more files were not shown because too many files have changed in this diff. Show more