Files
IPB/upload/admin/sources/classes/like/composite.php
T
2025-12-19 00:32:22 -08:00

1248 lines
29 KiB
PHP

<?php
/**
* Class to manage like
*
* @author Matt Mecham
* @copyright (c) 2001 - 2010 Invision Power Services, Inc.
* @license http://www.invisionpower.com/community/board/license.html
* @package Core
* @link http://www.invisionpower.com
* @version $Rev: 6651 $
*/
/* Factory, composite and cache classes all in one file to save requires
*
* To use API-like methods:
* $like = new classes_like( 'gallery', 'images' );
* print $like->isLiked( $relId );
* $html = $like->render( 'summary', $relId );
* print $html;
*
* Matt, Joe, Bob and 5 others like this
*
*
* This loads the app specific composite class (which inherits from the abstract class classes_like_composite
* The composite class calls upon the registry and cache classes to manage data
*/
if ( ! defined( 'IN_IPB' ) )
{
print "<h1>Incorrect access</h1>You cannot access this file directly. If you have recently upgraded, make sure you upgraded all the relevant files.";
exit();
}
/**
* Quick registry class for common methods
*
* @author matt
*/
class classes_like_registry
{
/**
* App key
*
* @var string
*/
static private $app = null;
/**
* Area key
*
* @var string
*/
static private $area = null;
/**
* Total count
*
* @var string
*/
static private $count = null;
/**
* Cached bootstrap loaders
*
* @var array
*/
static private $bootstraps = array();
/**
* Get app key
*
* @return string
*/
static public function getApp()
{
return self::$app;
}
/**
* Set app key
*
* @param string
* @return void
*/
static public function setApp( $app )
{
self::$app = $app;
}
/**
* Get area key
*
* @return string
*/
static public function getArea()
{
return self::$area;
}
/**
* Set area key
*
* @param string
* @return void
*/
static public function setArea( $area )
{
self::$area = $area;
}
/**
* Get total count (saves on queries)
*
* @return string
*/
static public function getTotalCount()
{
return self::$count;
}
/**
* Set total count (saves on queries)
*
* @param string
* @return void
*/
static public function setTotalCount( $count )
{
self::$count = $count;
}
/**
* Pack key. Either for cache table, or full table
*
* @param int relationship ID
* @param int member ID
* @return binary binary key
*/
static public function getKey( $relId, $memberId=null )
{
/* Check */
if ( empty( $relId ) )
{
trigger_error( "Relationship ID missing in " . __CLASS__ . '::' . __FUNCTION__, E_USER_WARNING );
}
if ( $memberId === null )
{
/* For relative item only */
return md5( self::$app . ';' . self::$area . ';' . $relId );
}
else if ( ! empty( $memberId ) )
{
/* For member speciifc relative item */
return md5( self::$app . ';' . self::$area . ';' . $relId . ';' . $memberId );
}
else
{
trigger_error( "Member ID missing in " . __CLASS__ . '::' . __FUNCTION__, E_USER_WARNING );
}
}
}
/**
* Simple static class for fetching meta data
* @author matt
*
*/
class classes_like_meta
{
/**
* Retrieve the content title
*
* @param array Like data
* @return string Title of content liked
*/
static public function getTitleFromId( $like )
{
if ( empty( $like['like_app'] ) OR empty( $like['like_area'] ) OR empty( $like['like_rel_id'] ) )
{
trigger_error( "You must have like_app, like_rel_id and like_area set", E_USER_WARNING );
}
$_bootstrap = classes_like::bootstrap( $like['like_app'], $like['like_area'] );
return $_bootstrap->getTitleFromId( $like['like_rel_id'] );
}
/**
* Retrieve the content URL
*
* @param array Like data
* @return string URL of content liked
*/
static public function getUrlFromId( $like )
{
if ( empty( $like['like_app'] ) OR empty( $like['like_area'] ) OR empty( $like['like_rel_id'] ) )
{
trigger_error( "You must have like_app, like_rel_id and like_area set", E_USER_WARNING );
}
$_bootstrap = classes_like::bootstrap( $like['like_app'], $like['like_area'] );
return $_bootstrap->getUrlFromId( $like['like_rel_id'] );
}
/**
* Fetch all meta data from various like rows
* @param array $likes
* @return array
*/
static public function get( array $likes )
{
$apps = array();
$process = array();
$lookUp = array();
foreach( $likes as $id => $like )
{
if ( empty( $like['like_app'] ) OR empty( $like['like_area'] ) OR empty( $like['like_rel_id'] ) )
{
continue;
}
$apps[ $like['like_app'] . '-' . $like['like_area'] ][ $id ] = $like;
$lookUp[ $like['like_app'] . '-' . $like['like_area'] . '-' . $like['like_rel_id'] ] = $like['like_id'];
}
/* Process based on apps */
foreach( $apps as $app => $data )
{
list( $_app, $_area ) = explode( '-', $app );
$_bootstrap = classes_like::bootstrap( $_app, $_area );
$relIds = array();
foreach( $data as $_k => $_v )
{
$relIds[] = $_v['like_rel_id'];
}
/* Bulk fetch */
$process[ $app ] = $_bootstrap->getMeta( $relIds );
}
/* Fold up array */
foreach( $process as $app => $data )
{
list( $_app, $_area ) = explode( '-', $app );
foreach( $data as $relId => $_like )
{
if ( $relId )
{
$like_id = $lookUp[ $_app . '-' . $_area . '-' . $relId ];
if ( $like_id AND is_array( $_like ) AND is_array( $likes[ $like_id ] ) )
{
$likes[ $like_id ] = array_merge( $likes[ $like_id ], $_like );
}
}
}
}
return $likes;
}
}
/**
* Factory class, loads composite and child class
*
* @author matt
*/
class classes_like
{
/**
* App object
*
* @var array
*/
static private $apps;
/**
* Construct
*
* @param string Application
* @param string Area
* @return string
*/
static public function bootstrap( $app=null, $area=null )
{
if ( $app === null OR $area === null )
{
trigger_error( "App or area missing from classes_like", E_USER_WARNING );
}
/* Pointless comment! */
$_file = IPSLib::getAppDir( $app ) . '/extensions/like/' . $area . '.php';
$_class = 'like_' . $app . '_' . $area . '_composite';
$_key = md5( $app . $area );
/* Get from cache if already cached */
if( isset( self::$apps[ $_key ] ) )
{
return self::$apps[ $_key ];
}
/* Otherwise create object and cache */
if ( file_exists( $_file ) )
{
require_once( $_file );
if ( class_exists( $_class ) )
{
classes_like_registry::setApp( $app );
classes_like_registry::setArea( $area );
self::$apps[ $_key ] = new $_class();
self::$apps[ $_key ]->init();
}
else
{
throw new Exception( "No like class available for $app - $area" );
}
}
else
{
throw new Exception( "No like class available for $app - $area" );
}
return self::$apps[ $_key ];
}
}
/**
* Composite class. Holds main functionality.
*
* @author matt
*/
abstract class classes_like_composite
{
/**#@+
* Registry Object Shortcuts
*
* @var object
*/
protected $registry;
protected $DB;
protected $settings;
protected $request;
protected $lang;
protected $member;
protected $memberData;
protected $cache;
protected $caches;
/**#@-*/
/**
* Cache object
*
* @var object
*/
protected $likeCache = null;
/**
* App key
*
* @var object
*/
protected $_app;
/**
* App key
*
* @var object
*/
protected $_area;
/**
* Local settings object
*
* @var array
*/
protected $_settings;
/**
* Init. Yes, it is.
*
* @return void
*/
public function init()
{
$this->_app = classes_like_registry::getApp();
$this->_area = classes_like_registry::getArea();
if ( empty( $this->_app ) OR empty( $this->_area ) )
{
trigger_error( "Missing area or app variable in " . __CLASS__ . '::' . __FUNCTION__, E_USER_WARNING );
}
/* Fetch cache class */
$this->likeCache = classes_like_cache::getInstance();
/* Set a default cache expiration of an hour */
$this->likeCache->setExpiration( 3600 );
}
/**
* Add a like
*
* @param int Relationship ID
* @param int Member ID of user being added
* @param array Notification options
* @param int Anon flag
* @return boolean
*/
public function add( $relId, $memberId, array $notifyOpts, $isAnon=false )
{
if ( empty( $relId ) OR empty( $memberId ) )
{
trigger_error( "Data missing in " . __CLASS__ . '::' . __FUNCTION__, E_USER_WARNING );
}
/* first check to ensure we've not already like'd this item */
if ( $this->isLiked($relId, $memberId) )
{
/* if any one cares to check, then we're all good */
return false;
}
$notifyOpts = $this->_cleanNotifyOptions($notifyOpts);
/* Save to deebee */
$this->DB->insert( 'core_like', array( 'like_id' => classes_like_registry::getKey( $relId, $memberId ),
'like_lookup_id' => classes_like_registry::getKey( $relId ),
'like_app' => $this->_app,
'like_area' => $this->_area,
'like_rel_id' => $relId,
'like_member_id' => $memberId,
'like_added' => time(),
'like_is_anon' => $isAnon,
'like_notify_do' => $notifyOpts['like_notify_do'],
'like_notify_meta' => $notifyOpts['like_notify_meta'],
'like_notify_freq' => ( $notifyOpts['like_notify_do'] ) ? $notifyOpts['like_notify_freq'] : '',
'like_notify_sent' => 0 ) );
/* Flag cache as stale */
$this->likeCache->isNowStale( $relId );
return true;
}
/**
* Send notifications to anyone subscribed to item
*
* @param int Relationship ID
* @param array Types of notifications to send (Possible: immediate, offline, daily, weekly)
* @param array Notification options (Keys: notification_key, notification_url, email_template, email_subject, build_message_array, from (optional))
* @return boolean
* @see allowedFrequencies()
*/
public function sendNotifications( $relId, $type, $notificationOpts=array() )
{
if ( empty( $relId ) )
{
trigger_error( "Data missing in " . __CLASS__ . '::' . __FUNCTION__, E_USER_WARNING );
}
$type = is_array($type) ? $type : array( $type );
//-----------------------------------------
// Get users who have liked this item
//-----------------------------------------
$data = $this->getDataByRelationshipId( $relId );
//-----------------------------------------
// If no users, just return
//-----------------------------------------
if ( is_null($data) )
{
return false;
}
$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . '/sources/classes/member/notifications.php', 'notifications' );
$notifyLibrary = new $classToLoad( $this->registry );
//-----------------------------------------
// Loop over members and send notifications
//-----------------------------------------
foreach( $data as $row )
{
//-----------------------------------------
// Make sure this user is subscribed with this type
//-----------------------------------------
if( !$row['like_notify_freq'] OR !in_array( $row['like_notify_freq'], $type ) )
{
continue;
}
//-----------------------------------------
// If "offline" type, make sure user is offline
//-----------------------------------------
if( $row['like_notify_freq'] == 'offline' AND $row['last_activity'] > ( time() - $this->settings['session_expiration'] ) )
{
continue;
}
//-----------------------------------------
// Start building notification
//-----------------------------------------
IPSText::getTextClass('email')->getTemplate( $notificationOpts['email_template'], $row['language'] );
//-----------------------------------------
// Dynamically replace per-user data in message array
//-----------------------------------------
$buildMessage = array();
if ( is_array( $notificationOpts['build_message_array'] ) and count( $notificationOpts['build_message_array'] ) )
{
foreach( $notificationOpts['build_message_array'] as $k => $v )
{
if ( preg_match( '/\-member:(.+?)\-/', $v, $_matches ) )
{
$v = str_replace( $_matches[0], $row[$_matches[1]], $v );
}
$buildMessage[$k] = $v;
}
}
IPSText::getTextClass('email')->buildMessage( $buildMessage );
$notifyLibrary->setMember( $row );
$notifyLibrary->setFrom( $notificationOpts['from'] ? $notificationOpts['from'] : $this->memberData );
$notifyLibrary->setNotificationKey( $notificationOpts['notification_key'] );
$notifyLibrary->setNotificationUrl( $notificationOpts['notification_url'] );
$notifyLibrary->setNotificationText( IPSText::getTextClass('email')->message );
$notifyLibrary->setNotificationTitle( $notificationOpts['email_subject'] );
try
{
$notifyLibrary->sendNotification();
}
catch( Exception $e ){}
//-----------------------------------------
// Update sent timestamp
//-----------------------------------------
$this->DB->update( 'core_like', array( 'like_notify_sent' => time() ), 'like_id=\'' . classes_like_registry::getKey( $row['like_rel_id'], $row['like_member_id'] ) . '\'' );
}
return true;
}
/**
* Removes a like
*
* @param int Relationship ID
* @param int Optional - If supplied, it'll remove that member rel. or it will remove all
* @param array Notification options
* @param int Anon flag
* @return boolean
*/
public function remove( $relId, $memberId=null )
{
if ( empty( $relId ) )
{
trigger_error( "Data missing in " . __CLASS__ . '::' . __FUNCTION__, E_USER_WARNING );
}
if ( $memberId === null )
{
/* Save to deebee */
$this->DB->delete( 'core_like', 'like_lookup_id=\'' . classes_like_registry::getKey( $relId ) . '\'' );
}
else
{
/* Not liked? Save us the bother, then */
if ( ! $this->isLiked($relId, $memberId) )
{
/* if any one cares to check, then we're all good */
return false;
}
/* Save to deebee */
$this->DB->delete( 'core_like', 'like_id=\'' . classes_like_registry::getKey( $relId, $memberId ) . '\'' );
}
/* Flag cache as stale */
$this->likeCache->isNowStale( $relId );
return true;
}
/**
* Render a view
*
* @param string $view
* @param int $relId
* @param array Options
* @param int $memberId
* @return string
*/
public function render( $view, $relId, $opts=array(), $memberId = null )
{
/* In the future we could abstract this out to its own class
* At this time we only have a few views so it would be overkill */
if ( $view == 'summary' )
{
$data = array( 'names' => array(), 'count' => 0, 'formatted' => '', 'iFave' => false );
$cache = $this->likeCache->get( $relId );
/* We had the total count set from cache.get */
if ( classes_like_registry::getTotalCount() )
{
/* fetch data */
if ( $this->memberData['member_id'] AND $this->isLiked($relId, $this->memberData['member_id'] ) )
{
/* Now mix up the data */
$data['names'][] = array( 'name' => $this->lang->words['fave_moi'], 'seo' => $this->memberData['members_seo_name'], 'id' => $this->memberData['member_id'] );
/* Flag as me */
$data['iFave'] = true;
}
if ( is_array( $cache['members'] ) )
{
$i = 1;
$max = 3;
foreach( $cache['members'] as $mid => $mdata )
{
$_last = ( $i == $cache['count'] || $i == $max ) ? 1 : 0;
/* Is this you? */
if ( $mid == $this->memberData['member_id'] )
{
continue;
}
/* Push it on */
$data['names'][] = array( 'name' => $mdata['n'], 'seo' => $mdata['s'], 'id' => $mid, 'last' => $_last );
$i++;
if ( $i > $max )
{
/* Done thanks */
break;
}
}
}
}
/* Finish off */
$data['totalCount'] = $cache['count'];
$data['othersCount'] = ( $cache['count'] > $max ) ? $cache['count'] - $max : 0;
$data['app'] = $this->_app;
$data['area'] = $this->_area;
$data['formatted'] = $this->_formatNameString( $data );
if ( IPS_IS_AJAX )
{
return $this->registry->output->getTemplate( $this->skin() )->likeSummaryContents( $data, $relId, $opts );
}
else
{
return $this->registry->output->getTemplate( $this->skin() )->likeSummary( $data, $relId, $opts );
}
}
else if ( $view == 'more' )
{
/* Fetch members who have wanted to favorite this item */
$data = $this->getDataByRelationshipId( $relId );
return $this->registry->output->getTemplate( $this->skin() )->likeMoreDialogue( $data, $relId );
}
}
/**
* Fetch form data for set dialogue
*
* @param int relationship id
* @return array
*/
public function getDataForSetDialogue( $relid )
{
$return = array( 'frequencies' => $this->allowedFrequencies(),
'notifyType' => $this->getNotifyType() );
return $return;
}
/**
* Has this user made this item a fave already dudes?
*
* @param int Relationship ID
* @param int Member ID
* @return boolean
*/
public function isLiked( $relId, $memberId )
{
/* Grab the data */
return ( $this->getDataByMemberIdAndRelationshipId( $relId, $memberId ) === null ) ? false : true;
}
/**
* Get data based on a relationship ID and a member ID
*
* @param mixed int $relId or array $relId (many)
* @param int $memberId
* @return array Favorite data OR null
*/
public function getDataByMemberIdAndRelationshipId( $relId, $memberId )
{
$where = '';
if ( is_numeric( $relId ) )
{
$where = 'like_id=\'' . classes_like_registry::getKey( $relId, $memberId ) . '\'';
}
else if ( is_array( $relId ) )
{
$relId = IPSLib::cleanIntArray( $relId );
$keys = array();
foreach( $relId as $id )
{
$keys[] = "'" . classes_like_registry::getKey( $id, $memberId ) . "'";
}
if ( ! count( $keys ) )
{
return null;
}
$where = 'like_id IN (' . implode( ',', $keys ) . ')';
}
$this->DB->build( array( 'select' => '*',
'from' => 'core_like',
'where' => $where ) );
$o = $this->DB->execute();
while( $row = $this->DB->fetch( $o ) )
{
$data[ $row['like_rel_id'] ] = $row;
}
/* Just the one? */
if ( is_numeric( $relId ) and count( $data ) )
{
$data = array_shift( $data );
}
return ( is_array( $data ) ) ? $data : null;
}
/**
* Get data based on a relationship ID
*
* @param int $relId
* @return mixed Array of like data OR null
*/
public function getDataByRelationshipId( $relId )
{
/* Init */
$mids = array();
$members = array();
$rows = array();
/* Fetch data */
$this->DB->build( array( 'select' => '*',
'from' => 'core_like',
'where' => 'like_lookup_id=\'' . classes_like_registry::getKey( $relId ) . '\' AND like_is_anon=0',
'order' => 'like_added DESC',
'limit' => array( 0, 250 ) ) );
$o = $this->DB->execute();
while( $row = $this->DB->fetch( $o ) )
{
$data[ $row['like_member_id'] ] = $row;
$mids[ $row['like_member_id'] ] = intval( $row['like_member_id'] );
}
/* Just the one? */
if ( count( $mids ) )
{
$members = IPSMember::load( $mids, 'all' );
foreach( $members as $i => $d )
{
$_m = IPSMember::buildProfilePhoto( $d );
$data[ $i ] = array_merge( (array) $_m, (array) $data[ $i ] );
}
}
return ( is_array( $data ) ) ? $data : null;
}
/**
* Clean the notification options to make sure they're all nice and fluffy
*
* @param array $notifyOpts
* @return array
*/
private function _cleanNotifyOptions( array $notifyOpts )
{
if ( isset( $notifyOpts['like_notify_do'] ) )
{
$notifyOpts['like_notify_do'] = intval( $notifyOpts['like_notify_do'] );
}
else
{
$notifyOpts['like_notify_do'] = 0;
}
if ( ! isset( $notifyOpts['like_notify_meta'] ) )
{
$notifyOpts['like_notify_meta'] = '';
}
if ( isset( $notifyOpts['like_notify_freq'] ) )
{
$notifyOpts['like_notify_freq'] = ( in_array( $notifyOpts['like_notify_freq'], $this->allowedFrequencies() ) ) ? $notifyOpts['like_notify_freq'] : '';
}
else
{
$notifyOpts['like_notify_freq'] = 0;
}
return $notifyOpts;
}
/**
* Return an array of acceptable frequencies
* Possible: immediate, offline, daily, weekly
*
* @return array
*/
public function allowedFrequencies()
{
return array( 'immediate', 'offline', 'daily', 'weekly' );
}
/**
* return type of notification available for this item
*
* @return array key, human readable
*/
public function getNotifyType()
{
return array( 'comments', 'comments' );
}
/**
* Fetch the template group
*
* @return string
*/
public function skin()
{
return 'global_other';
}
/**
* Return the title based on the passed id
*
* @param int Relationship ID
* @return string Title
*/
public function getTitleFromId( $relId )
{
$meta = $this->getMeta( $relId, array( 'title' ) );
if ( is_numeric( $relId ) )
{
return $meta[ $relId ]['like.title'];
}
else
{
$return = array();
foreach( $meta as $id => $data )
{
$return[ $id ] = $data['like.title'];
}
return $return;
}
}
/**
* Return the URL based on the passed id
*
* @param int Relationship ID
* @return string URL
*/
public function getUrlFromId( $relId )
{
$meta = $this->getMeta( $relId, array( 'url' ) );
if ( is_numeric( $relId ) )
{
return $meta[ $relId ]['like.url'];
}
else
{
$return = array();
foreach( $meta as $id => $data )
{
$return[ $id ] = $data['like.url'];
}
return $return;
}
}
/**
* Formats the Bob, Bill, Joe and 2038 Others Hate You
*
* @param array $data
* @return string
*/
private function _formatNameString( array $data )
{
$langString = '';
$seeMoreLink = 'app=core&amp;module=global&amp;section=like&amp;do=more';
if ( ! is_array( $data['names'] ) OR ! count( $data['names'] ) )
{
return false;
}
/* Format up the names */
$i = 0;
$_names = array();
foreach( $data['names'] as $name )
{
if ( $this->memberData['member_id'] AND ( $this->memberData['member_id'] == $name['id'] ) )
{
$_names[$i] = $name['name'];
}
else
{
$_names[$i] = IPSLib::makeProfileLink($name['name'], $name['id'], $name['seo'] );
}
$i++;
}
/* More than one? */
if ( $data['totalCount'] > 1 )
{
/* Joe and Matt love you */
if ( $data['totalCount'] == 2 )
{
$_n = $_names[0] . ' ' . $this->lang->words['fave_and'] . ' ' . $_names[1];
$langString = sprintf( $this->lang->words['fave_formatted_many'], $_n );
}
/* Joe, Matt and Mike love you more */
else if ( $data['totalCount'] == 3 )
{
$_n = $_names[0] . ', ' . $_names[1] . ' ' . $this->lang->words['fave_and'] . ' ' . $_names[2];
$langString = sprintf( $this->lang->words['fave_formatted_many'], $_n );
}
/* Joe, Matt, Mike and 1 more love you */
else if ( $data['totalCount'] == 4 )
{
$_n = $_names[0] . ', ' . $_names[1] . ' ' . $this->lang->words['fave_and'] . ' ' . $_names[2];
$langString = sprintf( $this->lang->words['fave_formatted_one_more'], $_n, $seeMoreLink );
}
/* Joe, Matt, Mike and 5 more are indifferent to your redonkulous comments */
else
{
$_n = $_names[0] . ', ' . $_names[1] . ', ' . $_names[2];
$langString = sprintf( $this->lang->words['fave_formatted_more'], $_n, $seeMoreLink, $data['othersCount'] );
}
}
else
{
/* Just the one and it might be you! */
if ( $data['names'][0]['id'] == $this->memberData['member_id'] )
{
$langString = $this->lang->words['fave_formatted_me'];
}
else
{
$langString = sprintf( $this->lang->words['fave_formatted_one'], $_names[0] );
}
}
return $langString;
}
}
/**
* Favorites cache class
*
* @author matt
*/
class classes_like_cache
{
/**#@+
* Registry Object Shortcuts
*
* @var object
*/
protected $registry;
protected $DB;
protected $settings;
protected $request;
protected $lang;
protected $member;
protected $cache;
/**#@-*/
/**
* Cache expiration
*
* @var int
*/
protected $_expire = 0;
/**
* App key
*
* @var object
*/
protected $_app;
/**
* App key
*
* @var object
*/
protected $_area;
/**
* Instance of an object
*
* @var object
*/
private static $instance = null;
/**
* Singleton
*
* @return object
*/
public static function getInstance()
{
if ( self::$instance === null )
{
self::$instance = new self();
}
return self::$instance;
}
/**
* Our desctructor. Just kidding.
*
* @return void
*/
public function __construct()
{
/* Fetch registry like a good boy */
$this->registry = ipsRegistry::instance();
$this->DB = $this->registry->DB();
$this->settings =& $this->registry->fetchSettings();
$this->request =& $this->registry->fetchRequest();
$this->lang = $this->registry->getClass('class_localization');
$this->member = $this->registry->member();
$this->memberData =& $this->registry->member()->fetchMemberData();
$this->cache = $this->registry->cache();
$this->caches =& $this->registry->cache()->fetchCaches();
$this->_app = classes_like_registry::getApp();
$this->_area = classes_like_registry::getArea();
if ( empty( $this->_app ) OR empty( $this->_area ) )
{
trigger_error( "Missing area or app variable in " . __CLASS__ . '::' . __FUNCTION__, E_USER_WARNING );
}
}
/**
* Set the cache expiration
*
* @param int $seconds
* @return void
*/
public function setExpiration( $seconds )
{
$this->_expire = intval( $seconds );
}
/**
* Fetch an item from the cache
*
* @param int $relId
* @param int $memberId
* @return array
*/
public function get( $relId, $memberId = null )
{
/* Possible future expansion */
if ( $memberId === null )
{
$cache = $this->DB->buildAndFetch( array( 'select' => '*',
'from' => 'core_like_cache',
'where' => 'like_cache_id=\'' . classes_like_registry::getKey( $relId ) . '\'' ) );
if ( ! is_array( $cache ) OR ( $cache['like_cache_expire'] <= time() ) )
{
/* We don't have a valid cache, so create one and return the data */
$cache = $this->create( $relId, $memberId );
}
$tmp = unserialize( $cache['like_cache_data'] );
$cache['members'] = $tmp['members'];
$cache['count'] = intval( $tmp['count'] );
/* Set total count for use elsewhere */
classes_like_registry::setTotalCount( $cache['count'] );
return $cache;
}
}
/**
* Creates/updates the relationship ID's cache.
*
* @param int $relId
* @param int $memberId
* @return array Array of data stored
*/
public function create( $relId, $memberId = null )
{
$items = array();
$members = array();
$mids = array();
$data = array( 'members' => null, 'count' => 0 );
/* Possible future expansion */
if ( $memberId === null )
{
/* Count all first */
$cou = $this->DB->buildAndFetch( array( 'select' => 'COUNT(*) as nt',
'from' => 'core_like',
'where' => 'like_lookup_id=\'' . classes_like_registry::getKey( $relId ) . '\' AND like_is_anon=0' ) );
$data['count'] = intval( $cou['nt'] );
/* Fetch all items for this app:key:$relId */
$this->DB->build( array( 'select' => '*',
'from' => 'core_like',
'where' => 'like_lookup_id=\'' . classes_like_registry::getKey( $relId ) . '\' AND like_is_anon=0',
'order' => 'like_added DESC',
'limit' => array( 0, 5 ) ) );
$o = $this->DB->execute();
while( $row = $this->DB->fetch($o) )
{
$items[ $row['like_rel_id'] ] = $row;
$mids[ $row['like_member_id'] ] = $row['like_member_id'];
}
/* Load members */
$members = IPSMember::load( $mids, 'core' );
/* We don't need all the member's infos */
foreach( $members as $mid => $mdata )
{
$data['members'][ $mid ] = array( 'n' => $mdata['members_display_name'], 's' => $mdata['members_seo_name'] );
}
/* Build save array */
$store = array( 'like_cache_id' => classes_like_registry::getKey( $relId ),
'like_cache_app' => $this->_app,
'like_cache_area' => $this->_area,
'like_cache_rel_id' => $relId,
'like_cache_data' => serialize( $data ),
'like_cache_expire' => time() + $this->_expire );
/* Update the cache */
$this->DB->replace( 'core_like_cache', $store, array( 'like_cache_id' ) );
return $store;
}
/* We know there's a previous cache row, so delete it */
$this->DB->delete( 'core_like_cache', 'like_cache_id=\'' . classes_like_registry::getKey( $relId ) . '\'' );
}
/**
* Deletes a cache.
*
* @param int $relId
* @param int $memberId
* @return void
*/
public function delete( $relId, $memberId = null )
{
/* Possible future expansion */
if ( $memberId === null )
{
$this->DB->delete( 'core_like_cache', 'like_cache_id=\'' . classes_like_registry::getKey( $relId ) . '\'' );
}
}
/**
* Flags a cache as stale. We choose to delete, but the cache class should make the call
* not the application
*
* @param int $relId
* @param int $memberId
* @return void
*/
public function isNowStale( $relId, $memberId = null )
{
return $this->delete( $relId, $memberId );
}
}