Version 4.1.2
No files matched your search
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
header("HTTP/1.0 404 Not Found");
|
||||
|
||||
print <<<EOF
|
||||
<html>
|
||||
<title>404 Not Found</title>
|
||||
<body>
|
||||
The file you were looking for could not be found
|
||||
</body>
|
||||
</html>
|
||||
EOF;
|
||||
|
||||
exit;
|
||||
@@ -5,27 +5,28 @@ Invision Power Services, Inc. is grateful to the following projects, whose work
|
||||
has been used throughout the IPS Community Suite to add style, flair and functionality
|
||||
to our product.
|
||||
|
||||
NULLING
|
||||
Last Updated: 13 September 2015
|
||||
Author: IAF
|
||||
|
||||
AES implementation in PHP
|
||||
Last Updated: 22 July 2014
|
||||
Website: http://www.movable-type.co.uk/scripts/aes-php.html
|
||||
License: http://creativecommons.org/licenses/by/3.0/
|
||||
|
||||
Base64.js Polyfill
|
||||
Included version: 0.3.0
|
||||
Website: https://github.com/davidchambers/Base64.js
|
||||
License: http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Buzz.js
|
||||
Included version: 1.1.8
|
||||
Website: http://buzz.jaysalvat.com/
|
||||
License: http://opensource.org/licenses/MIT
|
||||
|
||||
CKEditor
|
||||
Included version: 4.4.7
|
||||
Included version: 4.5.4
|
||||
Website: http://ckeditor.com
|
||||
License: http://www.gnu.org/copyleft/lesser.html
|
||||
|
||||
Codemirror (with XML, JavaScript, CSS, HTMLMixed, C-like and PHP modes and merge, search searchcursor addons)
|
||||
Included version: 4.13
|
||||
Codemirror (with C-like, CSS, HTMLMixed, JavaScript, PHP, SQL and XML modes and merge, search, and searchcursor addons)
|
||||
Included version: 5.8
|
||||
Website: http://codemirror.net
|
||||
License: http://codemirror.net/LICENSE
|
||||
|
||||
@@ -40,7 +41,7 @@ Esrever
|
||||
License: http://opensource.org/licenses/MIT
|
||||
|
||||
FontAwesome
|
||||
Included version: 4.3.0
|
||||
Included version: 4.4.0
|
||||
Website: http://fortawesome.github.com/Font-Awesome
|
||||
License: http://fortawesome.github.com/Font-Awesome/#license
|
||||
|
||||
@@ -147,6 +148,11 @@ parseUri
|
||||
Payment Method Icons
|
||||
Website: http://www.dreamstale.com/free-download-payment-method-vector-icons/
|
||||
License: http://creativecommons.org/licenses/by/3.0/
|
||||
|
||||
PclZip
|
||||
Included version: 2.8.2
|
||||
Website: http://www.phpconcept.net/pclzip/
|
||||
License: http://www.gnu.org/copyleft/lesser.html
|
||||
|
||||
PEAR Mail
|
||||
Included version: 1.2.0
|
||||
@@ -176,6 +182,10 @@ pop3.class.inc
|
||||
|
||||
Preloaders.net
|
||||
Website: http://preloaders.net/
|
||||
|
||||
success.mp3 Notification Sound by RCP Tones
|
||||
Website: http://rcptones.com/dev_tones/
|
||||
License: http://creativecommons.org/licenses/by/3.0/us/
|
||||
|
||||
Underscore.js
|
||||
Included version: 1.7.0
|
||||
|
||||
@@ -76,6 +76,7 @@ class IPSUtf8
|
||||
'FORCE_CONVERT_CHARSET' => NULL,
|
||||
'FORCE_CONVERT_METHOD' => NULL,
|
||||
'SOURCE_DB_CHARSET' => NULL, /* If set, will force the source database connection to use this charset */
|
||||
'UTF8_INSERT_ONLY' => FALSE, /* If true, and sql_charset is present and set to utf8 in conf_global.php, then the "fast" method will simply insert without converting. Useful for mixed collation databases where the utf8 tables are real utf8 */
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,6 +113,7 @@ var ips = {};
|
||||
data: data,
|
||||
url: url,
|
||||
timeout: ips.getSetting('maxExecTime') !== false ? parseInt( ips.getSetting('maxExecTime') * 1000 ) : 30000,
|
||||
cache: false,
|
||||
success: function( data, textStatus, jqXHR )
|
||||
{
|
||||
success( data, textStatus, jqXHR );
|
||||
|
||||
@@ -32,7 +32,15 @@ class archive extends \IPSUtf8\Dispatcher\Controller
|
||||
$this->welcome();
|
||||
break;
|
||||
case 'completed':
|
||||
$this->completed();
|
||||
/* Regardless of current status, if the archive table is not utf8 we need to convert it */
|
||||
if ( \IPSUtf8\Convert\Archive::i()->getNonUtf8Tables( TRUE ) !== NULL )
|
||||
{
|
||||
$this->welcome();
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->completed();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ class browser extends \IPSUtf8\Dispatcher\Controller
|
||||
|
||||
$json = \IPSUtf8\Session::i()->json;
|
||||
$percent = round( ($json['convertedCount'] / \IPSUtf8\Convert::i()->getTotalRowsToConvert()) * 100, 2 );
|
||||
$msg = "Processing " . \IPSUtf8\Session::i()->current_table . ' (Total: ' . $percent . '%)';
|
||||
$msg = "Processing " . \IPSUtf8\Session::i()->current_table . '<br>Row: ' . \IPSUtf8\Session::i()->current_row . ' of ' . \IPSUtf8\Session::i()->tables[ \IPSUtf8\Session::i()->current_table ]['count'] . ' - Total: ' . $percent . '%';
|
||||
|
||||
if ( ! \IPSUtf8\Request::i()->isAjax() )
|
||||
{
|
||||
@@ -169,14 +169,14 @@ class browser extends \IPSUtf8\Dispatcher\Controller
|
||||
exit();
|
||||
}
|
||||
|
||||
if ( \IPSUtf8\Convert::i()->databaseIsUtf8() )
|
||||
if ( \IPSUtf8\Convert::i()->databaseIsUtf8() AND !count( \IPSUtf8\Convert::i()->getNonUtf8CollationTables() ) )
|
||||
{
|
||||
\IPSUtf8\Output\Browser::i()->error( 'The database tables are UTF-8, collations are correct and there is nothing to convert. You can <strong><a href="../upgrade">proceed with the upgrade</strong>.' );
|
||||
exit();
|
||||
}
|
||||
|
||||
$json = \IPSUtf8\Session::i()->json;
|
||||
$percent = ( \IPSUtf8\Convert::i()->getTotalRowsToConvert() ) ? round( ($json['convertedCount'] / \IPSUtf8\Convert::i()->getTotalRowsToConvert() ) * 100, 2 ) : 100;
|
||||
$percent = ( \IPSUtf8\Convert::i()->getTotalRowsToConvert() ) ? sprintf ("%6.2f", round( ($json['convertedCount'] / \IPSUtf8\Convert::i()->getTotalRowsToConvert() ) * 100, 2 ) ) : 100;
|
||||
|
||||
$isUtf8 = (boolean) ( \IPSUtf8\Convert::i()->databaseIsUtf8() );
|
||||
$processing = (boolean) ( \IPSUtf8\Session::i()->status === 'processing' );
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
</p>
|
||||
<p><a class="btn btn-lg btn-info" href="index.php?controller=browser">Start Web Converter</a></p>
|
||||
<div class="footer">
|
||||
<p>© 2015 Invision Power Services, Inc.</p>
|
||||
<p>© <script type="text/javascript">document.write( new Date().getFullYear() );</script><noscript>2015</noscript> Invision Power Services, Inc.</p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="js/jquery.min.js"></script>
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace IPSUtf8;
|
||||
*/
|
||||
class Convert
|
||||
{
|
||||
const VERSION_ID = '1.1.17';
|
||||
const VERSION_ID = '1.1.18';
|
||||
|
||||
/**
|
||||
* @brief Data Store
|
||||
@@ -301,9 +301,13 @@ class Convert
|
||||
/* Even if the current charset is set to UTF-8, if the Table Charset is latin1, we need to use this method */
|
||||
/* ... but only if the actual column isn't using utf8 */
|
||||
$columnCollation = $schematic['definition']['columns'][$col]['collation'];
|
||||
if ( \IPSUtf8\Session::i()->current_charset != 'utf-8' OR ( $tableCharSet != 'utf8' AND ! in_array( $columnCollation, array( 'utf8_unicode_ci', 'utf8mb4_unicode_ci' ) ) ) OR ( $tableCharSet == 'utf8' AND mb_substr( $columnCollation, 0, 6 ) == 'latin1' ) )
|
||||
if ( defined( 'UTF8_INSERT_ONLY' ) AND UTF8_INSERT_ONLY === TRUE AND $tableCharSet == 'utf8' )
|
||||
{
|
||||
if ( \IPSUtf8\Session::i()->current_charset == 'iso-8859-1' AND $tableCharSet == 'latin1' )
|
||||
$select[] = 'CAST( `' . $col . '` AS BINARY )';
|
||||
}
|
||||
else if ( \IPSUtf8\Session::i()->current_charset != 'utf-8' OR ( $tableCharSet != 'utf8' AND ! in_array( $columnCollation, array( 'utf8_unicode_ci', 'utf8mb4_unicode_ci' ) ) ) OR ( $tableCharSet == 'utf8' AND mb_substr( $columnCollation, 0, 5 ) == 'latin' ) )
|
||||
{
|
||||
if ( \IPSUtf8\Session::i()->current_charset == 'iso-8859-1' OR mb_substr( $columnCollation, 0, 5 ) == 'latin' )
|
||||
{
|
||||
/* Casting as binary truncates non-latin characters, so if we are using real Latin1, just convert */
|
||||
$select[] = 'CONVERT( `' . $col . '` USING utf8 )';
|
||||
@@ -317,17 +321,19 @@ class Convert
|
||||
else
|
||||
{
|
||||
/**
|
||||
* @note This looks a little weird but bare with me. Semi-old databases (post-2.x but pre-4.x) can have UTF8 Tables and Columns, but contain Latin1 data.
|
||||
* We need to try and sniff this out and apply a different type of conversion, because in this instance you cannot just extract
|
||||
* as BINARY and then insert into the source. Instead, you need to convert to latin1, then to binary, then to utf8. But you can't
|
||||
* do that on actual UTF8 data because it will then truncate multibyte characters so we need to compare the conversion against what
|
||||
* is stored.
|
||||
*/
|
||||
This looks a little weird but bare with me. Semi-old databases (post-2.x but pre-4.x) can have UTF8 Tables and Columns, but contain Latin1 data.
|
||||
We need to try and sniff this out and apply a different type of conversion, because in this instance you cannot just extract
|
||||
as BINARY and then insert into the source. Instead, you need to convert to latin1, then to binary, then to utf8. But you can't
|
||||
do that on actual UTF8 data because it will then truncate multibyte characters so we need to compare the conversion against what
|
||||
is stored.
|
||||
Mind = blown.
|
||||
*/
|
||||
$collation = 'utf8_unicode_ci';
|
||||
|
||||
if ( $tableCharSet == 'utf8mb4' OR $columnCollation == 'utf8mb4_unicode_ci' )
|
||||
$using = 'utf8';
|
||||
if ( $columnCollation == 'utf8mb4_unicode_ci' )
|
||||
{
|
||||
$collation = 'utf8mb4_unicode_ci';
|
||||
$using = 'utf8mb4';
|
||||
}
|
||||
|
||||
$source_charset = 'latin1';
|
||||
@@ -336,7 +342,7 @@ class Convert
|
||||
$source_charset = SOURCE_DB_CHARSET;
|
||||
}
|
||||
|
||||
$select[] = 'CASE WHEN STRCMP(CONVERT(CONVERT(CONVERT(`' . $col . '` USING ' . $source_charset . ') USING BINARY) USING utf8), `' . $col . '` COLLATE ' . $collation . ') = 0 THEN CONVERT(`' . $col . '` USING BINARY) ELSE CONVERT(CONVERT(CONVERT(`' . $col . '` USING ' . $source_charset . ') USING BINARY) USING utf8) END';
|
||||
$select[] = 'CASE WHEN STRCMP(CONVERT(CONVERT(CONVERT(`' . $col . '` USING ' . $source_charset . ') USING BINARY) USING ' . $using . '), `' . $col . '` COLLATE ' . $collation . ') = 0 THEN CONVERT(`' . $col . '` USING BINARY) ELSE CONVERT(CONVERT(CONVERT(`' . $col . '` USING ' . $source_charset . ') USING BINARY) USING ' . $using . ') END';
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -452,6 +458,7 @@ class Convert
|
||||
{
|
||||
if ( isset( $row[ $col ] ) AND ! empty( $row[ $col ] ) )
|
||||
{
|
||||
$currentCharSet = ( defined( 'FORCE_CONVERT_CHARSET' ) AND FORCE_CONVERT_CHARSET != NULL ) ? FORCE_CONVERT_CHARSET : $currentCharSet;
|
||||
if ( static::isSerialized( $row[ $col ] ) AND \IPSUtf8\Text\Charset::i()->needsConverting( $row[ $col ], $currentCharSet, 'UTF-8' ) )
|
||||
{
|
||||
/* Store a copy in case it doesn't work */
|
||||
@@ -513,10 +520,13 @@ class Convert
|
||||
$tmp = $row; // Use a copy so the reference in array_walk doesn't overwrite the row to be inserted
|
||||
|
||||
/* Make sure it's an associative array as topic_views only has 1 column so DB driver returns an indexed array only */
|
||||
array_walk_recursive( $tmp, function( &$input, $key )
|
||||
if ( is_array( $tmp ) )
|
||||
{
|
||||
$input = htmlentities( (string) $input, ENT_QUOTES | ENT_IGNORE, 'utf-8', false );
|
||||
} );
|
||||
array_walk_recursive( $tmp, function( &$input, $key )
|
||||
{
|
||||
$input = htmlentities( (string) $input, ENT_QUOTES | ENT_IGNORE, 'utf-8', false );
|
||||
} );
|
||||
}
|
||||
|
||||
$batchBytes += mb_strlen( @json_encode( $tmp ), '8bit');
|
||||
unset( $tmp );
|
||||
@@ -649,13 +659,14 @@ class Convert
|
||||
{
|
||||
static::log( "Pre inserts for InnoDB table " . $table['name'] );
|
||||
|
||||
/* This doesn't seem necessary
|
||||
try
|
||||
{
|
||||
static::$utf->query("SET autocommit=0");
|
||||
static::$utf->query("SET unique_checks=0");
|
||||
static::$utf->query("SET foreign_key_checks=0");
|
||||
}
|
||||
catch ( Exception $e ) { }
|
||||
catch ( Exception $e ) { }*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,14 +694,15 @@ class Convert
|
||||
else if ( \strtolower( static::$utfTableEngine ) === 'innodb' )
|
||||
{
|
||||
static::log( "Post inserts for InnoDB table " . $table['name'] );
|
||||
|
||||
|
||||
/* This doesn't seem necessary
|
||||
try
|
||||
{
|
||||
static::$utf->query("SET autocommit=1");
|
||||
static::$utf->query("SET unique_checks=1");
|
||||
static::$utf->query("SET foreign_key_checks=1");
|
||||
}
|
||||
catch ( Exception $e ) { }
|
||||
catch ( Exception $e ) { }*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -881,27 +893,45 @@ class Convert
|
||||
|
||||
while ( $stmt->fetch() === true )
|
||||
{
|
||||
if( mb_substr( $name, 0, 6 ) === 'x_utf_' )
|
||||
{
|
||||
$tables[] = $name;
|
||||
}
|
||||
$tables[] = $name;
|
||||
}
|
||||
|
||||
foreach( $tables as $name )
|
||||
{
|
||||
$tableNameNoPrefix = $name;
|
||||
$tableName = mb_substr( $name, mb_strlen( static::$utf->prefix ) );
|
||||
$isConvertedTable = ( mb_substr( $name, 0, 6 ) === 'x_utf_' );
|
||||
$isOrigTable = ( mb_substr( $name, 0, 5 ) === 'orig_' );
|
||||
|
||||
if ( $tableName !== 'convert_session' AND $tableName !== 'convert_session_tables' )
|
||||
if ( $isOrigTable )
|
||||
{
|
||||
if( static::$utf->checkForTable( $tableName ) )
|
||||
{
|
||||
static::$db->query( "DROP TABLE IF EXISTS `" . $origPrefix . $tableName . '`' );
|
||||
static::log( "DROP TABLE IF EXISTS `" . $origPrefix . $tableName . '`' );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
static::$utf->query( "RENAME TABLE `" . $tableNameNoPrefix . '` TO `' . $origPrefix . $tableName . '`' );
|
||||
static::log( "RENAME TABLE `" . $tableNameNoPrefix . '` TO `' . $origPrefix . $tableName . '`' );
|
||||
if ( ! $isConvertedTable and $origPrefix )
|
||||
{
|
||||
$tableNameNoPrefix = mb_substr( $name, mb_strlen( $origPrefix ) );
|
||||
}
|
||||
|
||||
/* Rename original tables */
|
||||
if ( ( ! $isConvertedTable ) and mb_substr( $name, 0, mb_strlen( $origPrefix ) ) === $origPrefix )
|
||||
{
|
||||
static::$db->query( "RENAME TABLE `" . $origPrefix . $tableNameNoPrefix . '` TO `orig_' . $origPrefix . $tableNameNoPrefix . '`' );
|
||||
|
||||
static::log( "RENAME TABLE `" . $origPrefix . $tableNameNoPrefix . '` TO `orig_' . $origPrefix . $tableNameNoPrefix . '`' );
|
||||
}
|
||||
|
||||
/* Grab x_utf_ prefixed tables */
|
||||
if ( $isConvertedTable )
|
||||
{
|
||||
$tableName = mb_substr( $name, mb_strlen( static::$utf->prefix ) );
|
||||
|
||||
/* Rename the new one */
|
||||
if ( $tableName !== 'convert_session' AND $tableName !== 'convert_session_tables' )
|
||||
{
|
||||
static::$utf->query( "RENAME TABLE `" . $name . '` TO `' . $origPrefix . $tableName . '`' );
|
||||
|
||||
static::log( "RENAME TABLE `" . $name . '` TO `' . $origPrefix . $tableName . '`' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -984,13 +1014,33 @@ class Convert
|
||||
/* We don't need to drop any indexes - just create a copy of the table and insert ignore */
|
||||
if ( $hasUnique === TRUE )
|
||||
{
|
||||
static::$utf->query( "RENAME TABLE `" . static::$db->prefix . $name . "` TO `" . static::$db->prefix . $name . "_temp`" );
|
||||
static::$utf->query( "CREATE TABLE `" . static::$db->prefix . $name . "` LIKE `" . static::$db->prefix . $name . "_temp`" );
|
||||
static::$utf->query( "INSERT IGNORE INTO `" . static::$db->prefix . $name . "` SELECT * FROM `" . static::$db->prefix . $name . "_temp`" );
|
||||
static::$utf->query( "DROP TABLE `" . static::$db->prefix . $name . "_temp`" );
|
||||
/* Let's try an alter first - below may not be necessary */
|
||||
try
|
||||
{
|
||||
static::$utf->query( "ALTER TABLE `" . static::$db->prefix . $name . "` CONVERT TO CHARACTER SET " . $charset . " COLLATE " . $collation );
|
||||
static::$utf->query( "ALTER TABLE `" . static::$db->prefix . $name . "` DEFAULT CHARACTER SET " . $charset . " COLLATE " . $collation );
|
||||
}
|
||||
catch( \IPSUtf8\Db\Exception $e )
|
||||
{
|
||||
/* Did not work - try the long way */
|
||||
static::$utf->query( "RENAME TABLE `" . static::$db->prefix . $name . "` TO `" . static::$db->prefix . $name . "_temp`" );
|
||||
static::log( $name . " has Unique Index - temp table created from main." );
|
||||
static::$utf->query( "CREATE TABLE `" . static::$db->prefix . $name . "` LIKE `" . static::$db->prefix . $name . "_temp`" );
|
||||
static::log( $name . " created from temp table." );
|
||||
static::$utf->query( "REPLACE INTO `" . static::$db->prefix . $name . "` SELECT * FROM `" . static::$db->prefix . $name . "_temp`" );
|
||||
static::log( $name . " data copied to new table." );
|
||||
static::$utf->query( "DROP TABLE `" . static::$db->prefix . $name . "_temp`" );
|
||||
static::log( $name . "_temp dropped" );
|
||||
|
||||
static::$utf->query( "ALTER TABLE `" . static::$db->prefix . $name . "` CONVERT TO CHARACTER SET " . $charset . " COLLATE " . $collation );
|
||||
static::$utf->query( "ALTER TABLE `" . static::$db->prefix . $name . "` DEFAULT CHARACTER SET " . $charset . " COLLATE " . $collation );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static::$utf->query( "ALTER TABLE `" . static::$db->prefix . $name . "` CONVERT TO CHARACTER SET " . $charset . " COLLATE " . $collation );
|
||||
static::$utf->query( "ALTER TABLE `" . static::$db->prefix . $name . "` DEFAULT CHARACTER SET " . $charset . " COLLATE " . $collation );
|
||||
}
|
||||
|
||||
static::$utf->query( "ALTER TABLE `" . static::$db->prefix . $name . "` CONVERT TO CHARACTER SET " . $charset . " COLLATE " . $collation );
|
||||
|
||||
if ( count( $cols ) )
|
||||
{
|
||||
@@ -1565,7 +1615,7 @@ class Convert
|
||||
foreach( \IPSUtf8\Session::i()->tables as $table => $definition )
|
||||
{
|
||||
/* If the table itself is not utf8_unicode_ci, don't bother check columns */
|
||||
if ( $definition['collation'] AND !in_array( $definition['collation'], array( 'utf8_unicode_ci', 'utf8mb4_unicode_ci' ) ) )
|
||||
if ( $definition['definition']['collation'] AND !in_array( $definition['definition']['collation'], array( 'utf8_unicode_ci', 'utf8mb4_unicode_ci' ) ) )
|
||||
{
|
||||
static::$nonUtf8Collations[] = $table;
|
||||
continue;
|
||||
|
||||
@@ -61,6 +61,11 @@ class Db extends \mysqli
|
||||
* @brief Multiton Store
|
||||
*/
|
||||
protected static $multitons;
|
||||
|
||||
/**
|
||||
* @brief Return Query
|
||||
*/
|
||||
public $returnQuery = FALSE;
|
||||
|
||||
/**
|
||||
* Get instance
|
||||
@@ -111,7 +116,30 @@ class Db extends \mysqli
|
||||
{
|
||||
throw new \IPSUtf8\Db\Exception( $error, self::$multitons[ $identifier ]->connect_errno );
|
||||
}
|
||||
|
||||
|
||||
/* If we succeeded, set the charset */
|
||||
if ( mb_substr( $identifier, 0, 4 ) == 'utf8' )
|
||||
{
|
||||
/* UTF8MB4? */
|
||||
if ( isset( $connectionSettings['sql_utf8mb4'] ) and $connectionSettings['sql_utf8mb4'] )
|
||||
{
|
||||
self::$multitons[ $identifier ]->charset = 'utf8mb4';
|
||||
self::$multitons[ $identifier ]->collation = 'utf8mb4_unicode_ci';
|
||||
self::$multitons[ $identifier ]->binaryCollation = 'utf8mb4_bin';
|
||||
}
|
||||
|
||||
/* If we succeeded, set the charset */
|
||||
if ( !self::$multitons[ $identifier ]->set_charset( self::$multitons[ $identifier ]->charset ) )
|
||||
{
|
||||
/* Fallback to UTF8 */
|
||||
self::$multitons[ $identifier ]->charset = 'utf8';
|
||||
self::$multitons[ $identifier ]->collation = 'utf8_unicode_ci';
|
||||
self::$multitons[ $identifier ]->binaryCollation = 'utf8_bin';
|
||||
|
||||
self::$multitons[ $identifier ]->set_charset( 'utf8' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the prefix */
|
||||
if ( isset( $connectionSettings['sql_tbl_prefix'] ) )
|
||||
{
|
||||
@@ -148,12 +176,6 @@ class Db extends \mysqli
|
||||
*/
|
||||
public $prefix = '';
|
||||
|
||||
/**
|
||||
* @brief Return the query instead of executing it
|
||||
* @note Only designed to work with methods that call query() vs prepared statements
|
||||
*/
|
||||
public $returnQuery = FALSE;
|
||||
|
||||
/**
|
||||
* Run a query
|
||||
*
|
||||
|
||||
@@ -103,6 +103,7 @@ class Browser extends \IPSUtf8\Output
|
||||
|
||||
/* Flush and exit */
|
||||
@ob_end_flush();
|
||||
@flush();
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
@@ -1,23 +1,86 @@
|
||||
{
|
||||
">:(": "angry.png",
|
||||
":D": "biggrin.png",
|
||||
"O.o": "blink.png",
|
||||
":$": "blush.png",
|
||||
"B|": "cool.png",
|
||||
"¬¬": "dry.png",
|
||||
"^_^": "happy.png",
|
||||
"o.O": "huh.png",
|
||||
"xD": "laugh.png",
|
||||
":|": "mellow.png",
|
||||
":o": "ohmy.png",
|
||||
":ph34r:": "ph34r.png",
|
||||
"9_9": "rolleyes.gif",
|
||||
":(": "sad.png",
|
||||
"-_-": "sleep.png",
|
||||
":)": "smile.png",
|
||||
":P": "tongue.png",
|
||||
":/": "unsure.png",
|
||||
":S": "wacko.png",
|
||||
";)": "wink.png",
|
||||
":x": "wub.png"
|
||||
">:(": {
|
||||
"image": "angry.png",
|
||||
"image_2x": "angry@2x.png"
|
||||
},
|
||||
":D": {
|
||||
"image": "biggrin.png",
|
||||
"image_2x": "biggrin@2x.png"
|
||||
},
|
||||
"O.o": {
|
||||
"image": "blink.png",
|
||||
"image_2x": "blink@2x.png"
|
||||
},
|
||||
":$": {
|
||||
"image": "blush.png",
|
||||
"image_2x": "blush@2x.png"
|
||||
},
|
||||
"B|": {
|
||||
"image": "cool.png",
|
||||
"image_2x": "cool@2x.png"
|
||||
},
|
||||
"¬¬": {
|
||||
"image": "dry.png",
|
||||
"image_2x": "dry@2x.png"
|
||||
},
|
||||
"^_^": {
|
||||
"image": "happy.png",
|
||||
"image_2x": "happy@2x.png"
|
||||
},
|
||||
"o.O": {
|
||||
"image": "huh.png",
|
||||
"image_2x": "huh@2x.png"
|
||||
},
|
||||
"xD": {
|
||||
"image": "laugh.png",
|
||||
"image_2x": "laugh@2x.png"
|
||||
},
|
||||
":|": {
|
||||
"image": "mellow.png",
|
||||
"image_2x": "mellow@2x.png"
|
||||
},
|
||||
":o": {
|
||||
"image": "ohmy.png",
|
||||
"image_2x": "ohmy@2x.png"
|
||||
},
|
||||
":ph34r:": {
|
||||
"image": "ph34r.png",
|
||||
"image_2x": "ph34r@2x.png"
|
||||
},
|
||||
"9_9": {
|
||||
"image": "rolleyes.gif",
|
||||
"image_2x": "rolleyes@2x.png"
|
||||
},
|
||||
":(": {
|
||||
"image": "sad.png",
|
||||
"image_2x": "sad@2x.png"
|
||||
},
|
||||
"-_-": {
|
||||
"image": "sleep.png",
|
||||
"image_2x": "sleep@2x.png"
|
||||
},
|
||||
":)": {
|
||||
"image": "smile.png",
|
||||
"image_2x": "smile@2x.png"
|
||||
},
|
||||
":P": {
|
||||
"image": "tongue.png",
|
||||
"image_2x": "tongue@2x.png"
|
||||
},
|
||||
":/": {
|
||||
"image": "unsure.png",
|
||||
"image_2x": "unsure@2x.png"
|
||||
},
|
||||
":S": {
|
||||
"image": "wacko.png",
|
||||
"image_2x": "wacko@2x.png"
|
||||
},
|
||||
";)": {
|
||||
"image": "wink.png",
|
||||
"image_2x": "wink@2x.png"
|
||||
},
|
||||
":x": {
|
||||
"image": "wub.png",
|
||||
"image_2x": "wub@2x.png"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
@@ -1 +1,27 @@
|
||||
=============================[NOTE]=============================
This software is Nulled!
Nulled by IAF
================================================================
IPS 4.0.13.1 Release (100045)
=============================[NOTE]=============================
Invision Power Services End User License Agreement
1. Acceptance
This software license agreement (the “Agreement”) is between you (either an individual or entity, hereinafter referred to as “You” or “Your”) and Invision Power Services, Inc. (“IPS”, “We”, “Our” or “Us”) and pertains to the IPS Community Suite software, its components, features, enhancements, updates and modifications (collectively the “Software” or “Suite”) and any related services (“Services”) provided by IPS under this Agreement.
By purchasing, downloading, accessing, installing, facilitating the installation or using the Software or Services (or allowing or authorizing any other person to do so) you are warranting that you have the authority provided by your state, country or jurisdiction to enter into a legally binding contract and that you have read and agree to be bound by the terms of this Agreement. You understand and acknowledge that this Agreement comprises the entire agreement between You and IPS. This Agreement supersedes any prior agreements, promises, representations or descriptions. If you do not agree with the terms and conditions set forth hereinafter, you may not purchase, download, access, install or use the Software or Services. This Agreement may only be modified in writing, signed by an officer of IPS and You.
2. License Scope and Grant
In consideration for payment of all applicable license fees and subject to the terms and conditions of this Agreement, IPS grants you a revocable, limited and non-exclusive license to install and use the Software and Services on a single installation, accessible via one URL. Access to services, components, software updates and technical support require an active license. All rights in and to the Software and Services are reserved to the use and benefit of IPS and/or its licensors, successors and assigners.
(a) Test Installation. You may install and test one additional instance of the Software for the purpose of development and testing. This installation must be and remain isolated and inaccessible to the general public at all times.
3. Restrictions
Your license to use the Software and Services is subject to the following terms, conditions and restrictions on use:
(a) You may alter and modify the Software’s source code for Your use, subject to this Agreement, however, you may not distribute, publish, resell, or otherwise share the Software or derivative works based on the Software without prior express written consent from IPS.
(b) You may not utilize the Software or Services to engage in, facilitate, or otherwise allow others to engage in any activity that violates any law or regulation or the terms and conditions within this Agreement.
(c) You are solely responsible for complying with all governmental regulations and policies. You agree to indemnify Us from any loss, action or damage arising from Your failure to use the Software in a manner inconsistent with applicable legislation.
(d) You may not remove any copyright or proprietary notices on or within the software’s source code at any time. A copyright removal license may be purchased to remove the public display of the Software’s publicly displayed copyright notice.
4. Intellectual Property
We have the sole and exclusive right to the Software which is being licensed, not sold, to you by IPS under the terms and conditions of this agreement. The Software is protected by copyright, trademark and other intellectual property laws. IPS reserves any rights not expressly granted herein.
5. Assignment
You may not rent, lease, sell, share or authorize or temporarily assign your rights to the license or this Agreement to another individual or entity except as expressly permitted herein.
(a) You may, after six months from the original purchase date, permanently transfer your licensing rights and interest in this Agreement to a third party, provided the license is active and in good standing. Any transfer and reassignment must occur via the mechanisms provided within the invisionpower.com client area and all applicable fees must be paid for the reassignment to be considered valid.
(b) You agree to provide this Agreement in its entirety to the assignee prior to reassignment and the assignee must agree to be bound to the terms of this Agreement.
(c) You acknowledge that account and non license specific materials and purchases, including, but not limited to: account credits and third party (“marketplace”) add-ons and purchases are non-transferrable under any circumstances.
(d) We reserve the right to refuse or reject reassignment at our sole discretion.
6. Termination
This Agreement shall remain in effLine truncated
|
||||
Invision Power Services End User License Agreement
|
||||
|
||||
|
||||
1. Acceptance
|
||||
|
||||
This software license agreement (the “Agreement”) is between you (either an individual or entity, hereinafter referred to as “You” or “Your”) and Invision Power Services, Inc. (“IPS”, “We”, “Our” or “Us”) and pertains to the IPS Community Suite software, its components, features, enhancements, updates and modifications (collectively the “Software” or “Suite”) and any related services (“Services”) provided by IPS under this Agreement.␍␍By purchasing, downloading, accessing, installing, facilitating the installation or using the Software or Services (or allowing or authorizing any other person to do so) you are warranting that you have the authority provided by your state, country or jurisdiction to enter into a legally binding contract and that you have read and agree to be bound by the terms of this Agreement. You understand and acknowledge that this Agreement comprises the entire agreement between You and IPS. This Agreement supersedes any prior agreements, promises, representations or descriptions. If you do not agree with the terms and conditions set forth hereinafter, you may not purchase, download, access, install or use the Software or Services. This Agreement may only be modified in writing, signed by an officer of IPS and You.␍␍␍2. License Scope and Grant
|
||||
|
||||
In consideration for payment of all applicable license fees and subject to the terms and conditions of this Agreement, IPS grants you a revocable, limited and non-exclusive license to install and use the Software and Services on a single installation, accessible via one URL. Access to services, components, software updates and technical support require an active license. All rights in and to the Software and Services are reserved to the use and benefit of IPS and/or its licensors, successors and assigners.␍␍(a) Test Installation. You may install and test one additional instance of the Software for the purpose of development and testing. This installation must be and remain isolated and inaccessible to the general public at all times.␍␍␍3. Restrictions␍␍Your license to use the Software and Services is subject to the following terms, conditions and restrictions on use: ␍␍(a) You may alter and modify the Software’s source code for Your use, subject to this Agreement, however, you may not distribute, publish, resell, or otherwise share the Software or derivative works based on the Software without prior express written consent from IPS.
|
||||
|
||||
(b) You may not utilize the Software or Services to engage in, facilitate, or otherwise allow others to engage in any activity that violates any law or regulation or the terms and conditions within this Agreement. ␍␍(c) You are solely responsible for complying with all governmental regulations and policies. You agree to indemnify Us from any loss, action or damage arising from Your failure to use the Software in a manner inconsistent with applicable legislation. ␍␍(d) You may not remove any copyright or proprietary notices on or within the software’s source code at any time. A copyright removal license may be purchased to remove the public display of the Software’s publicly displayed copyright notice.
|
||||
|
||||
|
||||
4. Intellectual Property
|
||||
|
||||
We have the sole and exclusive right to the Software which is being licensed, not sold, to you by IPS under the terms and conditions of this agreement. The Software is protected by copyright, trademark and other intellectual property laws. IPS reserves any rights not expressly granted herein.␍␍␍5. Assignment␍␍You may not rent, lease, sell, share or authorize or temporarily assign your rights to the license or this Agreement to another individual or entity except as expressly permitted herein.␍␍(a) You may, after six months from the original purchase date, permanently transfer your licensing rights and interest in this Agreement to a third party, provided the license is active and in good standing. Any transfer and reassignment must occur via the mechanisms provided within the invisionpower.com client area and all applicable fees must be paid for the reassignment to be considered valid. ␍␍(b) You agree to provide this Agreement in its entirety to the assignee prior to reassignment and the assignee must agree to be bound to the terms of this Agreement. ␍␍(c) You acknowledge that account and non license specific materials and purchases, including, but not limited to: account credits and third party (“marketplace”) add-ons and purchases are non-transferrable under any circumstances. ␍␍(d) We reserve the right to refuse or reject reassignment at our sole discretion.
|
||||
|
||||
|
||||
6. Termination
|
||||
␍This Agreement shall remain in effect until terminated. Your rights under this Agreement will automatically terminate without notice from Us in the event you fail to comply with any term or condition within this Agreement. Upon termination of this Agreement, you shall immediately cease all use of the Software and destroy all copies, full or partial, of the Software that may be in your possession or otherwise under your control.
|
||||
|
||||
␍7. Modification
|
||||
␍We reserve the right to amend or modify the terms of this Agreement at any time, and to change, discontinue or impose conditions on any aspect of the Software or related Service and to provide notification solely by posting an updated version of the Agreement on the invisionpower.com website. You acknowledge that you are solely responsible for regularly reviewing this Agreement and our policies. Continued use of the Software after modification to the Agreement constitutes your binding consent to such changes.
|
||||
|
||||
␍8. Disclaimer of Warranty
|
||||
␍THE SOFTWARE IS PROVIDED “AS-IS” AND TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, WE DISCLAIM ALL OTHER WARRANTIES, CONDITIONS, REPRESENTATIONS OR TERMS, EXPRESS OR IMPLIED, BY STATUTE, COMMON LAW, USAGE OR OTHERWISE, REGARDING THE SOFTWARE AND ANY RELATED SERVICES, INCLUDING THEIR FITNESS FOR A PARTICULAR PURPOSE, THEIR QUALITY, THEIR MERCHANTABILITY, OR THEIR NON-INFRINGEMENT. WE DO NOT WARRANT THAT THE SOFTWARE OR ANY RELATED SERVICES IS SECURE, OR IS FREE FROM BUGS, VIRUSES, ERRORS, OR OTHER PROGRAM LIMITATIONS, OR THAT DEFECTS WILL BE CORRECTED. SOME JURISDICTIONS DO NOT ALLOW EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSIONS MAY NOT APPLY TO YOU. THE ENTIRE RISK AS TO THE RESULTS, QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. NO ADVICE OR INFORMATION, WHETHER ORAL OR WRITTEN, OBTAINED BY YOU FROM US OR OUR EMPLOYEES, REPRESENTATIVE OR AGENTS OR THROUGH OR FROM THE SOFTWARE OR OUR WEBSITE SHALL CREATE ANY WARRANTY NOT EXPRESSLY STATED WITHIN. THIS SECTION WILL SURVIVE THE TERMINATION OF THIS AGREEMENT.
|
||||
|
||||
␍9. Limitation of Liability␍␍TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL WE, OUR SUBSIDIARIES, OFFICERS, DIRECTORS, SHAREHOLDERS, PARTNERS, EMPLOYEES, AGENTS, CONTRACTORS OR OUR SUCCESSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING, BUT NOT LIMITED TO PERSONAL INJURY OR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, EXEMPLARY, PUNITIVE, COVER, CONSEQUENTIAL OR OTHER DAMAGES, INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, LOSS OF DATA, LOSS OF USE, COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, LOSS OF GOODWILL OR ANY OTHER COMMERCIAL DAMAGES OR LOSSES, ARISING OUT OF OR RELATED TO THE USE OF, OR INABILITY TO USE, THE SOFTWARE OR ANY RELATED SERVICES OR CONTENT, HOWEVER CAUSED, REGARDLESS OF THE THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, TORT (INCLUDING NEGLIGENCE), PRODUCT LIABILITY OR OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES AND EVEN IF A REMEDY SET FORTH HEREIN IS FOUND TO HAVE FAILED OF ITS ESSENTIAL PURPOSE. WITHOUT LIMITING THE FOREGOING, IN NO EVENT SHALL OUR TOTAL LIABILITY TO YOU FOR ACTUAL DAMAGES FOR ANY CAUSE WHATSOEVER EXCEED THE AMOUNT PAID BY YOU TO LICENSE THE SOFTWARE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF LIABILITY FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE FOREGOING LIMITATION OR EXCLUSION MAY NOT APPLY TO YOU. THESE LIMITATIONS WILL SURVIVE THE TERMINATION OF THIS AGREEMENT.␍␍␍10. Indemnification␍␍You agree to fully indemnify and hold us, our successors, officers, directors, shareholders, partners, employees, agents, contracts and our successors harmless from and against any claim, suit, hearing, action, expense or demand, including without limitation to: all claims for damages, fees or costs (including attorneys’ fees), arising out of or related to the use of the Software and/or any related Services by you, your agents or representatives, anyone under your control, or by any third party using your equipment or accounts to use the Software or Services (for purposes of this section, collectively, “you”); the violation by you of any provision of this Agreement; the violation by you and any laws or regulations; or the infringement or misappropriation by you any copyright, trademark or any other intellectual property right, proprietary right, property right or any other right of ours or any third party. We reserve the right to assume the exclusive defense and control of any matter otherwise subject to indemnification by you, in which event you will cooperate with us in asserting any available defenses and, as set forth above, be fully responsible for our attorneys’ fees.␍␍␍11. Governing Law␍␍The license and this Agreement are governed by and construed in accordance with the laws of the State of Virginia, United States of America. You hereby consent to exclusive jurisdiction and venue in the County of Bedford and State of Virginia. By agreeing to the terms of this Agreement, you are waiving any claims that you might otherwise have against IPS based on the laws of other jurisdictions.␍␍␍12. Severability␍␍If, for any reason, a court of competent jurisdiction deems any provision or part of this Agreement to be unlawful or unenforceable, the remainder of the Agreement shall remain in full force and effect.␍
|
||||
@@ -21,7 +21,7 @@
|
||||
<script src="js/multipleRedirect.js"></script>
|
||||
</head>
|
||||
<body class='ipsApp ipsApp_installer'>
|
||||
<!-- Nulled by IAF -->
|
||||
|
||||
<div id='elInstaller_wrap'>
|
||||
<div id='ipsLayout_header' class='ipsClearfix' role='banner'>
|
||||
<header>
|
||||
@@ -63,7 +63,8 @@
|
||||
The installation process is now complete and your IPS Community Suite is now ready!
|
||||
</p>
|
||||
<br><br>
|
||||
<a href='{url="&" base="front"}' class='ipsButton ipsButton_large ipsButton_primary'>Go to the suite</a>
|
||||
<a href='{expression="\IPS\Settings::i()->base_url"}' class='ipsButton ipsButton_large ipsButton_primary'>Go to the suite</a>
|
||||
<a href='{expression="rtrim( \IPS\Settings::i()->base_url, '/' ) . '/' . \IPS\CP_DIRECTORY"}' class='ipsButton ipsButton_large ipsButton_normal'>Go to the AdminCP</a>
|
||||
<br><br>
|
||||
<a href="{expression="\IPS\Http\Url::ips('docs/docs')"}" target="_blank">Suite Documentation</a>
|
||||
</div>
|
||||
@@ -85,7 +86,6 @@
|
||||
<a href="{expression="\IPS\Http\Url::ips('docs/install_guide')"}" target="_blank">Install Guide</a>
|
||||
</div>
|
||||
{{endif}}
|
||||
<p style="text-align: right">Nulled by IAF</p>
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
<br><br>
|
||||
<p class="ipsType_normal">None of these items are required in order to continue with the installation right now. However, they will be required in a future version of IPS Community Suite. You should make a note of them and contact your hosting provider or system administrator after the installation to address them. You can re-run these checks later from the <em>Support</em> section of the Administrator Control Panel.</p>
|
||||
<ul class="ipsPad ipsType_large ipsList_checks">
|
||||
{{foreach $requirements['advice'] as $item}}
|
||||
<li class="advisory">{$item}</li>
|
||||
{{foreach $requirements['advice'] as $key => $item}}
|
||||
<li class="{{if $key === 'php'}}ipsMessage ipsMessage_error{{else}}advisory{{endif}}">{$item}</li>
|
||||
{{endforeach}}
|
||||
</ul>
|
||||
{{endif}}
|
||||
|
||||
@@ -6,6 +6,7 @@ $(function(){
|
||||
|
||||
$.ajax( url, {
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
timeout: IPS_TIMEOUT !== false ? parseInt( IPS_TIMEOUT * 1000 ) : 30000,
|
||||
complete: function( jqXHR, textStatus )
|
||||
{
|
||||
|
||||
@@ -32,8 +32,9 @@ $lang = array(
|
||||
'err_password_length' => "Passwords must be at least 3 characters",
|
||||
|
||||
'requirements_php_version_success' => "PHP version %s.",
|
||||
'requirements_php_version_success_53x' => "PHP version %s. <strong>Please see advice below</strong>",
|
||||
'requirements_php_version_fail' => "You are running PHP version %s. You need PHP 5.3.0 or above. You should contact your hosting provider or system administrator to ask for an upgrade.",
|
||||
'requirements_php_version_advice' => "You are running PHP version %s. While this version is compatible, we recommend version 5.4.0 or above.",
|
||||
'requirements_php_version_advice' => "You are running PHP version %s which is now end of life.<br>Please note that IPS Community Suite 4.1.1 and newer <strong>will require PHP 5.4.0</strong> as a minimum.<br>You can continue to install IPS Community Suite 4.1.0 using your current PHP version.",
|
||||
'requirements_curl_success' => "cURL extension loaded.",
|
||||
'requirements_curl_fopen' => "fsockopen function available",
|
||||
'requirements_curl_advice' => "You do not have the cURL PHP extension loaded or it is running a version less than 7.36. While this is not required, it is recommended.",
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
<pre class="ipsCode prettyprint lang-sql">{$query}{{if mb_substr( $query, -1 ) != ';'}};{{endif}}</pre>
|
||||
{{endforeach}}
|
||||
<div class="ipsAreaBackground ipsPad ipsType_center">
|
||||
<a href="{$url->setQueryString( array( 'key' => $_SESSION['uniqueKey'], 'mr_continue' => NULL, 'run_anyway' => 1, 'mr' => \IPS\Request::i()->mr ) )}" data-action="redirectContinue" class="ipsButton ipsButton_primary">{lang="manual_query_auto"}</a>
|
||||
{{$mr = \IPS\core\Setup\Upgrade::adjustMultipleRedirect( array( 'extra' => array( 'lastSqlId' => $_SESSION['lastJsonIndex'] - 0.1 ) ) );}}
|
||||
<a href="{$url->setQueryString( array( 'key' => $_SESSION['uniqueKey'], 'mr_continue' => NULL, 'run_anyway' => 1, 'mr' => $mr ) )}" data-action="redirectContinue" class="ipsButton ipsButton_primary">{lang="manual_query_auto"}</a>
|
||||
{lang="or"}
|
||||
<a href="{$url}" data-action="redirectContinue" class="ipsButton ipsButton_primary">{lang="manual_query_manual"}</a>
|
||||
</div>
|
||||
@@ -21,7 +21,7 @@
|
||||
<script src="js/multipleRedirect.js"></script>
|
||||
</head>
|
||||
<body class='ipsApp ipsApp_installer'>
|
||||
<!-- Nulled by IAF -->
|
||||
|
||||
<div id='elInstaller_wrap'>
|
||||
<div id='ipsLayout_header' class='ipsClearfix' role='banner'>
|
||||
<header>
|
||||
@@ -59,6 +59,7 @@
|
||||
</p>
|
||||
<br><br>
|
||||
<a href='{expression="\IPS\Settings::i()->base_url"}' class='ipsButton ipsButton_large ipsButton_primary'>Go to the suite</a>
|
||||
<a href='{expression="rtrim( \IPS\Settings::i()->base_url, '/' ) . '/' . \IPS\CP_DIRECTORY"}' class='ipsButton ipsButton_large ipsButton_normal'>Go to the AdminCP</a>
|
||||
<br><br>
|
||||
<a href="{expression="\IPS\Http\Url::ips('docs/docs')"}" target="_blank">Suite Documentation</a>
|
||||
</div>
|
||||
@@ -80,7 +81,6 @@
|
||||
<a href="{expression="\IPS\Http\Url::ips('docs/install_guide')"}" target="_blank">Install Guide</a>
|
||||
</div>
|
||||
{{endif}}
|
||||
<p style="text-align: right">Nulled by IAF</p>
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
<br><br>
|
||||
<p class="ipsType_normal">None of these items are required in order to continue with the upgrade right now. However, they will be required in a future version of IPS Community Suite. You should make a note of them and contact your hosting provider or system administrator after the upgrade to address them. You can re-run these checks later from the <em>Support</em> section of the Administrator Control Panel.</p>
|
||||
<ul class="ipsPad ipsType_large ipsList_checks">
|
||||
{{foreach $requirements['advice'] as $item}}
|
||||
<li class="advisory">{$item}</li>
|
||||
{{foreach $requirements['advice'] as $key => $item}}
|
||||
<li class="{{if $key === 'php'}}ipsMessage ipsMessage_warning{{else}}advisory{{endif}}">{$item}</li>
|
||||
{{endforeach}}
|
||||
</ul>
|
||||
{{endif}}
|
||||
|
||||
@@ -6,6 +6,7 @@ $(function(){
|
||||
|
||||
$.ajax( url, {
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
timeout: IPS_TIMEOUT !== false ? parseInt( IPS_TIMEOUT * 1000 ) : 30000,
|
||||
complete: function( jqXHR, textStatus )
|
||||
{
|
||||
|
||||
@@ -43,7 +43,7 @@ $lang = array(
|
||||
'login_err_bad_password' => "The password you entered is incorrect. Please try again (make sure your caps lock is off).",
|
||||
'login_err_locked_unlock' => "Your account has been locked. Try again in {# [1:minute][?:minutes]}.",
|
||||
'login_err_locked_nounlock' => "Your account has been locked. Try again later.",
|
||||
'login_err_no_cookies' => "Your browser does not accept cookies which is required in order to log in.",
|
||||
'login_err_no_cookies' => "Your browser does not accept cookies which are required in order to log in.",
|
||||
'sign_in_with_these' => "Or sign in with one of these services",
|
||||
'login_err_remote_validate' => "You must validate your account at another site before you can log in successfully. Please <a href='%s' target='_blank'>click here</a> to validate your account.",
|
||||
'login_connect_generic_error' => "There was an error processing your login request at one of the sites in our network.",
|
||||
@@ -58,8 +58,9 @@ $lang = array(
|
||||
'login_live' => "Sign in with Microsoft",
|
||||
|
||||
'requirements_php_version_success' => "PHP version %s.",
|
||||
'requirements_php_version_success_53x' => "PHP version %s. <strong>Please see advice below</strong>",
|
||||
'requirements_php_version_fail' => "You are running PHP version %s. You need PHP 5.3.0 or above. You should contact your hosting provider or system administrator to ask for an upgrade.",
|
||||
'requirements_php_version_advice' => "You are running PHP version %s. While this version is compatible, we recommend version 5.4.0 or above.",
|
||||
'requirements_php_version_advice' => "You are running PHP version %s which is now end of life.<br>Please note that IPS Community Suite 4.1.1 and newer <strong>will require PHP 5.4.0</strong> as a minimum.<br>You can continue to upgrade to IPS Community Suite 4.1.0 using your current PHP version.",
|
||||
'requirements_curl_success' => "cURL extension loaded.",
|
||||
'requirements_curl_fopen' => "fsockopen function available",
|
||||
'requirements_curl_advice' => "You do not have the cURL PHP extension loaded or it is running a version less than 7.36. While this is not required, it is recommended.",
|
||||
@@ -487,4 +488,13 @@ $lang = array(
|
||||
'100003_no_convert' => "Don't convert",
|
||||
'100003_convert' => "Convert",
|
||||
'100003_convert_desc' => "In this version of IPS Community Suite, members can no longer add other members as friends. However members can follow other members and receive notifications when the members they are following post. You can convert friends to followers, so any members who are friends with another member will now be following them, however this will mean they will start receiving notifications which may be undesired. It is recommended you do not convert.",
|
||||
|
||||
/* ! 101000 revert globalTemplate */
|
||||
'101000_globalTemplate_revert' => "Revert custom themes which contain out of date globalTemplate templates?",
|
||||
'101000_globalTemplate_revert_desc' => "In IPS Community Suite 4.1, the template 'utilitiesMenu' has been removed. This is used within the globalTemplate. After upgrading, you may see a message about the theme being out of date if you do not revert.<br><strong>Reverting templates will lose any customizations</strong>",
|
||||
'101000_yes' => "Yes, revert losing customiztions",
|
||||
'101000_no' => "No, I will manually adjust the templates after upgrading",
|
||||
|
||||
/* ! CMS 101000 Options */
|
||||
'40000_cms_htmlconversion' => "Pages HTML",
|
||||
);
|
||||
@@ -49,6 +49,6 @@ class _Application extends \IPS\Application
|
||||
*/
|
||||
protected function get__icon()
|
||||
{
|
||||
return 'file-text-o';
|
||||
return 'file-text';
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"blogs": {
|
||||
"blogs": {
|
||||
"tab": "community",
|
||||
"controller": "blogs",
|
||||
"do": "",
|
||||
"restriction": "blogs_manage"
|
||||
},
|
||||
"settings": {
|
||||
"tab": "community",
|
||||
"controller": "settings",
|
||||
"do": "",
|
||||
"restriction": "settings_manage"
|
||||
},
|
||||
"blogs": {
|
||||
"tab": "community",
|
||||
"controller": "blogs",
|
||||
"do": "",
|
||||
"restriction": "blogs_manage"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<emails><template><template_app>blog</template_app><template_name>digests__item</template_name><template_content_html><![CDATA[<tr style='border-bottom: 1px solid #eeeeee'>
|
||||
<td width='40' align='center' valign='top' class=' '>
|
||||
<td dir='{dir}' width='40' align='center' valign='top' class=' '>
|
||||
<img src='{$entry->author()->photo}' width='32' height='32' style='border: 1px solid #000; vertical-align: middle;'>
|
||||
</td>
|
||||
<td align='left'>
|
||||
<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 ) ) )}
|
||||
</p>
|
||||
@@ -27,10 +27,10 @@
|
||||
</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()})
|
||||
]]></template_content_plaintext></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 width='40' align='center' valign='top' class=' '>
|
||||
<td dir='{dir}' width='40' align='center' valign='top' class=' '>
|
||||
<img src='{$comment->author()->photo}' width='32' height='32' style='border: 1px solid #000; vertical-align: middle;'>
|
||||
</td>
|
||||
<td align='left'>
|
||||
<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_commented_entry", FALSE, array( 'sprintf' => array( $comment->author()->name ) ) )}
|
||||
</p>
|
||||
|
||||
@@ -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.list.js" javascript_type="controller" javascript_version="100045" 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="101012" javascript_position="1000050">/**
|
||||
* IPS Social Suite 4
|
||||
* (c) 2013 Invision Power Services - http://www.invisionpower.com
|
||||
*
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<language>
|
||||
<app key="blog" version="100045">
|
||||
<app key="blog" version="101012">
|
||||
<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>
|
||||
<word key="__indefart_blog_entry" js="0">a blog entry</word>
|
||||
<word key="blog_entry_container" js="0">blog</word>
|
||||
<word key="module__blog_blogs" js="0">Blogs</word>
|
||||
<word key="menu__blog_blogs" js="0">Blogs</word>
|
||||
<word key="menu__blog_blogs_settings" js="0">Settings</word>
|
||||
@@ -112,8 +113,8 @@
|
||||
<word key="unpublished" js="0">Unpublished</word>
|
||||
<word key="blog_entry_locked_can_comment" js="0">This blog entry is locked, but your permissions allow you to add new comments.</word>
|
||||
<word key="blog_entry_locked_cannot_comment" js="0">This blog entry is now closed to further comments.</word>
|
||||
<word key="entry_posted" js="0">Entry posted</word>
|
||||
<word key="entry_future_posted" js="0">Entry publishes on</word>
|
||||
<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="blog_comments" js="0">{!#[1:comment][?:comments]}</word>
|
||||
<word key="blog_entries" js="0">{!#[1:entry][?:entries]}</word>
|
||||
@@ -124,7 +125,6 @@
|
||||
<word key="my_blogs" js="0">My Blogs</word>
|
||||
<word key="blogs_with_content" js="0">Blogs With Entries</word>
|
||||
<word key="sort_last_edate" js="0">Last Entry</word>
|
||||
<word key="sort_num_views" js="0">Views</word>
|
||||
<word key="sort_rating_total" js="0">Rating</word>
|
||||
<word key="from_the_blog" js="0">From the blog</word>
|
||||
<word key="see_more_entries" js="0">See more entries from %s</word>
|
||||
@@ -211,5 +211,13 @@
|
||||
<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>
|
||||
<word key="block_blogCommentFeed" js="0">Blog Comments</word>
|
||||
<word key="block_blogCommentFeed_desc" js="0">Display comments from blogs.</word>
|
||||
<word key="block_blogs" js="0">Blogs</word>
|
||||
<word key="block_blogs_desc" js="0">Display a list of blogs.</word>
|
||||
<word key="widget_blog_last_date" js="0">Last entry posted</word>
|
||||
<word key="widget__blog_edate" js="0">Last entry date</word>
|
||||
<word key="widget__blog_count_entries" js="0">Number of entries</word>
|
||||
<word key="widget__blog_count_comments" js="0">Number of comments</word>
|
||||
</app>
|
||||
</language>
|
||||
@@ -142,20 +142,6 @@
|
||||
"values": [],
|
||||
"zerofill": false
|
||||
},
|
||||
"blog_view_level": {
|
||||
"allow_null": false,
|
||||
"auto_increment": false,
|
||||
"binary": false,
|
||||
"comment": "",
|
||||
"decimals": null,
|
||||
"default": "",
|
||||
"length": 12,
|
||||
"name": "blog_view_level",
|
||||
"type": "VARCHAR",
|
||||
"unsigned": false,
|
||||
"values": [],
|
||||
"zerofill": false
|
||||
},
|
||||
"blog_seo_name": {
|
||||
"allow_null": true,
|
||||
"auto_increment": false,
|
||||
@@ -255,130 +241,130 @@
|
||||
"zerofill": false
|
||||
},
|
||||
"blog_count_entries": {
|
||||
"allow_null": false,
|
||||
"auto_increment": false,
|
||||
"binary": false,
|
||||
"comment": "",
|
||||
"decimals": null,
|
||||
"default": "0",
|
||||
"length": 11,
|
||||
"name": "blog_count_entries",
|
||||
"type": "INT",
|
||||
"length": 11,
|
||||
"decimals": null,
|
||||
"values": [],
|
||||
"allow_null": false,
|
||||
"default": "0",
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"zerofill": false,
|
||||
"auto_increment": false,
|
||||
"binary": false
|
||||
"values": [],
|
||||
"zerofill": false
|
||||
},
|
||||
"blog_count_comments": {
|
||||
"allow_null": false,
|
||||
"auto_increment": false,
|
||||
"binary": false,
|
||||
"comment": "",
|
||||
"decimals": null,
|
||||
"default": "0",
|
||||
"length": 11,
|
||||
"name": "blog_count_comments",
|
||||
"type": "INT",
|
||||
"length": 11,
|
||||
"decimals": null,
|
||||
"values": [],
|
||||
"allow_null": false,
|
||||
"default": "0",
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"zerofill": false,
|
||||
"auto_increment": false,
|
||||
"binary": false
|
||||
"values": [],
|
||||
"zerofill": false
|
||||
},
|
||||
"blog_count_entries_hidden": {
|
||||
"allow_null": false,
|
||||
"auto_increment": false,
|
||||
"binary": false,
|
||||
"comment": "",
|
||||
"decimals": null,
|
||||
"default": "0",
|
||||
"length": 11,
|
||||
"name": "blog_count_entries_hidden",
|
||||
"type": "INT",
|
||||
"length": 11,
|
||||
"decimals": null,
|
||||
"values": [],
|
||||
"allow_null": false,
|
||||
"default": "0",
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"zerofill": false,
|
||||
"auto_increment": false,
|
||||
"binary": false
|
||||
"values": [],
|
||||
"zerofill": false
|
||||
},
|
||||
"blog_count_comments_hidden": {
|
||||
"allow_null": false,
|
||||
"auto_increment": false,
|
||||
"binary": false,
|
||||
"comment": "",
|
||||
"decimals": null,
|
||||
"default": "0",
|
||||
"length": 11,
|
||||
"name": "blog_count_comments_hidden",
|
||||
"type": "INT",
|
||||
"length": 11,
|
||||
"decimals": null,
|
||||
"values": [],
|
||||
"allow_null": false,
|
||||
"default": "0",
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"zerofill": false,
|
||||
"auto_increment": false,
|
||||
"binary": false
|
||||
"values": [],
|
||||
"zerofill": false
|
||||
},
|
||||
"blog_rating_average": {
|
||||
"allow_null": false,
|
||||
"auto_increment": false,
|
||||
"binary": false,
|
||||
"comment": "",
|
||||
"decimals": null,
|
||||
"default": "0",
|
||||
"length": 11,
|
||||
"name": "blog_rating_average",
|
||||
"type": "INT",
|
||||
"length": 11,
|
||||
"decimals": null,
|
||||
"values": [],
|
||||
"allow_null": false,
|
||||
"default": "0",
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"zerofill": false,
|
||||
"auto_increment": false,
|
||||
"binary": false
|
||||
"values": [],
|
||||
"zerofill": false
|
||||
},
|
||||
"blog_cover_photo": {
|
||||
"allow_null": true,
|
||||
"auto_increment": false,
|
||||
"binary": false,
|
||||
"comment": "",
|
||||
"decimals": null,
|
||||
"default": null,
|
||||
"length": 0,
|
||||
"name": "blog_cover_photo",
|
||||
"type": "TEXT",
|
||||
"length": null,
|
||||
"decimals": null,
|
||||
"values": [],
|
||||
"allow_null": true,
|
||||
"default": null,
|
||||
"comment": "",
|
||||
"unsigned": false,
|
||||
"zerofill": false,
|
||||
"auto_increment": false,
|
||||
"binary": false
|
||||
"values": [],
|
||||
"zerofill": false
|
||||
},
|
||||
"blog_cover_photo_offset": {
|
||||
"allow_null": true,
|
||||
"auto_increment": false,
|
||||
"binary": false,
|
||||
"comment": "",
|
||||
"decimals": null,
|
||||
"default": null,
|
||||
"length": 10,
|
||||
"name": "blog_cover_photo_offset",
|
||||
"type": "INT",
|
||||
"length": 10,
|
||||
"decimals": null,
|
||||
"values": [],
|
||||
"allow_null": true,
|
||||
"default": null,
|
||||
"comment": "",
|
||||
"unsigned": false,
|
||||
"zerofill": false,
|
||||
"auto_increment": false,
|
||||
"binary": false
|
||||
"values": [],
|
||||
"zerofill": false
|
||||
},
|
||||
"blog_social_group": {
|
||||
"allow_null": true,
|
||||
"auto_increment": false,
|
||||
"binary": false,
|
||||
"comment": "The social group ID, is this is a private blog",
|
||||
"decimals": null,
|
||||
"default": null,
|
||||
"length": 10,
|
||||
"name": "blog_social_group",
|
||||
"type": "INT",
|
||||
"length": 10,
|
||||
"decimals": null,
|
||||
"values": [],
|
||||
"allow_null": true,
|
||||
"default": null,
|
||||
"comment": "The social group ID, is this is a private blog",
|
||||
"unsigned": true,
|
||||
"zerofill": false,
|
||||
"auto_increment": false,
|
||||
"binary": false
|
||||
"values": [],
|
||||
"zerofill": false
|
||||
},
|
||||
"blog_count_entries_future": {
|
||||
"allow_null": false,
|
||||
"auto_increment": false,
|
||||
"binary": false,
|
||||
"comment": "",
|
||||
"decimals": null,
|
||||
"default": "0",
|
||||
"length": 10,
|
||||
"name": "blog_count_entries_future",
|
||||
"type": "INT",
|
||||
"length": 10,
|
||||
"decimals": null,
|
||||
"values": [],
|
||||
"allow_null": false,
|
||||
"default": "0",
|
||||
"comment": "",
|
||||
"unsigned": true,
|
||||
"zerofill": false,
|
||||
"auto_increment": false,
|
||||
"binary": false
|
||||
"values": [],
|
||||
"zerofill": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
@@ -406,22 +392,10 @@
|
||||
"type": "key",
|
||||
"name": "blog_grabber",
|
||||
"length": [
|
||||
null,
|
||||
null
|
||||
],
|
||||
"columns": [
|
||||
"blog_disabled",
|
||||
"blog_view_level"
|
||||
]
|
||||
},
|
||||
"blog_view_level": {
|
||||
"type": "key",
|
||||
"name": "blog_view_level",
|
||||
"length": [
|
||||
null
|
||||
],
|
||||
"columns": [
|
||||
"blog_view_level"
|
||||
"blog_disabled"
|
||||
]
|
||||
},
|
||||
"blog_pinned": {
|
||||
@@ -459,7 +433,7 @@
|
||||
"name": "auth_user",
|
||||
"length": [
|
||||
null,
|
||||
253
|
||||
190
|
||||
],
|
||||
"columns": [
|
||||
"blog_owner_only",
|
||||
@@ -482,7 +456,9 @@
|
||||
"blog_last_edate"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"collation": "utf8mb4_unicode_ci",
|
||||
"engine": "InnoDB"
|
||||
},
|
||||
"blog_entries": {
|
||||
"name": "blog_entries",
|
||||
|
||||
@@ -149,12 +149,6 @@
|
||||
<div>
|
||||
<strong class='ipsType_minorHeading'>{lang="latest_entry"}</strong><br>
|
||||
<h3 class='ipsType_reset ipsType_sectionHead ipsType_blendLinks'>
|
||||
<a href='{$blog->latestEntry()->url()}' title='{lang="view_this_entry" sprintf="$blog->latestEntry()->name"}'>
|
||||
{{if $blog->latestEntry()->unread()}}
|
||||
<span class='ipsItemStatus' data-ipsTooltip title="{lang="unread_blog"}"><i class="fa fa-circle"></i></span>
|
||||
{{endif}}
|
||||
{wordbreak="$blog->latestEntry()->name"}
|
||||
</a>
|
||||
{{if $blog->latestEntry()->locked()}}<i class='fa fa-lock'></i> {{endif}}{$blog->latestEntry()->caption}
|
||||
{{if $blog->latestEntry()->isFutureDate() || $blog->latestEntry()->mapped('pinned') || $blog->latestEntry()->mapped('featured') || $blog->latestEntry()->hidden() === -1 || $blog->latestEntry()->hidden() === 1 || $blog->latestEntry()->status === 'draft'}}
|
||||
{{if $blog->latestEntry()->isFutureDate()}}
|
||||
@@ -174,13 +168,20 @@
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_positive" data-ipsTooltip title='{lang="featured"}'><i class='fa fa-star'></i></span>
|
||||
{{endif}}
|
||||
{{endif}}
|
||||
|
||||
<a href='{$blog->latestEntry()->url()}' title='{lang="view_this_entry" sprintf="$blog->latestEntry()->name"}'>
|
||||
{{if $blog->latestEntry()->unread()}}
|
||||
<span class='ipsItemStatus' data-ipsTooltip title="{lang="unread_blog"}"><i class="fa fa-circle"></i></span>
|
||||
{{endif}}
|
||||
{wordbreak="$blog->latestEntry()->name"}
|
||||
</a>
|
||||
</h3>
|
||||
{{if !( $blog->owner() instanceof \IPS\Member )}}
|
||||
<p class='ipsType_medium ipsType_reset ipsType_light'>{lang="byline" htmlsprintf="trim( $blog->latestEntry()->author()->link() )"} {datetime="$blog->latestEntry()->date"}</p>
|
||||
{{endif}}
|
||||
</div>
|
||||
</div>
|
||||
<div class='ipsType_medium ipsType_richText ipsSpacer_both cBlogInfo_content'>
|
||||
<div class='ipsType_medium ipsType_richText ipsSpacer_both cBlogInfo_content' data-controller="core.front.core.lightboxedImages">
|
||||
{$blog->latestEntry()->content()|raw}
|
||||
</div>
|
||||
<ul class='ipsList_inline'>
|
||||
@@ -339,40 +340,6 @@
|
||||
{template="blogViewMedium" group="view" app="blog" params="$entry, $table, FALSE"}
|
||||
</li>
|
||||
{{endforeach}}]]></template>
|
||||
<template template_group="global" template_name="snippet" template_data="$activity, $type='activity'" template_location="front" template_app="blog"><![CDATA[
|
||||
{{if $activity instanceof \IPS\calendar\Event\Comment or $activity instanceof \IPS\calendar\Event\Review}}
|
||||
{{$item = $activity->item();}}
|
||||
{{else}}
|
||||
{{$item = $activity;}}
|
||||
{{endif}}
|
||||
|
||||
{{if $activity instanceof \IPS\blog\Entry\Comment}}
|
||||
{{if mb_strlen( trim( strip_tags( $activity->truncated() ) ) ) }}
|
||||
<div class='cSearchActivity_info ipsContained'>
|
||||
<div class='ipsType_medium ipsType_richText ipsContained ipsSpacer_bottom' data-ipsTruncate data-ipsTruncate-size='3 lines' data-ipsTruncate-type='remove'>
|
||||
{$activity->truncated()|raw}
|
||||
</div>
|
||||
{{if $type != 'search'}}
|
||||
<ul class='ipsList_inline ipsType_light'>
|
||||
<li>{template="reputationMini" group="global" app="core" params="$activity, '', NULL, TRUE"}</li>
|
||||
</ul>
|
||||
{{endif}}
|
||||
</div>
|
||||
{{endif}}
|
||||
{{else}}
|
||||
<div class='cSearchActivity_info ipsContained'>
|
||||
{{if $type != 'search'}}<a href='{$activity->url()}' class='ipsType_normal ipsType_break'>{$item->mapped('title')}</a>{{endif}}
|
||||
<div class='ipsType_medium ipsType_richText ipsContained ipsSpacer_both ipsSpacer_half' data-ipsTruncate data-ipsTruncate-size='3 lines' data-ipsTruncate-type='remove'>
|
||||
{$item->truncated()|raw}
|
||||
</div>
|
||||
<ul class='ipsList_inline ipsType_light'>
|
||||
<li>{lang="num_comments" pluralize="$item->count_comments"}</li>
|
||||
{{if $type != 'search' and $item instanceof \IPS\Content\Reputation and settings.reputation_enabled}}
|
||||
<li>{template="reputationMini" group="global" app="core" params="$item, '', NULL, TRUE"}</li>
|
||||
{{endif}}
|
||||
</ul>
|
||||
</div>
|
||||
{{endif}}]]></template>
|
||||
<template template_group="livesearch" template_name="blog" template_data="$blog" template_location="admin" template_app="blog"><![CDATA[<li class='ipsPad_half ipsClearfix' data-role='result'>
|
||||
<a href='{url="app=blog&module=blogs&controller=blogs&do=form&id="}{$blog->id}' class='ipsPos_left'>{$blog->_title}</a>
|
||||
</li>
|
||||
@@ -402,7 +369,7 @@
|
||||
{{endif}}
|
||||
{{if count( $elements ) > 1}}
|
||||
<h2 class='ipsType_sectionTitle ipsType_reset'>{lang="entry_information"}</h2>
|
||||
<div class='ipsTabs ipsTabs_contained ipsClearfix ipsJS_show' id='tabs_{$id}' data-ipsTabBar data-ipsTabBar-contentArea='#ipsTabs_content_{$id}'>
|
||||
<div class='ipsTabs ipsClearfix ipsJS_show' id='tabs_{$id}' data-ipsTabBar data-ipsTabBar-contentArea='#ipsTabs_content_{$id}'>
|
||||
<a href='#tabs_{$id}' data-action='expandTabs'><i class='fa fa-caret-down'></i></a>
|
||||
<ul role='tablist'>
|
||||
{{foreach $elements as $name => $content}}
|
||||
@@ -414,7 +381,7 @@
|
||||
{{endforeach}}
|
||||
</ul>
|
||||
</div>
|
||||
<div id='ipsTabs_content_{$id}' class='ipsTabs_panels ipsTabs_contained'>
|
||||
<div id='ipsTabs_content_{$id}' class='ipsTabs_panels'>
|
||||
{{foreach $elements as $name => $contents}}
|
||||
<div id='ipsTabs_tabs_{$id}_{$id}_tab_{$name}_panel' class="ipsTabs_panel ipsPad" aria-labelledby="{$id}_tab_{$name}" aria-hidden="false">
|
||||
<ul class='ipsForm ipsForm_vertical'>
|
||||
@@ -644,20 +611,11 @@
|
||||
{{endif}}
|
||||
</div>]]></template>
|
||||
<template template_group="view" template_name="blogViewLarge" template_data="$entry, $table, $first = FALSE" template_location="front" template_app="blog"><![CDATA[
|
||||
<article class='cBlogView_entry {{if $entry->hidden()}}ipsModerated{{endif}}'>
|
||||
<article class='cBlogView_entry ipsContained {{if $entry->hidden()}}ipsModerated{{endif}}' data-controller="core.front.core.lightboxedImages">
|
||||
<header class='ipsPhotoPanel ipsPhotoPanel_notPhone ipsPhotoPanel_small ipsSpacer_bottom'>
|
||||
{template="userPhoto" app="core" params="$entry->author()" group="global"}
|
||||
<div>
|
||||
<h2 class='ipsType_pageTitle'>
|
||||
{{if $entry->prefix()}}
|
||||
{template="prefix" group="global" app="core" params="$entry->prefix( TRUE ), $entry->prefix()"}
|
||||
{{endif}}
|
||||
<a href="{$entry->url()}" title="{lang="read_more_about" sprintf="$entry->name"}" {{if $entry->canEdit()}}data-role="editableTitle"{{endif}}>
|
||||
{{if $entry->unread()}}
|
||||
<span class='ipsItemStatus' data-ipsTooltip title="{lang="unread_blog"}"><i class="fa fa-circle"></i></span>
|
||||
{{endif}}
|
||||
{{if $entry->canEdit()}}<span data-role="editableTitle">{wordbreak="$entry->name"}</span>{{else}}{wordbreak="$entry->name"}{{endif}}
|
||||
</a>
|
||||
{{if $entry->locked()}}<i class='fa fa-lock'></i> {{endif}}{$entry->caption}
|
||||
{{if $entry->isFutureDate() || $entry->mapped('pinned') || $entry->mapped('featured') || $entry->hidden() === -1 || $entry->hidden() === 1 || $entry->status === 'draft'}}
|
||||
{{if $entry->isFutureDate() and $entry->status !== 'draft'}}
|
||||
@@ -677,8 +635,18 @@
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_positive" data-ipsTooltip title='{lang="featured"}'><i class='fa fa-star'></i></span>
|
||||
{{endif}}
|
||||
{{endif}}
|
||||
|
||||
{{if $entry->prefix()}}
|
||||
{template="prefix" group="global" app="core" params="$entry->prefix( TRUE ), $entry->prefix()"}
|
||||
{{endif}}
|
||||
<a href="{$entry->url()}" class='ipsType_blendLinks' title="{lang="read_more_about" sprintf="$entry->name"}" {{if $entry->canEdit()}}data-role="editableTitle"{{endif}}>
|
||||
{{if $entry->unread()}}
|
||||
<span class='ipsItemStatus' data-ipsTooltip title="{lang="unread_blog"}"><i class="fa fa-circle"></i></span>
|
||||
{{endif}}
|
||||
{{if $entry->canEdit()}}<span data-role="editableTitle">{wordbreak="$entry->name"}</span>{{else}}{wordbreak="$entry->name"}{{endif}}
|
||||
</a>
|
||||
</h2>
|
||||
<p class='ipsType_light ipsType_reset'>
|
||||
<p class='ipsType_light ipsType_reset ipsType_blendLinks'>
|
||||
{lang="byline" htmlsprintf="$entry->author()->link()"}{datetime="$entry->date"}
|
||||
</p>
|
||||
</div>
|
||||
@@ -687,11 +655,13 @@
|
||||
<section class='ipsType_normal ipsType_richText ipsType_break ipsSpacer_both' data-ipsTruncate {{if $first}}data-ipsTruncate-size='20 lines'{{else}}data-ipsTruncate-size='7 lines'{{endif}}>
|
||||
{$entry->content|raw}
|
||||
</section>
|
||||
{{if count( $entry->tags() )}}
|
||||
{template="tags" group="global" app="core" params="$entry->tags()"}
|
||||
{{if count( $entry->tags() )}}
|
||||
<div class='ipsSpacer_top'>
|
||||
{template="tags" group="global" app="core" params="$entry->tags()"}
|
||||
</div>
|
||||
{{endif}}
|
||||
|
||||
<ul class='ipsList_inline'>
|
||||
<ul class='ipsList_inline ipsSpacer_top'>
|
||||
{{if $table->canModerate()}}
|
||||
<li class='ipsPos_left'>
|
||||
{{$idField = $entry::$databaseColumnId;}}
|
||||
@@ -702,25 +672,16 @@
|
||||
{{if \IPS\Settings::i()->blog_enable_rating}}
|
||||
<li>{template="rating" app="core" params="'small', $entry->averageRating()" group="global"}</li>
|
||||
{{endif}}
|
||||
<li><a href='{$entry->url()}#comments' title='{lang="view_comments"}'><i class='fa fa-comment'></i> {lang="num_comments" pluralize="$entry->num_comments"}</a></li>
|
||||
<li><a href='{$entry->url()}#comments' title='{lang="view_comments"}' class='ipsType_light'>{lang="num_comments" pluralize="$entry->num_comments"}</a></li>
|
||||
<li class='ipsType_light'>{lang="num_views_with_number" pluralize="$entry->views"}</li>
|
||||
</ul>
|
||||
</article>]]></template>
|
||||
<template template_group="view" template_name="blogViewMedium" template_data="$entry, $table" template_location="front" template_app="blog"><![CDATA[
|
||||
<article class='cBlogView_entry {{if $entry->hidden()}}ipsModerated{{endif}}'>
|
||||
<article class='cBlogView_entry ipsContained {{if $entry->hidden()}}ipsModerated{{endif}}' data-controller="core.front.core.lightboxedImages">
|
||||
<header class='ipsPhotoPanel ipsPhotoPanel_mini ipsPhotoPanel_notPhone'>
|
||||
{template="userPhoto" app="core" params="$entry->author(), 'mini'" group="global"}
|
||||
<div>
|
||||
<h2 class='ipsType_sectionHead ipsType_blendLinks ipsTruncate ipsTruncate_line'>
|
||||
{{if $entry->prefix()}}
|
||||
{template="prefix" group="global" app="core" params="$entry->prefix( TRUE ), $entry->prefix()"}
|
||||
{{endif}}
|
||||
<a href="{$entry->url()}" title="{lang="read_more_about" sprintf="$entry->name"}" {{if $entry->canEdit()}}data-role="editableTitle"{{endif}}>
|
||||
{{if $entry->unread()}}
|
||||
<span class='ipsItemStatus' data-ipsTooltip title="{lang="unread_blog"}"><i class="fa fa-circle"></i></span>
|
||||
{{endif}}
|
||||
{wordbreak="$entry->name"}
|
||||
</a>
|
||||
{{if $entry->isFutureDate() || $entry->mapped('pinned') || $entry->mapped('featured') || $entry->hidden() === -1 || $entry->hidden() === 1}}
|
||||
{{if $entry->isFutureDate() and $entry->status !== 'draft'}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_small ipsBadge_warning" data-ipsTooltip title='{$entry->futureDateBlurb()}'><i class='fa fa-clock-o'></i></span>
|
||||
@@ -734,8 +695,18 @@
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_small ipsBadge_positive" data-ipsTooltip title='{lang="featured"}'><i class='fa fa-star'></i></span>
|
||||
{{endif}}
|
||||
{{endif}}
|
||||
|
||||
{{if $entry->prefix()}}
|
||||
{template="prefix" group="global" app="core" params="$entry->prefix( TRUE ), $entry->prefix()"}
|
||||
{{endif}}
|
||||
<a href="{$entry->url()}" title="{lang="read_more_about" sprintf="$entry->name"}" {{if $entry->canEdit()}}data-role="editableTitle"{{endif}}>
|
||||
{{if $entry->unread()}}
|
||||
<span class='ipsItemStatus' data-ipsTooltip title="{lang="unread_blog"}"><i class="fa fa-circle"></i></span>
|
||||
{{endif}}
|
||||
{wordbreak="$entry->name"}
|
||||
</a>
|
||||
</h2>
|
||||
<p class='ipsType_light ipsType_reset'>
|
||||
<p class='ipsType_light ipsType_reset ipsType_blendLinks'>
|
||||
{lang="byline" htmlsprintf="$entry->author()->link()"}{datetime="$entry->date"}
|
||||
</p>
|
||||
{{if \IPS\Settings::i()->blog_enable_rating}}
|
||||
@@ -756,46 +727,15 @@
|
||||
</li>
|
||||
{{endif}}
|
||||
<li><strong><a href='{$entry->url()}' title="{lang="read_more_about" sprintf="$entry->name"}">{lang="read_more"}</a></strong></li>
|
||||
<li><a href='{$entry->url()}#comments' title='{lang="view_comments"}'><i class='fa fa-comment'></i> {lang="num_comments" pluralize="$entry->num_comments"}</a></li>
|
||||
<li><a href='{$entry->url()}#comments' title='{lang="view_comments"}' class='ipsType_light'>{lang="num_comments" pluralize="$entry->num_comments"}</a></li>
|
||||
<li class='ipsType_light'>{lang="num_views_with_number" pluralize="$entry->views"}</li>
|
||||
</ul>
|
||||
</article>]]></template>
|
||||
<template template_group="view" template_name="blogViewSmall" template_data="$entry, $table" template_location="front" template_app="blog"><![CDATA[
|
||||
<li class='cBlogView_entry'>
|
||||
<div class='ipsPhotoPanel ipsPhotoPanel_tiny ipsPhotoPanel_notPhone'>
|
||||
{template="userPhoto" app="core" params="$entry->author(), 'tiny'" group="global"}
|
||||
<div>
|
||||
{{if $entry->prefix()}}
|
||||
{template="prefix" group="global" app="core" params="$entry->prefix( TRUE ), $entry->prefix()"}
|
||||
{{endif}}
|
||||
<a href="{$entry->url()}" title="{lang="read_more_about" sprintf="$entry->name"}" class='ipsType_large ipsType_blendLinks' {{if $entry->canEdit()}}data-role="editableTitle"{{endif}}>
|
||||
{{if $entry->unread()}}
|
||||
<span class='ipsItemStatus' data-ipsTooltip title="{lang="unread_blog"}"><i class="fa fa-circle"></i></span>
|
||||
{{endif}}
|
||||
{wordbreak="$entry->name"}
|
||||
</a><br>
|
||||
<p class='ipsType_light ipsType_reset'>
|
||||
{lang="byline" htmlsprintf="$entry->author()->link()"}{datetime="$entry->date"}
|
||||
</p>
|
||||
|
||||
<ul class='ipsList_inline'>
|
||||
{{if $table->canModerate()}}
|
||||
<li class='ipsPos_left'>
|
||||
{{$idField = $entry::$databaseColumnId;}}
|
||||
<input type='checkbox' data-role='moderation' name="moderate[{$entry->$idField}]" data-actions="{expression="implode( ' ', $table->multimodActions( $entry ) )"}" data-state='{{if $entry->tableStates()}}{$entry->tableStates()}{{endif}}'>
|
||||
</li>
|
||||
{{endif}}
|
||||
<li>
|
||||
<a href='{$entry->url()}#comments' title='{lang="view_comments"}'><i class='fa fa-comment'></i> {lang="num_comments" pluralize="$entry->num_comments"}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>]]></template>
|
||||
<template template_group="view" template_name="comments" template_data="$entry" template_location="front" template_app="blog"><![CDATA[<div class='ipsBox'>
|
||||
<div data-controller='core.front.core.commentFeed' data-baseURL='{$entry->url()}' data-feedID='entry-{$entry->id}' id='comments'>
|
||||
<div data-controller='core.front.core.commentFeed' {{if settings.auto_polling_enabled}}data-autoPoll{{endif}} data-baseURL='{$entry->url()}' data-feedID='entry-{$entry->id}' id='comments'>
|
||||
<div class='ipsPad'>
|
||||
<h2 class='ipsType_sectionHead ipsSpacer_bottom' data-role="comment_count">{lang="num_comments_uc" pluralize="$entry->num_comments"}</h2>
|
||||
<h2 class='ipsType_sectionHead' data-role="comment_count">{lang="num_comments_uc" pluralize="$entry->num_comments"}</h2>
|
||||
<hr class='ipsHr'>
|
||||
{{if $entry->commentPageCount() > 1}}
|
||||
{$entry->commentPagination()|raw}
|
||||
<br><br>
|
||||
@@ -851,13 +791,10 @@
|
||||
{{endif}}
|
||||
<a href='{$blog->url()}' title='{lang="go_to_blog" sprintf="$blog->_title"}' class='ipsType_blendLinks'>
|
||||
<h1 class='ipsType_pageTitle ipsType_break ipsTruncate ipsTruncate_line'>
|
||||
{{if $blog->pinned && \IPS\Request::i()->module != 'view'}}
|
||||
{{if $blog->pinned}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_small ipsBadge_positive" data-ipsTooltip title='{lang="pinned"}'><i class='fa fa-thumb-tack'></i></span>
|
||||
{{endif}}
|
||||
{$blog->_title}
|
||||
{{if $blog->pinned && \IPS\Request::i()->module == 'view'}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_small ipsBadge_positive" data-ipsTooltip title='{lang="pinned"}'><i class='fa fa-thumb-tack'></i></span>
|
||||
{{endif}}
|
||||
</h1>
|
||||
</a>
|
||||
<p class='ipsType_normal ipsType_reset ipsType_blendLinks'>
|
||||
@@ -880,11 +817,6 @@
|
||||
<article class='ipsBox ipsPad ipsSpacer_top'>
|
||||
<header>
|
||||
<h1 class='ipsType_pageTitle ipsType_largeTitle ipsType_break'>
|
||||
{{if $entry->prefix()}}
|
||||
{template="prefix" group="global" app="core" params="$entry->prefix( TRUE ), $entry->prefix()"}
|
||||
{{endif}}
|
||||
{wordbreak="$entry->name"}
|
||||
{{if $entry->locked()}}<i class='fa fa-lock'></i> {{endif}}{$entry->caption}
|
||||
{{if $entry->isFutureDate() || $entry->mapped('pinned') || $entry->mapped('featured') || $entry->hidden() === -1 || $entry->hidden() === 1 || $entry->status === 'draft'}}
|
||||
{{if $entry->isFutureDate() and $entry->status !== 'draft'}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_warning" data-ipsTooltip title='{$entry->futureDateBlurb()}'><i class='fa fa-clock-o'></i></span>
|
||||
@@ -903,6 +835,12 @@
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_positive" data-ipsTooltip title='{lang="featured"}'><i class='fa fa-star'></i></span>
|
||||
{{endif}}
|
||||
{{endif}}
|
||||
|
||||
{{if $entry->prefix()}}
|
||||
{template="prefix" group="global" app="core" params="$entry->prefix( TRUE ), $entry->prefix()"}
|
||||
{{endif}}
|
||||
{wordbreak="$entry->name"}
|
||||
{{if $entry->locked()}}<i class='fa fa-lock'></i> {{endif}}{$entry->caption}
|
||||
</h1>
|
||||
|
||||
<div class='ipsPhotoPanel ipsPhotoPanel_tiny ipsSpacer_top'>
|
||||
@@ -911,7 +849,7 @@
|
||||
</div>
|
||||
{template="userPhoto" app="core" params="$entry->author(), 'tiny'" group="global"}
|
||||
<div>
|
||||
<p class='ipsType_light ipsType_reset'>{{if $entry->date > time()}}{lang="entry_future_posted"}{{else}}{lang="entry_posted"}{{endif}} {datetime="$entry->date"}</p>
|
||||
<p class='ipsType_light ipsType_reset ipsType_blendLinks'>{{if $entry->date > time()}}{lang="entry_future_posted" htmlsprintf="$entry->author()->link()"}{{else}}{lang="entry_posted" htmlsprintf="$entry->author()->link()"}{{endif}} · {datetime="$entry->date"}</p>
|
||||
<p class='ipsType_light ipsType_reset'>{lang="num_views_with_number" pluralize="$entry->views"}</p>
|
||||
{{if \IPS\Settings::i()->blog_enable_rating}}
|
||||
{$entry->rating()|raw}
|
||||
@@ -1135,6 +1073,206 @@
|
||||
<div class='ipsResponsive_showPhone ipsResponsive_block ipsSpacer_top'>
|
||||
{template="follow" app="core" group="global" params="'blog', 'blog', $blog->_id, \IPS\blog\Entry::containerFollowerCount( $blog )"}
|
||||
</div>]]></template>
|
||||
<template template_group="widgets" template_name="blogCommentFeed" template_data="$comments, $title, $orientation='vertical'" template_location="front" template_app="blog"><![CDATA[{{if !empty( $comments ) }}
|
||||
<h3 class='ipsType_reset ipsWidget_title'>{$title}</h3>
|
||||
{{if $orientation == 'vertical'}}
|
||||
<div class='ipsWidget_inner ipsPad_half'>
|
||||
<ul class='ipsDataList ipsDataList_reducedSpacing'>
|
||||
{{foreach $comments as $comment}}
|
||||
<li class='ipsDataItem'>
|
||||
<div class='ipsDataItem_icon ipsPos_top'>
|
||||
{template="userPhoto" group="global" app="core" params="$comment->author(), 'tiny'"}
|
||||
</div>
|
||||
<div class='ipsDataItem_main'>
|
||||
<a href="{$comment->url()}" class='ipsType_medium ipsType_break'>{wordbreak="$comment->item()->name"}</a><br>
|
||||
<p class='ipsType_reset ipsType_medium ipsType_light ipsType_blendLinks'>{lang="byline_nodate" htmlsprintf="$comment->author()->link()"} · <a href="{$comment->url()}" class='ipsDataItem_title ipsType_break ipsType_blendLinks'>{$comment->dateLine()|raw}</a></p>
|
||||
<div class='ipsType_medium ipsType_textBlock ipsType_richText ipsType_break ipsContained ipsSpacer_top ipsSpacer_half' data-ipsTruncate data-ipsTruncate-type='remove' data-ipsTruncate-size='{{if $orientation == 'vertical'}}6 lines{{else}}2 lines{{endif}}'>
|
||||
{$comment->truncated( true )|raw}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{endforeach}}
|
||||
</ul>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class='ipsWidget_inner'>
|
||||
<ul class='ipsDataList'>
|
||||
{{foreach $comments as $comment}}
|
||||
<li class='ipsDataItem ipsClearfix'>
|
||||
<div class='ipsComment_header ipsPhotoPanel ipsPhotoPanel_mini'>
|
||||
{template="userPhoto" app="core" group="global" params="$comment->author(), 'mini', $comment->warningRef()"}
|
||||
<div>
|
||||
<p class='ipsPos_right ipsType_reset ipsType_blendLinks'>
|
||||
<a href='{$comment->item()->url()->setQueryString( array( 'do' => 'findComment', 'comment' => $comment->id ) )}' data-ipsTooltip title='{lang="share_this_comment"}' data-ipsMenu data-ipsMenu-closeOnClick='false' id='elShareComment_{$comment->id}'><i class='fa fa-share-alt'></i></a>
|
||||
</p>
|
||||
<h3 class='ipsComment_author ipsType_blendLinks'>
|
||||
<strong class='ipsType_normal'>{template="userLink" app="core" group="global" params="$comment->author(), $comment->warningRef()"}</strong>
|
||||
{template="reputationBadge" group="global" app="core" params="$comment->author()"}
|
||||
</h3>
|
||||
<p class='ipsComment_meta ipsType_light ipsType_medium'>
|
||||
<a href='{$comment->item()->url()->setQueryString( array( 'do' => 'findComment', 'comment' => $comment->id ) )}' class='ipsType_blendLinks' title='{lang="share_this_comment"}'>{$comment->dateLine()|raw}</a>
|
||||
{{if $comment->editLine()}}
|
||||
({lang="edited_lc"})
|
||||
{{endif}}
|
||||
{{if $comment->hidden()}}
|
||||
· {$comment->hiddenBlurb()}
|
||||
{{endif}}
|
||||
{{if $comment instanceof \IPS\Content\ReportCenter and !\IPS\Member::loggedIn()->group['gbw_no_report'] and $comment->hidden() !== 1 }}
|
||||
· <a href='{$comment->url('report')}' data-ipsDialog data-ipsDialog-remoteSubmit data-ipsDialog-size='medium' data-ipsDialog-flashMessage='{lang="report_submit_success"}' data-ipsDialog-title="{lang="report"}" data-action='reportComment' title='{lang="report_content"}'>{lang="report"}</a>
|
||||
{{endif}}
|
||||
</p>
|
||||
|
||||
{{if member.modPermission('mod_see_warn') and $comment->warning}}
|
||||
{template="commentWarned" group="global" app="core" params="$comment"}
|
||||
{{endif}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='ipsPad ipsClearfix'>
|
||||
{{if in_array( 'IPS\Content\Reputation', class_implements( $comment ) ) and settings.reputation_highlight and $comment->reputation() >= settings.reputation_highlight}}
|
||||
<strong class='ipsComment_popularFlag' data-ipsTooltip title='{lang="this_is_a_popular_comment"}'><i class='fa fa-star'></i></strong>
|
||||
{{endif}}
|
||||
<a href="{$comment->url()}" class='ipsDataItem_title ipsType_break'>{wordbreak="$comment->item()->name"}</a><br>
|
||||
<div data-role='commentContent' class='ipsType_normal ipsType_richText ipsType_break ipsContained' data-controller='core.front.core.lightboxedImages'>
|
||||
{{if $comment->hidden() === 1 && $comment->author()->member_id == \IPS\Member::loggedIn()->member_id}}
|
||||
<strong class='ipsType_medium ipsType_warning'><i class='fa fa-info-circle'></i> {lang="comment_awaiting_approval"}</strong>
|
||||
{{endif}}
|
||||
{$comment->content()|raw}
|
||||
|
||||
{{if $comment->editLine()}}
|
||||
{$comment->editLine()|raw}
|
||||
{{endif}}
|
||||
</div>
|
||||
|
||||
{{if $comment->hidden() !== 1 && $comment instanceof \IPS\Content\Reputation and settings.reputation_enabled}}
|
||||
{template="reputation" group="global" app="core" params="$comment, 'ipsPos_right ipsResponsive_noFloat'"}
|
||||
{{endif}}
|
||||
</div>
|
||||
</li>
|
||||
{{endforeach}}
|
||||
</ul>
|
||||
</div>
|
||||
{{endif}}
|
||||
{{endif}}
|
||||
]]></template>
|
||||
<template template_group="widgets" template_name="blogs" template_data="$blogs, $title, $orientation='vertical'" template_location="front" template_app="blog"><![CDATA[<h3 class='ipsType_reset ipsWidget_title'>{$title}</h3>
|
||||
{{if $orientation == 'vertical'}}
|
||||
<div class='ipsPad_half ipsWidget_inner'>
|
||||
<ul class='ipsDataList ipsDataList_reducedSpacing'>
|
||||
{{foreach $blogs as $blog}}
|
||||
<li class='ipsDataItem'>
|
||||
<div class='ipsColumns ipsColumns_collapsePhone'>
|
||||
<h4 class='ipsType_large ipsType_reset'>{$blog->_title}</h4>
|
||||
<div>
|
||||
<ul class='ipsGrid'>
|
||||
<li class='ipsGrid_span4'><strong class='ipsType_normal'>{$blog->_items}</strong><br>{lang="blog_entries" pluralize="$blog->_items"}</li>
|
||||
<li class='ipsGrid_span4'><strong class='ipsType_normal'>{$blog->_comments}</strong><br>{lang="blog_comments" pluralize="$blog->_comments"}</li>
|
||||
<li class='ipsGrid_span4'><strong class='ipsType_normal'>{$blog->num_views}</strong><br>{lang="blog_views" pluralize="$blog->num_views"}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{endforeach}}
|
||||
</ul>
|
||||
</div>
|
||||
{{else}}
|
||||
<ol class="ipsDataList ipsClear cBlogList ipsAreaBackground ipsDataList_large" data-role="tableRows" itemscope="" itemtype="http://schema.org/ItemList">
|
||||
{{foreach $blogs as $blog}}
|
||||
<li class='ipsDataItem ipsAreaBackground_reset'>
|
||||
<div class='ipsColumns ipsColumns_collapsePhone'>
|
||||
<div class='ipsColumn ipsColumn_veryWide cBlogInfo ipsAreaBackground_light'>
|
||||
{$blog->coverPhoto()|raw}
|
||||
<div class='ipsPad'>
|
||||
<ul class='ipsGrid'>
|
||||
<li class='ipsGrid_span4'><strong class='ipsType_normal'>{$blog->_items}</strong><br>{lang="blog_entries" pluralize="$blog->_items"}</li>
|
||||
<li class='ipsGrid_span4'><strong class='ipsType_normal'>{$blog->_comments}</strong><br>{lang="blog_comments" pluralize="$blog->_comments"}</li>
|
||||
<li class='ipsGrid_span4'><strong class='ipsType_normal'>{$blog->num_views}</strong><br>{lang="blog_views" pluralize="$blog->num_views"}</li>
|
||||
</ul>
|
||||
{{if count( $blog->_recentEntries )}}
|
||||
<h4 class='ipsType_minorHeading'>{lang="recent_entries"}</h4>
|
||||
<ul class='ipsDataList ipsDataList_reducedSpacing ipsType_medium ipsList_reset ipsType_light'>
|
||||
{{foreach $blog->_recentEntries as $entry}}
|
||||
<li class='ipsDataItem'>
|
||||
<div class='ipsDataItem_main'>
|
||||
{{if $entry->unread()}}
|
||||
<a href='{$entry->url()}' title='{lang="view_this_entry" sprintf="$entry->name"}' class=''>
|
||||
<span class='ipsItemStatus ipsItemStatus_tiny'><i class='fa fa-circle'></i></span>
|
||||
</a>
|
||||
{{endif}}
|
||||
<a href='{$entry->url()}' title='{lang="view_this_entry" sprintf="$entry->name"}' class='ipsType_break'>
|
||||
{wordbreak="$entry->name"}
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
{{endforeach}}
|
||||
</ul>
|
||||
{{endif}}
|
||||
</div>
|
||||
</div>
|
||||
<div class='ipsColumn ipsColumn_fluid ipsPad'>
|
||||
{{if $blog->latestEntry()}}
|
||||
<div class='ipsPhotoPanel ipsPhotoPanel_mini'>
|
||||
{template="userPhoto" app="core" params="$blog->latestEntry()->author(), 'mini'" group="global"}
|
||||
<div>
|
||||
<strong class='ipsType_minorHeading'>{lang="latest_entry"}</strong><br>
|
||||
<h3 class='ipsType_reset ipsType_sectionHead ipsType_blendLinks'>
|
||||
<a href='{$blog->latestEntry()->url()}' title='{lang="view_this_entry" sprintf="$blog->latestEntry()->name"}'>
|
||||
{{if $blog->latestEntry()->unread()}}
|
||||
<span class='ipsItemStatus' data-ipsTooltip title="{lang="unread_blog"}"><i class="fa fa-circle"></i></span>
|
||||
{{endif}}
|
||||
{wordbreak="$blog->latestEntry()->name"}
|
||||
</a>
|
||||
{{if $blog->latestEntry()->locked()}}<i class='fa fa-lock'></i> {{endif}}{$blog->latestEntry()->caption}
|
||||
{{if $blog->latestEntry()->isFutureDate() || $blog->latestEntry()->mapped('pinned') || $blog->latestEntry()->mapped('featured') || $blog->latestEntry()->hidden() === -1 || $blog->latestEntry()->hidden() === 1 || $blog->latestEntry()->status === 'draft'}}
|
||||
{{if $blog->latestEntry()->isFutureDate()}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_warning" data-ipsTooltip title='{$blog->latestEntry()->futureDateBlurb()}'><i class='fa fa-clock-o'></i></span>
|
||||
{{elseif $blog->latestEntry()->hidden() === -1}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_warning" data-ipsTooltip title='{$blog->latestEntry()->hiddenBlurb()}'><i class='fa fa-eye-slash'></i></span>
|
||||
{{elseif $blog->latestEntry()->hidden() === 1}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_warning" data-ipsTooltip title='{lang="pending_approval"}'><i class='fa fa-warning'></i></span>
|
||||
{{endif}}
|
||||
{{if $blog->latestEntry()->status === 'draft'}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_warning" data-ipsTooltip title='{lang="unpublished"}'><i class='fa fa-pencil-square-o'></i></span>
|
||||
{{endif}}
|
||||
{{if $blog->latestEntry()->mapped('pinned')}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_positive" data-ipsTooltip title='{lang="pinned"}'><i class='fa fa-thumb-tack'></i></span>
|
||||
{{endif}}
|
||||
{{if $blog->latestEntry()->mapped('featured')}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_positive" data-ipsTooltip title='{lang="featured"}'><i class='fa fa-star'></i></span>
|
||||
{{endif}}
|
||||
{{endif}}
|
||||
</h3>
|
||||
{{if !( $blog->owner() instanceof \IPS\Member )}}
|
||||
<p class='ipsType_medium ipsType_reset ipsType_light'>{lang="byline" htmlsprintf="trim( $blog->latestEntry()->author()->link() )"} {datetime="$blog->latestEntry()->date"}</p>
|
||||
{{endif}}
|
||||
</div>
|
||||
</div>
|
||||
<div class='ipsType_medium ipsType_richText ipsSpacer_both cBlogInfo_content'>
|
||||
{$blog->latestEntry()->content()|raw}
|
||||
</div>
|
||||
<ul class='ipsList_inline'>
|
||||
<li>
|
||||
<strong><a href='{$blog->latestEntry()->url()}' title='{lang="read_more_entry"}'>{lang="read_more"}</a></strong>
|
||||
</li>
|
||||
{{if \IPS\Settings::i()->blog_enable_rating}}
|
||||
<li>{template="rating" app="core" params="'small', $blog->latestEntry()->averageRating()" group="global"}</li>
|
||||
{{endif}}
|
||||
{{if !$blog->latestEntry()->num_comments}}
|
||||
<li class='ipsType_light'>{lang="num_comments" pluralize="$blog->latestEntry()->num_comments"}</li>
|
||||
{{else}}
|
||||
<li><a href='{$blog->latestEntry()->url()}#comments' title='{lang="see_comments_on_entry"}'>{lang="num_comments" pluralize="$blog->latestEntry()->num_comments"}</a></li>
|
||||
{{endif}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<p class='ipsEmpty ipsType_center'>{lang="no_entries_yet"}</p>
|
||||
{{endif}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
{{endforeach}}
|
||||
</ol>
|
||||
{{endif}}]]></template>
|
||||
<template template_group="widgets" template_name="blogStatistics" template_data="$stats, $orientation='vertical'" template_location="front" template_app="blog"><![CDATA[<h3 class='ipsType_reset ipsWidget_title'>{lang="block_blogStatistics"}</h3>
|
||||
<div class='ipsWidget_inner'>
|
||||
{{if $orientation == 'vertical'}}
|
||||
@@ -1186,8 +1324,8 @@
|
||||
{template="userPhoto" app="core" params="$entry->author(), 'tiny'" group="global"}
|
||||
</div>
|
||||
<div class='ipsDataItem_main'>
|
||||
<a href="{$entry->url()}" title='{lang="view_this_entry" sprintf="$entry->_title"}' class='ipsType_normal ipsType_break'>{wordbreak="$entry->name"}</a><br>
|
||||
<span class='ipsType_light ipsType_medium ipsType_break ipsContained'>{lang="byline_nodate" htmlsprintf="$entry->author()->link()"} {lang="in"} <a href='{$entry->container()->url()}' class='ipsType_blendLinks'>{$entry->container()->_title}</a></span>
|
||||
<a href="{$entry->url('getLastComment')}" title='{lang="view_this_entry" sprintf="$entry->_title"}' class='ipsType_medium ipsType_break'>{wordbreak="$entry->name"}</a><br>
|
||||
<span class='ipsType_blendLinks ipsType_light ipsType_medium ipsType_break ipsContained'>{lang="byline_nodate" htmlsprintf="$entry->author()->link()"} {lang="in"} <a href='{$entry->container()->url()}' class='ipsType_blendLinks'>{$entry->container()->_title}</a></span>
|
||||
{{if \IPS\Settings::i()->blog_enable_rating}}
|
||||
{template="rating" group="global" location="front" app="core" params="'small', $entry->averageRating()"}
|
||||
{{endif}}
|
||||
|
||||
@@ -84,5 +84,18 @@
|
||||
"100042": "4.0.12",
|
||||
"100043": "4.0.12.1",
|
||||
"100044": "4.0.13",
|
||||
"100045": "4.0.13.1"
|
||||
"100045": "4.0.13.1",
|
||||
"101000": "4.1.0 Beta 1",
|
||||
"101001": "4.1.0 Beta 2",
|
||||
"101002": "4.1.0 Beta 3",
|
||||
"101003": "4.1.0 Beta 4",
|
||||
"101004": "4.1.0 Beta 5",
|
||||
"101005": "4.1.0 Beta 6",
|
||||
"101006": "4.1.0 Beta 7",
|
||||
"101007": "4.1.0 Beta 8",
|
||||
"101008": "4.1.0 Beta 9",
|
||||
"101009": "4.1.0 Beta 10",
|
||||
"101010": "4.1.0",
|
||||
"101011": "4.1.1",
|
||||
"101012": "4.1.2"
|
||||
}
|
||||
@@ -17,5 +17,27 @@
|
||||
"allow_reuse": true,
|
||||
"menu_style": "modal",
|
||||
"embeddable": true
|
||||
},
|
||||
"blogCommentFeed": {
|
||||
"class": "\\IPS\\Widget\\PermissionCache",
|
||||
"restrict": [
|
||||
"sidebar",
|
||||
"cms"
|
||||
],
|
||||
"default_area": "",
|
||||
"allow_reuse": true,
|
||||
"menu_style": "modal",
|
||||
"embeddable": true
|
||||
},
|
||||
"blogs": {
|
||||
"class": "\\IPS\\Widget\\PermissionCache",
|
||||
"restrict": [
|
||||
"sidebar",
|
||||
"cms"
|
||||
],
|
||||
"default_area": "",
|
||||
"allow_reuse": true,
|
||||
"menu_style": "menu",
|
||||
"embeddable": true
|
||||
}
|
||||
}
|
||||
@@ -23,14 +23,28 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
* @brief Content Router extension: Entries
|
||||
*/
|
||||
class _Blog
|
||||
{
|
||||
/**
|
||||
* @brief Content Item Classes
|
||||
*/
|
||||
public $classes = array( 'IPS\blog\Entry' );
|
||||
|
||||
{
|
||||
/**
|
||||
* @brief Owned Node Classes
|
||||
*/
|
||||
public $ownedNodes = array( 'IPS\blog\Blog' );
|
||||
|
||||
/**
|
||||
* @brief Content Item Classes
|
||||
*/
|
||||
public $classes = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \IPS\Member|NULL $member If checking access, the member to check for, or NULL to not check access
|
||||
* @return void
|
||||
*/
|
||||
public function __construct( \IPS\Member $member = NULL )
|
||||
{
|
||||
if ( $member === NULL or $member->canAccessModule( \IPS\Application\Module::get( 'blog', 'blogs', 'front' ) ) )
|
||||
{
|
||||
$this->classes[] = 'IPS\blog\Entry';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,18 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
/**
|
||||
* Front Navigation Extension: Blogs
|
||||
*/
|
||||
class _Blogs
|
||||
class _Blogs extends \IPS\core\FrontNavigation\FrontNavigationAbstract
|
||||
{
|
||||
/**
|
||||
* Get Type Title which will display in the AdminCP Menu Manager
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function typeTitle()
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack('frontnavigation_blogs');
|
||||
}
|
||||
|
||||
/**
|
||||
* Can access?
|
||||
*
|
||||
@@ -31,7 +41,7 @@ class _Blogs
|
||||
*/
|
||||
public function canView()
|
||||
{
|
||||
return !\IPS\Application::load('blog')->hide_tab and \IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( 'blog', 'blogs' ) );
|
||||
return parent::canView() and \IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( 'blog', 'blogs' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,14 +73,4 @@ class _Blogs
|
||||
{
|
||||
return \IPS\Dispatcher::i()->application->directory === 'blog';
|
||||
}
|
||||
|
||||
/**
|
||||
* Children
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function children()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ class _Blog
|
||||
/**
|
||||
* Process Form
|
||||
*
|
||||
* @param \IPS\Form\Tabbed $form The form
|
||||
* @param \IPS\Helpers\Form $form The form
|
||||
* @param \IPS\Member\Group $group Existing Group
|
||||
* @return void
|
||||
*/
|
||||
@@ -40,8 +40,9 @@ class _Blog
|
||||
$form->add(new \IPS\Helpers\Form\YesNo('g_blog_allowprivate', $group->g_blog_allowprivate, FALSE, array(), NULL, NULL, NULL, 'g_blog_allowprivate'));
|
||||
$form->add(new \IPS\Helpers\Form\YesNo('g_blog_allowownmod', $group->g_blog_allowownmod, FALSE, array(), NULL, NULL, NULL, 'g_blog_allowownmod'));
|
||||
$form->add(new \IPS\Helpers\Form\YesNo('g_blog_allowdelete', $group->g_blog_allowdelete, FALSE, array(), NULL, NULL, NULL, 'g_blog_allowdelete'));
|
||||
$form->add(new \IPS\Helpers\Form\YesNo('g_blog_allowcomment', $group->g_blog_allowcomment));
|
||||
}
|
||||
|
||||
$form->add(new \IPS\Helpers\Form\YesNo('g_blog_allowcomment', $group->g_blog_allowcomment));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,7 +61,8 @@ class _Blog
|
||||
$group->g_blog_allowprivate = $values['g_blog_allowprivate'];
|
||||
$group->g_blog_allowownmod = $values['g_blog_allowownmod'];
|
||||
$group->g_blog_allowdelete = $values['g_blog_allowdelete'];
|
||||
$group->g_blog_allowcomment = $values['g_blog_allowcomment'];
|
||||
}
|
||||
|
||||
$group->g_blog_allowcomment = $values['g_blog_allowcomment'];
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ class _Upgrade
|
||||
|
||||
$file = \IPS\File::create( 'core_Attachment', $entry['entry_image'], NULL, NULL, FALSE, $filePath );
|
||||
$attachment = $file->makeAttachment('');
|
||||
$fileName = htmlentities( $attachment['attach_file'], \IPS\HTMLENTITIES, 'UTF-8', TRUE );
|
||||
$fileName = htmlspecialchars( $attachment['attach_file'], \IPS\HTMLENTITIES, 'UTF-8', TRUE );
|
||||
|
||||
$image = <<<IMAGE
|
||||
<a href="<fileStore.core_Attachment>/{$file}" class="ipsAttachLink ipsAttachLink_image" style="float:left;"><img data-fileid="{$attachment['attach_id']}" src="<fileStore.core_Attachment>/{$file}" class="ipsImage ipsImage_thumbnailed" style="margin:10px;" alt="{$fileName}"></a>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"1": {
|
||||
"method": "dropColumn",
|
||||
"params": [
|
||||
"blog_blogs",
|
||||
"blog_view_level"
|
||||
]
|
||||
},
|
||||
"2": {
|
||||
"method": "changeIndex",
|
||||
"params": [
|
||||
"blog_blogs",
|
||||
"blog_grabber",
|
||||
{
|
||||
"type": "key",
|
||||
"name": "blog_grabber",
|
||||
"length": [
|
||||
null
|
||||
],
|
||||
"columns": [
|
||||
"blog_disabled"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -78,9 +78,9 @@ class _Upgrade
|
||||
}
|
||||
|
||||
/* Set language strings */
|
||||
\IPS\Lang::saveCustom( 'blog', "blogs_blog_{$blog->id}", html_entity_decode( $original['blog_name'], ENT_QUOTES, 'UTF-8' ) );
|
||||
\IPS\Lang::saveCustom( 'blog', "blogs_blog_{$blog->id}", \IPS\Text\Parser::utf8mb4SafeDecode( $original['blog_name'] ) );
|
||||
\IPS\Lang::saveCustom( 'blog', "blogs_blog_{$blog->id}_desc", \IPS\Text\Parser::parseStatic( $original['blog_desc'], TRUE, NULL, NULL, TRUE, TRUE, TRUE ) );
|
||||
\IPS\Lang::saveCustom( 'blog', "blogs_groupblog_name_{$blog->id}", html_entity_decode( $original['blog_groupblog_name'], ENT_QUOTES, 'UTF-8' ) );
|
||||
\IPS\Lang::saveCustom( 'blog', "blogs_groupblog_name_{$blog->id}", \IPS\Text\Parser::utf8mb4SafeDecode( $original['blog_groupblog_name'] ) );
|
||||
|
||||
$blog->save();
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ class _Blog extends \IPS\Node\Model implements \IPS\Node\Ratings, \IPS\Content\E
|
||||
/**
|
||||
* @brief Icon
|
||||
*/
|
||||
public static $icon = 'file-text-o';
|
||||
public static $icon = 'file-text';
|
||||
|
||||
/**
|
||||
* @brief [Node] If the node can be "owned", the owner "type" (typically "member" or "group") and the associated database column
|
||||
@@ -473,19 +473,19 @@ class _Blog extends \IPS\Node\Model implements \IPS\Node\Ratings, \IPS\Content\E
|
||||
}
|
||||
|
||||
/**
|
||||
* Get URL
|
||||
*
|
||||
* @return \IPS\Http\Url
|
||||
* @brief URL Base
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
if( $this->_url === NULL )
|
||||
{
|
||||
$this->_url = \IPS\Http\Url::internal( "app=blog&module=blogs&controller=view&id={$this->_id}", 'front', 'blogs_blog', array( $this->seo_name ) );
|
||||
}
|
||||
|
||||
return $this->_url;
|
||||
}
|
||||
public static $urlBase = 'app=blog&module=blogs&controller=view&id=';
|
||||
|
||||
/**
|
||||
* @brief URL Base
|
||||
*/
|
||||
public static $urlTemplate = 'blogs_blog';
|
||||
|
||||
/**
|
||||
* @brief SEO Title Column
|
||||
*/
|
||||
public static $seoTitleColumn = 'seo_name';
|
||||
|
||||
/**
|
||||
* @brief Cached latest entry
|
||||
@@ -672,7 +672,7 @@ class _Blog extends \IPS\Node\Model implements \IPS\Node\Ratings, \IPS\Content\E
|
||||
*/
|
||||
protected function get__title()
|
||||
{
|
||||
return htmlentities( \IPS\Member::loggedIn()->language()->get( static::$titleLangPrefix . $this->_id ), ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
return htmlspecialchars( \IPS\Member::loggedIn()->language()->get( static::$titleLangPrefix . $this->_id ), ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -70,7 +70,7 @@ class _Feed extends \IPS\Patterns\ActiveRecord
|
||||
|
||||
if ( $article['link'] )
|
||||
{
|
||||
$link = htmlentities( $this->import_show_link, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
$link = htmlspecialchars( $this->import_show_link, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
$entry->content .= "<br><p><a href='{$article['link']}'>{$link}</a></p>";
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ class _Comment extends \IPS\Content\Comment implements \IPS\Content\EditHistory,
|
||||
/**
|
||||
* @brief Icon
|
||||
*/
|
||||
public static $icon = 'file-text-o';
|
||||
public static $icon = 'file-text';
|
||||
|
||||
/**
|
||||
* @brief Reputation Type
|
||||
|
||||
@@ -120,7 +120,7 @@ class _Entry extends \IPS\Content\Item implements
|
||||
/**
|
||||
* @brief Icon
|
||||
*/
|
||||
public static $icon = 'file-text-o';
|
||||
public static $icon = 'file-text';
|
||||
|
||||
/**
|
||||
* @brief The map of permission columns
|
||||
@@ -203,29 +203,21 @@ class _Entry extends \IPS\Content\Item implements
|
||||
* @brief Cached URLs
|
||||
*/
|
||||
protected $_url = array();
|
||||
|
||||
/**
|
||||
* Get URL
|
||||
*
|
||||
* @param string|NULL $action Action
|
||||
* @return \IPS\Http\Url
|
||||
*/
|
||||
public function url( $action=NULL )
|
||||
{
|
||||
$_key = md5( $action );
|
||||
|
||||
if( !isset( $this->_url[ $_key ] ) )
|
||||
{
|
||||
$this->_url[ $_key ] = \IPS\Http\Url::internal( "app=blog&module=blogs&controller=entry&id={$this->id}", 'front', 'blog_entry', $this->name_seo );
|
||||
|
||||
if ( $action )
|
||||
{
|
||||
$this->_url[ $_key ] = $this->_url[ $_key ]->setQueryString( 'do', $action );
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_url[ $_key ];
|
||||
}
|
||||
/**
|
||||
* @brief URL Base
|
||||
*/
|
||||
public static $urlBase = 'app=blog&module=blogs&controller=entry&id=';
|
||||
|
||||
/**
|
||||
* @brief URL Base
|
||||
*/
|
||||
public static $urlTemplate = 'blog_entry';
|
||||
|
||||
/**
|
||||
* @brief SEO Title Column
|
||||
*/
|
||||
public static $seoTitleColumn = 'name_seo';
|
||||
|
||||
/**
|
||||
* Can view this entry
|
||||
@@ -307,13 +299,13 @@ class _Entry extends \IPS\Content\Item implements
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional WHERE clauses for New Content view
|
||||
* Additional WHERE clauses for Follow view
|
||||
*
|
||||
* @param bool $joinContainer If true, will join container data (set to TRUE if your $where clause depends on this data)
|
||||
* @param array $joins Other joins
|
||||
* @return array
|
||||
*/
|
||||
public static function vncWhere( &$joinContainer, &$joins )
|
||||
public static function followWhere( &$joinContainer, &$joins )
|
||||
{
|
||||
$joinContainer = TRUE;
|
||||
if ( \IPS\Member::loggedIn()->member_id )
|
||||
@@ -325,7 +317,7 @@ class _Entry extends \IPS\Content\Item implements
|
||||
$where = array( \IPS\Content::socialGroupGetItemsWithPermissionWhere( 'blog_blogs.blog_social_group', \IPS\Member::loggedIn() ) );
|
||||
}
|
||||
|
||||
return array_merge( parent::vncWhere( $joinContainer, $joins ), $where );
|
||||
return array_merge( parent::followWhere( $joinContainer, $joins ), $where );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief blogCommentFeed Widget
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Social Suite
|
||||
* @subpackage blog
|
||||
* @since 13 Jul 2015
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\blog\widgets;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* blogCommentFeed Widget
|
||||
*/
|
||||
class _blogCommentFeed extends \IPS\Content\WidgetComment
|
||||
{
|
||||
/**
|
||||
* @brief Widget Key
|
||||
*/
|
||||
public $key = 'blogCommentFeed';
|
||||
|
||||
/**
|
||||
* @brief App
|
||||
*/
|
||||
public $app = 'blog';
|
||||
|
||||
/**
|
||||
* @brief Plugin
|
||||
*/
|
||||
public $plugin = '';
|
||||
|
||||
/**
|
||||
* Class
|
||||
*/
|
||||
protected static $class = 'IPS\blog\Entry\Comment';
|
||||
|
||||
/**
|
||||
* Get where clause
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function buildWhere()
|
||||
{
|
||||
$where = parent::buildWhere();
|
||||
$where['item'][] = array( 'entry_status!=?', 'draft' );
|
||||
return $where;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief blogs Widget
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Social Suite
|
||||
* @subpackage blog
|
||||
* @since 13 Jul 2015
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\blog\widgets;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* blogs Widget
|
||||
*/
|
||||
class _blogs extends \IPS\Widget\PermissionCache
|
||||
{
|
||||
/**
|
||||
* @brief Widget Key
|
||||
*/
|
||||
public $key = 'blogs';
|
||||
|
||||
/**
|
||||
* @brief App
|
||||
*/
|
||||
public $app = 'blog';
|
||||
|
||||
/**
|
||||
* @brief Plugin
|
||||
*/
|
||||
public $plugin = '';
|
||||
|
||||
/**
|
||||
* Specify widget configuration
|
||||
*
|
||||
* @param null|\IPS\Helpers\Form $form Form object
|
||||
* @return null|\IPS\Helpers\Form
|
||||
*/
|
||||
public function configuration( &$form=null )
|
||||
{
|
||||
if ( $form === null )
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
}
|
||||
|
||||
/* Block title */
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'widget_feed_title', isset( $this->configuration['widget_feed_title'] ) ? $this->configuration['widget_feed_title'] : \IPS\Member::loggedIn()->language()->addToStack( 'blogs' ) ) );
|
||||
|
||||
/* Author */
|
||||
$author = NULL;
|
||||
try
|
||||
{
|
||||
if ( isset( $this->configuration['widget_feed_author'] ) and is_array( $this->configuration['widget_feed_author'] ) )
|
||||
{
|
||||
foreach( $this->configuration['widget_feed_author'] as $id )
|
||||
{
|
||||
$author[ $id ] = \IPS\Member::load( $id );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( \OutOfRangeException $ex ) { }
|
||||
$form->add( new \IPS\Helpers\Form\Member( 'widget_feed_author', $author, FALSE, array( 'multiple' => true ) ) );
|
||||
|
||||
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'widget_blog_last_date', isset( $this->configuration['widget_blog_last_date'] ) ? $this->configuration['widget_blog_last_date'] : '0', FALSE, array(
|
||||
'options' => array(
|
||||
0 => 'show_all',
|
||||
1 => 'today',
|
||||
5 => 'last_5_days',
|
||||
7 => 'last_7_days',
|
||||
10 => 'last_10_days',
|
||||
15 => 'last_15_days',
|
||||
20 => 'last_20_days',
|
||||
25 => 'last_25_days',
|
||||
30 => 'last_30_days',
|
||||
60 => 'last_60_days',
|
||||
90 => 'last_90_days',
|
||||
)
|
||||
) ) );
|
||||
|
||||
|
||||
/* Number to show */
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'widget_feed_show', isset( $this->configuration['widget_feed_show'] ) ? $this->configuration['widget_feed_show'] : 5, TRUE ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'widget_feed_sort_on', isset( $this->configuration['widget_feed_sort_on'] ) ? $this->configuration['widget_feed_sort_on'] : 'blog_edate', FALSE, array( 'options' => array(
|
||||
'blog_edate' => 'widget__blog_edate',
|
||||
'blog_entries' => 'widget__blog_count_entries',
|
||||
'blog_comments' => 'widget__blog_count_comments'
|
||||
) ) ), NULL, NULL, NULL, 'widget_feed_sort_on' );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'widget_feed_sort_dir', isset( $this->configuration['widget_feed_sort_dir'] ) ? $this->configuration['widget_feed_sort_dir'] : 'desc', FALSE, array(
|
||||
'options' => array(
|
||||
'desc' => 'descending',
|
||||
'asc' => 'ascending'
|
||||
)
|
||||
) ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a widget
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$where = array( array( 'blog_disabled=0 AND blog_social_group IS NULL' ) );
|
||||
$sortBy = ( isset( $this->configuration['widget_feed_sort_on'] ) and isset( $this->configuration['widget_feed_sort_dir'] ) ) ? ( $this->configuration['widget_feed_sort_on'] . ' ' . $this->configuration['widget_feed_sort_dir'] ) : NULL;
|
||||
$limit = isset( $this->configuration['widget_feed_show'] ) ? $this->configuration['widget_feed_show'] : 5;
|
||||
|
||||
if ( isset( $this->configuration['widget_feed_author'] ) and is_array( $this->configuration['widget_feed_author'] ) )
|
||||
{
|
||||
$where[] = array( \IPS\Db::i()->in( 'blog_member_id', $this->configuration['widget_feed_author'] ) );
|
||||
}
|
||||
|
||||
/* Get results */
|
||||
$blogs = array();
|
||||
|
||||
foreach( \IPS\Db::i()->select( '*', 'blog_blogs', $where, $sortBy, array( 0, $limit ) ) as $row )
|
||||
{
|
||||
$blog = \IPS\blog\Blog::constructFromData( $row );
|
||||
$blog->coverPhoto()->editable = false;
|
||||
$blogs[] = $blog;
|
||||
}
|
||||
|
||||
if ( count( $blogs ) )
|
||||
{
|
||||
return $this->output( $blogs, isset( $this->configuration['widget_feed_title'] ) ? $this->configuration['widget_feed_title'] : \IPS\Member::loggedIn()->language()->addToStack( 'blogs' ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<emails><template><template_app>calendar</template_app><template_name>digests__item</template_name><template_content_html><![CDATA[<tr style='border-bottom: 1px solid #eeeeee'>
|
||||
<td width='120' valign='top' align='center'>
|
||||
<td dir='{dir}' width='120' valign='top' align='center'>
|
||||
<table width='120' cellpadding='10' cellspacing='0' border='0' bgcolor='#fafafa'>
|
||||
<tr>
|
||||
<td>
|
||||
<td dir='{dir}'>
|
||||
<table width='100' cellpadding='0' cellspacing='0' border='0' bgcolor='#ffffff' style='border: 1px solid #cccccc;'>
|
||||
<tr>
|
||||
<td align='center' style="color: #a93848; font-size: 18px; line-height: 30px; text-transform: uppercase; font-family: 'Helvetica Neue', helvetica, sans-serif; font-weight: bold; padding-top: 5px;">
|
||||
<td dir='{dir}' align='center' style="color: #a93848; font-size: 18px; line-height: 30px; text-transform: uppercase; font-family: 'Helvetica Neue', helvetica, sans-serif; font-weight: bold; padding-top: 5px;">
|
||||
{$event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )->monthNameShort}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align='center' style="color: #333333; line-height: 40px; font-size: 44px; font-family: 'Helvetica Neue', helvetica, sans-serif; font-weight: 300; padding-bottom: 10px">
|
||||
<td dir='{dir}' align='center' style="color: #333333; line-height: 40px; font-size: 44px; font-family: 'Helvetica Neue', helvetica, sans-serif; font-weight: 300; padding-bottom: 10px">
|
||||
{$event->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )->mday}
|
||||
</td>
|
||||
</tr>
|
||||
@@ -20,7 +20,7 @@
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td align='left'>
|
||||
<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_event_in", FALSE, array( 'sprintf' => array( $event->author()->name, $event->container()->_title ) ) )}
|
||||
</p>
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
{{if $event->rsvp}}
|
||||
<div style="font-size: 13px; font-family: 'Helvetica Neue', helvetica, sans-serif; margin-top: 10px">
|
||||
{{if $attendees = $row->attendees()}}{{endif}}
|
||||
{{if $attendees = $event->attendees()}}{{endif}}
|
||||
<strong style="text-transform: uppercase; font-size: 12px; font-family: 'Helvetica Neue', helvetica, sans-serif;">{$email->language->addToStack("digest_users_going", FALSE, array( 'pluralize' => array( count( $attendees[1] ) ) ) )}</strong>
|
||||
{{if count( $attendees[1] )}}
|
||||
{{foreach $attendees[1] as $idx => $attendee}}
|
||||
@@ -74,18 +74,18 @@
|
||||
</td>
|
||||
</tr>]]></template_content_html><template_data>$event, $email</template_data><template_content_plaintext><![CDATA[{$email->language->addToStack("x_created_event_in", FALSE, array( 'sprintf' => array( $event->author()->name, $event->container()->_title ) ) )}: {$event->title} ({$event->url()})
|
||||
]]></template_content_plaintext></template><template><template_app>calendar</template_app><template_name>digests__comment</template_name><template_content_html><![CDATA[<tr style='border-bottom: 1px solid #eeeeee'>
|
||||
<td width='120' valign='top' align='center'>
|
||||
<td dir='{dir}' width='120' valign='top' align='center'>
|
||||
<table width='120' cellpadding='10' cellspacing='0' border='0' bgcolor='#fafafa'>
|
||||
<tr>
|
||||
<td>
|
||||
<td dir='{dir}'>
|
||||
<table width='100' cellpadding='0' cellspacing='0' border='0' bgcolor='#ffffff' style='border: 1px solid #cccccc;'>
|
||||
<tr>
|
||||
<td align='center' style="color: #a93848; font-size: 18px; line-height: 30px; text-transform: uppercase; font-family: 'Helvetica Neue', helvetica, sans-serif; font-weight: bold; padding-top: 5px;">
|
||||
<td dir='{dir}' align='center' style="color: #a93848; font-size: 18px; line-height: 30px; text-transform: uppercase; font-family: 'Helvetica Neue', helvetica, sans-serif; font-weight: bold; padding-top: 5px;">
|
||||
{$comment->item()->nextOccurrence( $today, 'startDate' )->monthNameShort}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align='center' style="color: #333333; line-height: 40px; font-size: 44px; font-family: 'Helvetica Neue', helvetica, sans-serif; font-weight: 300; padding-bottom: 10px">
|
||||
<td dir='{dir}' align='center' style="color: #333333; line-height: 40px; font-size: 44px; font-family: 'Helvetica Neue', helvetica, sans-serif; font-weight: 300; padding-bottom: 10px">
|
||||
{$comment->item()->nextOccurrence( $today, 'startDate' )->mday}
|
||||
</td>
|
||||
</tr>
|
||||
@@ -94,7 +94,7 @@
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td align='left'>
|
||||
<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_commented_event", FALSE, array( 'sprintf' => array( $comment->author()->name ) ) )}
|
||||
</p>
|
||||
@@ -102,7 +102,7 @@
|
||||
<a href='{$comment->item()->url()}' style='text-decoration: none;'>{$comment->item()->name}</a>
|
||||
</h2>
|
||||
<p style='font-family: "Helvetica Neue", helvetica, sans-serif; margin: 0; color: #8c8c8c; font-size: 13px;'>
|
||||
{$email->language->addToStack("email_event_on", FALSE)} {$comment->item()->_start_date->dayName} {$comment->item()->_start_date->mday} {$comment->item()->_start_date->monthName} {$comment->item()->_start_date->year}{{if !$comment->item()->all_day}}, {$comment->item()->_start_date->localeTime( FALSE )}{{endif}}
|
||||
{$email->language->addToStack("digest_event_on", FALSE)} {$comment->item()->_start_date->dayName} {$comment->item()->_start_date->mday} {$comment->item()->_start_date->monthName} {$comment->item()->_start_date->year}{{if !$comment->item()->all_day}}, {$comment->item()->_start_date->localeTime( FALSE )}{{endif}}
|
||||
{{if $comment->item()->_end_date}}
|
||||
»
|
||||
{$comment->item()->_end_date->dayName} {$comment->item()->_end_date->mday} {$comment->item()->_end_date->monthName} {$comment->item()->_end_date->year}{{if !$comment->item()->all_day}}, {$comment->item()->_end_date->localeTime( FALSE )}{{endif}}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<javascript app="calendar">
|
||||
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.main.js" javascript_type="controller" javascript_version="100045" javascript_position="1000050"><![CDATA[/**
|
||||
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.main.js" javascript_type="controller" javascript_version="101012" javascript_position="1000050"><![CDATA[/**
|
||||
* IPS Social Suite 4
|
||||
* (c) 2013 Invision Power Services - http://www.invisionpower.com
|
||||
*
|
||||
@@ -109,7 +109,7 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));]]></file>
|
||||
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.monthView.js" javascript_type="controller" javascript_version="100045" javascript_position="1000050"><![CDATA[/**
|
||||
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/browse" javascript_name="ips.browse.monthView.js" javascript_type="controller" javascript_version="101012" javascript_position="1000050"><![CDATA[/**
|
||||
* IPS Social Suite 4
|
||||
* (c) 2013 Invision Power Services - http://www.invisionpower.com
|
||||
*
|
||||
@@ -251,7 +251,7 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));]]></file>
|
||||
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.dates.js" javascript_type="controller" javascript_version="100045" javascript_position="1000100"><![CDATA[/**
|
||||
<file javascript_app="calendar" javascript_location="front" javascript_path="controllers/submit" javascript_name="ips.submit.dates.js" javascript_type="controller" javascript_version="101012" javascript_position="1000100"><![CDATA[/**
|
||||
* IPS Social Suite 4
|
||||
* (c) 2013 Invision Power Services - http://www.invisionpower.com
|
||||
*
|
||||
@@ -451,10 +451,17 @@
|
||||
*/
|
||||
_getDate: function(input) {
|
||||
/* jQuery UI Polyfill needs to be changed into the correct format */
|
||||
if ( input.hasClass('hasDatepicker') ) {
|
||||
if( !ips.utils.time.supportsHTMLDate() ) {
|
||||
/* If it has been initiated, we can use the getDate method */
|
||||
try {
|
||||
return input.datepicker( "getDate" );
|
||||
var thisDate = input.datepicker( "getDate" );
|
||||
|
||||
if( _.isNull( thisDate ) )
|
||||
{
|
||||
thisDate = new Date( input.attr('value') );
|
||||
}
|
||||
|
||||
return thisDate;
|
||||
}
|
||||
/* If it hasn't we can pull the 'value' attribute which can't have been changed yet. Not .val() as that will be in the wrong format */
|
||||
catch(err) {
|
||||
@@ -484,7 +491,7 @@
|
||||
}
|
||||
|
||||
// We need to add the offset to ensure the day stays correct
|
||||
if ( this.scope.find( 'input[name="event_dates[start_date]"]' ).hasClass('hasDatepicker') ) {
|
||||
if( !ips.utils.time.supportsHTMLDate() ){
|
||||
startDate.setTime( startDate.getTime() - new Date().getTimezoneOffset()*60000 );
|
||||
}
|
||||
|
||||
@@ -497,8 +504,7 @@
|
||||
|
||||
// If we have a valid end date...
|
||||
if( !singleDay.is(':checked') && ips.utils.time.isValidDateObj( endDate ) ){
|
||||
if ( this.scope.find('input[name="event_dates[end_date]"]' ).hasClass( 'hasDatepicker' ) )
|
||||
{
|
||||
if( !ips.utils.time.supportsHTMLDate() ){
|
||||
endDate.setTime( endDate.getTime() - new Date().getTimezoneOffset()*60000 );
|
||||
}
|
||||
endDateString = ips.utils.time.localeDateString( endDate, { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric', timeZone: 'UTC' } );
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<language>
|
||||
<app key="calendar" version="100045">
|
||||
<app key="calendar" version="101012">
|
||||
<word key="__app_calendar" js="0">Calendar</word>
|
||||
<word key="frontnavigation_calendar" js="0">Calendar</word>
|
||||
<word key="__indefart_calendar_event_comment" js="0">a comment on a calendar event</word>
|
||||
<word key="__indefart_calendar_event" js="0">a calendar event</word>
|
||||
<word key="__indefart_calendar_event_review" js="0">a review on a calendar event</word>
|
||||
<word key="calendar_event_container" js="0">calendar</word>
|
||||
<word key="menu__calendar_calendars" js="0">Calendar</word>
|
||||
<word key="menu__calendar_calendars_calendars" js="0">Calendars</word>
|
||||
<word key="menu__calendar_calendars_ical" js="0">iCalendar Feeds</word>
|
||||
@@ -322,6 +323,7 @@
|
||||
<word key="no_recent_reviews" js="0">No recent reviews found</word>
|
||||
<word key="announce_calendars" js="0">Calendars</word>
|
||||
<word key="review_count" js="0">Number of reviews to show</word>
|
||||
<word key="widget_calendar" js="0">Calendar</word>
|
||||
<word key="embed_calendar_event" js="0">Calendar Event</word>
|
||||
<word key="x_users_going" js="0">{# [1:user][?:users]} going</word>
|
||||
<word key="timezone_offset_short" js="0">GMT %s</word>
|
||||
@@ -366,6 +368,7 @@
|
||||
<word key="timezone_offset_14" js="0">[GMT + 14] Line Island Time</word>
|
||||
<word key="task__icalendar" js="0">Checks iCalendar feeds for new events and imports into IP.Calendar.</word>
|
||||
<word key="digest_area_calendar" js="0">Events</word>
|
||||
<word key="digest_area_event" js="0">Event</word>
|
||||
<word key="x_created_event_in" js="0">%s posted an event in %s</word>
|
||||
<word key="x_commented_event" js="0">%s commented on an event</word>
|
||||
<word key="digest_event_on" js="0">Event on</word>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
},
|
||||
{
|
||||
"key": "ipb_calendar_mon",
|
||||
"default": "1"
|
||||
"default": "0"
|
||||
},
|
||||
{
|
||||
"key": "show_bday_calendar",
|
||||
|
||||
@@ -133,8 +133,8 @@
|
||||
</div>
|
||||
{{endif}}
|
||||
<span class="ipsType_pageTitle">
|
||||
<a href='#elCalendars_menu' id='elCalendars' data-ipsMenu data-ipsMenu-appendTo="#elCalendarsHeader">{{if $thisCalendar}}{$thisCalendar->_title}{{else}}{lang="all_calendars"}{{endif}} <i class='fa fa-caret-down'></i></a>
|
||||
<a href='#elCalendarSettings_menu' id='elCalendarSettings' data-ipsMenu data-ipsMenu-alignCenter data-ipsMenu-appendTo="#elCalendarsHeader"><i class='fa fa-cog'></i></a>
|
||||
<a href='#elCalendars_menu' id='elCalendars' data-ipsMenu data-ipsMenu-appendTo="#elCalendarsHeader" class='ipsType_blendLinks'>{{if $thisCalendar}}{$thisCalendar->_title}{{else}}{lang="all_calendars"}{{endif}} <i class='fa fa-caret-down'></i></a>
|
||||
<a href='#elCalendarSettings_menu' id='elCalendarSettings' data-ipsMenu data-ipsMenu-alignCenter data-ipsMenu-appendTo="#elCalendarsHeader" class='ipsType_blendLinks'><i class='fa fa-cog'></i></a>
|
||||
{{if ( $thisCalendar AND $thisCalendar->can('add') ) OR ( !$thisCalendar AND \IPS\calendar\Calendar::canOnAny('add') )}}
|
||||
|
||||
{{if $thisCalendar}}
|
||||
@@ -417,7 +417,7 @@
|
||||
{{foreach $collection as $input}}
|
||||
{{if $input instanceof \IPS\Helpers\Form\Date}}
|
||||
<li class='ipsFieldRow ipsFieldRow_fullWidth'>
|
||||
<input type="date" data-control="date" placeholder="{lang="jump_to_placeholder"}" name='{$input->name}' id='{$input->htmlId}' {{if $input->required === TRUE}}required aria-required='true'{{endif}} value="{{if $input->defaultValue instanceof \IPS\DateTime}}{$input->defaultValue->format('Y-m-d')}{{endif}}">
|
||||
<input type="date" data-control="date" placeholder="{lang="jump_to_placeholder"}" name='{$input->name}' id='{$input->htmlId}' {{if $input->required === TRUE}}required{{endif}} value="{{if $input->defaultValue instanceof \IPS\DateTime}}{$input->defaultValue->format('Y-m-d')}{{endif}}">
|
||||
</li>
|
||||
{{else}}
|
||||
{$input->rowHtml($form)|raw}
|
||||
@@ -501,6 +501,97 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>]]></template>
|
||||
<template template_group="global" template_name="manageFollowRow" template_data="$table, $headers, $rows, $includeFirstCommentInCommentCount=TRUE" template_location="front" template_app="calendar"><![CDATA[{{if count( $rows )}}
|
||||
{{foreach $rows as $row}}
|
||||
{{$idField = $row::$databaseColumnId;}}
|
||||
<li class="ipsDataItem ipsDataItem_responsivePhoto {{if $row->unread()}}ipsDataItem_unread{{endif}} {{if method_exists( $row, 'tableClass' ) && $row->tableClass()}}ipsDataItem_{$row->tableClass()}{{endif}} {{if $row->hidden()}}ipsModerated{{endif}}" data-controller='core.front.system.manageFollowed' data-followID='{$row->_followData['follow_area']}-{$row->_followData['follow_rel_id']}'>
|
||||
<div class='ipsDataItem_generic ipsDataItem_size2'>
|
||||
{{if $row->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )}}
|
||||
<time datetime='{$row->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )->mysqlDatetime()}' class='ipsCalendarDate ipsCalendarDate_large'>
|
||||
<span class='ipsCalendarDate_month'>{$row->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )->monthNameShort}</span>
|
||||
<span class='ipsCalendarDate_date'>{$row->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' )->mday}</span>
|
||||
</time>
|
||||
{{else}}
|
||||
<time datetime='{$row->lastOccurrence( 'startDate' )->mysqlDatetime()}' class='ipsCalendarDate ipsCalendarDate_large'>
|
||||
<span class='ipsCalendarDate_month'>{$row->lastOccurrence( 'startDate' )->monthNameShort}</span>
|
||||
<span class='ipsCalendarDate_date'>{$row->lastOccurrence( 'startDate' )->mday}</span>
|
||||
</time>
|
||||
{{endif}}
|
||||
</div>
|
||||
<div class='ipsDataItem_main ipsPos_middle'>
|
||||
<h4 class='ipsDataItem_title ipsType_break ipsType_normal'>
|
||||
{{if $row->mapped('locked')}}
|
||||
<i class="fa fa-lock"></i>
|
||||
{{endif}}
|
||||
|
||||
{{if $row->mapped('pinned') || $row->mapped('featured') || $row->hidden() === -1 || $row->hidden() === 1}}
|
||||
<span>
|
||||
{{if $row->hidden() === -1}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_small ipsBadge_warning" data-ipsTooltip title='{$row->hiddenBlurb()}'><i class='fa fa-eye-slash'></i></span>
|
||||
{{elseif $row->hidden() === 1}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_small ipsBadge_warning" data-ipsTooltip title='{lang="pending_approval"}'><i class='fa fa-warning'></i></span>
|
||||
{{endif}}
|
||||
{{if $row->mapped('pinned')}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_small ipsBadge_positive" data-ipsTooltip title='{lang="pinned"}'><i class='fa fa-thumb-tack'></i></span>
|
||||
{{endif}}
|
||||
{{if $row->mapped('featured')}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_small ipsBadge_positive" data-ipsTooltip title='{lang="featured"}'><i class='fa fa-star'></i></span>
|
||||
{{endif}}
|
||||
</span>
|
||||
{{endif}}
|
||||
|
||||
{{if $row->prefix()}}
|
||||
{template="prefix" group="global" app="core" params="$row->prefix( TRUE ), $row->prefix()"}
|
||||
{{endif}}
|
||||
|
||||
<a href='{$row->url()}'>
|
||||
{{if $row->mapped('title')}}{wordbreak="$row->mapped('title')"}{{else}}<em class="ipsType_light">{lang="content_deleted"}</em>{{endif}}
|
||||
</a>
|
||||
</h4>
|
||||
<div class='ipsDataItem_meta ipsType_light ipsType_blendLinks' data-ipsTruncate data-ipsTruncate-size='2 lines' data-ipsTruncate-type='remove'>
|
||||
{{if method_exists( $row, 'tableDescription' )}}
|
||||
{$row->tableDescription()|raw}
|
||||
{{else}}
|
||||
{lang="byline" htmlsprintf="$row->author()->link( $row->warningRef() )"}{datetime="$row->__get( $row::$databaseColumnMap['date'] )"}
|
||||
{lang="in"} <a href="{$row->container()->url()}">{$row->container()->_title}</a>
|
||||
{{endif}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='ipsDataItem_generic ipsDataItem_size1 ipsType_center ipsType_large'>
|
||||
<span class='ipsBadge ipsBadge_icon ipsBadge_new {{if !$row->_followData['follow_is_anon']}}ipsHide{{endif}}' data-role='followAnonymous' data-ipsTooltip title='{lang="follow_is_anon"}'><i class='fa fa-eye-slash'></i></span>
|
||||
</div>
|
||||
|
||||
<div class='ipsDataItem_generic ipsDataItem_size6'>
|
||||
<ul class='ipsList_reset'>
|
||||
<li title='{lang="follow_when"}' data-role='followDate'><i class='fa fa-clock-o'></i> {datetime="$row->_followData['follow_added']"}</li>
|
||||
<li title='{lang="follow_how"}' data-role='followFrequency'>
|
||||
{{if $row->_followData['follow_notify_freq'] == 'none'}}
|
||||
<i class='fa fa-bell-slash-o'></i>
|
||||
{{else}}
|
||||
<i class='fa fa-bell'></i>
|
||||
{{endif}} {lang="follow_freq_{$row->_followData['follow_notify_freq']}"}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class='ipsDataItem_generic ipsDataItem_size6 ipsType_center'>
|
||||
{template="manageFollow" group="system" app="core" params="$row->_followData['follow_app'], $row->_followData['follow_area'], $row->_followData['follow_rel_id']"}
|
||||
</div>
|
||||
|
||||
{{if $table->canModerate()}}
|
||||
<div class='ipsDataItem_modCheck'>
|
||||
<span class='ipsCustomInput'>
|
||||
<input type='checkbox' data-role='moderation' name="moderate[{$row->$idField}]" data-actions="{expression="implode( ' ', $table->multimodActions( $row ) )"}" data-state='{{if $row->tableStates()}}{$row->tableStates()}{{endif}}'>
|
||||
<span></span>
|
||||
</span>
|
||||
</div>
|
||||
{{endif}}
|
||||
|
||||
</li>
|
||||
{{endforeach}}
|
||||
{{endif}}
|
||||
]]></template>
|
||||
<template template_group="global" template_name="rows" template_data="$table, $headers, $rows" template_location="front" template_app="calendar"><![CDATA[{{if count( $rows )}}
|
||||
{{foreach $rows as $row}}
|
||||
<li class="ipsDataItem {{if method_exists( $row, 'tableClass' ) && $row->tableClass()}}ipsDataItem_{$row->tableClass()}{{endif}} {{if $row->hidden()}}ipsModerated{{endif}}">
|
||||
@@ -523,14 +614,6 @@
|
||||
<i class="fa fa-lock"></i>
|
||||
{{endif}}
|
||||
|
||||
{{if $row->prefix()}}
|
||||
{template="prefix" group="global" app="core" params="$row->prefix( TRUE ), $row->prefix()"}
|
||||
{{endif}}
|
||||
|
||||
<a href='{$row->url()}' class='ipsType_break' {{if $row->tableHoverUrl}}data-ipsHover{{endif}}>
|
||||
{{if $row->mapped('title')}}{wordbreak="$row->mapped('title')"}{{else}}<em class="ipsType_light">{lang="content_deleted"}</em>{{endif}}
|
||||
</a>
|
||||
|
||||
{{if $row->mapped('pinned') || $row->mapped('featured') || $row->hidden() === -1 || $row->hidden() === 1}}
|
||||
{{if $row->hidden() === -1}}
|
||||
<span class="ipsBadge ipsBadge_small ipsBadge_icon ipsBadge_warning" data-ipsTooltip title='{$row->hiddenBlurb()}'><i class='fa fa-eye-slash'></i></span>
|
||||
@@ -544,6 +627,14 @@
|
||||
<span class="ipsBadge ipsBadge_small ipsBadge_icon ipsBadge_positive" data-ipsTooltip title='{lang="featured"}'><i class='fa fa-star'></i></span>
|
||||
{{endif}}
|
||||
{{endif}}
|
||||
|
||||
{{if $row->prefix()}}
|
||||
{template="prefix" group="global" app="core" params="$row->prefix( TRUE ), $row->prefix()"}
|
||||
{{endif}}
|
||||
|
||||
<a href='{$row->url()}' class='ipsType_break' {{if $row->tableHoverUrl}}data-ipsHover{{endif}}>
|
||||
{{if $row->mapped('title')}}{wordbreak="$row->mapped('title')"}{{else}}<em class="ipsType_light">{lang="content_deleted"}</em>{{endif}}
|
||||
</a>
|
||||
</h4>
|
||||
<div class='ipsDataItem_meta ipsType_light ipsType_blendLinks'>
|
||||
{$row->eventBlurb()|raw}
|
||||
@@ -613,76 +704,89 @@
|
||||
{{if $table->canModerate()}}
|
||||
<div class='ipsDataItem_modCheck'>
|
||||
{{$idField = $row::$databaseColumnId;}}
|
||||
<input type='checkbox' data-role='moderation' name="moderate[{$row->$idField}]" data-actions="{expression="implode( ' ', $table->multimodActions( $row ) )"}" data-state='{{if $row->tableStates()}}{$row->tableStates()}{{endif}}'>
|
||||
<span class='ipsCustomInput'>
|
||||
<input type='checkbox' data-role='moderation' name="moderate[{$row->$idField}]" data-actions="{expression="implode( ' ', $table->multimodActions( $row ) )"}" data-state='{{if $row->tableStates()}}{$row->tableStates()}{{endif}}'>
|
||||
<span></span>
|
||||
</span>
|
||||
</div>
|
||||
{{endif}}
|
||||
</li>
|
||||
{{endforeach}}
|
||||
{{endif}}]]></template>
|
||||
<template template_group="global" template_name="snippet" template_data="$activity, $type='activity'" template_location="front" template_app="calendar"><![CDATA[
|
||||
{{if $activity instanceof \IPS\calendar\Event\Comment or $activity instanceof \IPS\calendar\Event\Review}}
|
||||
{{$item = $activity->item();}}
|
||||
<template template_group="global" template_name="searchResultCommentSnippet" template_data="$indexData, $nextOccurance, $startDate, $endDate, $allDay, $reviewRating, $condensed" template_location="front" template_app="calendar"><![CDATA[{{if $condensed}}
|
||||
<time datetime='{$nextOccurance->mysqlDatetime()}' class='ipsCalendarDate ipsCalendarDate_small ipsPos_left'>
|
||||
<span class='ipsCalendarDate_month'>{$nextOccurance->monthNameShort}</span>
|
||||
<span class='ipsCalendarDate_date'>{$nextOccurance->mday}</span>
|
||||
</time>
|
||||
{{else}}
|
||||
{{$item = $activity;}}
|
||||
{{endif}}
|
||||
<div class='cSearchActivity_info ipsContained'>
|
||||
<div class='ipsColumns'>
|
||||
<div class='ipsColumn ipsColumn_veryNarrow'>
|
||||
{{$date = ( $item->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' ) == NULL ) ? $item->lastOccurrence() : $item->nextOccurrence( \IPS\calendar\Date::getDate(), 'startDate' );}}
|
||||
<time datetime='{$date->mysqlDatetime()}' class='ipsCalendarDate'>
|
||||
<span class='ipsCalendarDate_month'>{$date->monthNameShort}</span>
|
||||
<span class='ipsCalendarDate_date'>{$date->mday}</span>
|
||||
<div class='ipsColumns ipsColumns_collapsePhone ipsColumns_noSpacing'>
|
||||
<div class='ipsColumn ipsColumn_narrow'>
|
||||
<time datetime='{$nextOccurance->mysqlDatetime()}' class='ipsCalendarDate ipsCalendarDate_large ipsPos_center'>
|
||||
<span class='ipsCalendarDate_month'>{$nextOccurance->monthNameShort}</span>
|
||||
<span class='ipsCalendarDate_date'>{$nextOccurance->mday}</span>
|
||||
</time>
|
||||
</div>
|
||||
<div class='ipsColumn ipsColumn_fluid'>
|
||||
{{if $activity instanceof \IPS\calendar\Event\Comment or $activity instanceof \IPS\calendar\Event\Review}}
|
||||
{{if $activity instanceof \IPS\calendar\Event\Review}}
|
||||
{template="rating" group="global" location="front" app="core" params="'large', $activity->mapped('rating'), \IPS\Settings::i()->reviews_rating_out_of"}
|
||||
{{endif}}
|
||||
<div class='ipsType_medium ipsType_richText ipsContained {{if $activity instanceof \IPS\calendar\Event\Review}}ipsSpacer_both{{else}}ipsSpacer_bottom{{endif}} ipsSpacer_half' data-ipsTruncate data-ipsTruncate-size='3 lines' data-ipsTruncate-type='remove'>
|
||||
{$activity->truncated()|raw}
|
||||
</div>
|
||||
<ul class='ipsList_inline ipsType_light'>
|
||||
{{if $activity instanceof \IPS\calendar\Event\Review}}
|
||||
<li>{lang="x_members_found_helpful" sprintf="$activity->mapped('votes_helpful'), \IPS\Member::loggedIn()->language()->pluralize( \IPS\Member::loggedIn()->language()->get( 'x_members' ), array( $activity->mapped('votes_total') ) )"}</li>
|
||||
{{endif}}
|
||||
{{if $type != 'search' and $activity instanceof \IPS\Content\Reputation and settings.reputation_enabled}}
|
||||
<li>{template="reputationMini" group="global" app="core" params="$activity, '', NULL, TRUE"}</li>
|
||||
{{endif}}
|
||||
</ul>
|
||||
{{else}}
|
||||
{{if $type != 'search'}}<a href='{$activity->url()}' class='ipsType_normal ipsType_break'>{$activity->mapped('title')}</a>{{endif}}
|
||||
<p class='ipsType_reset ipsType_small'>
|
||||
<strong>
|
||||
<time itemprop='startDate' content='{expression="$item->_start_date->format( 'Y-m-d' )"}'>
|
||||
{$item->_start_date->dayName} {$item->_start_date->mday} {$item->_start_date->monthName} {$item->_start_date->year}{{if !$item->all_day}}, {$item->_start_date->localeTime( FALSE )}{{endif}}
|
||||
<div class='ipsStream_comment ipsPad'>
|
||||
<p class='ipsType_reset ipsType_normal'>
|
||||
<strong class='ipsType_normal'>
|
||||
<time itemprop='startDate' content='{expression="$startDate->format( 'Y-m-d' )"}'>
|
||||
{$startDate->dayName} {$startDate->mday} {$startDate->monthName} {$startDate->year}{{if !$allDay}}, {$startDate->localeTime( FALSE )}{{endif}}
|
||||
</time>
|
||||
{{if $item->_end_date}}
|
||||
<em class='ipsType_light'>{lang="until"}</em>
|
||||
<time itemprop='startDate' content='{expression="$item->_end_date->format( 'Y-m-d' )"}'>
|
||||
{$item->_end_date->dayName} {$item->_end_date->mday} {$item->_end_date->monthName} {$item->_end_date->year}{{if !$item->all_day}}, {$item->_end_date->localeTime( FALSE )}{{endif}}
|
||||
{{if $endDate}}
|
||||
{lang="until_lc"}
|
||||
<time itemprop='endDate' content='{expression="$endDate->format( 'Y-m-d' )"}'>
|
||||
{$endDate->dayName} {$endDate->mday} {$endDate->monthName} {$endDate->year}{{if !$allDay}}, {$endDate->localeTime( FALSE )}{{endif}}
|
||||
</time>
|
||||
{{endif}}
|
||||
</strong>
|
||||
</p>
|
||||
<div class='ipsType_medium ipsType_richText ipsContained ipsSpacer_both ipsSpacer_half' data-ipsTruncate data-ipsTruncate-size='3 lines' data-ipsTruncate-type='remove'>
|
||||
{$activity->truncated()|raw}
|
||||
{{if $reviewRating !== NULL}}
|
||||
{template="rating" app="core" params="'medium', $reviewRating" group="global"}
|
||||
{{endif}}
|
||||
{{if trim( $indexData['index_content'] ) !== ''}}
|
||||
<div class='ipsType_richText ipsType_break ipsType_medium ipsSpacer_top ipsSpacer_half' {{if !( \IPS\Dispatcher::i()->application->directory == 'core' and \IPS\Dispatcher::i()->module and \IPS\Dispatcher::i()->module->key == 'search' )}}data-ipsTruncate data-ipsTruncate-type='remove' data-ipsTruncate-size='3 lines'{{else}}data-searchable data-findTerm{{endif}}>
|
||||
{$indexData['index_content']|raw}
|
||||
</div>
|
||||
{{endif}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{endif}}]]></template>
|
||||
<template template_group="global" template_name="searchResultEventSnippet" template_data="$indexData, $itemData, $nextOccurance, $startDate, $endDate, $allDay, $condensed" template_location="front" template_app="calendar"><![CDATA[{{if $condensed}}
|
||||
<time datetime='{$nextOccurance->mysqlDatetime()}' class='ipsCalendarDate ipsCalendarDate_small ipsPos_left'>
|
||||
<span class='ipsCalendarDate_month'>{$nextOccurance->monthNameShort}</span>
|
||||
<span class='ipsCalendarDate_date'>{$nextOccurance->mday}</span>
|
||||
</time>
|
||||
{{else}}
|
||||
<div class='ipsColumns ipsColumns_collapsePhone'>
|
||||
<div class='ipsColumn ipsColumn_narrow'>
|
||||
<time datetime='{$nextOccurance->mysqlDatetime()}' class='ipsCalendarDate ipsCalendarDate_large ipsPos_center'>
|
||||
<span class='ipsCalendarDate_month'>{$nextOccurance->monthNameShort}</span>
|
||||
<span class='ipsCalendarDate_date'>{$nextOccurance->mday}</span>
|
||||
</time>
|
||||
</div>
|
||||
<div class='ipsColumn ipsColumn_fluid ipsStream_snippetInfo'>
|
||||
<strong class='ipsType_normal'>
|
||||
<time itemprop='startDate' content='{expression="$startDate->format( 'Y-m-d' )"}'>
|
||||
{$startDate->dayName} {$startDate->mday} {$startDate->monthName} {$startDate->year}{{if !$allDay}}, {$startDate->localeTime( FALSE )}{{endif}}
|
||||
</time>
|
||||
{{if $endDate}}
|
||||
{lang="until_lc"}
|
||||
<time itemprop='endDate' content='{expression="$endDate->format( 'Y-m-d' )"}'>
|
||||
{$endDate->dayName} {$endDate->mday} {$endDate->monthName} {$endDate->year}{{if !$allDay}}, {$endDate->localeTime( FALSE )}{{endif}}
|
||||
</time>
|
||||
{{endif}}
|
||||
</strong>
|
||||
|
||||
{{if trim( $indexData['index_content'] ) !== ''}}
|
||||
<div class='ipsSpacer_top ipsSpacer_half ipsType_richText ipsType_break ipsType_medium' {{if !( \IPS\Dispatcher::i()->application->directory == 'core' and \IPS\Dispatcher::i()->module and \IPS\Dispatcher::i()->module->key == 'search' )}}data-ipsTruncate data-ipsTruncate-type='remove' data-ipsTruncate-size='2 lines'{{else}}data-searchable data-findTerm{{endif}}>
|
||||
{$indexData['index_content']|raw}
|
||||
</div>
|
||||
<ul class='ipsList_inline ipsType_light'>
|
||||
{{if $item->container()->allow_comments}}
|
||||
<li>{lang="num_comments" pluralize="$activity->comments"}</li>
|
||||
{{endif}}
|
||||
{{if $item->container()->allow_reviews}}
|
||||
<li>{lang="num_reviews" pluralize="$activity->reviews"} {{if $activity->reviews > 0}} {template="rating" group="global" location="front" app="core" params="'tiny', $item->rating, \IPS\Settings::i()->reviews_rating_out_of"}{{endif}}</li>
|
||||
{{endif}}
|
||||
{{if $type != 'search' and $item instanceof \IPS\Content\Reputation and settings.reputation_enabled}}
|
||||
<li>{template="reputationMini" group="global" app="core" params="$activity, '', NULL, TRUE"}</li>
|
||||
{{endif}}
|
||||
</ul>
|
||||
{{endif}}
|
||||
</div>
|
||||
</div>
|
||||
</div>]]></template>
|
||||
{{endif}}]]></template>
|
||||
<template template_group="livesearch" template_name="calendar" template_data="$calendar" template_location="admin" template_app="calendar"><![CDATA[<li class='ipsPad_half ipsClearfix' data-role='result'>
|
||||
<a href='{url="app=calendar&module=calendars&controller=calendars&do=form&id="}{$calendar->id}' class='ipsPos_left'>{$calendar->_title}</a>
|
||||
</li>
|
||||
@@ -878,7 +982,7 @@
|
||||
<li>
|
||||
<input type='radio' name='event_dates[repeat_end]' id='event_repeat_end_ondate' value='date'{{if $value['repeat_end_date']}} checked{{endif}}>
|
||||
<div class='ipsField_fieldList_content'>
|
||||
<label for="event_repeat_end_ondate">{lang="event_rpm_ends_date"}</label> <input type='date' name='event_dates[repeat_end_date]' class='cCalendar_shortInput' size='10' value='{$value['repeat_end_date']}'>
|
||||
<label for="event_repeat_end_ondate">{lang="event_rpm_ends_date"}</label> <input type='date' name='event_dates[repeat_end_date]' class='cCalendar_shortInput' size='10' value='{{if $value['repeat_end_date'] instanceof \IPS\calendar\Date}}{$value['repeat_end_date']->mysqlDatetime( FALSE )}{{endif}}'>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -973,7 +1077,7 @@
|
||||
</ul>
|
||||
{{endif}}
|
||||
</div>]]></template>
|
||||
<template template_group="view" template_name="comments" template_data="$event" template_location="front" template_app="calendar"><![CDATA[<div class='' data-controller='core.front.core.commentFeed' data-baseURL='{$event->url()}' {{if $event->isLastPage()}}data-lastPage{{endif}} data-feedID='event-{$event->id}' id='comments'>
|
||||
<template template_group="view" template_name="comments" template_data="$event" template_location="front" template_app="calendar"><![CDATA[<div class='' data-controller='core.front.core.commentFeed' {{if settings.auto_polling_enabled}}data-autoPoll{{endif}} data-baseURL='{$event->url()}' {{if $event->isLastPage()}}data-lastPage{{endif}} data-feedID='event-{$event->id}' id='comments'>
|
||||
{{if $event->commentPageCount() > 1}}
|
||||
{$event->commentPagination( array( 'tab' ) )|raw}
|
||||
<br><br>
|
||||
@@ -1027,7 +1131,8 @@
|
||||
{template="prefix" group="global" app="core" params="$event->prefix( TRUE ), $event->prefix()"}
|
||||
{{endif}}
|
||||
|
||||
{{if $event->locked()}}<i class='fa fa-lock'></i> {{endif}}<span itemprop='name'>{$event->title}</span>
|
||||
{{if $event->locked()}}<i class='fa fa-lock'></i> {{endif}}
|
||||
|
||||
{{if $event->mapped('pinned') || $event->mapped('featured') || $event->hidden() === -1 || $event->hidden() === 1}}
|
||||
{{if $event->hidden() === -1}}
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_warning" data-ipsTooltip title='{$event->hiddenBlurb()}'><i class='fa fa-eye-slash'></i></span>
|
||||
@@ -1041,6 +1146,8 @@
|
||||
<span class="ipsBadge ipsBadge_icon ipsBadge_positive" data-ipsTooltip title='{lang="featured"}'><i class='fa fa-star'></i></span>
|
||||
{{endif}}
|
||||
{{endif}}
|
||||
|
||||
<span itemprop='name'>{$event->title}</span>
|
||||
</h1>
|
||||
<p class='ipsType_normal ipsType_reset'>
|
||||
<time itemprop='startDate' content='{expression="$event->_start_date->format( 'Y-m-d' )"}'>
|
||||
@@ -1164,7 +1271,7 @@
|
||||
|
||||
<div class='ipsBox'>
|
||||
<h3 class='ipsType_reset ipsType_sectionHead ipsHide'>{lang="event_rsvp_attendees"}</h3>
|
||||
<div class='ipsTabs ipsTabs_small ipsClearfix' id='elAttendees{$tabId}' data-ipsTabBar data-ipsTabBar-stretch data-ipsTabBar-contentArea='#elAttendees{$tabId}_content'>
|
||||
<div class='ipsTabs ipsTabs_small ipsTabs_stretch ipsClearfix' id='elAttendees{$tabId}' data-ipsTabBar data-ipsTabBar-contentArea='#elAttendees{$tabId}_content'>
|
||||
<a href='#elAttendees{$tabId}' data-action='expandTabs'><i class='fa fa-caret-down'></i></a>
|
||||
<ul role="tablist">
|
||||
<li>
|
||||
@@ -1242,7 +1349,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{{endif}}]]></template>
|
||||
<template template_group="view" template_name="reviews" template_data="$event" template_location="front" template_app="calendar"><![CDATA[<div data-controller='core.front.core.commentFeed' data-baseURL='{$event->url()}' {{if $event->isLastPage('reviews')}}data-lastPage{{endif}} data-feedID='event-{$event->id}-reviews' id='reviews'>
|
||||
<template template_group="view" template_name="reviews" template_data="$event" template_location="front" template_app="calendar"><![CDATA[<div data-controller='core.front.core.commentFeed' {{if settings.auto_polling_enabled}}data-autoPoll{{endif}} data-baseURL='{$event->url()}' {{if $event->isLastPage('reviews')}}data-lastPage{{endif}} data-feedID='event-{$event->id}-reviews' id='reviews'>
|
||||
{{if $event->canReview()}}
|
||||
{{if $event->locked()}}
|
||||
<strong class='ipsType_warning'><i class='fa fa-info-circle'></i> {lang="item_locked_can_review"}</strong>
|
||||
@@ -1296,6 +1403,8 @@
|
||||
<hr class='ipsHr'>
|
||||
{$event->reviewPagination( array( 'tab', 'sort' ) )|raw}
|
||||
{{endif}}
|
||||
{{elseif !$event->canReview()}}
|
||||
<p class="ipsType_normal ipsType_light ipsType_reset" data-role="noReviews">{lang="no_reviews"}</p>
|
||||
{{endif}}
|
||||
</div>]]></template>
|
||||
<template template_group="view" template_name="rsvpControls" template_data="$event, $attendees" template_location="front" template_app="calendar"><![CDATA[<!-- Don't use IDs here, this template is called twice in view -->
|
||||
@@ -1606,11 +1715,11 @@
|
||||
<span class='ipsCalendarDate_date'>{$event->nextOccurrence( $today, 'startDate' )->mday}</span>
|
||||
</time>
|
||||
</div>
|
||||
<div class='ipsDataItem_main ipsType_break'>
|
||||
<div class='ipsDataItem_main ipsType_break ipsContained'>
|
||||
{{if $event->container()->allow_comments && $orientation == 'vertical'}}
|
||||
<div class="ipsCommentCount ipsPos_right {{if $event->comments === 0}}ipsFaded{{endif}}" data-ipsTooltip title='{lang="replies_number" pluralize="$event->comments"}'>{expression="$event->comments"}</div>
|
||||
{{endif}}
|
||||
{{if $event->unread()}}<span class="ipsItemStatus ipsItemStatus_tiny"><i class="fa fa-circle"></i></span> <strong>{{endif}}<a href="{$event->url()}" title='{lang="view_this_event" sprintf="$event->title"}'>{wordbreak="$event->title"}</a>{{if $event->unread()}}</strong>{{endif}}<br>
|
||||
{{if $event->unread()}}<span class="ipsItemStatus ipsItemStatus_tiny"><i class="fa fa-circle"></i></span> <strong>{{endif}}<a href="{$event->url()}" title='{lang="view_this_event" sprintf="$event->title"}'>{$event->title}</a>{{if $event->unread()}}</strong>{{endif}}<br>
|
||||
<strong class='ipsType_small'>
|
||||
{{if $event->nextOccurrence( $today, 'startDate' )}}
|
||||
{$event->nextOccurrence( $today, 'startDate' )->calendarDate()}{{if !$event->all_day}} {$event->nextOccurrence( $today, 'startDate' )->localeTime( FALSE )} {{endif}}
|
||||
@@ -1988,7 +2097,9 @@ a.cEvents_event, .cEvents_event a, .cEvents_event.cEvents_empty span {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
html[dir="rtl"] a.cEvents_event, .cEvents_event a, .cEvents_event.cEvents_empty span {
|
||||
html[dir="rtl"] a.cEvents_event,
|
||||
html[dir="rtl"] .cEvents_event a,
|
||||
html[dir="rtl"] .cEvents_event.cEvents_empty span {
|
||||
padding: 0 10px 0 8px;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,5 +55,18 @@
|
||||
"100042": "4.0.12",
|
||||
"100043": "4.0.12.1",
|
||||
"100044": "4.0.13",
|
||||
"100045": "4.0.13.1"
|
||||
"100045": "4.0.13.1",
|
||||
"101000": "4.1.0 Beta 1",
|
||||
"101001": "4.1.0 Beta 2",
|
||||
"101002": "4.1.0 Beta 3",
|
||||
"101003": "4.1.0 Beta 4",
|
||||
"101004": "4.1.0 Beta 5",
|
||||
"101005": "4.1.0 Beta 6",
|
||||
"101006": "4.1.0 Beta 7",
|
||||
"101007": "4.1.0 Beta 8",
|
||||
"101008": "4.1.0 Beta 9",
|
||||
"101009": "4.1.0 Beta 10",
|
||||
"101010": "4.1.0",
|
||||
"101011": "4.1.1",
|
||||
"101012": "4.1.2"
|
||||
}
|
||||
@@ -27,5 +27,19 @@ class _Calendar
|
||||
/**
|
||||
* @brief Content Item Classes
|
||||
*/
|
||||
public $classes = array( 'IPS\calendar\Event' );
|
||||
public $classes = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \IPS\Member|NULL $member If checking access, the member to check for, or NULL to not check access
|
||||
* @return void
|
||||
*/
|
||||
public function __construct( \IPS\Member $member = NULL )
|
||||
{
|
||||
if ( $member === NULL or $member->canAccessModule( \IPS\Application\Module::get( 'calendar', 'calendar', 'front' ) ) )
|
||||
{
|
||||
$this->classes[] = 'IPS\calendar\Event';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,18 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
/**
|
||||
* Front Navigation Extension: Calendar
|
||||
*/
|
||||
class _Calendar
|
||||
class _Calendar extends \IPS\core\FrontNavigation\FrontNavigationAbstract
|
||||
{
|
||||
/**
|
||||
* Get Type Title which will display in the AdminCP Menu Manager
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function typeTitle()
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack('frontnavigation_calendar');
|
||||
}
|
||||
|
||||
/**
|
||||
* Can access?
|
||||
*
|
||||
@@ -31,7 +41,7 @@ class _Calendar
|
||||
*/
|
||||
public function canView()
|
||||
{
|
||||
return !\IPS\Application::load('calendar')->hide_tab and \IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( 'calendar', 'calendar' ) );
|
||||
return parent::canView() and \IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( 'calendar', 'calendar' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,14 +73,4 @@ class _Calendar
|
||||
{
|
||||
return \IPS\Dispatcher::i()->application->directory === 'calendar';
|
||||
}
|
||||
|
||||
/**
|
||||
* Children
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function children()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
}
|
||||
@@ -185,7 +185,7 @@ class _event extends \IPS\Content\Controller
|
||||
}
|
||||
|
||||
/* We delete either way at this point, because even if we select a different action we have to remove any existing RSVP preference */
|
||||
\IPS\Db::i()->delete( 'calendar_event_rsvp', array( 'rsvp_event_id=? AND rsvp_member_id=?', $this->event->id, \IPS\Member::loggedIn()->member_id ) );
|
||||
\IPS\Db::i()->delete( 'calendar_event_rsvp', array( 'rsvp_event_id=? AND rsvp_member_id=?', $this->event->id, (int) \IPS\Member::loggedIn()->member_id ) );
|
||||
|
||||
if( \IPS\Request::i()->action == 'leave' )
|
||||
{
|
||||
@@ -229,7 +229,7 @@ class _event extends \IPS\Content\Controller
|
||||
|
||||
\IPS\Db::i()->insert( 'calendar_event_rsvp', array(
|
||||
'rsvp_event_id' => $this->event->id,
|
||||
'rsvp_member_id' => \IPS\Member::loggedIn()->member_id,
|
||||
'rsvp_member_id' => (int) \IPS\Member::loggedIn()->member_id,
|
||||
'rsvp_date' => time(),
|
||||
'rsvp_response' => (int) $_go
|
||||
) );
|
||||
@@ -239,4 +239,16 @@ class _event extends \IPS\Content\Controller
|
||||
|
||||
\IPS\Output::i()->redirect( $this->event->url(), $message );
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit Item
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function edit()
|
||||
{
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_submit.js', 'calendar', 'front' ) );
|
||||
|
||||
return parent::edit();
|
||||
}
|
||||
}
|
||||
@@ -495,21 +495,25 @@ class _view extends \IPS\Dispatcher\Controller
|
||||
|
||||
if( $values = $form->values() )
|
||||
{
|
||||
\IPS\Request::i()->view = 'day';
|
||||
|
||||
if( \IPS\Request::i()->goto )
|
||||
{
|
||||
\IPS\Request::i()->y = null;
|
||||
\IPS\Request::i()->m = null;
|
||||
\IPS\Request::i()->d = null;
|
||||
\IPS\Request::i()->w = null;
|
||||
$dateToGoTo = \IPS\DateTime::create();
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Request::i()->y = $values['jump_to']->format('Y');
|
||||
\IPS\Request::i()->m = $values['jump_to']->format('m');
|
||||
\IPS\Request::i()->d = $values['jump_to']->format('j');
|
||||
$dateToGoTo = $values['jump_to'];
|
||||
}
|
||||
|
||||
if ( $this->_calendar )
|
||||
{
|
||||
$url = \IPS\Http\Url::internal( "app=calendar&module=calendar&controller=view&view=day&id={$this->_calendar->_id}&y={$dateToGoTo->format('Y')}&m={$dateToGoTo->format('m')}&d={$dateToGoTo->format('j')}", 'front', 'calendar_calday', $this->_calendar->title_seo );
|
||||
}
|
||||
else
|
||||
{
|
||||
$url = \IPS\Http\Url::internal( "app=calendar&module=calendar&controller=view&view=day&y={$dateToGoTo->format('Y')}&m={$dateToGoTo->format('m')}&d={$dateToGoTo->format('j')}", 'front', 'calendar_day' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
}
|
||||
|
||||
return $form;
|
||||
|
||||
@@ -107,6 +107,3 @@ $SQL[] = "INSERT INTO cal_events SELECT event_id, event_calendar_id, event_membe
|
||||
event_recurring, FROM_UNIXTIME(event_unix_from), CASE WHEN event_unix_to > 0 THEN FROM_UNIXTIME(event_unix_to) ELSE NULL END, '', 0, 0, 0, 0, MD5( CONCAT( event_id, event_title ) ), 0, 1 FROM " . \IPS\Db::i()->prefix . "cal_events_bak;";
|
||||
|
||||
$SQL[] = "DROP TABLE cal_events_bak;";
|
||||
|
||||
$SQL[] = "ALTER TABLE cal_events ADD event_all_day TINYINT NOT NULL DEFAULT '0';";
|
||||
$SQL[] = "UPDATE cal_events SET event_all_day=1 WHERE TIME(event_start_date) = '00:00:00';";
|
||||
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
|
||||
$SQL[] = "ALTER TABLE cal_events ADD event_all_day TINYINT NOT NULL DEFAULT '0';";
|
||||
$SQL[] = "UPDATE cal_events SET event_all_day=1 WHERE TIME(event_start_date) = '00:00:00';";
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief 4.0.0 Upgrade Code
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Social Suite
|
||||
* @subpackage Calendar
|
||||
* @since 8 October 2015
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\calendar\setup\upg_32005;
|
||||
|
||||
/* 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.0.0 Upgrade Code
|
||||
*/
|
||||
class _Upgrade
|
||||
{
|
||||
/**
|
||||
* Conversion from 3.0
|
||||
*
|
||||
* @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()
|
||||
{
|
||||
\IPS\core\Setup\Upgrade::runLegacySql( 'calendar', 32005 );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ class _Upgrade
|
||||
{
|
||||
foreach( \IPS\Db::i()->select( '*', 'calendar_calendars' ) as $calendar )
|
||||
{
|
||||
\IPS\Lang::saveCustom( 'calendar', "calendar_calendar_{$calendar['cal_id']}", html_entity_decode( $calendar['cal_title'], ENT_QUOTES, 'UTF-8' ) );
|
||||
\IPS\Lang::saveCustom( 'calendar', "calendar_calendar_{$calendar['cal_id']}", \IPS\Text\Parser::utf8mb4SafeDecode( $calendar['cal_title'] ) );
|
||||
}
|
||||
|
||||
\IPS\Db::i()->dropColumn( 'calendar_calendars', 'cal_title' );
|
||||
|
||||
@@ -185,21 +185,21 @@ class _Calendar extends \IPS\Node\Model implements \IPS\Node\Permissions
|
||||
* @brief Cached URL
|
||||
*/
|
||||
protected $_url = NULL;
|
||||
|
||||
|
||||
/**
|
||||
* Get URL
|
||||
*
|
||||
* @return \IPS\Http\Url
|
||||
* @brief URL Base
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
if( $this->_url === NULL )
|
||||
{
|
||||
$this->_url = \IPS\Http\Url::internal( "app=calendar&module=calendar&controller=view&id={$this->_id}", 'front', 'calendar_calendar', $this->title_seo );
|
||||
}
|
||||
|
||||
return $this->_url;
|
||||
}
|
||||
public static $urlBase = 'app=calendar&module=calendar&controller=view&id=';
|
||||
|
||||
/**
|
||||
* @brief URL Base
|
||||
*/
|
||||
public static $urlTemplate = 'calendar_calendar';
|
||||
|
||||
/**
|
||||
* @brief SEO Title Column
|
||||
*/
|
||||
public static $seoTitleColumn = 'title_seo';
|
||||
|
||||
/**
|
||||
* [ActiveRecord] Delete Record
|
||||
|
||||
@@ -425,11 +425,11 @@ class _Date extends \IPS\DateTime
|
||||
{
|
||||
if( \IPS\Settings::i()->calendar_date_format == -1 AND \IPS\Settings::i()->calendar_date_format_custom )
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->convertString( strftime( \IPS\Settings::i()->calendar_date_format_custom, $this->getTimestamp() + $this->getTimezone()->getOffset( $this ) ) );
|
||||
return \IPS\Member::loggedIn()->language()->convertString( strftime( \IPS\Settings::i()->calendar_date_format_custom, $this->getTimestamp() + $this->offset ) );
|
||||
}
|
||||
elseif( isset( static::$dateFormats[ \IPS\Settings::i()->calendar_date_format ] ) )
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->convertString( strftime( static::$dateFormats[ \IPS\Settings::i()->calendar_date_format ], $this->getTimestamp() + $this->getTimezone()->getOffset( $this ) ) );
|
||||
return \IPS\Member::loggedIn()->language()->convertString( strftime( static::$dateFormats[ \IPS\Settings::i()->calendar_date_format ], $this->getTimestamp() + $this->offset ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -731,4 +731,16 @@ class _Date extends \IPS\DateTime
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the time according to the user's locale (without the date)
|
||||
*
|
||||
* @param bool $seconds If TRUE, will include seconds
|
||||
* @param bool $minutes If TRUE, will include minutes
|
||||
* @return string
|
||||
*/
|
||||
public function localeTime( $seconds=TRUE, $minutes=TRUE )
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->convertString( strftime( $this->localeTimeFormat( $seconds, $minutes ), $this->getTimestamp() + $this->offset ) );
|
||||
}
|
||||
}
|
||||
@@ -105,4 +105,37 @@ class _Comment extends \IPS\Content\Comment implements \IPS\Content\EditHistory,
|
||||
{
|
||||
return array( \IPS\Theme::i()->getTemplate( 'tables', 'core' ), 'commentRows' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get snippet HTML for search result display
|
||||
*
|
||||
* @param array $indexData Data from the search index
|
||||
* @param array $authorData Basic data about the author. Only includes columns returned by \IPS\Member::columnsForPhoto()
|
||||
* @param array $itemData Basic data about the item. Only includes columns returned by item::basicDataColumns()
|
||||
* @param array|NULL $containerData Basic data about the author. Only includes columns returned by container::basicDataColumns()
|
||||
* @param array $reputationData Array of people who have given reputation and the reputation they gave
|
||||
* @param int|NULL $reviewRating If this is a review, the rating
|
||||
* @param string $view 'expanded' or 'condensed'
|
||||
* @return callable
|
||||
*/
|
||||
public static function searchResultSnippet( array $indexData, array $authorData, array $itemData, array $containerData = NULL, array $reputationData, $reviewRating, $view )
|
||||
{
|
||||
$startDate = \IPS\calendar\Date::parseTime( $itemData['event_start_date'], $itemData['event_all_day'] ? FALSE : TRUE );
|
||||
$endDate = $itemData['event_end_date'] ? \IPS\calendar\Date::parseTime( $itemData['event_end_date'], $itemData['event_all_day'] ? FALSE : TRUE ) : NULL;
|
||||
$nextOccurance = $startDate;
|
||||
if ( $itemData['event_recurring'] )
|
||||
{
|
||||
$occurances = \IPS\calendar\Event::_findOccurances( $startDate, $endDate, $startDate->adjust( "-1 month" ), $startDate->adjust( "+2 years" ), \IPS\calendar\Icalendar\ICSParser::parseRrule( $itemData['event_recurring'] ) );
|
||||
foreach( $occurances as $occurrence )
|
||||
{
|
||||
if( $occurrence['startDate'] AND $occurrence['startDate']->mysqlDatetime( FALSE ) >= $startDate->mysqlDatetime( FALSE ) )
|
||||
{
|
||||
$nextOccurance = $occurrence['startDate'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'calendar', 'front' )->searchResultCommentSnippet( $indexData, $nextOccurance, $startDate, $endDate, $itemData['event_all_day'], $reviewRating, $view == 'condensed' );
|
||||
}
|
||||
}
|
||||
@@ -145,6 +145,21 @@ class _Event extends \IPS\Content\Item implements
|
||||
const RSVP_YES = 1;
|
||||
const RSVP_MAYBE = 2;
|
||||
|
||||
/**
|
||||
* Columns needed to query for search result / stream view
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function basicDataColumns()
|
||||
{
|
||||
$return = parent::basicDataColumns();
|
||||
$return[] = 'event_recurring';
|
||||
$return[] = 'event_start_date';
|
||||
$return[] = 'event_end_date';
|
||||
$return[] = 'event_all_day';
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the title
|
||||
*
|
||||
@@ -308,10 +323,27 @@ class _Event extends \IPS\Content\Item implements
|
||||
//return $results;
|
||||
}
|
||||
|
||||
/* Now figure out when this event occurs on */
|
||||
/* Return the results we found after storing them */
|
||||
$this->parsedOccurrences = static::_findOccurances( $this->_start_date, $this->_end_date, $startDate, $endDate, $recurringData );
|
||||
|
||||
return $this->parsedOccurrences;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get occurances
|
||||
*
|
||||
* @param \IPS\calendar\Date $eventStart Event start date
|
||||
* @param \IPS\calendar\Date $eventEnd Event end date
|
||||
* @param \IPS\calendar\Date $startDate Date to start from
|
||||
* @param \IPS\calendar\Date $endDate Date to end at
|
||||
* @param array $recurringData Reccurance data
|
||||
*/
|
||||
public static function _findOccurances( $eventStart, $eventEnd, $startDate, $endDate, $recurringData )
|
||||
{
|
||||
$instances = array();
|
||||
$occurrences = 0;
|
||||
$keyword = NULL;
|
||||
$results = array();
|
||||
|
||||
switch( $recurringData['event_repeats'] )
|
||||
{
|
||||
@@ -338,8 +370,8 @@ class _Event extends \IPS\Content\Item implements
|
||||
}
|
||||
else
|
||||
{
|
||||
$date = $this->_start_date;
|
||||
$eDate = $this->_end_date;
|
||||
$date = $eventStart;
|
||||
$eDate = $eventEnd;
|
||||
|
||||
if( ( $date->mysqlDatetime( FALSE ) >= $startDate->mysqlDatetime( FALSE ) AND $date->mysqlDatetime( FALSE ) <= $endDate->mysqlDatetime( FALSE ) ) OR
|
||||
( $eDate !== NULL AND $eDate->mysqlDatetime( FALSE ) >= $startDate->mysqlDatetime( FALSE ) AND $eDate->mysqlDatetime( FALSE ) <= $endDate->mysqlDatetime( FALSE ) ) OR
|
||||
@@ -348,8 +380,18 @@ class _Event extends \IPS\Content\Item implements
|
||||
{
|
||||
$results[] = array( 'startDate' => $date, 'endDate' => $eDate );
|
||||
}
|
||||
|
||||
$nextDay = current( $_repeatDays );
|
||||
|
||||
/* Figure out which of teh days is next. For example, if the start date is a Wednesday, and the
|
||||
event repeats every Monday and Friday, we need to start with Friday (not Monday) because that's
|
||||
when the first occurance is */
|
||||
$nextTimes = array();
|
||||
foreach ( $_repeatDays as $repeatDay )
|
||||
{
|
||||
$nextTimes[ $repeatDay ] = $date->adjust( "next {$repeatDay}" )->getTimestamp();
|
||||
}
|
||||
asort( $nextTimes );
|
||||
$nextTimes = array_keys( $nextTimes );
|
||||
$nextDay = array_shift( $nextTimes );
|
||||
|
||||
/* Do we have an occurrences limit? */
|
||||
if( $recurringData['repeat_end_occurrences'] )
|
||||
@@ -445,8 +487,8 @@ class _Event extends \IPS\Content\Item implements
|
||||
/* Normal recurrence checks */
|
||||
if( $keyword !== NULL )
|
||||
{
|
||||
$date = $this->_start_date;
|
||||
$eDate = $this->_end_date;
|
||||
$date = $eventStart;
|
||||
$eDate = $eventEnd;
|
||||
|
||||
if( ( $date->mysqlDatetime( FALSE ) >= $startDate->mysqlDatetime( FALSE ) AND $date->mysqlDatetime( FALSE ) <= $endDate->mysqlDatetime( FALSE ) ) OR
|
||||
( $eDate !== NULL AND $eDate->mysqlDatetime( FALSE ) >= $startDate->mysqlDatetime( FALSE ) AND $eDate->mysqlDatetime( FALSE ) <= $endDate->mysqlDatetime( FALSE ) ) OR
|
||||
@@ -496,7 +538,7 @@ class _Event extends \IPS\Content\Item implements
|
||||
/* Recurs indefinitely... the most fun type... */
|
||||
else
|
||||
{
|
||||
while( $date->mysqlDatetime( FALSE ) < $endDate->mysqlDatetime( FALSE ) )
|
||||
while( $date->mysqlDatetime( FALSE ) <= $endDate->mysqlDatetime( FALSE ) )
|
||||
{
|
||||
if( ( $date->mysqlDatetime( FALSE ) >= $startDate->mysqlDatetime( FALSE ) AND $date->mysqlDatetime( FALSE ) <= $endDate->mysqlDatetime( FALSE ) ) OR
|
||||
( $eDate !== NULL AND $eDate->mysqlDatetime( FALSE ) >= $startDate->mysqlDatetime( FALSE ) AND $eDate->mysqlDatetime( FALSE ) <= $endDate->mysqlDatetime( FALSE ) ) OR
|
||||
@@ -511,11 +553,8 @@ class _Event extends \IPS\Content\Item implements
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the results we found after storing them */
|
||||
$this->parsedOccurrences = $results;
|
||||
|
||||
return $this->parsedOccurrences;
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -716,29 +755,21 @@ class _Event extends \IPS\Content\Item implements
|
||||
* @brief Cached URLs
|
||||
*/
|
||||
protected $_url = array();
|
||||
|
||||
/**
|
||||
* Get URL
|
||||
*
|
||||
* @param string|NULL $action Action
|
||||
* @return \IPS\Http\Url
|
||||
*/
|
||||
public function url( $action=NULL )
|
||||
{
|
||||
$_key = md5( $action );
|
||||
|
||||
if( !isset( $this->_url[ $_key ] ) )
|
||||
{
|
||||
$this->_url[ $_key ] = \IPS\Http\Url::internal( "app=calendar&module=calendar&controller=event&id={$this->id}", 'front', 'calendar_event', $this->title_seo );
|
||||
|
||||
if ( $action )
|
||||
{
|
||||
$this->_url[ $_key ] = $this->_url[ $_key ]->setQueryString( 'do', $action );
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_url[ $_key ];
|
||||
}
|
||||
/**
|
||||
* @brief URL Base
|
||||
*/
|
||||
public static $urlBase = 'app=calendar&module=calendar&controller=event&id=';
|
||||
|
||||
/**
|
||||
* @brief URL Base
|
||||
*/
|
||||
public static $urlTemplate = 'calendar_event';
|
||||
|
||||
/**
|
||||
* @brief SEO Title Column
|
||||
*/
|
||||
public static $seoTitleColumn = 'title_seo';
|
||||
|
||||
/**
|
||||
* Get URL for last comment page
|
||||
@@ -772,6 +803,40 @@ class _Event extends \IPS\Content\Item implements
|
||||
return array( \IPS\Theme::i()->getTemplate( 'global', 'calendar' ), 'rows' );
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML to manage an item's follows
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public static function manageFollowRows()
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'calendar.css', 'calendar' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'calendar_responsive.css', 'calendar' ) );
|
||||
return array( \IPS\Theme::i()->getTemplate( 'global', 'calendar', 'front' ), 'manageFollowRow' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Are comments supported by this class?
|
||||
*
|
||||
* @param \IPS\Member\NULL $member The member to check for or NULL fto not check permission
|
||||
* @return int
|
||||
*/
|
||||
public static function supportsComments( \IPS\Member $member = NULL )
|
||||
{
|
||||
return parent::supportsComments() and ( !$member or \IPS\calendar\Calendar::countWhere( 'read', $member, array( 'cal_allow_comments=1' ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Are reviews supported by this class?
|
||||
*
|
||||
* @param \IPS\Member\NULL $member The member to check for or NULL to not check permission
|
||||
* @return int
|
||||
*/
|
||||
public static function supportsReviews( \IPS\Member $member = NULL )
|
||||
{
|
||||
return parent::supportsReviews() and ( !$member or \IPS\calendar\Calendar::countWhere( 'read', $member, array( 'cal_allow_reviews=1' ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available comment/review tabs
|
||||
*
|
||||
@@ -1009,12 +1074,12 @@ class _Event extends \IPS\Content\Item implements
|
||||
|
||||
/* Cover photo and location */
|
||||
$return['header'] = new \IPS\Helpers\Form\Upload( 'event_cover_photo', ( $item AND $item->cover_photo ) ? \IPS\File::get( 'calendar_Events', $item->cover_photo ) : NULL, FALSE, array( 'image' => TRUE, 'storageExtension' => 'calendar_Events' ) );
|
||||
$return['location'] = new \IPS\Helpers\Form\Address( 'event_location', ( $item AND $item->location ) ? \IPS\GeoLocation::buildFromJson( $item->location ) : NULL, FALSE, array( 'minimize' => TRUE ) );
|
||||
$return['location'] = new \IPS\Helpers\Form\Address( 'event_location', ( $item AND $item->location ) ? \IPS\GeoLocation::buildFromJson( $item->location ) : NULL, FALSE, array( 'minimize' => TRUE, 'requireFullAddress' => FALSE ) );
|
||||
|
||||
/* Gallery album association */
|
||||
if( \IPS\Application::appIsEnabled( 'gallery' ) )
|
||||
{
|
||||
$return['album'] = new \IPS\Helpers\Form\Node( 'event_album', ( $item AND $item->event_album ) ? $item->event_album : NULL, FALSE, array(
|
||||
$return['album'] = new \IPS\Helpers\Form\Node( 'event_album', ( $item AND $item->album ) ? $item->album : NULL, FALSE, array(
|
||||
'url' => \IPS\Http\Url::internal( 'app=calendar&module=calendar&controller=submit', 'front', 'calendar_submit' ),
|
||||
'class' => 'IPS\gallery\Album',
|
||||
'permissionCheck' => 'add',
|
||||
@@ -1049,7 +1114,7 @@ class _Event extends \IPS\Content\Item implements
|
||||
* @return void
|
||||
*/
|
||||
public function processForm( $values )
|
||||
{
|
||||
{
|
||||
/* Anything but Chrome, basically, falls back to a text input and submitter might submit 22.00 instead of 22:00 */
|
||||
if( isset( $values['event_dates']['start_time'] ) )
|
||||
{
|
||||
@@ -1183,11 +1248,11 @@ class _Event extends \IPS\Content\Item implements
|
||||
/**
|
||||
* Retrieve events to show based on a provided start and end date, optionally filtering by a supplied calendar
|
||||
*
|
||||
* @param \IPS\calendar\Date $startDate Date to start from
|
||||
* @param \IPS\calendar\Date|NULL $endDate Cut off date for events. NULL accepted as a possible value only if $formatEvents is set to FALSE.
|
||||
* @param \IPS\calendar\Calendar|NULL $calendar Calendar to filter by
|
||||
* @param int|null $limit Maximum number of events to return (only supported when not formatting events)
|
||||
* @param bool $formatEvents Whether or not to format events into a structured array
|
||||
* @param \IPS\calendar\Date $startDate Date to start from
|
||||
* @param \IPS\calendar\Date|NULL $endDate Cut off date for events. NULL accepted as a possible value only if $formatEvents is set to FALSE.
|
||||
* @param \IPS\calendar\Calendar|NULL|array $calendar Calendar to filter by
|
||||
* @param int|null $limit Maximum number of events to return (only supported when not formatting events)
|
||||
* @param bool $formatEvents Whether or not to format events into a structured array
|
||||
* @return \IPS\Patterns\ActiveRecordIterator
|
||||
* @throws \InvalidArgumentException
|
||||
* @see \IPS\Content\_Item::getItemsWithPermission()
|
||||
@@ -1198,7 +1263,15 @@ class _Event extends \IPS\Content\Item implements
|
||||
|
||||
if( $calendar !== NULL )
|
||||
{
|
||||
$where[] = array( 'event_calendar_id=?', (int) $calendar->_id );
|
||||
if ( is_array( $calendar ) )
|
||||
{
|
||||
$where[] = array( \IPS\Db::i()->in( 'event_calendar_id', $calendar ) );
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
$where[] = array( 'event_calendar_id=?', (int) $calendar->_id );
|
||||
}
|
||||
}
|
||||
|
||||
if( $endDate === NULL AND $formatEvents === TRUE )
|
||||
@@ -1475,4 +1548,37 @@ class _Event extends \IPS\Content\Item implements
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'calendar' )->embedCalendar_event( $this, $this->url()->setQueryString( $params ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get snippet HTML for search result display
|
||||
*
|
||||
* @param array $indexData Data from the search index
|
||||
* @param array $authorData Basic data about the author. Only includes columns returned by \IPS\Member::columnsForPhoto()
|
||||
* @param array $itemData Basic data about the item. Only includes columns returned by item::basicDataColumns()
|
||||
* @param array|NULL $containerData Basic data about the author. Only includes columns returned by container::basicDataColumns()
|
||||
* @param array $reputationData Array of people who have given reputation and the reputation they gave
|
||||
* @param int|NULL $reviewRating If this is a review, the rating
|
||||
* @param string $view 'expanded' or 'condensed'
|
||||
* @return callable
|
||||
*/
|
||||
public static function searchResultSnippet( array $indexData, array $authorData, array $itemData, array $containerData = NULL, array $reputationData, $reviewRating, $view )
|
||||
{
|
||||
$startDate = \IPS\calendar\Date::parseTime( $itemData['event_start_date'], $itemData['event_all_day'] ? FALSE : TRUE );
|
||||
$endDate = $itemData['event_end_date'] ? \IPS\calendar\Date::parseTime( $itemData['event_end_date'], $itemData['event_all_day'] ? FALSE : TRUE ) : NULL;
|
||||
$nextOccurance = $startDate;
|
||||
if ( $itemData['event_recurring'] )
|
||||
{
|
||||
$occurances = \IPS\calendar\Event::_findOccurances( $startDate, $endDate, $startDate->adjust( "-1 month" ), $startDate->adjust( "+2 years" ), \IPS\calendar\Icalendar\ICSParser::parseRrule( $itemData['event_recurring'] ) );
|
||||
foreach( $occurances as $occurrence )
|
||||
{
|
||||
if( $occurrence['startDate'] AND $occurrence['startDate']->mysqlDatetime( FALSE ) >= $startDate->mysqlDatetime( FALSE ) )
|
||||
{
|
||||
$nextOccurance = $occurrence['startDate'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'calendar', 'front' )->searchResultEventSnippet( $indexData, $itemData, $nextOccurance, $startDate, $endDate, $itemData['event_all_day'], $view == 'condensed' );
|
||||
}
|
||||
}
|
||||
@@ -109,4 +109,21 @@ class _Review extends \IPS\Content\Review implements \IPS\Content\EditHistory, \
|
||||
{
|
||||
return array( \IPS\Theme::i()->getTemplate( 'tables', 'core' ), 'commentRows' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get snippet HTML for search result display
|
||||
*
|
||||
* @param array $indexData Data from the search index
|
||||
* @param array $authorData Basic data about the author. Only includes columns returned by \IPS\Member::columnsForPhoto()
|
||||
* @param array $itemData Basic data about the item. Only includes columns returned by item::basicDataColumns()
|
||||
* @param array|NULL $containerData Basic data about the author. Only includes columns returned by container::basicDataColumns()
|
||||
* @param array $reputationData Array of people who have given reputation and the reputation they gave
|
||||
* @param int|NULL $reviewRating If this is a review, the rating
|
||||
* @param string $view 'expanded' or 'condensed'
|
||||
* @return callable
|
||||
*/
|
||||
public static function searchResultSnippet( array $indexData, array $authorData, array $itemData, array $containerData = NULL, array $reputationData, $reviewRating, $view )
|
||||
{
|
||||
return \IPS\calendar\Event\Comment::searchResultSnippet( $indexData, $authorData, $itemData, $containerData, $reputationData, $reviewRating, $view );
|
||||
}
|
||||
}
|
||||
@@ -383,7 +383,7 @@ class _ICSParser
|
||||
{
|
||||
try
|
||||
{
|
||||
$eventId = \IPS\Db::i()->select( 'import_event_id', 'calendar_import_map', array( 'import_guid=?', $event['uid'] ) )->first();
|
||||
$eventId = \IPS\Db::i()->select( 'import_event_id', 'calendar_import_map', array( array( 'import_guid=? and import_feed_id=?', $event['uid'], $this->feed->id ) ) )->first();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -696,8 +696,8 @@ class _ICSParser
|
||||
}
|
||||
else
|
||||
{
|
||||
$output .= "DTSTART;TZID=Europe/London:" . $event->_start_date->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "DTEND;TZID=Europe/London:" . $event->_end_date->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "DTSTART;" . $event->_start_date->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "DTEND;" . $event->_end_date->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -708,7 +708,7 @@ class _ICSParser
|
||||
}
|
||||
else
|
||||
{
|
||||
$output .= "DTSTART;TZID=Europe/London:" . $event->_start_date->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
$output .= "DTSTART;" . $event->_start_date->modifiedIso8601( TRUE, TRUE ) . "\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1124,8 +1124,11 @@ class _ICSParser
|
||||
break;
|
||||
|
||||
case 'ORGANIZER':
|
||||
$line = explode( ':', $_data );
|
||||
$_event['organizer'] = array( 'name' => str_replace( 'CN=', '', $line[0] ), 'email' => $line[1] );
|
||||
if ( $_data )
|
||||
{
|
||||
$line = explode( ':', $_data );
|
||||
$_event['organizer'] = array( 'name' => str_replace( 'CN=', '', $line[0] ), 'email' => $line[1] );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'ATTENDEE':
|
||||
|
||||
@@ -50,13 +50,37 @@ class _recentReviews extends \IPS\Widget\PermissionCache
|
||||
if ( $form === null )
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
}
|
||||
}
|
||||
|
||||
/* Container */
|
||||
$form->add( new \IPS\Helpers\Form\Node( 'widget_calendar', isset( $this->configuration['widget_calendar'] ) ? $this->configuration['widget_calendar'] : 0, FALSE, array(
|
||||
'class' => '\IPS\calendar\Calendar',
|
||||
'zeroVal' => 'all',
|
||||
'permissionCheck' => 'view',
|
||||
'multiple' => true
|
||||
) ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'review_count', isset( $this->configuration['review_count'] ) ? $this->configuration['review_count'] : 5, TRUE ) );
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ran before saving widget configuration
|
||||
*
|
||||
* @param array $values Values from form
|
||||
* @return array
|
||||
*/
|
||||
public function preConfig( $values )
|
||||
{
|
||||
if ( is_array( $values['widget_calendar'] ) )
|
||||
{
|
||||
$values['widget_calendar'] = array_keys( $values['widget_calendar'] );
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a widget
|
||||
*
|
||||
@@ -64,12 +88,14 @@ class _recentReviews extends \IPS\Widget\PermissionCache
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
if( !\IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( 'calendar', 'calendar' ) ) )
|
||||
$where = array();
|
||||
|
||||
if ( ! empty( $this->configuration['widget_calendar'] ) )
|
||||
{
|
||||
return '';
|
||||
$where['item'][] = array( \IPS\Db::i()->in( 'event_calendar_id', $this->configuration['widget_calendar'] ) );
|
||||
}
|
||||
|
||||
$reviews = \IPS\calendar\Event\Review::getItemsWithPermission( array(), NULL, ( isset( $this->configuration['review_count'] ) AND $this->configuration['review_count'] > 0 ) ? $this->configuration['review_count'] : 5 );
|
||||
|
||||
$reviews = \IPS\calendar\Event\Review::getItemsWithPermission( $where, NULL, ( isset( $this->configuration['review_count'] ) AND $this->configuration['review_count'] > 0 ) ? $this->configuration['review_count'] : 5 );
|
||||
|
||||
return $this->output( $reviews );
|
||||
}
|
||||
|
||||
@@ -44,7 +44,26 @@ class _upcomingEvents extends \IPS\Widget\PermissionCache
|
||||
* @note We allow this cache to be valid for 12 hours
|
||||
*/
|
||||
public $cacheExpiration = 43200;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param String $uniqueKey Unique key for this specific instance
|
||||
* @param array $configuration Widget custom configuration
|
||||
* @param null|string|array $access Array/JSON string of executable apps (core=sidebar only, content=IP.Content only, etc)
|
||||
* @param null|string $orientation Orientation (top, bottom, right, left)
|
||||
* @param boolean $allowReuse If true, when the block is used, it will remain in the sidebar so it can be used again.
|
||||
* @param string $menuStyle Menu is a drop down menu, modal is a bigger modal panel.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct( $uniqueKey, array $configuration, $access=null, $orientation=null )
|
||||
{
|
||||
parent::__construct( $uniqueKey, $configuration, $access, $orientation );
|
||||
|
||||
/* We need to adjust for timezone too */
|
||||
$this->cacheKey = "widget_{$this->key}_" . $this->uniqueKey . '_' . md5( json_encode( $configuration ) . "_" . \IPS\Member::loggedIn()->language()->id . "_" . \IPS\Member::loggedIn()->skin . "_" . json_encode( \IPS\Member::loggedIn()->groups ) . "_" . $orientation . \IPS\Member::loggedIn()->timezone );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this widget
|
||||
*
|
||||
@@ -70,12 +89,36 @@ class _upcomingEvents extends \IPS\Widget\PermissionCache
|
||||
$form = new \IPS\Helpers\Form;
|
||||
}
|
||||
|
||||
/* Container */
|
||||
$form->add( new \IPS\Helpers\Form\Node( 'widget_calendar', isset( $this->configuration['widget_calendar'] ) ? $this->configuration['widget_calendar'] : 0, FALSE, array(
|
||||
'class' => '\IPS\calendar\Calendar',
|
||||
'zeroVal' => 'all',
|
||||
'permissionCheck' => 'view',
|
||||
'multiple' => true
|
||||
) ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'auto_hide', isset( $this->configuration['auto_hide'] ) ? $this->configuration['auto_hide'] : FALSE, FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'days_ahead', isset( $this->configuration['days_ahead'] ) ? $this->configuration['days_ahead'] : NULL, TRUE, array( 'unlimited' => -1 ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'maximum_count', isset( $this->configuration['maximum_count'] ) ? $this->configuration['maximum_count'] : 5, TRUE, array( 'unlimited' => -1 ) ) );
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ran before saving widget configuration
|
||||
*
|
||||
* @param array $values Values from form
|
||||
* @return array
|
||||
*/
|
||||
public function preConfig( $values )
|
||||
{
|
||||
if ( is_array( $values['widget_calendar'] ) )
|
||||
{
|
||||
$values['widget_calendar'] = array_keys( $values['widget_calendar'] );
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a widget
|
||||
*
|
||||
@@ -97,8 +140,15 @@ class _upcomingEvents extends \IPS\Widget\PermissionCache
|
||||
{
|
||||
$endDate = $_today->adjust( "+" . $this->configuration['days_ahead'] . " days" );
|
||||
}
|
||||
|
||||
$events = \IPS\calendar\Event::retrieveEvents( $_today, $endDate, NULL, ( isset( $this->configuration['maximum_count'] ) AND $this->configuration['maximum_count'] > 0 ) ? $this->configuration['maximum_count'] : 5, FALSE );
|
||||
|
||||
$calendars = NULL;
|
||||
|
||||
if ( ! empty( $this->configuration['widget_calendar'] ) )
|
||||
{
|
||||
$calendars = $this->configuration['widget_calendar'];
|
||||
}
|
||||
|
||||
$events = \IPS\calendar\Event::retrieveEvents( $_today, $endDate, $calendars, ( isset( $this->configuration['maximum_count'] ) AND $this->configuration['maximum_count'] > 0 ) ? $this->configuration['maximum_count'] : 5, FALSE );
|
||||
|
||||
/* Auto hiding? */
|
||||
if( !count($events) AND isset( $this->configuration['auto_hide'] ) AND $this->configuration['auto_hide'] )
|
||||
|
||||
@@ -41,4 +41,56 @@ class _Application extends \IPS\Application
|
||||
{
|
||||
return 'comment';
|
||||
}
|
||||
|
||||
/**
|
||||
* Is chat online? Returns error message if not
|
||||
*
|
||||
* @return string|TRUE
|
||||
*/
|
||||
public function offlineMessage()
|
||||
{
|
||||
if( \IPS\Settings::i()->ipschat_online )
|
||||
{
|
||||
$times = explode( ',', \IPS\Settings::i()->ipschat_online );
|
||||
|
||||
if( count( $times ) AND $times[0] )
|
||||
{
|
||||
/* Do we need to adjust the time zone? */
|
||||
if( isset( $times[2] ) AND $times[2] != \IPS\Member::loggedIn()->timezone )
|
||||
{
|
||||
$start = new \IPS\DateTime( '2015-01-01 ' . $times[0], new \DateTimeZone( $times[2] ) );
|
||||
$start->setTimezone( new \DateTimeZone( \IPS\Member::loggedIn()->timezone ) );
|
||||
$times[0] = $start->format( 'H:i' );
|
||||
|
||||
$end = new \IPS\DateTime( '2015-01-01 ' . $times[1], new \DateTimeZone( $times[2] ) );
|
||||
$end->setTimezone( new \DateTimeZone( \IPS\Member::loggedIn()->timezone ) );
|
||||
$times[1] = $end->format( 'H:i' );
|
||||
}
|
||||
|
||||
$currentTime = new \IPS\DateTime( NULL, new \DateTimeZone( ( isset( $times[2] ) ) ? $times[2] : \IPS\Member::loggedIn()->timezone ) );
|
||||
$currentTime->setTimezone( new \DateTimeZone( \IPS\Member::loggedIn()->timezone ) );
|
||||
$currentTime = $currentTime->format( 'H:i' );
|
||||
|
||||
/* Convert times to floats, as that is simple to compare */
|
||||
$start = str_replace( ':', '.', $times[0] );
|
||||
$end = str_replace( ':', '.', $times[1] );
|
||||
$currentTime = str_replace( ':', '.', $currentTime );
|
||||
|
||||
if( $end > $start )
|
||||
{
|
||||
if( !( $currentTime >= $start ) OR !( $currentTime < $end ) )
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'chat_currently_offline', FALSE, array( 'sprintf' => $start ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !( $currentTime >= $start ) AND $currentTime >= $end )
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'chat_currently_offline', FALSE, array( 'sprintf' => $start ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"chat": {
|
||||
"logs": {
|
||||
"tab": "community",
|
||||
"controller": "logs",
|
||||
"do": "",
|
||||
"restriction": "logs_manage"
|
||||
},
|
||||
"settings": {
|
||||
"tab": "community",
|
||||
"controller": "settings",
|
||||
"do": "",
|
||||
"restriction": "settings_manage"
|
||||
},
|
||||
"logs": {
|
||||
"tab": "community",
|
||||
"controller": "logs",
|
||||
"do": "",
|
||||
"restriction": "logs_manage"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<javascript app="chat">
|
||||
<file javascript_app="chat" javascript_location="front" javascript_path="controllers/chat" javascript_name="ips.chat.main.js" javascript_type="controller" javascript_version="100045" javascript_position="1000050"><![CDATA[/**
|
||||
<file javascript_app="chat" javascript_location="front" javascript_path="controllers/chat" javascript_name="ips.chat.main.js" javascript_type="controller" javascript_version="101012" javascript_position="1000050"><![CDATA[/**
|
||||
* IPS Social Suite 4
|
||||
* (c) 2013 Invision Power Services - http://www.invisionpower.com
|
||||
*
|
||||
@@ -52,12 +52,29 @@
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup method
|
||||
* Setup wrapper method
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
setup: function () {
|
||||
//return;
|
||||
var self = this;
|
||||
|
||||
if( window.btoa && window.atob ){
|
||||
this._doSetup();
|
||||
} else {
|
||||
// If bas64 isn't supported in the browser (< IE10), then load a polyfill before continuing
|
||||
ips.loader.get( ['chat/interface/base64/base64.js'] ).then( function () {
|
||||
self._doSetup();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Performs setup tasks
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
_doSetup: function () {
|
||||
var self = this;
|
||||
|
||||
this._setUpMainPanel();
|
||||
@@ -331,7 +348,8 @@
|
||||
* @returns {void}
|
||||
*/
|
||||
_createBadge: function () {
|
||||
$('.elNavigation_app_chat_Chat').append( $('<span/>').addClass('ipsNotificationCount').text('0') );
|
||||
// This is now added with a hook and doesn't need to be done here
|
||||
//$('.elNavigation_app_chat_Chat').append( $('<span/>').addClass('ipsNotificationCount').text('0') );
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -457,7 +475,8 @@
|
||||
*/
|
||||
_ping: function () {
|
||||
var url = '?app=chat&module=chat&controller=action&do=ping';
|
||||
|
||||
var self = this;
|
||||
|
||||
// Load the mini profile to show in the sidebar
|
||||
ips.getAjax()( url, {
|
||||
data: {
|
||||
@@ -466,6 +485,17 @@
|
||||
})
|
||||
.done( function (response) {
|
||||
// We don't need to do anything
|
||||
})
|
||||
.fail(function(response){
|
||||
if ( response.responseJSON.message ) {
|
||||
var containers = self._getAllStorageContainers();
|
||||
containers.append( ips.templates.render('chat.system', {
|
||||
text: response.responseJSON.message,
|
||||
date: self._getChatTime( self._getCurrentTime() )
|
||||
}));
|
||||
self._kicked = true;
|
||||
self._scrollToBottom( self._activeTab );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -809,8 +839,8 @@
|
||||
this._checkInactivity( curtime );
|
||||
|
||||
if( this._kicked ){
|
||||
clearTimeout( this._poller );
|
||||
clearTimeout( this._updater );
|
||||
clearInterval( this._poller );
|
||||
clearInterval( this._updater );
|
||||
}
|
||||
|
||||
// If current time - last polled time is less than the polling timeperiod,
|
||||
@@ -1319,7 +1349,7 @@
|
||||
this.scope.find('[data-role="onlineChatters"]').html( ips.pluralize( ips.getString('usersChatting'), total ) );
|
||||
|
||||
// Update global chat tab
|
||||
$('.elNavigation_app_chat_Chat .ipsNotificationCount').text( total );
|
||||
$('.ipsNavBar_primary [data-navapp="chat"] .ipsNotificationCount').text( total );
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1348,9 +1378,9 @@
|
||||
_unCleanMessage: function (message) {
|
||||
return message
|
||||
.replace( /__PS__/g, "+" )
|
||||
.replace( /__E__/g, "=" )
|
||||
.replace( /__P__/g, "%" )
|
||||
.replace( /__A__/g, "&" )
|
||||
.replace( /__E__/g, "=" )
|
||||
.replace( /__C__/g, "," )
|
||||
.replace( /__N__/g, "<br />" );
|
||||
},
|
||||
@@ -1374,10 +1404,20 @@
|
||||
// @todo this line still needed?
|
||||
message = message.replace( '!', '!' );
|
||||
|
||||
_.each( ips.getSetting('chatEmoticons'), function (url, emoticon) {
|
||||
var img = "$1<img src='" + url + "'>$2";
|
||||
_.each( ips.getSetting('chatEmoticons'), function (url, emoticon) {
|
||||
var img = $('<img/>').attr({ 'src': url['image'], 'data-emoticon': 'true' });
|
||||
if ( url['width'] ) {
|
||||
img.attr( 'width', url['width'] );
|
||||
}
|
||||
if ( url['height'] ) {
|
||||
img.attr( 'height', url['width'] );
|
||||
}
|
||||
if ( url['image_2x'] ) {
|
||||
img.attr( 'srcset', url['image_2x'] );
|
||||
}
|
||||
img = "$1" + $('<div/>').append( img ).html() + "$2";
|
||||
|
||||
var regexp = new RegExp( "(^|\\s)" + self._escapeRegex( emoticon ) + "(\\s|$)", "gi" );
|
||||
|
||||
while( message.match( regexp ) ){
|
||||
message = message.replace( regexp, img );
|
||||
}
|
||||
@@ -1657,7 +1697,7 @@
|
||||
var indexOfURL = text.indexOf( url, lastPos );
|
||||
var returnURL = url;
|
||||
|
||||
if( text.substring( indexOfURL, indexOfURL - 5) !== "src='" ){
|
||||
if( text.substring( indexOfURL, indexOfURL - 5) !== 'src="' && text.substring( indexOfURL, indexOfURL - 8) !== 'srcset="' ){
|
||||
returnURL = '<a href="' + url + '" target="_blank">' + url + '</a>';
|
||||
}
|
||||
|
||||
@@ -1744,7 +1784,9 @@
|
||||
msgDetails[2] = _details.prefix.replace( /__DBQ__/g, '"' ) + msgDetails[2] + _details.suffix.replace( /__DBQ__/g, '"' );
|
||||
}
|
||||
|
||||
var tab = this.scope.find('#elChatTabs [data-user="' + msgDetails[2] + '"]')
|
||||
// https://community.invisionpower.com/4bugtrack/active-reports/chat-tabs-with-html-in-group-name-r8351/
|
||||
// This line isn't actually used and was causing the error.
|
||||
//var tab = this.scope.find('#elChatTabs [data-user="' + msgDetails[2] + '"]')
|
||||
|
||||
state.alsoTo = details[1];
|
||||
|
||||
@@ -1837,7 +1879,7 @@
|
||||
}
|
||||
});
|
||||
}(jQuery, _));]]></file>
|
||||
<file javascript_app="chat" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.chat.js" javascript_type="template" javascript_version="100045" javascript_position="1000100"><![CDATA[ips.templates.set('chat.tabs.tab', " \
|
||||
<file javascript_app="chat" javascript_location="front" javascript_path="templates" javascript_name="ips.templates.chat.js" javascript_type="template" javascript_version="101012" javascript_position="1000100"><![CDATA[ips.templates.set('chat.tabs.tab', " \
|
||||
<li role='presentation' data-roomID='{{roomID}}'>\
|
||||
<a href='#' role='tab' id='{{roomID}}' class='ipsFaded_withHover ipsTabs_item ipsType_blendLinks {{#active}}ipsTabs_activeItem{{/active}}' aria-selected='false'>\
|
||||
{{roomTitle}} {{#close}} <span class='ipsFaded ipsFaded_more' data-action='closeTab' data-ipsTooltip title='{{#lang}}closeThisTab{{/lang}}'><i class='fa fa-times'></i></span>{{/close}}\
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<language>
|
||||
<app key="chat" version="100045">
|
||||
<app key="chat" version="101012">
|
||||
<word key="__app_chat" js="0">Chat</word>
|
||||
<word key="frontnavigation_chat" js="0">Chat</word>
|
||||
<word key="chat_title" js="0">Chat</word>
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</li>
|
||||
<li>
|
||||
{{$leave = \IPS\Request::i()->_popup ? '&_popup=' . \IPS\Request::i()->_popup : '';}}
|
||||
<a href='{url="app=chat&module=chat&controller=view&do=leave{$leave}" seoTemplate="chat" csrf="true"}' class='ipsPos_right ipsButton ipsButton_verySmall ipsButton_overlaid' data-action='leaveChat' data-ipsTooltip title='{lang="chat_leave_room"}'>{lang="chat_leave_room"}</a>
|
||||
<a href='{url="app=chat&module=chat&controller=view&do=leave{$leave}" seoTemplate="chat" csrf="true"}' class='ipsPos_right ipsButton ipsButton_verySmall ipsButton_overlaid' data-action='leaveChat'>{lang="chat_leave_room"}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a href="#elChatTabs" data-action="expandTabs"><i class="fa fa-caret-down"></i></a>
|
||||
@@ -74,7 +74,7 @@
|
||||
</li>
|
||||
<li>
|
||||
{{$leave = \IPS\Request::i()->_popup ? '&_popup=' . \IPS\Request::i()->_popup : '';}}
|
||||
<a href='{url="app=chat&module=chat&controller=view&do=leave{$leave}" seoTemplate="chat" csrf="true"}' class='ipsPos_right ipsButton ipsButton_verySmall ipsButton_light' data-action='leaveChat' data-ipsTooltip title='{lang="chat_leave_room"}'>{lang="chat_leave_room"}</a>
|
||||
<a href='{url="app=chat&module=chat&controller=view&do=leave{$leave}" seoTemplate="chat" csrf="true"}' class='ipsPos_right ipsButton ipsButton_verySmall ipsButton_light' data-action='leaveChat'>{lang="chat_leave_room"}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -169,7 +169,9 @@
|
||||
<a href='#'>{lang="ipchat_ban"}</a>
|
||||
</li>
|
||||
{{endif}}
|
||||
<li class='ipsMenu_sep'><hr></li>
|
||||
{{if $data['forumUserID']}}
|
||||
<li class='ipsMenu_sep'><hr></li>
|
||||
{{endif}}
|
||||
{{endif}}
|
||||
{{if $data['forumUserID']}}
|
||||
<li class='ipsMenu_item'>
|
||||
|
||||
@@ -85,5 +85,18 @@
|
||||
"100042": "4.0.12",
|
||||
"100043": "4.0.12.1",
|
||||
"100044": "4.0.13",
|
||||
"100045": "4.0.13.1"
|
||||
"100045": "4.0.13.1",
|
||||
"101000": "4.1.0 Beta 1",
|
||||
"101001": "4.1.0 Beta 2",
|
||||
"101002": "4.1.0 Beta 3",
|
||||
"101003": "4.1.0 Beta 4",
|
||||
"101004": "4.1.0 Beta 5",
|
||||
"101005": "4.1.0 Beta 6",
|
||||
"101006": "4.1.0 Beta 7",
|
||||
"101007": "4.1.0 Beta 8",
|
||||
"101008": "4.1.0 Beta 9",
|
||||
"101009": "4.1.0 Beta 10",
|
||||
"101010": "4.1.0",
|
||||
"101011": "4.1.1",
|
||||
"101012": "4.1.2"
|
||||
}
|
||||
@@ -22,8 +22,18 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
/**
|
||||
* Front Navigation Extension: Chat
|
||||
*/
|
||||
class _Chat
|
||||
class _Chat extends \IPS\core\FrontNavigation\FrontNavigationAbstract
|
||||
{
|
||||
/**
|
||||
* Get Type Title which will display in the AdminCP Menu Manager
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function typeTitle()
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack('frontnavigation_chat');
|
||||
}
|
||||
|
||||
/**
|
||||
* Can access?
|
||||
*
|
||||
@@ -31,7 +41,7 @@ class _Chat
|
||||
*/
|
||||
public function canView()
|
||||
{
|
||||
return !\IPS\Application::load('chat')->hide_tab and \IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( 'chat', 'chat' ) );
|
||||
return parent::canView() and \IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( 'chat', 'chat' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,14 +73,4 @@ class _Chat
|
||||
{
|
||||
return \IPS\Dispatcher::i()->application->directory === 'chat';
|
||||
}
|
||||
|
||||
/**
|
||||
* Children
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function children()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ class _ChatAccess
|
||||
/**
|
||||
* Process Form
|
||||
*
|
||||
* @param \IPS\Form\Tabbed $form The form
|
||||
* @param \IPS\Helpers\Form $form The form
|
||||
* @param \IPS\Member\Group $group Existing Group
|
||||
* @return void
|
||||
*/
|
||||
|
||||
@@ -27,7 +27,7 @@ class _ChatBanned
|
||||
/**
|
||||
* Process Form
|
||||
*
|
||||
* @param \IPS\Form\Tabbed $form The form
|
||||
* @param \IPS\Helpers\Form $form The form
|
||||
* @param \IPS\Member $member Existing Member
|
||||
* @return void
|
||||
*/
|
||||
|
||||
@@ -49,7 +49,7 @@ class chat_hook_tabCount extends _HOOK_CLASS_
|
||||
|
||||
\IPS\Output::i()->endBodyCode .= <<<HTML
|
||||
<script type='text/javascript'>
|
||||
$('.elNavigation_app_chat_Chat').append( $('<span/>').addClass('ipsNotificationCount').text('{$count}') );
|
||||
$('[data-role="navBarItem"][data-navApp="chat"][data-navExt="Chat"]').append( $('<span/>').addClass('ipsNotificationCount').text('{$count}') );
|
||||
</script>
|
||||
HTML;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,10 @@ class chat_hook_tabCountLoad extends _HOOK_CLASS_
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->initLoad[] = 'chatters';
|
||||
if ( \IPS\CACHE_METHOD === 'None' )
|
||||
{
|
||||
$this->initLoad[] = 'chatters';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
!function(){function t(t){this.message=t}var r="undefined"!=typeof exports?exports:this,e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";t.prototype=new Error,t.prototype.name="InvalidCharacterError",r.btoa||(r.btoa=function(r){for(var o,n,a=String(r),i=0,c=e,d="";a.charAt(0|i)||(c="=",i%1);d+=c.charAt(63&o>>8-i%1*8)){if(n=a.charCodeAt(i+=.75),n>255)throw new t("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");o=o<<8|n}return d}),r.atob||(r.atob=function(r){var o=String(r).replace(/=+$/,"");if(o.length%4==1)throw new t("'atob' failed: The string to be decoded is not correctly encoded.");for(var n,a,i=0,c=0,d="";a=o.charAt(c++);~a&&(n=i%4?64*n+a:a,i++%4)?d+=String.fromCharCode(255&n>>(-2*i&6)):0)a=e.indexOf(a);return d})}();
|
||||
@@ -87,11 +87,12 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
), NULL, NULL, NULL, 'ipschat_online' ) );
|
||||
|
||||
if ( $values = $form->values( TRUE ) )
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
\IPS\Lang::saveCustom( 'chat', "ipschat_rules", $values['ipschat_rules_text'] );
|
||||
unset( $values['ipschat_rules_text'] );
|
||||
$values['ipchat_hide_usermessage'] = !$values['ipchat_hide_usermessage'];
|
||||
$values['ipschat_online'] = implode( ',', $values['ipschat_online'] );
|
||||
$form->saveAsSettings( $values );
|
||||
|
||||
/* Clear guest page caches */
|
||||
|
||||
@@ -175,6 +175,12 @@ class _action extends \IPS\Content\Controller
|
||||
*/
|
||||
protected function ping()
|
||||
{
|
||||
/* Still online? */
|
||||
if ( $offlineMessage = \IPS\Application::load('chat')->offlineMessage() )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'message' => $offlineMessage ), 500 );
|
||||
}
|
||||
|
||||
/* Make sure there is an ID */
|
||||
if( !\IPS\Request::i()->id )
|
||||
{
|
||||
|
||||