1375 lines
37 KiB
PHP
1375 lines
37 KiB
PHP
<?php
|
|
/**
|
|
* @brief Javascript Handler
|
|
* @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
|
|
* @since 12 Aug 2013
|
|
* @version SVN_VERSION_NUMBER
|
|
*/
|
|
|
|
namespace IPS\Output;
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/**
|
|
* Javascript: Javascript handler
|
|
*/
|
|
class _Javascript extends \IPS\Patterns\ActiveRecord
|
|
{
|
|
/**
|
|
* @brief [Javascript] Array of found javascript keys and objects
|
|
*/
|
|
protected static $foundJsObjects = array();
|
|
|
|
/**
|
|
* @brief [Javascript] Position index for writing javascript to core_javascript
|
|
*/
|
|
protected static $positions = array();
|
|
|
|
/**
|
|
* @brief [ActiveRecord] Multiton Store
|
|
*/
|
|
protected static $multitons;
|
|
|
|
/**
|
|
* @brief [ActiveRecord] Database Table
|
|
*/
|
|
public static $databaseTable = 'core_javascript';
|
|
|
|
/**
|
|
* @brief [ActiveRecord] Database Prefix
|
|
*/
|
|
public static $databasePrefix = 'javascript_';
|
|
|
|
/**
|
|
* @brief Javascript map of file object URLs
|
|
*/
|
|
protected static $javascriptObjects = null;
|
|
|
|
/**
|
|
* Find JavaScript file
|
|
*
|
|
* @param string $app Application key or Plugin key
|
|
* @param string $location Location (front, admin, etc)
|
|
* @param string $path Path
|
|
* @param string $name Filename
|
|
* @return \IPS\Output\Javascript
|
|
* @throws \OutOfRangeException
|
|
*/
|
|
public static function find( $app, $location, $path, $name )
|
|
{
|
|
$key = md5( $app . '-' . $location . '-' . $path . '-' . $name );
|
|
|
|
if ( !in_array( $key, static::$foundJsObjects ) )
|
|
{
|
|
$where = array( 'javascript_app=?', 'javascript_location=?', 'javascript_path=?', 'javascript_name=?' );
|
|
|
|
if ( ! is_string( $app ) )
|
|
{
|
|
$where[] = 'javascript_plugin=?';
|
|
$bindings = array( 'core', 'plugins', '/', $name, $app );
|
|
}
|
|
else
|
|
{
|
|
$bindings = array( $app, $location, $path, $name );
|
|
}
|
|
|
|
try
|
|
{
|
|
$js = \IPS\Db::i()->select( '*', 'core_javascript', array_merge( array( implode( ' AND ', $where ) ), $bindings ) )->first();
|
|
static::$foundJsObjects[ $key ] = parent::constructFromData( $js );
|
|
}
|
|
catch ( \UnderflowException $e )
|
|
{
|
|
throw new \OutOfRangeException;
|
|
}
|
|
}
|
|
|
|
return static::$foundJsObjects[ $key ];
|
|
}
|
|
|
|
/**
|
|
* Set class properties if this object belongs to an application or a plugin
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function setAppOrPluginProperties()
|
|
{
|
|
if ( ( $this->app AND ! is_string( $this->app ) ) OR ( $this->plugin ) )
|
|
{
|
|
$this->app = 'core';
|
|
$this->location = 'plugins';
|
|
$this->path = '/';
|
|
$this->type = 'plugin';
|
|
$this->plugin = ( ! is_string( $this->app ) ) ? $this->app : $this->plugin;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a javascript file. This overwrites any existing JS that matches the same parameters.
|
|
* If a $this->app is not a string, then it will assume plugin and automatically determine the correct 'app', 'location' and 'path' so these do not need to
|
|
* be defined.
|
|
*
|
|
* @throws \InvalidArgumentException
|
|
* @throws \RuntimeException
|
|
* @return void
|
|
*/
|
|
public function save()
|
|
{
|
|
$this->setAppOrPluginProperties();
|
|
|
|
if ( ! isset( $this->path ) OR empty( $this->path ) )
|
|
{
|
|
$this->path = '/';
|
|
}
|
|
|
|
if ( ! $this->app OR ! $this->location OR ! $this->name )
|
|
{
|
|
throw new \InvalidArgumentException;
|
|
}
|
|
|
|
if ( ! $this->type )
|
|
{
|
|
$this->type = static::_getType( $this->path, $this->name );
|
|
}
|
|
|
|
$key = '';
|
|
|
|
if ( \IPS\IN_DEV AND $this->type == 'plugin' )
|
|
{
|
|
/* Write the file to disk in the correct location */
|
|
$path = \IPS\ROOT_PATH . '/plugins/' . $this->plugin . '/dev/js';
|
|
|
|
if ( !\is_dir( $path ) )
|
|
{
|
|
if ( !@\mkdir( $path, 0777, true ) or !@\chmod( $path, 0777 ) )
|
|
{
|
|
throw new \RuntimeException;
|
|
}
|
|
}
|
|
$key = md5( $this->app . ';' . $this->location . ';' . $this->path . ';' . $this->name );
|
|
\file_put_contents( $path . '/' . $this->name, $this->content );
|
|
}
|
|
|
|
\IPS\Db::i()->replace( 'core_javascript', array(
|
|
'javascript_app' => $this->app,
|
|
'javascript_location' => $this->location,
|
|
'javascript_plugin' => $this->plugin,
|
|
'javascript_path' => $this->path,
|
|
'javascript_name' => $this->name,
|
|
'javascript_type' => $this->type,
|
|
'javascript_content' => $this->content,
|
|
'javascript_version' => $this->version,
|
|
'javascript_position' => ( $this->position ) ? $this->position : 2000000,
|
|
'javascript_key' => $key
|
|
),
|
|
array(
|
|
'javascript_app', 'javascript_location', 'javascript_path', 'javascript_name'
|
|
) );
|
|
}
|
|
|
|
/**
|
|
* Delete a javascript file
|
|
* be defined.
|
|
*
|
|
* @throws \InvalidArgumentException
|
|
* @return void
|
|
*/
|
|
public function delete()
|
|
{
|
|
$this->setAppOrPluginProperties();
|
|
|
|
if ( ! isset( $this->path ) OR empty( $this->path ) )
|
|
{
|
|
$this->path = '/';
|
|
}
|
|
|
|
if ( ! $this->app OR ! $this->location OR ! $this->name )
|
|
{
|
|
throw new \InvalidArgumentException;
|
|
}
|
|
|
|
if ( ! $this->type )
|
|
{
|
|
$this->type = static::_getType( $this->path, $this->name );
|
|
}
|
|
|
|
if ( \IPS\IN_DEV AND $this->location == 'plugins' )
|
|
{
|
|
/* Write the file to disk in the correct location */
|
|
$file = \IPS\ROOT_PATH . '/plugins/' . $this->plugin . '/dev/js/' . $this->name;
|
|
|
|
if ( \is_file( $file ) )
|
|
{
|
|
\unlink( $file );
|
|
}
|
|
}
|
|
|
|
$where = array( 'javascript_app=?', 'javascript_location=?', 'javascript_path=?', 'javascript_name=?' );
|
|
$bindings = array( $this->app, $this->location, $this->path, $this->name );
|
|
|
|
if ( $this->location == 'plugins' )
|
|
{
|
|
$where[] = 'javascript_plugin=?';
|
|
$bindings[] = $this->plugin;
|
|
}
|
|
|
|
\IPS\Db::i()->delete( 'core_javascript', array( implode( ' AND ', $where ), $bindings ) );
|
|
}
|
|
|
|
/**
|
|
* Create an XML document
|
|
*
|
|
* @param string $app Application
|
|
* @return XML Object
|
|
*/
|
|
public static function createXml( $app )
|
|
{
|
|
static::importDev($app);
|
|
|
|
if ( $app === 'core' )
|
|
{
|
|
static::importDev('global');
|
|
}
|
|
|
|
/* Build XML and write to app directory */
|
|
$xml = new \XMLWriter;
|
|
$xml->openMemory();
|
|
$xml->setIndent( TRUE );
|
|
$xml->startDocument( '1.0', 'UTF-8' );
|
|
|
|
/* Root tag */
|
|
$xml->startElement('javascript');
|
|
$xml->startAttribute('app');
|
|
$xml->text( $app );
|
|
$xml->endAttribute();
|
|
|
|
/* Loop */
|
|
foreach ( \IPS\Db::i()->select( '*', 'core_javascript', ( $app === 'core' ) ? \IPS\Db::i()->in( 'javascript_app', array('core', 'global') ) : array( 'javascript_app=?', $app ), 'javascript_path, javascript_name' ) as $js )
|
|
{
|
|
/* Initiate the <template> tag */
|
|
$xml->startElement('file');
|
|
|
|
foreach( $js as $k => $v )
|
|
{
|
|
if ( in_array( \substr( $k, 11 ), array('app', 'location', 'path', 'name', 'type', 'version', 'position' ) ) )
|
|
{
|
|
$xml->startAttribute( $k );
|
|
$xml->text( $v );
|
|
$xml->endAttribute();
|
|
}
|
|
}
|
|
|
|
/* Write value */
|
|
if ( preg_match( '/<|>|&/', $js['javascript_content'] ) )
|
|
{
|
|
$xml->writeCData( str_replace( ']]>', ']]]]><![CDATA[>', $js['javascript_content'] ) );
|
|
}
|
|
else
|
|
{
|
|
$xml->text( $js['javascript_content'] );
|
|
}
|
|
|
|
/* Close the <template> tag */
|
|
$xml->endElement();
|
|
}
|
|
|
|
if( count( static::$_orders ) )
|
|
{
|
|
foreach( static::$_orders as $_app => $orderArray )
|
|
{
|
|
foreach( $orderArray as $order )
|
|
{
|
|
$xml->startElement('order');
|
|
|
|
$xml->startAttribute( 'app' );
|
|
$xml->text( $_app );
|
|
$xml->endAttribute();
|
|
|
|
$xml->startAttribute( 'path' );
|
|
$xml->text( $order['path'] );
|
|
$xml->endAttribute();
|
|
|
|
$xml->text( $order['contents'] );
|
|
|
|
$xml->endElement();
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Finish */
|
|
$xml->endDocument();
|
|
|
|
return $xml;
|
|
}
|
|
|
|
/**
|
|
* Import from an XML file on disk
|
|
*
|
|
* @param string $file File to import from (can be from applications dir, or tmp uploaded file)
|
|
* @param int|null $offset Offset to begin import from
|
|
* @param int|null $limit Number of rows to import
|
|
* @return bool|int False if the file is invalid, otherwise the number of rows inserted
|
|
*/
|
|
public static function importXml( $file, $offset=null, $limit=null )
|
|
{
|
|
if ( ! \is_file( $file ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
$i = 0;
|
|
$inserted = 0;
|
|
|
|
/* Try to prevent timeouts to the extent possible */
|
|
$cutOff = null;
|
|
|
|
if( $maxExecution = @ini_get( 'max_execution_time' ) )
|
|
{
|
|
$cutOff = time() + ( $maxExecution * .5 );
|
|
}
|
|
|
|
/* Open XML file */
|
|
$xml = new \XMLReader;
|
|
$xml->open( $file );
|
|
|
|
$xml->read();
|
|
|
|
$app = $xml->getAttribute('app');
|
|
|
|
/* Remove existing elements */
|
|
if( $offset === null or $offset === 0 )
|
|
{
|
|
\IPS\Db::i()->delete( 'core_javascript', array( 'javascript_app=? and (javascript_plugin is null or javascript_plugin=?)', $app, '' ) );
|
|
|
|
if ( $app === 'core' )
|
|
{
|
|
\IPS\Db::i()->delete( 'core_javascript', array( 'javascript_app=?', 'global' ) );
|
|
}
|
|
}
|
|
|
|
while( $xml->read() )
|
|
{
|
|
if( $xml->nodeType != \XMLReader::ELEMENT )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( $cutOff !== null AND time() >= $cutOff )
|
|
{
|
|
break;
|
|
}
|
|
|
|
$i++;
|
|
|
|
if ( $offset !== null )
|
|
{
|
|
if ( $i - 1 < $offset )
|
|
{
|
|
$xml->next();
|
|
continue;
|
|
}
|
|
}
|
|
|
|
$inserted++;
|
|
|
|
if( $xml->name == 'file' )
|
|
{
|
|
\IPS\Db::i()->insert( 'core_javascript', array(
|
|
'javascript_app' => $xml->getAttribute('javascript_app'),
|
|
'javascript_key' => '',
|
|
'javascript_plugin' => '',
|
|
'javascript_location' => $xml->getAttribute('javascript_location'),
|
|
'javascript_path' => $xml->getAttribute('javascript_path'),
|
|
'javascript_name' => $xml->getAttribute('javascript_name'),
|
|
'javascript_type' => $xml->getAttribute('javascript_type'),
|
|
'javascript_content' => $xml->readString(),
|
|
'javascript_version' => $xml->getAttribute('javascript_version'),
|
|
'javascript_position' => $xml->getAttribute('javascript_position')
|
|
) );
|
|
}
|
|
|
|
if( $limit !== null AND $i === ( $limit + $offset ) )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $inserted;
|
|
}
|
|
|
|
/**
|
|
* Export Javascript to /dev/js
|
|
*
|
|
* @param string $app Application Directory
|
|
* @return void
|
|
* @throws \RuntimeException
|
|
*/
|
|
public static function exportDev( $app )
|
|
{
|
|
try
|
|
{
|
|
\IPS\Developer::writeDirectory( $app, 'js' );
|
|
}
|
|
catch( \RuntimeException $e )
|
|
{
|
|
throw new \RuntimeException( $e->getMessage() );
|
|
}
|
|
|
|
foreach( \IPS\Db::i()->select( '*', 'core_javascript', array( 'javascript_app=?', $app ) )->setKeyField('javascript_id') as $jsId => $js )
|
|
{
|
|
try
|
|
{
|
|
$pathToWrite = \IPS\Developer::writeDirectory( $app, 'js/', $js['javascript_location'] );
|
|
}
|
|
catch( \RuntimeException $e )
|
|
{
|
|
throw new \RuntimeException( $e->getMessage() );
|
|
}
|
|
|
|
if ( $js['javascript_path'] != '/' )
|
|
{
|
|
$_path = '';
|
|
|
|
foreach( explode( '/', trim( $js['javascript_path'], '/' ) ) as $dir )
|
|
{
|
|
$_path .= '/' . trim( $dir, '/' );
|
|
|
|
try
|
|
{
|
|
$pathToWrite = \IPS\Developer::writeDirectory( $app, 'js/' . $js['javascript_location'] . $_path );
|
|
}
|
|
catch( \RuntimeException $e )
|
|
{
|
|
throw new \RuntimeException( $e->getMessage() );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ! @\file_put_contents( $pathToWrite . '/' . $js['javascript_name'], $js['javascript_content'] ) )
|
|
{
|
|
throw new \RuntimeException('core_theme_dev_cannot_write_js,' . $pathToWrite . '/' . $js['javascript_name']);
|
|
}
|
|
else
|
|
{
|
|
@chmod( $pathToWrite . '/' . $js['javascript_name'], 0777 );
|
|
}
|
|
}
|
|
|
|
/* Open XML file */
|
|
if( file_exists( \IPS\ROOT_PATH . '/applications/' . $app . '/data/javascript.xml' ) )
|
|
{
|
|
$xml = new \XMLReader;
|
|
$xml->open( \IPS\ROOT_PATH . '/applications/' . $app . '/data/javascript.xml' );
|
|
|
|
$xml->read();
|
|
|
|
while( $xml->read() )
|
|
{
|
|
if( $xml->nodeType != \XMLReader::ELEMENT )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( $xml->name == 'order' )
|
|
{
|
|
$path = rtrim( $xml->getAttribute('path'), '/' ) . '/';
|
|
$app = $xml->getAttribute('app');
|
|
$content = $xml->readString();
|
|
|
|
file_put_contents( \IPS\ROOT_PATH . $path . 'order.txt', $content );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Track order.txt files for writing
|
|
*/
|
|
protected static $_orders = array();
|
|
|
|
/**
|
|
* Import JS from dev folders and store into core_javascript
|
|
*
|
|
* @param string $app Application
|
|
* @return void
|
|
*/
|
|
public static function importDev( $app )
|
|
{
|
|
$root = \IPS\ROOT_PATH . '/applications/' . $app . '/dev/js';
|
|
|
|
if ( $app == 'global' )
|
|
{
|
|
$root = \IPS\ROOT_PATH . '/dev/js/';
|
|
}
|
|
|
|
static::$_orders[ $app ] = array();
|
|
|
|
if ( is_dir( $root ) )
|
|
{
|
|
\IPS\Db::i()->delete( 'core_javascript', array( 'javascript_app=? and javascript_plugin = \'\'', $app ) );
|
|
static::$positions = array();
|
|
|
|
foreach( new \DirectoryIterator( $root ) as $location )
|
|
{
|
|
if ( $location->isDot() OR mb_substr( $location->getFilename(), 0, 1 ) === '.' )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( $location->isDir() )
|
|
{
|
|
static::_importDevDirectory( $root, $app, $location->getFilename() );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Import a /dev directory recursively.
|
|
*
|
|
* @param string $root Root directory to recurse
|
|
* @param string $app Application key
|
|
* @param string $location Location (front, global, etc)
|
|
* @param string $path Additional path information
|
|
* @return void
|
|
*/
|
|
protected static function _importDevDirectory( $root, $app, $location, $path='' )
|
|
{
|
|
$dir = $root . '/' . $location . '/' . $path;
|
|
$parentDir = preg_replace( '#^(.*)/([^\/]+?)$#', '\2', $dir );
|
|
|
|
if ( \file_exists( $dir . '/order.txt' ) )
|
|
{
|
|
static::$_orders[ $app ][] = array( 'path' => str_replace( \IPS\ROOT_PATH, '', $dir ), 'contents' => file_get_contents( $dir . '/order.txt' ) );
|
|
|
|
$order = \file( $dir . '/order.txt' );
|
|
|
|
foreach( $order as $item )
|
|
{
|
|
$item = trim( $item );
|
|
|
|
if ( isset( static::$positions[ $app . '-' . $location . '-' . $parentDir ] ) AND static::$positions[ $app . '-' . $location . '-' . $parentDir ] < 1000000 )
|
|
{
|
|
static::$positions[ $app . '-' . $location . '-' . $item ] = ++static::$positions[ $app . '-' . $location . '-' . $parentDir ];
|
|
}
|
|
else
|
|
{
|
|
static::$positions[ $app . '-' . $location . '-' . $item ] = static::_getNextPosition( $app, $location );
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach ( new \DirectoryIterator( $dir ) as $file )
|
|
{
|
|
if ( $file->isDot() || mb_substr( $file->getFilename(), 0, 1 ) === '.' || $file == 'index.html' )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( $file->isDir() )
|
|
{
|
|
static::_importDevDirectory( $root, $app, $location, $path . '/' . $file->getFileName() );
|
|
}
|
|
else if ( mb_substr( $file->getFileName(), -3 ) === '.js' )
|
|
{
|
|
$js = \file_get_contents( $dir . '/' . $file->getFilename() );
|
|
|
|
if ( isset( static::$positions[ $app . '-' . $location . '-' . $file->getFilename() ] ) )
|
|
{
|
|
$position = static::$positions[ $app . '-' . $location . '-' . $file->getFilename() ];
|
|
}
|
|
else
|
|
{
|
|
/* Attempt to order by files */
|
|
if ( ! isset( static::$positions[ $app . '-' . $location . '-' . $parentDir ] ) )
|
|
{
|
|
static::$positions[ $app . '-' . $location . '-' . $parentDir ] = static::_getNextPosition( $app, $location ) + 1000000;
|
|
}
|
|
|
|
$position = static::$positions[ $app . '-' . $location . '-' . $parentDir ];
|
|
}
|
|
|
|
/* Check to see if 'ips.{dir}.js' exists and if so, put that first */
|
|
if ( $file->getFilename() == 'ips.' . $parentDir . '.js' )
|
|
{
|
|
$position = $position - 1;
|
|
}
|
|
|
|
$path = trim( $path, '/' );
|
|
|
|
\IPS\Db::i()->delete( 'core_javascript', array( 'javascript_app=? AND javascript_location=? AND javascript_path=? AND javascript_name=?', $app, $location, $path, $file->getFileName() ) );
|
|
|
|
\IPS\Db::i()->insert( 'core_javascript', array(
|
|
'javascript_app' => $app,
|
|
'javascript_location' => $location,
|
|
'javascript_plugin' => '',
|
|
'javascript_path' => $path,
|
|
'javascript_name' => $file->getFileName(),
|
|
'javascript_type' => static::_getType( $dir . '/', $file->getFileName() ),
|
|
'javascript_content' => $js,
|
|
'javascript_position' => $position,
|
|
'javascript_version' => \IPS\Application::load( ( $app == 'global' ? 'core' : $app ) )->long_version,
|
|
'javascript_key' => md5( $app . ';' . $location . ';' . $path . ';' . $file->getFileName() )
|
|
) );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Compiles JS into fewer minified files suitable for non IN_DEV use.
|
|
* Imports the fewer files into a database for writing out.
|
|
*
|
|
* @param string $app Application
|
|
* @param string|null $location Location (front, global, etc)
|
|
* @param string|null $file File to build
|
|
* @return boolean|null
|
|
*/
|
|
public static function compile( $app, $location=null, $file=null )
|
|
{
|
|
$flagKey = 'js_compiling_' . md5( $app . ',' . $location . ',' . $file );
|
|
|
|
if ( isset( \IPS\Data\Store::i()->$flagKey ) and ! empty( \IPS\Data\Store::i()->$flagKey ) )
|
|
{
|
|
/* We're currently rebuilding */
|
|
if ( time() - \IPS\Data\Store::i()->$flagKey < 30 )
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
\IPS\Data\Store::i()->$flagKey = time();
|
|
|
|
$map = ( isset( \IPS\Data\Store::i()->javascript_map ) ) ? \IPS\Data\Store::i()->javascript_map : array();
|
|
$files = ( isset( \IPS\Data\Store::i()->javascript_file_map ) ) ? \IPS\Data\Store::i()->javascript_file_map : array();
|
|
|
|
if ( $location === null and $file === null )
|
|
{
|
|
$map[ $app ] = array();
|
|
$files[ $app ] = array();
|
|
|
|
\IPS\Data\Store::i()->javascript_file_map = $files;
|
|
}
|
|
|
|
if ( $app == 'global' )
|
|
{
|
|
if ( $location === null and $file === null )
|
|
{
|
|
\IPS\File::getClass('core_Theme')->deleteContainer( 'javascript_' . $app );
|
|
}
|
|
|
|
if ( mb_substr( $file, 0, 8 ) === 'js_lang_' )
|
|
{
|
|
$langId = intval( mb_substr( $file, 8, -3 ) );
|
|
|
|
if ( $langId > 0 )
|
|
{
|
|
/* Write it */
|
|
$obj = static::_writeJavascriptFromResultset( array( array(
|
|
'javascript_app' => 'global',
|
|
'javascript_location' => 'root',
|
|
'javascript_path' => '',
|
|
'javascript_name' => $file,
|
|
'javascript_type' => 'lang',
|
|
'javascript_content' => static::getJavascriptLanguage( $langId ),
|
|
'javascript_position' => 0
|
|
) ), $file, 'global', 'root' );
|
|
|
|
$map[ $app ][ md5( 'global-root-' . $file ) ] = (string) $obj;
|
|
}
|
|
}
|
|
|
|
foreach( \IPS\Output::$globalJavascript as $fileName )
|
|
{
|
|
if ( $file === null OR $file == $fileName )
|
|
{
|
|
if ( $fileName === 'map.js' )
|
|
{
|
|
/* Write it */
|
|
$obj = static::_writeJavascriptFromResultset( array( array(
|
|
'javascript_app' => 'global',
|
|
'javascript_location' => 'root',
|
|
'javascript_path' => '',
|
|
'javascript_name' => 'map.js',
|
|
'javascript_type' => 'framework',
|
|
'javascript_content' => static::_getMapAsScript(),
|
|
'javascript_position' => 0
|
|
) ), 'map.js', 'global', 'root' );
|
|
|
|
$map[ $app ][ md5( 'global-root-map.js' ) ] = (string) $obj;
|
|
}
|
|
else
|
|
{
|
|
$rows = iterator_to_array( \IPS\Db::i()->select(
|
|
'*',
|
|
'core_javascript', array( 'javascript_app=? AND javascript_location=?', $app, mb_substr( $fileName, 0, -3 ) ),
|
|
'javascript_app, javascript_location, javascript_position'
|
|
)->setKeyField('javascript_id') );
|
|
|
|
/* Write it */
|
|
$obj = static::_writeJavascriptFromResultset( $rows, $fileName, $app, 'root' );
|
|
|
|
$map[ $app ][ md5( $app .'-' . 'root' . '-' . $fileName ) ] = $obj ? (string) $obj : null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( $location === null and $file === null )
|
|
{
|
|
\IPS\File::getClass('core_Theme')->deleteContainer( 'javascript_' . $app );
|
|
}
|
|
|
|
/* Plugins */
|
|
if ( $app === 'core' )
|
|
{
|
|
if ( $file === null OR $file === 'plugins.js' )
|
|
{
|
|
$obj = static::_writeJavascriptFromResultset( \IPS\Db::i()->select( '*', 'core_javascript', array( 'javascript_app=? AND javascript_location=? AND javascript_type=?', 'core', 'plugins', 'plugin' ), 'javascript_app, javascript_location, javascript_position' )->setKeyField('javascript_id'), 'plugins.js', 'core', 'plugins' );
|
|
|
|
$map[ $app ][ md5( 'core-plugins-plugins.js' ) ] = $obj ? (string) $obj : null;
|
|
}
|
|
}
|
|
|
|
foreach( array( 'front', 'admin', 'global' ) as $loc )
|
|
{
|
|
if ( ( $file === null OR $file === 'app.js' ) AND ( $location === null OR $location === $loc ) )
|
|
{
|
|
/* app.js: All models and ui for the app */
|
|
$obj = static::_writeJavascriptFromResultset( \IPS\Db::i()->select( '*', 'core_javascript', array( 'javascript_app=? AND javascript_location=? AND javascript_type IN (\'mixins\', \'model\',\'ui\')', $app, $loc ), 'javascript_app, javascript_location, javascript_position' )->setKeyField('javascript_id'), 'app.js', $app, $loc );
|
|
|
|
$map[ $app ][ md5( $app .'-' . $loc . '-' . 'app.js' ) ] = $obj ? (string) $obj : null;
|
|
}
|
|
|
|
/* {location}_{controller}.js: Controllers and templates bundles */
|
|
$controllers = array();
|
|
$templates = array();
|
|
|
|
foreach( \IPS\Db::i()->select( '*', 'core_javascript', array( 'javascript_app=? AND javascript_location=? AND javascript_type IN (\'controller\', \'template\')', $app, $loc ), 'javascript_app, javascript_location, javascript_position' )->setKeyField('javascript_id') as $id => $row )
|
|
{
|
|
if ( $row['javascript_type'] == 'controller' )
|
|
{
|
|
list( $dir, $controller ) = explode( '/', $row['javascript_path'] );
|
|
|
|
$controllers[ $controller ][] = $row;
|
|
}
|
|
else
|
|
{
|
|
/* ips . templates . {controller} . js */
|
|
$bits = explode( '.', $row['javascript_name'] );
|
|
$templates[ $bits[2] ][] = $row;
|
|
}
|
|
}
|
|
|
|
/* Check to see if we have a template that does not have a controller */
|
|
$templateOnlyKeys = array_diff( array_keys( $templates ), array_keys( $controllers ) );
|
|
|
|
foreach( array_merge( array_keys( $controllers ), array_keys( $templates ) ) as $key )
|
|
{
|
|
if ( ( $file === null ) OR ( $file === $loc . '_' . $key . '.js' ) )
|
|
{
|
|
$files = array();
|
|
|
|
if ( isset( $templates[ $key ] ) )
|
|
{
|
|
foreach( $templates[ $key ] as $id => $row )
|
|
{
|
|
$files[ $row['javascript_id'] ] = $row;
|
|
}
|
|
}
|
|
|
|
if ( isset( $controllers[ $key ] ) )
|
|
{
|
|
foreach( $controllers[ $key ] as $controller )
|
|
{
|
|
$files[ $controller['javascript_id'] ] = $controller;
|
|
}
|
|
}
|
|
|
|
/* Template only? */
|
|
if ( count( $templateOnlyKeys ) AND in_array( $key, $templateOnlyKeys ) )
|
|
{
|
|
foreach( $templates[ $key ] as $tmpl )
|
|
{
|
|
$files[ $tmpl['javascript_id'] ] = $tmpl;
|
|
}
|
|
}
|
|
|
|
$obj = static::_writeJavascriptFromResultset( $files, $loc . '_' . $key . '.js', $app, $loc );
|
|
|
|
$map[ $app ][ md5( $app .'-' . $loc . '-' . $loc . '_' . $key . '.js' ) ] = $obj ? (string) $obj : null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
\IPS\Data\Store::i()->javascript_map = $map;
|
|
unset( \IPS\Data\Store::i()->$flagKey );
|
|
|
|
/* As the filename has changed, rebuild the JS map */
|
|
if ( ( $app !== 'global' and ( $location === NULL or in_array( $location, array( 'admin', 'front', 'global' ) ) ) ) )
|
|
{
|
|
\IPS\Output\Javascript::compile( 'global', 'root', 'map.js' );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* Combines the DB rows into a single string for writing.
|
|
*
|
|
* @param \IPS\Db\Select $files Result set
|
|
* @param string $fileName Filename to use
|
|
* @param string $app Application
|
|
* @param string $location Location (front, global, etc)
|
|
* @return object|null \IPS\File object
|
|
*/
|
|
protected static function _writeJavascriptFromResultset( $files, $fileName, $app, $location )
|
|
{
|
|
$content = '';
|
|
$jsMap = ( isset( \IPS\Data\Store::i()->javascript_map ) ) ? \IPS\Data\Store::i()->javascript_map : array();
|
|
|
|
/* Try and remove any existing files */
|
|
try
|
|
{
|
|
$md5 = md5( $app . '-' . $location . '-' . $fileName );
|
|
|
|
if ( isset( $jsMap[ $app ] ) and in_array( $md5, array_keys( $jsMap[ $app ] ) ) )
|
|
{
|
|
\IPS\File::get( 'core_Theme', $jsMap[ $app ][ $md5 ] )->delete();
|
|
}
|
|
}
|
|
catch ( \InvalidArgumentException $e ) { }
|
|
|
|
|
|
if ( ! count( $files ) )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
foreach( $files as $row )
|
|
{
|
|
$content[] = static::_minify( $row['javascript_content'] ) . ";";
|
|
}
|
|
|
|
$fileObject = static::_writeJavascript( implode( "\n", $content ), $fileName, $app, $location );
|
|
|
|
try
|
|
{
|
|
$map = \IPS\Data\Store::i()->javascript_file_map;
|
|
}
|
|
catch ( \OutOfRangeException $e )
|
|
{
|
|
$map = array();
|
|
}
|
|
|
|
foreach( $files as $row )
|
|
{
|
|
$path = ( ( ! empty( $row['javascript_path'] ) AND $row['javascript_path'] !== '/' ) ? '/' . $row['javascript_path'] . '/' : '/' );
|
|
$map[ $row['javascript_app'] ][ $row['javascript_location'] ][ $path ][ $row['javascript_name'] ] = (string) $fileObject;
|
|
}
|
|
|
|
\IPS\Data\Store::i()->javascript_file_map = $map;
|
|
|
|
return $fileObject;
|
|
}
|
|
|
|
/**
|
|
* Combines the DB rows into a single string for writing.
|
|
*
|
|
* @param string $content Javascript string to write
|
|
* @param string $fileName Filename to use
|
|
* @param string $app Application
|
|
* @param string $location Location (front, global, etc)
|
|
* @return object \IPS\File object
|
|
*/
|
|
protected static function _writeJavascript( $content, $fileName, $app, $location )
|
|
{
|
|
$header = <<<EOF
|
|
/**
|
|
* IPS Social Suite 4
|
|
* (c) 2013 Invision Power Services - http://www.invisionpower.com
|
|
* This file contains minified javascript and is not directly editable
|
|
*/
|
|
EOF;
|
|
|
|
return \IPS\File::create( 'core_Theme', $location . '_' . $fileName, $header . "\n\n" . $content, 'javascript_' . $app, TRUE );
|
|
}
|
|
|
|
/**
|
|
* Get javascript language as a script
|
|
*
|
|
* @param int $lang ID of language to fetch
|
|
* @return string
|
|
*/
|
|
public static function getJavascriptLanguage( $langId )
|
|
{
|
|
$_lang = array();
|
|
|
|
foreach ( \IPS\Db::i()->select( '*', 'core_sys_lang_words', array( 'lang_id=? AND word_js=?', $langId, TRUE ) ) as $row )
|
|
{
|
|
$_lang[ $row['word_key'] ] = $row['word_custom'] ?: $row['word_default'];
|
|
}
|
|
|
|
if ( \IPS\IN_DEV )
|
|
{
|
|
foreach ( \IPS\Application::applications() as $app )
|
|
{
|
|
if ( file_exists( \IPS\ROOT_PATH . "/applications/{$app->directory}/dev/jslang.php" ) )
|
|
{
|
|
require \IPS\ROOT_PATH . "/applications/{$app->directory}/dev/jslang.php";
|
|
$_lang = array_merge( $_lang, $lang );
|
|
}
|
|
}
|
|
foreach ( \IPS\Plugin::plugins() as $plugin )
|
|
{
|
|
if ( file_exists( \IPS\ROOT_PATH . "/plugins/{$plugin->location}/dev/lang.php" ) )
|
|
{
|
|
require \IPS\ROOT_PATH . "/plugins/{$plugin->location}/dev/lang.php";
|
|
$_lang = array_merge( $_lang, $lang );
|
|
}
|
|
}
|
|
}
|
|
|
|
return 'ips.setString( ' . json_encode( $_lang ) . ')';
|
|
}
|
|
|
|
/**
|
|
* Get javascript map as a script
|
|
*
|
|
* @return string
|
|
*/
|
|
protected static function _getMapAsScript()
|
|
{
|
|
$fileMap = isset(\IPS\Data\Store::i()->javascript_file_map) ? \IPS\Data\Store::i()->javascript_file_map : array();
|
|
$map = array();
|
|
|
|
/* Fix up the map a little */
|
|
foreach( $fileMap as $app => $location )
|
|
{
|
|
if ( $app === 'global' )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
foreach( $location as $locName => $locData )
|
|
{
|
|
foreach( $locData as $name => $items )
|
|
{
|
|
if ( mb_stristr( $name, '/controllers/' ) )
|
|
{
|
|
$url = array_pop( $items );
|
|
|
|
$map[ $app ][ $locName . '_' . trim( str_replace( '/controllers/', '', $name ) , '/' ) ] = (string) \IPS\File::get( 'core_Theme', $url )->url;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$json = version_compare( PHP_VERSION, '5.4.0' ) >= 0 ? json_encode( $map, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ) : str_replace( '\\/', '/', json_encode( $map ) );
|
|
|
|
return 'var ipsJavascriptMap = ' . $json . ';';
|
|
}
|
|
|
|
/**
|
|
* Minifies javascript if IPS created
|
|
*
|
|
* @param string $js Javascript code
|
|
* @return string
|
|
*/
|
|
protected static function _minify( $js )
|
|
{
|
|
require_once( \IPS\ROOT_PATH . '/system/3rd_party/Minify/lib/JSMin.php' );
|
|
|
|
if ( mb_stristr( mb_substr( $js, 0, 1000 ), '* IPS Social Suite 4' ) )
|
|
{
|
|
$js = \JSMin::minify( $js );
|
|
}
|
|
|
|
return $js;
|
|
}
|
|
|
|
/**
|
|
* Get JS
|
|
*
|
|
* @param string $file Filename
|
|
* @param string|null $app Application
|
|
* @param string|null $location Location (e.g. 'admin', 'front')
|
|
* @return array URL to JS files
|
|
*/
|
|
public static function inDevJs( $file, $app=NULL, $location=NULL )
|
|
{
|
|
/* 1: Is this the magic plugin JS */
|
|
if ( $app === 'core' and $location === 'plugins' and $file === 'plugins.js' )
|
|
{
|
|
$return = array();
|
|
|
|
foreach ( new \GlobIterator( \IPS\ROOT_PATH . '/plugins/*/dev/js/*' ) as $file )
|
|
{
|
|
$url = str_replace( \IPS\ROOT_PATH, rtrim( \IPS\Settings::i()->base_url, '/' ), $file );
|
|
$return[] = str_replace( '\\', '/', $url );
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
/* 2: Is it a named grouped collection? */
|
|
if ( $app === NULL AND $location === NULL )
|
|
{
|
|
if ( $file === 'map.js' )
|
|
{
|
|
return array();
|
|
}
|
|
|
|
if ( in_array( $file, \IPS\Output::$globalJavascript ) )
|
|
{
|
|
$app = 'global';
|
|
$location = '/';
|
|
}
|
|
|
|
if ( mb_substr( $file, 0, 8 ) === 'js_lang_' )
|
|
{
|
|
return array( \IPS\Settings::i()->base_url . "/applications/core/interface/js/jslang.php?langId=" . intval( mb_substr( $file, 8, -3 ) ) );
|
|
}
|
|
}
|
|
|
|
$app = $app ?: ( \IPS\Dispatcher::i()->application ? \IPS\Dispatcher::i()->application->directory : NULL );
|
|
$location = $location ?: \IPS\Dispatcher::i()->controllerLocation;
|
|
|
|
/* 3: App JS? */
|
|
if ( $file == 'app.js' )
|
|
{
|
|
return static::_appJs( $app, $location );
|
|
}
|
|
|
|
/* 3: Is this a controller/template combo? */
|
|
if ( mb_strstr( $file, '_') AND mb_substr( $file, -3 ) === '.js' )
|
|
{
|
|
list( $location, $key ) = explode( '_', mb_substr( $file, 0, -3 ) );
|
|
|
|
if ( ( $location == 'front' OR $location == 'admin' OR $location == 'global' ) AND ! empty( $key ) )
|
|
{
|
|
return static::_sectionJs( $key, $location, $app );
|
|
}
|
|
}
|
|
|
|
/* 4: Is it in the interface directory? */
|
|
if ( $location === 'interface' )
|
|
{
|
|
$path = \IPS\ROOT_PATH . "/applications/{$app}/interface/{$file}";
|
|
}
|
|
else if ( $app === 'global' )
|
|
{
|
|
$return = array();
|
|
|
|
if ( in_array( $file, \IPS\Output::$globalJavascript ) )
|
|
{
|
|
return static::_directoryJs( \IPS\ROOT_PATH . "/dev/js/" . mb_substr( $file, 0, -3 ) );
|
|
}
|
|
|
|
$path = \IPS\ROOT_PATH . "/dev/js";
|
|
}
|
|
else
|
|
{
|
|
$path = \IPS\ROOT_PATH . "/applications/{$app}/dev/js/{$location}/{$file}";
|
|
}
|
|
|
|
if ( is_dir( $path ) )
|
|
{
|
|
return static::_directoryJs( $path );
|
|
}
|
|
else
|
|
{
|
|
return array( str_replace( \IPS\ROOT_PATH, \IPS\Settings::i()->base_url, $path ) );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the map for IN_DEV use
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function inDevMapJs()
|
|
{
|
|
$files = array();
|
|
|
|
foreach( \IPS\Application::applications() as $app => $data )
|
|
{
|
|
$root = \IPS\ROOT_PATH . "/applications/{$app}/dev/js/";
|
|
|
|
foreach( array( 'front', 'admin', 'global' ) as $location )
|
|
{
|
|
if ( is_dir( $root . "{$location}/controllers" ) )
|
|
{
|
|
foreach ( new \DirectoryIterator( $root . "{$location}/controllers" ) as $controllerDir )
|
|
{
|
|
if ( $controllerDir->isDot() || mb_substr( $controllerDir->getFilename(), 0, 1 ) === '.' )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( $controllerDir->isDir() )
|
|
{
|
|
$controllerPath = \IPS\ROOT_PATH . "/applications/{$app}/dev/js/{$location}/controllers/{$controllerDir}";
|
|
|
|
foreach ( new \DirectoryIterator( $root . "{$location}/controllers/{$controllerDir}" ) as $file )
|
|
{
|
|
if ( $file->isDot() || mb_substr( $file->getFilename(), 0, 1 ) === '.' || $file == 'index.html' )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$files[ $app ][ $location . '_' . $controllerDir ] = str_replace( \IPS\ROOT_PATH, trim( \IPS\Settings::i()->base_url, '/' ), $controllerPath ) . '/' . $file->getFileName();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$json = version_compare( PHP_VERSION, '5.4.0' ) >= 0 ? json_encode( $files, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ) : str_replace( '\\/', '/', json_encode( $files ) );
|
|
return 'var ipsJavascriptMap = ' . $json . ';';
|
|
}
|
|
|
|
/**
|
|
* Returns the component parts from a URL
|
|
*
|
|
* @param string $url Full URL of javascript file
|
|
* @return array Array( 'app' => .., 'location' => .., 'path' => .., 'name' => .. );
|
|
*/
|
|
protected static function _urlToComponents( $url )
|
|
{
|
|
$url = ltrim( str_replace( \IPS\Settings::i()->base_url . 'applications', '', $url ), '/' );
|
|
$bits = explode( "/", $url );
|
|
|
|
$app = array_shift( $bits );
|
|
|
|
/* Remove dev/js */
|
|
array_shift( $bits );
|
|
array_shift( $bits );
|
|
|
|
$location = array_shift( $bits );
|
|
$name = array_pop( $bits );
|
|
$path = preg_replace( '#/{2,}#', '/', '/' . trim( implode( '/', $bits ), '/' ) . '/' );
|
|
|
|
return array( 'app' => $app, 'location' => $location, 'name' => $name, 'path' => $path );
|
|
}
|
|
|
|
/**
|
|
* Gets app specific Javascript
|
|
*
|
|
* @param string $key Application
|
|
* @param string $location Location (front, global, etc)
|
|
* @return void
|
|
*/
|
|
protected static function _appJs( $app, $location )
|
|
{
|
|
$models = array();
|
|
|
|
if ( \is_dir( \IPS\ROOT_PATH . "/applications/" . $app ) )
|
|
{
|
|
foreach( array( \IPS\ROOT_PATH . "/applications/{$app}/dev/js/{$location}/mixins", \IPS\ROOT_PATH . "/applications/{$app}/dev/js/{$location}/models", \IPS\ROOT_PATH . "/applications/{$app}/dev/js/{$location}/ui" ) as $durr )
|
|
{
|
|
/* Models */
|
|
if ( \is_dir( $durr ) )
|
|
{
|
|
$models = static::_directoryJs( $durr );
|
|
}
|
|
}
|
|
}
|
|
|
|
return $models;
|
|
}
|
|
|
|
/**
|
|
* Returns section specific JS (controller, models and any template files required)
|
|
*
|
|
* @param string $key Controller Key (messages, reports, etc)
|
|
* @param string $location Location (front, admin)
|
|
* @param string $app Application
|
|
*/
|
|
protected static function _sectionJs( $key, $location, $app )
|
|
{
|
|
$return = array();
|
|
$controllerDir = \IPS\ROOT_PATH . "/applications/{$app}/dev/js/{$location}/controllers/{$key}";
|
|
$templatesDir = \IPS\ROOT_PATH . "/applications/{$app}/dev/js/{$location}/templates";
|
|
$controllers = array();
|
|
$templates = array();
|
|
|
|
/* Get controllers */
|
|
if ( \is_dir( $controllerDir ) )
|
|
{
|
|
$controllers = static::_directoryJs( $controllerDir );
|
|
}
|
|
|
|
/* Templates */
|
|
if ( \is_dir( $templatesDir . '/' . $key ) )
|
|
{
|
|
$templates = static::_directoryJs( $templatesDir . '/' . $key );
|
|
}
|
|
else if ( \file_exists( $templatesDir . '/ips.templates.' . $key . '.js' ) )
|
|
{
|
|
$templates = array( str_replace( \IPS\ROOT_PATH, trim( \IPS\Settings::i()->base_url, '/' ), $templatesDir . '/ips.templates.' . $key . '.js' ) );
|
|
}
|
|
|
|
return array_merge( $templates, $controllers );
|
|
}
|
|
|
|
/**
|
|
* Get Javascript files recursively.
|
|
*
|
|
* @param string $path Path to open
|
|
* @param array $return Items retreived so far
|
|
* @return array
|
|
*/
|
|
protected static function _directoryJs( $path, $return=array() )
|
|
{
|
|
$path = rtrim( $path, '/' );
|
|
$contents = array();
|
|
|
|
foreach ( new \DirectoryIterator( $path ) as $file )
|
|
{
|
|
if ( $file->isDot() || mb_substr( $file->getFilename(), 0, 1 ) === '.' )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( $file->isDir() )
|
|
{
|
|
$return = static::_directoryJs( $path . '/' . $file->getFileName(), $return );
|
|
}
|
|
else if ( mb_substr( $file->getFileName(), -3 ) === '.js' )
|
|
{
|
|
$contents[] = str_replace( \IPS\ROOT_PATH, trim( \IPS\Settings::i()->base_url, '/' ), $path ) . '/' . $file->getFileName();
|
|
}
|
|
}
|
|
|
|
if ( count( $contents ) )
|
|
{
|
|
/* Check to see if 'ips.{dir}.js' exists and if so, put that first */
|
|
$parentDir = preg_replace( '#^(.*)/([^\/]+?)$#', '\2', $path );
|
|
|
|
$reordered = array();
|
|
|
|
foreach( $contents as $url )
|
|
{
|
|
if ( mb_strstr( $url, '/' . $parentDir . '/' ) AND mb_strstr( $url, '/' . $parentDir . '/ips.' . $parentDir . '.js' ) )
|
|
{
|
|
$reordered[] = $url;
|
|
break;
|
|
}
|
|
}
|
|
|
|
$return = array_merge( $reordered, array_diff( $contents, $reordered ), $return );
|
|
}
|
|
|
|
$reordered = array();
|
|
|
|
if ( is_dir( $path ) AND \file_exists( $path . '/order.txt' ) )
|
|
{
|
|
$order = \file( $path . '/order.txt' );
|
|
|
|
foreach( $order as $item )
|
|
{
|
|
foreach( $return as $url )
|
|
{
|
|
$item = trim( $item );
|
|
|
|
if ( mb_substr( $item, -3 ) === '.js' )
|
|
{
|
|
if ( mb_substr( $url, -(mb_strlen( $item ) ) ) == $item )
|
|
{
|
|
$reordered[] = $url;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( mb_substr( str_replace( \IPS\Settings::i()->base_url . ltrim( str_replace( \IPS\ROOT_PATH, '', $path ), '/' ), '', $url ), 1, (mb_strlen( $item ) ) ) == $item )
|
|
{
|
|
$reordered[] = $url;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( count( $reordered ) )
|
|
{
|
|
/* Add in items not specified in the order */
|
|
$diff = array_diff( $return, $reordered );
|
|
|
|
if ( count( $diff ) )
|
|
{
|
|
foreach( $diff as $url )
|
|
{
|
|
$reordered[] = $url;
|
|
}
|
|
}
|
|
|
|
return $reordered;
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* Returns the type of javascript file
|
|
* @param string $path Path
|
|
* @param string $name File Name
|
|
* @return string
|
|
*/
|
|
protected static function _getType( $path, $name )
|
|
{
|
|
$type = 'framework';
|
|
|
|
if ( mb_strstr( $path, '/controllers/' ) )
|
|
{
|
|
$type = 'controller';
|
|
}
|
|
else if ( mb_strstr( $path, '/models/' ) )
|
|
{
|
|
$type = 'model';
|
|
}
|
|
else if ( mb_strstr( $path, '/mixins/' ) )
|
|
{
|
|
$type = 'mixins';
|
|
}
|
|
else if ( mb_strstr( $path, '/ui/' ) )
|
|
{
|
|
$type = 'ui';
|
|
}
|
|
else if ( mb_strstr( $name, 'ips.templates.' ) )
|
|
{
|
|
$type = 'template';
|
|
}
|
|
|
|
return $type;
|
|
}
|
|
|
|
/**
|
|
* Returns an incremented position integer for this app and location
|
|
*
|
|
* @param string $app Application key
|
|
* @param string $location Location (front, global, etc)
|
|
* @return int
|
|
*/
|
|
protected static function _getNextPosition( $app, $location )
|
|
{
|
|
if ( ! isset( static::$positions[ $app . '-' . $location ] ) )
|
|
{
|
|
static::$positions[ $app . '-' . $location ] = 0;
|
|
}
|
|
|
|
static::$positions[ $app . '-' . $location ] += 50;
|
|
|
|
return static::$positions[ $app . '-' . $location ];
|
|
}
|
|
}
|