Version 4.1.19

This commit is contained in:
Neo committed 2025-12-19 05:38:56 -08:00
1 parent 28bd025b35
commit 2bd5025018
2674 files changed
+233518 -77766

No files matched your search

+18 -2
View File
@@ -2,9 +2,9 @@
/**
* @brief Abstract Data Class
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 25 Sep 2013
* @version SVN_VERSION_NUMBER
*/
@@ -92,6 +92,22 @@ abstract class _AbstractData
$this->_data[ $key ] = $value;
$this->_exists[ $key ] = $key;
}
else
{
/* We can only really log if datastore fails, because if cache fails we create a catch-22 where settings can't/hasn't loaded but
we rely on that data for logging, so don't log if this is for cache */
$classname = explode( '\\', get_class( $this ) );
if( $classname[2] == 'Cache' )
{
return;
}
$classarea = array_pop( $classname );
$namespace = array_pop( $classname );
\IPS\Log::log( "Could not write to {$namespace}-{$classarea} ({$key})", 'datastore' );
}
}
/**
+31 -49
View File
@@ -2,9 +2,9 @@
/**
* @brief Abstract Storage Class
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 07 May 2013
* @version SVN_VERSION_NUMBER
*/
@@ -51,7 +51,14 @@ abstract class _Cache extends AbstractData
if ( $classname::supported() )
{
static::$instance = new $classname( json_decode( \IPS\CACHE_CONFIG, TRUE ) );
try
{
static::$instance = new $classname( json_decode( \IPS\CACHE_CONFIG, TRUE ) );
}
catch( \IPS\Data\Cache\Exception $e )
{
static::$instance = new \IPS\Data\Cache\None( array() );
}
}
else
{
@@ -73,20 +80,17 @@ abstract class _Cache extends AbstractData
*/
public function storeWithExpire( $key, $value, \IPS\DateTime $expire, $fallback=FALSE )
{
if ( \IPS\CACHE_METHOD === 'None' )
$value = array( 'value' => $value, 'expires' => $expire->getTimestamp() );
if ( \IPS\CACHING_LOG )
{
if ( $fallback )
{
\IPS\Db::i()->replace( 'core_cache', array(
'cache_key' => $key,
'cache_value' => json_encode( $value ),
'cache_expire' => $expire->getTimestamp()
) );
}
$this->log[] = array( 'set', $key, version_compare( PHP_VERSION, '5.4.0' ) >= 0 ? json_encode( $value, JSON_PRETTY_PRINT ) : json_encode( $value ), var_export( debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ), TRUE ) );
}
else
if ( $this->set( $key, json_encode( $value ), $expire ) )
{
$this->$key = array( 'value' => $value, 'expires' => $expire->getTimestamp() );
$this->_data[ $key ] = $value;
$this->_exists[ $key ] = $key;
}
}
@@ -100,44 +104,18 @@ abstract class _Cache extends AbstractData
*/
public function getWithExpire( $key, $fallback=FALSE )
{
if ( \IPS\CACHE_METHOD === 'None' )
if ( !isset( $this->$key ) )
{
if ( $fallback )
{
try
{
return json_decode( \IPS\Db::i()->select( 'cache_value', 'core_cache', array( 'cache_key=? AND cache_expire>?', $key, time() ) )->first(), TRUE );
}
catch ( \UnderflowException $e )
{
throw new \OutOfRangeException;
}
}
else
{
throw new \OutOfRangeException;
}
throw new \OutOfRangeException;
}
else
$data = $this->$key;
if( count( $data ) and isset( $data['value'] ) and isset( $data['expires'] ) )
{
if ( !isset( $this->$key ) )
/* Is it expired? */
if( $data['expires'] AND time() < $data['expires'] )
{
throw new \OutOfRangeException;
}
$data = $this->$key;
if( count( $data ) and isset( $data['value'] ) and isset( $data['expires'] ) )
{
/* Is it expired? */
if( $data['expires'] AND time() < $data['expires'] )
{
return $data['value'];
}
else
{
unset( $this->$key );
throw new \OutOfRangeException;
}
return $data['value'];
}
else
{
@@ -145,6 +123,11 @@ abstract class _Cache extends AbstractData
throw new \OutOfRangeException;
}
}
else
{
unset( $this->$key );
throw new \OutOfRangeException;
}
}
/**
@@ -160,5 +143,4 @@ abstract class _Cache extends AbstractData
does not allow us to actually clear them */
\IPS\Data\Store::i()->cacheKeys = array();
}
}
+19 -18
View File
@@ -2,9 +2,9 @@
/**
* @brief APC Caching Class
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 17 Sept 2013
* @version SVN_VERSION_NUMBER
*/
@@ -30,7 +30,7 @@ class _Apc extends \IPS\Data\Cache
*/
public static function supported()
{
return function_exists('apc_fetch');
return function_exists('apcu_fetch');
}
/**
@@ -43,27 +43,28 @@ class _Apc extends \IPS\Data\Cache
{
if( isset( $this->cache[ $key ] ) )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Get {$key} from APC (already loaded)", 'cache' );
\IPS\Log::debug( "Get {$key} from APC (already loaded)", 'cache' );
return $this->cache[ $key ];
}
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Get {$key} from APC", 'cache' );
\IPS\Log::debug( "Get {$key} from APC", 'cache' );
$this->cache[ $key ] = apc_fetch( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
$this->cache[ $key ] = apcu_fetch( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
return $this->cache[ $key ];
}
/**
* Abstract Method: Set
*
* @param string $key Key
* @param string $value Value
* @param string $key Key
* @param string $value Value
* @para, \IPS\DateTime $expire Expreation time, or NULL for no expiration
* @return bool
*/
protected function set( $key, $value )
protected function set( $key, $value, \IPS\DateTime $expire = NULL )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Set {$key} in APC", 'cache' );
return (bool) apc_store( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $value );
\IPS\Log::debug( "Set {$key} in APC", 'cache' );
return (bool) apcu_store( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $value, $expire ? ( $expire->getTimestamp() - time() ) : 0 );
}
/**
@@ -76,13 +77,13 @@ class _Apc extends \IPS\Data\Cache
{
if( isset( $this->cache[ $key ] ) )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Check exists {$key} from APC (already loaded)", 'cache' );
return TRUE;
\IPS\Log::debug( "Check exists {$key} from APC (already loaded)", 'cache' );
return ( $this->cache[ $key ] === FALSE ) ? FALSE : TRUE;
}
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Check exists {$key} from APC", 'cache' );
\IPS\Log::debug( "Check exists {$key} from APC", 'cache' );
$result = apc_fetch( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $exists );
$result = apcu_fetch( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $exists );
if ( $exists )
{
$this->cache[ $key ] = $result;
@@ -102,8 +103,8 @@ class _Apc extends \IPS\Data\Cache
*/
protected function delete( $key )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Delete {$key} from APC", 'cache' );
return (bool) apc_delete( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
\IPS\Log::debug( "Delete {$key} from APC", 'cache' );
return (bool) apcu_delete( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
}
/**
@@ -114,6 +115,6 @@ class _Apc extends \IPS\Data\Cache
public function clearAll()
{
parent::clearAll();
apc_clear_cache();
apcu_clear_cache();
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
/**
* @brief Abstract Storage Class
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @since 07 May 2013
* @version SVN_VERSION_NUMBER
*/
namespace IPS\Data\Cache;
/* 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;
}
/**
* Cache Exception Class
*/
class _Exception extends \RuntimeException
{
}
+23 -7
View File
@@ -2,9 +2,9 @@
/**
* @brief Memcache Cache Class
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 17 Sept 2013
* @version SVN_VERSION_NUMBER
*/
@@ -137,19 +137,35 @@ class _Memcache extends \IPS\Data\Cache
/**
* Abstract Method: Set
*
* @param string $key Key
* @param string $value Value
* @param string $key Key
* @param string $value Value
* @para, \IPS\DateTime $expire Expreation time, or NULL for no expiration
* @return bool
*/
protected function set( $key, $value )
protected function set( $key, $value, \IPS\DateTime $expire = NULL )
{
if ( in_array( $key, $this->doesNotExist ) )
{
unset( $this->doesNotExist[ array_search( $key, $this->doesNotExist ) ] );
}
$this->cache[ $key ] = $value;
return (bool) $this->link->set( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $value );
if ( $this->link instanceof \Memcached )
{
$result = (bool) $this->link->set( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $value, $expire ? $expire->getTimestamp() : 0 );
if ( !$result )
{
$error = $this->link->getResultCode();
/** will log the error code returned by memcached; lookup: http://php.net/manual/en/memcached.getresultcode.php */
\IPS\Log::debug( 'error code ' . $error, 'memcached_set_error' );
}
return $result;
}
else
{
return (bool) $this->link->set( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $value, MEMCACHE_COMPRESSED, $expire ? $expire->getTimestamp() : 0 );
}
}
/**
+50 -2
View File
@@ -2,9 +2,9 @@
/**
* @brief Dummy Cache Class
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 17 Sept 2013
* @version SVN_VERSION_NUMBER
*/
@@ -103,6 +103,33 @@ class _None extends \IPS\Data\Cache
throw new \RuntimeException;
}
/**
* Get value using cache method if available or falling back to the database
*
* @param string $key Key
* @param bool $fallback Use database if no caching method is available?
* @return mixed
* @throws \OutOfRangeException
*/
public function getWithExpire( $key, $fallback=FALSE )
{
if ( $fallback )
{
try
{
return json_decode( \IPS\Db::i()->select( 'cache_value', 'core_cache', array( 'cache_key=? AND cache_expire>?', $key, time() ) )->first(), TRUE );
}
catch ( \UnderflowException $e )
{
throw new \OutOfRangeException;
}
}
else
{
throw new \OutOfRangeException;
}
}
/**
* Abstract Method: Set
*
@@ -115,6 +142,27 @@ class _None extends \IPS\Data\Cache
return FALSE;
}
/**
* Store value using cache method if available or falling back to the database
*
* @param string $key Key
* @param mixed $value Value
* @param \IPS\DateTime $expire Expiration if using database
* @param bool $fallback Use database if no caching method is available?
* @return void
*/
public function storeWithExpire( $key, $value, \IPS\DateTime $expire, $fallback=FALSE )
{
if ( $fallback )
{
\IPS\Db::i()->replace( 'core_cache', array(
'cache_key' => $key,
'cache_value' => json_encode( $value ),
'cache_expire' => $expire->getTimestamp()
) );
}
}
/**
* Abstract Method: Exists?
*
+145 -35
View File
@@ -2,9 +2,9 @@
/**
* @brief Redis Cache Class
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 18 Oct 2013
* @version SVN_VERSION_NUMBER
*/
@@ -63,7 +63,17 @@ class _Redis extends \IPS\Data\Cache
/**
* @brief Connection resource
*/
protected $link = null;
protected static $links = array();
/**
* @brief Connection key
*/
protected $connectionKey = NULL;
/**
* @brief Connection timeout - keep low or you negate the benefits of caching
*/
protected $timeout = 2;
/**
* Constructor
@@ -73,71 +83,140 @@ class _Redis extends \IPS\Data\Cache
*/
public function __construct( $configuration )
{
/* Figure out our connection key, as you could theoretically attempt to connect to more than one Redis server */
$this->connectionKey = md5( $configuration['server'] . ':' . $configuration['port'] );
/* If we've already attempted to establish this link, just return now */
if( isset( static::$links[ $this->connectionKey ] ) )
{
return;
}
/* Connect to server */
try
{
$this->link = new \Redis;
static::$links[ $this->connectionKey ] = new \Redis;
if( $this->link->connect( $configuration['server'], $configuration['port'] ) === FALSE )
if( static::$links[ $this->connectionKey ]->connect( $configuration['server'], $configuration['port'], $this->timeout ) === FALSE )
{
$this->link = NULL;
$this->resetConnection();
throw new \RedisException;
}
else
{
if( $configuration['password'] )
{
if( $this->link->auth( $configuration['password'] ) === FALSE )
if( static::$links[ $this->connectionKey ]->auth( $configuration['password'] ) === FALSE )
{
$this->link = NULL;
$this->resetConnection();
throw new \RedisException;
}
}
}
if( $this->link !== NULL )
if( static::$links[ $this->connectionKey ] !== NULL )
{
$this->link->setOption( \Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP );
static::$links[ $this->connectionKey ]->setOption( \Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP );
}
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Connected to Redis", 'cache' );
/* If connection times out, connect can return TRUE and we won't know until our next attempt to talk to the server,
so we should ping now to verify we were able to connect successfully */
static::$links[ $this->connectionKey ]->ping();
register_shutdown_function( function( $object ){
try
{
if( isset( static::$links[ $object->connectionKey ] ) AND static::$links[ $object->connectionKey ] )
{
static::$links[ $object->connectionKey ]->close();
unset( static::$links[ $object->connectionKey ] );
}
}
catch( \RedisException $e ){}
}, $this );
\IPS\Log::debug( "Connected to Redis", 'cache' );
}
catch( \RedisException $e )
{
$this->link = NULL;
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Connection to Redis failed", 'cache' );
$this->resetConnection( $e );
\IPS\Log::debug( "Connection to Redis failed", 'cache' );
}
}
/**
* Abstract Method: Get
*
* @param string $key Key
* @return string Value from the _datastore
* @param string $key
* @return string|FALSE Value from the _datastore; FALSE if key doesn't exist
*/
protected function get( $key )
{
if( isset( $this->cache[ $key ] ) )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Get {$key} from Redis (already loaded)", 'cache' );
\IPS\Log::debug( "Get {$key} from Redis (already loaded)", 'cache' );
return $this->cache[ $key ];
}
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Get {$key} from Redis", 'cache' );
if ( static::$links[ $this->connectionKey ] )
{
\IPS\Log::debug( "Get {$key} from Redis", 'cache' );
$this->cache[ $key ] = $this->link->get( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
return $this->cache[ $key ];
try
{
$this->cache[ $key ] = static::$links[ $this->connectionKey ]->get( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
return $this->cache[ $key ];
}
catch( \RedisException $e )
{
$this->resetConnection( $e );
return FALSE;
}
}
/* No connection */
return FALSE;
}
/**
* Abstract Method: Set
*
* @param string $key Key
* @param string $value Value
* @param string $key Key
* @param string $value Value
* @param \IPS\DateTime $expire Expreation time, or NULL for no expiration
* @return bool
*/
protected function set( $key, $value )
protected function set( $key, $value, \IPS\DateTime $expire = NULL )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Set {$key} in Redis", 'cache' );
return (bool) $this->link->set( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $value );
if ( static::$links[ $this->connectionKey ] )
{
\IPS\Log::debug( "Set {$key} in Redis", 'cache' );
try
{
if ( $expire )
{
return (bool) static::$links[ $this->connectionKey ]->setex( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $expire->getTimestamp() - time(), $value );
}
else
{
return (bool) static::$links[ $this->connectionKey ]->set( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $value );
}
}
catch( \RedisException $e )
{
$this->resetConnection( $e );
return FALSE;
}
}
/* No connection */
return FALSE;
}
/**
@@ -150,11 +229,12 @@ class _Redis extends \IPS\Data\Cache
{
if( isset( $this->cache[ $key ] ) )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Check exists {$key} from Redis (already loaded)", 'cache' );
return TRUE;
\IPS\Log::debug( "Check exists {$key} from Redis (already loaded)", 'cache' );
return ( $this->cache[ $key ] === FALSE ) ? FALSE : TRUE;
}
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Check exists {$key} from Redis", 'cache' );
\IPS\Log::debug( "Check exists {$key} from Redis", 'cache' );
/* We do a get instead of an exists() check because it will cause the cache value to be fetched and cached inline, saving another call to the server */
return ( $this->get( $key ) === FALSE ) ? FALSE : TRUE;
}
@@ -167,22 +247,52 @@ class _Redis extends \IPS\Data\Cache
*/
protected function delete( $key )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Delete {$key} from Redis", 'cache' );
return (bool) $this->link->delete( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
if ( static::$links[ $this->connectionKey ] )
{
\IPS\Log::debug( "Delete {$key} from Redis", 'cache' );
try
{
return (bool) static::$links[ $this->connectionKey ]->delete( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
}
catch( \RedisException $e )
{
$this->resetConnection( $e );
}
}
/* No connection */
return FALSE;
}
/**
* Destructor
* Reset connection
*
* @param \RedisException|NULL If this was called as a result of an exception, log that to the debug log
* @return void
*/
protected function resetConnection( \RedisException $e = NULL )
{
if ( $e !== NULL )
{
\IPS\Log::debug( $e, 'redis_exception' );
}
static::$links[ $this->connectionKey ] = NULL;
throw new \IPS\Data\Cache\Exception;
}
/**
* Abstract Method: Clear All Caches
*
* @return void
*/
public function __destruct()
public function clearAll()
{
if( $this->link )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Disconnect from Redis", 'cache' );
parent::clearAll();
$this->link->close();
if ( static::$links[ $this->connectionKey ] )
{
static::$links[ $this->connectionKey ]->flushDb();
}
}
}
+6 -5
View File
@@ -2,9 +2,9 @@
/**
* @brief Test Cache Class
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 7 Jan 2015
* @version SVN_VERSION_NUMBER
*/
@@ -74,11 +74,12 @@ class _Test extends \IPS\Data\Cache
/**
* Abstract Method: Set
*
* @param string $key Key
* @param string $value Value
* @param string $key Key
* @param string $value Value
* @para, \IPS\DateTime $expire Expreation time, or NULL for no expiration
* @return bool
*/
protected function set( $key, $value )
protected function set( $key, $value, \IPS\DateTime $expire = NULL )
{
$return = \file_put_contents( $this->_path . '/' . $key . '.txt', $value );
chmod( $this->_path . '/' . $key . '.txt', \IPS\IPS_FILE_PERMISSION );
+14 -13
View File
@@ -2,9 +2,9 @@
/**
* @brief Wincache Cache Class
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 17 Sept 2013
* @version SVN_VERSION_NUMBER
*/
@@ -43,11 +43,11 @@ class _Wincache extends \IPS\Data\Cache
{
if( isset( $this->cache[ $key ] ) )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Get {$key} from Wincache (already loaded)", 'cache' );
\IPS\Log::debug( "Get {$key} from Wincache (already loaded)", 'cache' );
return $this->cache[ $key ];
}
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Get {$key} from Wincache", 'cache' );
\IPS\Log::debug( "Get {$key} from Wincache", 'cache' );
$this->cache[ $key ] = wincache_ucache_get( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
return $this->cache[ $key ];
@@ -56,14 +56,15 @@ class _Wincache extends \IPS\Data\Cache
/**
* Abstract Method: Set
*
* @param string $key Key
* @param string $value Value
* @param string $key Key
* @param string $value Value
* @para, \IPS\DateTime $expire Expreation time, or NULL for no expiration
* @return bool
*/
protected function set( $key, $value )
protected function set( $key, $value, \IPS\DateTime $expire = NULL )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Set {$key} in Wincache", 'cache' );
return (bool) wincache_ucache_set( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $value );
\IPS\Log::debug( "Set {$key} in Wincache", 'cache' );
return (bool) wincache_ucache_set( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $value, $expire ? ( $expire->getTimestamp() - time() ) : 0 );
}
/**
@@ -76,11 +77,11 @@ class _Wincache extends \IPS\Data\Cache
{
if( isset( $this->cache[ $key ] ) )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Check exists {$key} from Wincache (already loaded)", 'cache' );
return TRUE;
\IPS\Log::debug( "Check exists {$key} from Wincache (already loaded)", 'cache' );
return ( $this->cache[ $key ] === FALSE ) ? FALSE : TRUE;
}
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Check exists {$key} from Wincache", 'cache' );
\IPS\Log::debug( "Check exists {$key} from Wincache", 'cache' );
return wincache_ucache_exists( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
}
@@ -92,7 +93,7 @@ class _Wincache extends \IPS\Data\Cache
*/
protected function delete( $key )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Delete {$key} from Wincache", 'cache' );
\IPS\Log::debug( "Delete {$key} from Wincache", 'cache' );
return (bool) wincache_ucache_delete( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
}
+14 -13
View File
@@ -2,9 +2,9 @@
/**
* @brief XCache Cache Class
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 17 Sept 2013
* @version SVN_VERSION_NUMBER
*/
@@ -43,11 +43,11 @@ class _Xcache extends \IPS\Data\Cache
{
if( isset( $this->cache[ $key ] ) )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Get {$key} from Xcache (already loaded)", 'cache' );
\IPS\Log::debug( "Get {$key} from Xcache (already loaded)", 'cache' );
return $this->cache[ $key ];
}
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Get {$key} from Xcache", 'cache' );
\IPS\Log::debug( "Get {$key} from Xcache", 'cache' );
$this->cache[ $key ] = xcache_get( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
return $this->cache[ $key ];
@@ -56,14 +56,15 @@ class _Xcache extends \IPS\Data\Cache
/**
* Abstract Method: Set
*
* @param string $key Key
* @param string $value Value
* @param string $key Key
* @param string $value Value
* @para, \IPS\DateTime $expire Expreation time, or NULL for no expiration
* @return bool
*/
protected function set( $key, $value )
protected function set( $key, $value, \IPS\DateTime $expire = NULL )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Set {$key} in Xcache", 'cache' );
return (bool) xcache_set( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $value );
\IPS\Log::debug( "Set {$key} in Xcache", 'cache' );
return (bool) xcache_set( \IPS\SUITE_UNIQUE_KEY . '_' . $key, $value, $expire ? ( $expire->getTimestamp() - time() ) : 0 );
}
/**
@@ -76,11 +77,11 @@ class _Xcache extends \IPS\Data\Cache
{
if( isset( $this->cache[ $key ] ) )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Check exists {$key} from Xcache (already loaded)", 'cache' );
return TRUE;
\IPS\Log::debug( "Check exists {$key} from Xcache (already loaded)", 'cache' );
return ( $this->cache[ $key ] === FALSE OR $this->cache[ $key ] === NULL ) ? FALSE : TRUE;
}
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Check exists {$key} from Xcache", 'cache' );
\IPS\Log::debug( "Check exists {$key} from Xcache", 'cache' );
return xcache_isset( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
}
@@ -92,7 +93,7 @@ class _Xcache extends \IPS\Data\Cache
*/
protected function delete( $key )
{
\IPS\Log::i( LOG_DEBUG )->setIpAddress( $_SERVER['REMOTE_ADDR'] )->write( "Delete {$key} from Xcache", 'cache' );
\IPS\Log::debug( "Delete {$key} from Xcache", 'cache' );
return (bool) xcache_unset( \IPS\SUITE_UNIQUE_KEY . '_' . $key );
}
}
+34 -7
View File
@@ -2,9 +2,9 @@
/**
* @brief Abstract Storage Class
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 07 May 2013
* @version SVN_VERSION_NUMBER
*/
@@ -35,13 +35,13 @@ abstract class _Store extends AbstractData
*/
public static function i()
{
if( self::$instance === NULL )
if( static::$instance === NULL )
{
$classname = 'IPS\Data\Store\\' . \IPS\STORE_METHOD;
self::$instance = new $classname( json_decode( \IPS\STORE_CONFIG, TRUE ) );
static::$instance = new $classname( json_decode( \IPS\STORE_CONFIG, TRUE ) );
}
return self::$instance;
return static::$instance;
}
/**
@@ -70,6 +70,33 @@ abstract class _Store extends AbstractData
{
}
/**
* Test the datastore engine to make sure it's working
*
* @return bool
*/
public function test()
{
/* Set a test key */
$key = 'test_' . md5( uniqid() );
$this->$key = '1';
/* Now clear our internal cache to ensure the value isn't returned from there */
unset( $this->_data[ $key ], $this->_exists[ $key ], static::$cache[ $key ] );
/* And then try to retrieve it */
if( isset( $this->$key ) )
{
$value = $this->$key;
unset( $this->$key );
return ( $value == 1 ) ? TRUE : FALSE;
}
return FALSE;
}
/**
* Magic Method: Get
@@ -93,7 +120,7 @@ abstract class _Store extends AbstractData
$value = \IPS\Data\Cache::i()->$key;
/* But only use it if the hash matches */
if ( $cacheKeys[ $key ] === md5( json_encode( $value ) ) )
if( \IPS\Login::compareHashes( $cacheKeys[ $key ], md5( json_encode( $value ) ) ) )
{
return $value;
}
@@ -177,7 +204,7 @@ abstract class _Store extends AbstractData
/* But only use it if the hash matches */
$cacheKeys = ( isset( $this->cacheKeys ) and is_array( $this->cacheKeys ) ) ? $this->cacheKeys : array();
if ( isset( $cacheKeys[ $key ] ) and $cacheKeys[ $key ] === md5( json_encode( $value ) ) )
if ( isset( $cacheKeys[ $key ] ) and \IPS\Login::compareHashes( $cacheKeys[ $key ], md5( json_encode( $value ) ) ) )
{
return TRUE;
}
+12 -5
View File
@@ -2,9 +2,9 @@
/**
* @brief Database Storage Class
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 07 May 2013
* @version SVN_VERSION_NUMBER
*/
@@ -36,7 +36,7 @@ class _Database extends \IPS\Data\Store
/**
* @brief Always needed Store keys
*/
public $initLoad = array( 'cacheKeys', 'settings', 'storageConfigurations', 'themes', 'languages', 'groups', 'applications', 'modules', 'widgets', 'furl', 'javascript_map', 'metaTags', 'bannedIpAddresses', 'license_data', 'furl_configuration' );
public $initLoad = array( 'cacheKeys', 'settings', 'storageConfigurations', 'themes', 'languages', 'groups', 'applications', 'modules', 'widgets', 'furl', 'javascript_map', 'metaTags', 'bannedIpAddresses', 'license_data', 'furl_configuration', 'rssFeeds', 'frontNavigation', 'globalStreamIds' );
/**
* @brief Have we done the intitial load?
@@ -107,8 +107,15 @@ class _Database extends \IPS\Data\Store
}
if ( !isset( static::$cache[ $key ] ) )
{
static::$cache[ $key ] = \IPS\Db::i()->select( 'store_value', 'core_store', array( 'store_key=?', $key ) )->first();
{
try
{
static::$cache[ $key ] = \IPS\Db::i()->select( 'store_value', 'core_store', array( 'store_key=?', $key ) )->first();
}
catch ( \IPS\Db\Exception $e )
{
throw new \UnderflowException;
}
}
return static::$cache[ $key ];
+32 -17
View File
@@ -2,9 +2,9 @@
/**
* @brief File System Storage Class
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 07 May 2013
* @version SVN_VERSION_NUMBER
*/
@@ -93,14 +93,14 @@ class _FileSystem extends \IPS\Data\Store
{
if ( !isset( static::$cache[ $key ] ) )
{
/* It is remotely possible that the file was removed in between an exists check and a get call on a busy site,
so we need to make sure the file still exists in order to prevent a php warning */
clearstatcache();
if ( file_exists( $this->_path . '/' . $key . '.' . \IPS\SUITE_UNIQUE_KEY . '.php' ) )
if ( @filesize( $this->_path . '/' . $key . '.' . \IPS\SUITE_UNIQUE_KEY . '.php' ) )
{
static::$cache[ $key ] = require( $this->_path . '/' . $key . '.' . \IPS\SUITE_UNIQUE_KEY . '.php' );
}
else
{
throw new \UnderflowException;
}
}
return static::$cache[ $key ];
@@ -139,9 +139,9 @@ CONTENTS;
static::$cache[ $key ] = $value;
/* Clear zend opcache if enabled */
if( function_exists('opcache_reset') )
if ( function_exists( 'opcache_invalidate' ) )
{
@opcache_reset();
@opcache_invalidate( $this->_path . '/' . $key . '.' . \IPS\SUITE_UNIQUE_KEY . '.php' );
}
return $result;
@@ -159,8 +159,18 @@ CONTENTS;
{
return TRUE;
}
return is_file( $this->_path . '/' . $key . '.' . \IPS\SUITE_UNIQUE_KEY . '.php' );
else
{
try
{
$this->get( $key );
return TRUE;
}
catch ( \UnderflowException $e )
{
return FALSE;
}
}
}
/**
@@ -171,21 +181,24 @@ CONTENTS;
*/
public function delete( $key )
{
$return = false;
if ( file_exists( $this->_path . '/' . $key . '.' . \IPS\SUITE_UNIQUE_KEY . '.php' ) )
{
return @unlink( $this->_path . '/' . $key . '.' . \IPS\SUITE_UNIQUE_KEY . '.php' );
$return = @unlink( $this->_path . '/' . $key . '.' . \IPS\SUITE_UNIQUE_KEY . '.php' );
}
if( isset( static::$cache[ $key ] ) )
if( array_key_exists( $key, static::$cache ) )
{
unset( static::$cache[ $key ] );
}
/* Clear zend opcache if enabled */
if( function_exists('opcache_reset') )
if ( function_exists( 'opcache_invalidate' ) )
{
@opcache_reset();
@opcache_invalidate( $this->_path . '/' . $key . '.' . \IPS\SUITE_UNIQUE_KEY . '.php' );
}
return $return;
}
/**
@@ -211,8 +224,10 @@ CONTENTS;
}
}
/* Clear zend opcache if enabled */
if( function_exists('opcache_reset') )
/* Clear zend opcache if enabled - we call reset here since we're wiping multiple files
and since this gets called as part of a general 'rebuild everything', a reset is
probably a good idea anyway */
if ( function_exists( 'opcache_reset' ) )
{
@opcache_reset();
}