526 lines
11 KiB
PHP
526 lines
11 KiB
PHP
<?php
|
|
|
|
/**
|
|
* <pre>
|
|
* Invision Power Services
|
|
* IP.Board v3.4.8
|
|
* Mobile iOS App image class
|
|
* Owner: Matt Mecham
|
|
* Last Updated: $Date: 2012-05-10 16:10:13 -0400 (Thu, 10 May 2012) $
|
|
*
|
|
* @author $Author: bfarber $
|
|
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
|
|
* @license http://www.invisionpower.com/company/standards.php#license
|
|
* @package IP.Board
|
|
* @link http://www.invisionpower.com
|
|
* @since 9th March 2005 11:03
|
|
* @version $Revision: 10721 $
|
|
*/
|
|
|
|
/**
|
|
* Manages mobile app images for the ACP
|
|
*
|
|
* @author matt
|
|
*
|
|
*/
|
|
class classes_mobile_iosImages
|
|
{
|
|
/**
|
|
* Image names
|
|
* @var string
|
|
*/
|
|
protected $_fileNames = array( 'ActionBarBackground',
|
|
'actionButton',
|
|
'actionButtonActive',
|
|
'backButton',
|
|
'backButtonActive',
|
|
'menuButton',
|
|
'menuButtonActive',
|
|
'NavBarBackground',
|
|
'readIcon',
|
|
'unreadIcon' );
|
|
|
|
/**
|
|
* Retina suffix
|
|
* @var string
|
|
*/
|
|
protected $_retinaSuffix = '@2x';
|
|
|
|
|
|
/**
|
|
* Mobile app folder
|
|
*/
|
|
protected $_imageDir = '';
|
|
protected $_imageUrl = '';
|
|
protected $_defaultDir = '';
|
|
protected $_defaultImageUrl = '';
|
|
|
|
protected $_cache = array( 'default' => array(), 'current' => array() );
|
|
/**
|
|
* Style last updated timestampe
|
|
*/
|
|
protected $_styleLastUpdated = 0;
|
|
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
public function __construct()
|
|
{
|
|
$this->registry = ipsRegistry::instance();
|
|
$this->DB = $this->registry->DB();
|
|
|
|
/* Set up */
|
|
$this->setImageDir();
|
|
$this->setImageUrl();
|
|
$this->setStyleLastUpdated();
|
|
$this->setDefaultImageDir();
|
|
$this->setDefaultImageUrl();
|
|
}
|
|
|
|
/**
|
|
* Sets style last updated
|
|
* @param string (Optional dir)
|
|
*/
|
|
public function setStyleLastUpdated( $time=0 )
|
|
{
|
|
$this->_styleLastUpdated = ( $time ) ? $time : intval( ipsRegistry::$settings['style_last_updated'] );
|
|
|
|
/* Do we need to update the setting? */
|
|
if ( $time && ( $time > ipsRegistry::$settings['style_last_updated'] ) )
|
|
{
|
|
/* Rebuild DB */
|
|
$this->_refreshDatabase();
|
|
|
|
/* Update setting */
|
|
IPSLib::updateSettings( array( 'style_last_updated' => $time + 1 ) );
|
|
|
|
/* Flsuh cache */
|
|
$this->_flushCache();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get image dir
|
|
* @return string
|
|
*/
|
|
public function getStyleLastUpdated()
|
|
{
|
|
return $this->_styleLastUpdated;
|
|
}
|
|
|
|
/**
|
|
* Sets the default image url
|
|
* @param string (Optional dir)
|
|
*/
|
|
public function setDefaultImageUrl( $url='' )
|
|
{
|
|
$this->_defaultImageUrl = ( $url ) ? $url : ipsRegistry::$settings['public_dir'] . 'style_extra/default_mobile_app/';
|
|
}
|
|
|
|
/**
|
|
* Sets the default image dir
|
|
* @param string (Optional dir)
|
|
*/
|
|
public function setDefaultImageDir( $dir='' )
|
|
{
|
|
$this->_defaultDir = ( $dir ) ? $dir : DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_extra/default_mobile_app/';
|
|
}
|
|
|
|
/**
|
|
* Sets the image dir
|
|
* @param string (Optional dir)
|
|
*/
|
|
public function setImageDir( $dir='' )
|
|
{
|
|
$this->_imageDir = ( $dir ) ? $dir : DOC_IPS_ROOT_PATH . PUBLIC_DIRECTORY . '/style_images/mobile_app/';
|
|
}
|
|
|
|
/**
|
|
* Sets the image url
|
|
* @param string (Optional dir)
|
|
*/
|
|
public function setImageUrl( $url='' )
|
|
{
|
|
$this->_imageUrl = ( $url ) ? $url : ipsRegistry::$settings['public_dir'] . 'style_images/mobile_app/';
|
|
}
|
|
|
|
/**
|
|
* Get default image dir
|
|
* @return string
|
|
*/
|
|
public function getDefaultImageDir()
|
|
{
|
|
return $this->_defaultDir;
|
|
}
|
|
|
|
/**
|
|
* Get image dir
|
|
* @return string
|
|
*/
|
|
public function getImageDir()
|
|
{
|
|
return $this->_imageDir;
|
|
}
|
|
|
|
/**
|
|
* Get default image url
|
|
* @return string
|
|
*/
|
|
public function getDefaultImageUrl()
|
|
{
|
|
return $this->_defaultImageUrl;
|
|
}
|
|
|
|
/**
|
|
* Get image url
|
|
* @return string
|
|
*/
|
|
public function getImageUrl()
|
|
{
|
|
return $this->_imageUrl;
|
|
}
|
|
|
|
/**
|
|
* Get retina suffix
|
|
* @return string
|
|
*/
|
|
public function getRetinaSuffix()
|
|
{
|
|
return $this->_retinaSuffix;
|
|
}
|
|
|
|
/**
|
|
* Get default image dir contents
|
|
* @return array Of data (filename, mtime, size)
|
|
*/
|
|
public function getDefaultImageDirContents()
|
|
{
|
|
$images = array();
|
|
$cache = $this->_getCache( 'default' );
|
|
|
|
if ( $cache !== false )
|
|
{
|
|
return $cache;
|
|
}
|
|
|
|
/* Grab data */
|
|
try
|
|
{
|
|
foreach( new DirectoryIterator( $this->getDefaultImageDir() ) as $file )
|
|
{
|
|
if ( ! $file->isDot() AND ! $file->isDir() )
|
|
{
|
|
$_name = $file->getFileName();
|
|
|
|
if ( substr( $_name, 0, 1 ) != '.' )
|
|
{
|
|
if ( substr( $_name, -4 ) == '.png' )
|
|
{
|
|
try
|
|
{
|
|
$data = getimagesize( $this->getDefaultImageDir() . '/' . $_name );
|
|
}
|
|
catch( Exception $e ) { }
|
|
|
|
$images[] = array( 'filename' => $_name,
|
|
'imgsrc' => $this->getImageUrl() . $file,
|
|
'dimensions' => array( $data[0], $data[1] ),
|
|
'mtime' => $file->getMTime(),
|
|
'size' => $file->getSize(),
|
|
'writeable' => $file->isWritable() );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch ( Exception $e ) {}
|
|
|
|
/* Add to cache */
|
|
$this->_addCache( 'default', $images );
|
|
|
|
return $images;
|
|
}
|
|
|
|
/**
|
|
* Get current image dir contents
|
|
* @return array Of data (filename, mtime, size)
|
|
*/
|
|
public function getImageDirContents()
|
|
{
|
|
$images = array();
|
|
$cache = $this->_getCache( 'current' );
|
|
|
|
if ( $cache !== false )
|
|
{
|
|
return $cache;
|
|
}
|
|
try
|
|
{
|
|
foreach( new DirectoryIterator( $this->getImageDir() ) as $file )
|
|
{
|
|
if ( ! $file->isDot() AND ! $file->isDir() )
|
|
{
|
|
$_name = $file->getFileName();
|
|
|
|
if ( substr( $_name, 0, 1 ) != '.' )
|
|
{
|
|
if ( substr( $_name, -4 ) == '.png' )
|
|
{
|
|
try
|
|
{
|
|
$data = getimagesize( $this->getImageDir() . '/' . $_name );
|
|
}
|
|
catch( Exception $e ) { }
|
|
|
|
$images[] = array( 'filename' => $_name,
|
|
'imgsrc' => $this->getImageUrl() . $file,
|
|
'dimensions' => array( $data[0], $data[1] ),
|
|
'mtime' => $file->getMTime(),
|
|
'size' => $file->getSize(),
|
|
'writeable' => $file->isWritable() );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch ( Exception $e ) { }
|
|
|
|
/* Add to cache */
|
|
$this->_addCache( 'current', $images );
|
|
|
|
return $images;
|
|
}
|
|
|
|
/**
|
|
* Get filenames
|
|
* @return array
|
|
*/
|
|
public function getFileNames()
|
|
{
|
|
return $this->_fileNames;
|
|
}
|
|
|
|
/**
|
|
* Checks directories
|
|
* @return array Error codes
|
|
*/
|
|
public function checkDirectories()
|
|
{
|
|
$errors = array();
|
|
|
|
/* Exists */
|
|
if ( ! is_dir( $this->getImageDir() ) )
|
|
{
|
|
$errors[] = array( 'key' => 'doesnt_exist',
|
|
'extra' => $this->getImageDir() );
|
|
}
|
|
|
|
if ( ! is_dir( $this->getDefaultImageDir() ) )
|
|
{
|
|
$errors[] = array( 'key' => 'doesnt_exist',
|
|
'extra' => $this->getDefaultImageDir() );
|
|
}
|
|
|
|
/* is writeable */
|
|
if ( ! is_writeable( $this->getImageDir() ) )
|
|
{
|
|
$errors[] = array( 'key' => 'cannot_write',
|
|
'extra' => $this->getImageDir() );
|
|
}
|
|
|
|
return ( count( $errors ) ) ? $errors : false;
|
|
}
|
|
|
|
/**
|
|
* Check images
|
|
* @return array Error codes
|
|
*/
|
|
public function checkImages()
|
|
{
|
|
$default = $this->getDefaultImageDirContents();
|
|
$images = $this->getImageDirContents();
|
|
$fileNames = $this->getFileNames();
|
|
$workingImages = array();
|
|
$errors = array( 'missing' => false, 'dimensions' => false, 'writeable' => false );
|
|
|
|
foreach( $images as $i )
|
|
{
|
|
$workingImages[ $i['filename'] ] = true;
|
|
}
|
|
|
|
/* Lets see if any are missing */
|
|
foreach( $fileNames as $name )
|
|
{
|
|
$image = $this->_getFileFromArray( $name . '.png', $images );
|
|
|
|
if ( $image === false )
|
|
{
|
|
$errors['missing'][] = $name . '.png';
|
|
}
|
|
}
|
|
|
|
/* Are they the correct size? */
|
|
foreach( $default as $def )
|
|
{
|
|
$image = $this->_getFileFromArray( $def['filename'], $images );
|
|
|
|
if ( $image['dimensions'] && $def['dimensions'] )
|
|
{
|
|
if ( ( $image['dimensions'][0] != $def['dimensions'][0] ) || ( $image['dimensions'][1] != $def['dimensions'][1] ) )
|
|
{
|
|
$errors['dimensions'][] = $def['filename'];
|
|
}
|
|
}
|
|
|
|
if ( ! is_writeable( $this->getImageDir() . $image['filename'] ) )
|
|
{
|
|
$errors['writeable'][] = $image['filename'];
|
|
}
|
|
}
|
|
|
|
return ( count( $errors ) ) ? $errors : false;
|
|
}
|
|
|
|
/**
|
|
* Return an XML archive
|
|
* @return string
|
|
*/
|
|
public function getXmlArchive()
|
|
{
|
|
require_once( IPS_KERNEL_PATH . 'classXMLArchive.php' );/*noLibHook*/
|
|
$xmlArchive = new classXMLArchive();
|
|
$xmlArchive->setStripPath( $this->getImageDir() );
|
|
$xmlArchive->add( $this->getImageDir() );
|
|
|
|
$xml = $xmlArchive->getArchiveContents();
|
|
|
|
return $xml;
|
|
}
|
|
|
|
/**
|
|
* Imports a set XMLArchive
|
|
*
|
|
* @access public
|
|
* @param string XMLArchive content to import
|
|
* @return mixed Number of items added, or bool
|
|
*/
|
|
public function importXmlArchive( $content )
|
|
{
|
|
/* Correct file type ? */
|
|
if ( ! strstr( $content, "<xmlarchive" ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/* Get XML class */
|
|
require_once( IPS_KERNEL_PATH . 'classXMLArchive.php' );/*noLibHook*/
|
|
$xmlArchive = new classXMLArchive();
|
|
$xmlArchive->readXML( $content );
|
|
|
|
/* Got stuff? */
|
|
if ( ! $xmlArchive->countFileArray() )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/* Write it */
|
|
if ( $xmlArchive->write( $content, $this->getImageDir() ) === FALSE )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/* Check images */
|
|
$errors = $this->checkImages();
|
|
|
|
if ( $errors['missing'] !== false OR $errors['dimensions'] !== false OR $errors['writeable'] !== false )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/* Push changes to the app */
|
|
$this->setStyleLastUpdated( time() );
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Rebuild the db
|
|
*/
|
|
private function _refreshDatabase()
|
|
{
|
|
$images = $this->getImageDirContents();
|
|
|
|
/* Delete current contents */
|
|
$this->DB->delete( 'mobile_app_style' );
|
|
|
|
foreach( $images as $img )
|
|
{
|
|
if ( ! stristr( $img['filename'], $this->getRetinaSuffix() . '.png') )
|
|
{
|
|
$hasRetina = ( $this->_getFileFromArray( str_replace( '.png', $this->getRetinaSuffix() . '.png', $img['filename'] ), $images ) ) ? 1 : 0;
|
|
$insert = array( 'filename' => $img['filename'],
|
|
'isInUse' => 1,
|
|
'hasRetina' => $hasRetina,
|
|
'lastUpdated' => IPS_UNIX_TIME_NOW );
|
|
|
|
$this->DB->insert( 'mobile_app_style', $insert );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches a file by name from the array
|
|
* @param string $file
|
|
* @param array $array
|
|
* @return array|boolean
|
|
*/
|
|
private function _getFileFromArray( $file, array $array )
|
|
{
|
|
foreach( $array as $image )
|
|
{
|
|
if ( $file == $image['filename'] )
|
|
{
|
|
return $image;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Fetch data from a cache
|
|
* @param string $key
|
|
* @return mixed
|
|
*/
|
|
private function _getCache( $key )
|
|
{
|
|
if ( $key && ! empty( $this->_cache[ $key ] ) )
|
|
{
|
|
return $this->_cache[ $key ];
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Add an item to the local cache
|
|
* @param string $key
|
|
* @param array $value
|
|
*/
|
|
private function _addCache( $key, $value )
|
|
{
|
|
if ( $key )
|
|
{
|
|
$this->_cache[ $key ] = $value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Flush cache
|
|
*/
|
|
private function _flushCache()
|
|
{
|
|
$this->_cache = array( 'default' => array(), 'current' => array() );
|
|
}
|
|
|
|
}
|