├── .gitignore ├── src ├── GeoIP-Lite │ └── GeoIP.dat ├── Sifo │ ├── Session │ │ ├── SessionNameStrategy.php │ │ └── SessionEnvironmentStrategy.php │ ├── View │ │ ├── Interface.php │ │ └── Smarty.php │ ├── Debug │ │ ├── PredisProxyClient.php │ │ └── Sphinxql.php │ ├── AmazonS3.php │ ├── Cache │ │ ├── Memcache.php │ │ ├── Memcached.php │ │ ├── MemcacheAdapter.php │ │ ├── Lock.php │ │ └── Disk.php │ ├── Keyspace.php │ ├── CssPacker.php │ ├── Model.php │ ├── Crypt.php │ ├── JsPacker.php │ ├── MysqlModel.php │ ├── Mail.php │ ├── Benchmark.php │ ├── FlashMessages.php │ ├── View.php │ ├── CLBootstrap.php │ ├── Cache.php │ ├── Registry.php │ ├── imageController.php │ ├── RedisModel.php │ ├── MediaPacker.php │ ├── Dir.php │ ├── Cookie.php │ ├── Session.php │ ├── Images.php │ ├── API │ │ └── Youtube.php │ ├── LoadBalancer.php │ ├── Metadata.php │ ├── Router.php │ ├── Exceptions.php │ ├── Search.php │ ├── Config.php │ └── DirectoryList.php ├── Twig-sifo-plugins │ ├── function.t.php │ ├── filter.normalize.php │ ├── function.paginate.php │ ├── filter.link_urls.php │ ├── filter.number_format.php │ ├── filter.search_links.php │ ├── filter.custom_tpl.php │ ├── filter.currency.php │ ├── filter.time_format.php │ ├── filter.create_links.php │ ├── filter.size_format.php │ ├── function.pagelink.php │ ├── function.filln.php │ ├── function.fill.php │ ├── filter.time_since.php │ └── function.email_obfuscator.php ├── Smarty-sifo-plugins │ ├── function.paginate.php │ ├── modifier.lower.php │ ├── modifier.normalize.php │ ├── modifier.nl2br.php │ ├── modifier.custom_tpl.php │ ├── modifier.link_urls.php │ ├── modifier.search_links.php │ ├── modifier.number_format.php │ ├── modifier.currency.php │ ├── modifier.time_format.php │ ├── function.pagelink.php │ ├── modifier.create_links.php │ ├── modifier.size_format.php │ ├── function.filln.php │ ├── modifier.time_since.php │ ├── function.email_obfuscator.php │ ├── block.t.php │ └── function.fill.php ├── RSS_PHP │ └── rss_php.php └── Core-js │ └── classes │ └── modals.min.js ├── .gitattributes ├── LICENSE ├── README.md ├── composer.json └── .idea └── workspace.xml /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | composer.lock 3 | .idea 4 | -------------------------------------------------------------------------------- /src/GeoIP-Lite/GeoIP.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sifophp/SIFO/HEAD/src/GeoIP-Lite/GeoIP.dat -------------------------------------------------------------------------------- /src/Sifo/Session/SessionNameStrategy.php: -------------------------------------------------------------------------------- 1 | fetch( $aParam['data']['template'] ); 9 | } 10 | 11 | return $sOut; 12 | 13 | }//smarty_paginate 14 | ?> -------------------------------------------------------------------------------- /src/Twig-sifo-plugins/function.paginate.php: -------------------------------------------------------------------------------- 1 | fetch($args[0]['data']['template']); 11 | } 12 | 13 | return $sOut; 14 | }, ['is_variadic' => true] 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /src/Twig-sifo-plugins/filter.link_urls.php: -------------------------------------------------------------------------------- 1 | ".($matches[0]).""; 13 | }, 14 | $string 15 | ); 16 | } 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /src/Sifo/Session/SessionEnvironmentStrategy.php: -------------------------------------------------------------------------------- 1 | getInstanceInheritance(); 10 | $vertical_instance = array_pop($instance_inheritance); 11 | $instance_environment_initial = isset($_SERVER['APP_ENV'][0]) ? $_SERVER['APP_ENV'][0] : ''; 12 | $instance_session_name = "SSID_{$instance_environment_initial}_{$vertical_instance}"; 13 | session_name($instance_session_name); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Twig-sifo-plugins/filter.number_format.php: -------------------------------------------------------------------------------- 1 | getLanguage()); 11 | $locale = localeconv(); 12 | setlocale(LC_NUMERIC, null); 13 | $thousand_separator = ($locale['thousands_sep'] == '') ? '.' : $locale['thousands_sep']; 14 | $decimal_separator = $locale['decimal_point']; 15 | 16 | return @utf8_encode(number_format($string, $decimals, $decimal_separator, $thousand_separator)); 17 | } 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /src/Twig-sifo-plugins/filter.search_links.php: -------------------------------------------------------------------------------- 1 | $url", $text); 18 | } 19 | } 20 | 21 | return $text; 22 | } 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/modifier.lower.php: -------------------------------------------------------------------------------- 1 | 13 | * Name: lower
14 | * Purpose: convert string to lowercase 15 | * 16 | * @link http://smarty.php.net/manual/en/language.modifier.lower.php lower (Smarty online manual) 17 | * @author Monte Ohrt 18 | * @param string $ 19 | * @return string 20 | */ 21 | function smarty_modifier_lower($string) 22 | { 23 | if (function_exists('mb_strtolower')) { 24 | return mb_strtolower($string); 25 | } else { 26 | return strtolower($string); 27 | } 28 | } 29 | 30 | ?> 31 | -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/modifier.normalize.php: -------------------------------------------------------------------------------- 1 | 13 | * Name: default
14 | * Purpose: designate default value for empty variables 15 | * @link http://smarty.php.net/manual/en/language.modifier.default.php 16 | * default (Smarty online manual) 17 | * @author Monte Ohrt 18 | * 19 | * Slightly modified to normalize usign SIFO class. 20 | * @param string 21 | * @param string 22 | * @return string 23 | */ 24 | function smarty_modifier_normalize($string, $strict = false) 25 | { 26 | $normalized_url = \Sifo\Urls::normalize( $string ); 27 | 28 | return $normalized_url; 29 | } 30 | 31 | /* vim: set expandtab: */ 32 | 33 | ?> 34 | -------------------------------------------------------------------------------- /src/Twig-sifo-plugins/filter.custom_tpl.php: -------------------------------------------------------------------------------- 1 | getConfig('templates'); 15 | if (isset($instance_templates[$template])) 16 | { 17 | $selected_template = $instance_templates[$template]; 18 | } 19 | else 20 | { 21 | trigger_error("The template '{$template}' has not been found in the templates folder.", E_USER_ERROR); 22 | 23 | return false; 24 | } 25 | 26 | return $selected_template; 27 | } 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/modifier.nl2br.php: -------------------------------------------------------------------------------- 1 | 13 | * Name: nl2br
14 | * Date: Feb 26, 2003 15 | * Purpose: convert \r\n, \r or \n to <
> 16 | * Input:
17 | * - contents = contents to replace 18 | * - preceed_test = if true, includes preceeding break tags 19 | * in replacement 20 | * Example: {$text|nl2br} 21 | * @link http://smarty.php.net/manual/en/language.modifier.nl2br.php 22 | * nl2br (Smarty online manual) 23 | * @version 1.0 24 | * @author Monte Ohrt 25 | * @param string 26 | * @return string 27 | */ 28 | function smarty_modifier_nl2br($string) 29 | { 30 | return nl2br($string); 31 | } 32 | 33 | /* vim: set expandtab: */ 34 | 35 | ?> 36 | -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/modifier.custom_tpl.php: -------------------------------------------------------------------------------- 1 | getConfig( 'templates' ); 19 | if ( isset( $instance_templates[$template] ) ) 20 | { 21 | $selected_template = $instance_templates[$template]; 22 | } 23 | else 24 | { 25 | trigger_error( "The template '{$template}' has not been found in the templates folder.", E_USER_ERROR ); 26 | return false; 27 | } 28 | 29 | return ( ROOT_PATH . "/$selected_template" ); 30 | } -------------------------------------------------------------------------------- /src/Sifo/Debug/PredisProxyClient.php: -------------------------------------------------------------------------------- 1 | client ) ) 10 | { 11 | $call_data = array(); 12 | $call_data['connection'] = $this->connection_params; 13 | $call_data['method'] = $method; 14 | $call_data['args'] = $args; 15 | $call_data['controller'] = $this->getCallerClass(); 16 | $call_data['results'] = call_user_func_array( array( $this->client, $method ), $args ); 17 | 18 | Debug::push( 'redis', $call_data ); 19 | 20 | return $call_data['results']; 21 | } 22 | 23 | return null; 24 | } 25 | 26 | public function getCallerClass() 27 | { 28 | $trace = debug_backtrace(); 29 | foreach( $trace as $steps ) 30 | { 31 | $classes[$steps['class']] = $steps['class']; 32 | } 33 | 34 | return implode( ' > ', array_slice( $classes, 0, 4 ) ); 35 | } 36 | } -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/modifier.link_urls.php: -------------------------------------------------------------------------------- 1 | 12 | * Name: link_urls
13 | * Purpose: performs a regex and replaces any url's with links containing themselves as the text 14 | * This could be improved by using a better regex. 15 | * And maybe it would be better for usability if the http:// was cut off the front? 16 | * @author Andrew 17 | * @return string 18 | */ 19 | 20 | function smarty_modifier_link_urls($string) 21 | { 22 | $linkedString = preg_replace_callback( 23 | "/\b(https?):\/\/([-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]*)\b/i", 24 | static function($matches) { 25 | return "".($matches[0]).""; 26 | }, 27 | $string 28 | ); 29 | 30 | return $linkedString; 31 | } 32 | 33 | ?> -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/modifier.search_links.php: -------------------------------------------------------------------------------- 1 | 13 | * Name: search_links
14 | * Date: 28 Dic, 2010 15 | * Purpose: In a plain text convert links to HTML. 16 | * Example: {$text|search_links} 17 | * @link http://www.harecoded.com 18 | * @version 1.0 19 | * @author Albert Lombarte 20 | * @param string 21 | * @return string 22 | */ 23 | function smarty_modifier_search_links( $text, $title = '', $rel='nofollow' ) 24 | { 25 | preg_match_all( '/(http|ftp)+(s)?:(\/\/)((\w|\.)+)(\/)?(\S+)?(\.*)?/i', $text, $matches ); 26 | if ( !empty( $matches[0] ) ) 27 | { 28 | array_unique( $matches[0] ); 29 | foreach ( $matches[0] as $url ) 30 | { 31 | $text = str_replace( $url, "$url", $text ); 32 | } 33 | } 34 | 35 | return $text; 36 | 37 | } 38 | 39 | ?> -------------------------------------------------------------------------------- /src/Sifo/AmazonS3.php: -------------------------------------------------------------------------------- 1 | getConfig( 'amazon', 's3' ); 31 | 32 | return parent::__construct( 33 | $config['awsAccessKey'], 34 | $config['awsSecretKey'], 35 | $config['useSSL'] 36 | ); 37 | } 38 | } 39 | 40 | ?> 41 | -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/modifier.number_format.php: -------------------------------------------------------------------------------- 1 | 13 | * Name: number_format
14 | * Purpose: format strings via number_format 15 | * @author Albert Lombarte 16 | * @param string 17 | * @param string 18 | * @param string 19 | * @param string 20 | * @return string 21 | */ 22 | function smarty_modifier_number_format( $string, $decimals = 2 ) 23 | { 24 | // Numeric locale vars. 25 | // Remember to change the size_format modifier if you change the locales management here. 26 | setlocale( LC_NUMERIC, \Sifo\Domains::getInstance()->getLanguage() ); 27 | $locale = localeconv(); 28 | setlocale( LC_NUMERIC, null ); 29 | $thousand_separator = ( $locale['thousands_sep'] == '' ) ? '.' : $locale['thousands_sep']; 30 | $decimal_separator = $locale['decimal_point']; 31 | 32 | return @utf8_encode(number_format( $string, $decimals, $decimal_separator, $thousand_separator )); 33 | } 34 | 35 | /* vim: set expandtab: */ 36 | 37 | ?> 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2010-2012 Albert Lombarte 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | ---------------------------------------------------------------------- 16 | This license applies to all the folders of this project excluding the 17 | folders located under libs/ not named "SIFO". See their original 18 | license file (included in the source code) for more information. 19 | ---------------------------------------------------------------------- 20 | 21 | Some SIFO files are licensed (because they created the files for SIFO) to: 22 | 23 | Albert Garcia 24 | Sergio Ambel 25 | Pablo Ros 26 | Jorge Tarrero 27 | Carlos Soriano 28 | Manel Fernández -------------------------------------------------------------------------------- /src/Twig-sifo-plugins/filter.currency.php: -------------------------------------------------------------------------------- 1 | '€', 13 | 'GBP' => '£', 14 | 'USD' => '$' 15 | ); 16 | 17 | $currency_symbol = $currency; 18 | 19 | if (array_key_exists($currency, $currency_symbols)) 20 | { 21 | $currency_symbol = $currency_symbols[$currency]; 22 | } 23 | 24 | if (!empty($tag)) 25 | { 26 | $currency_symbol = '<' . $tag . '>' . $currency_symbol . ''; 27 | } 28 | 29 | switch ($currency) 30 | { 31 | case 'USD': 32 | case 'GBP': 33 | { 34 | return $currency_symbol . number_format($amount, 2); 35 | } 36 | 37 | default: 38 | { 39 | return number_format($amount, 2, ',', '.') . $currency_symbol; 40 | } 41 | } 42 | } 43 | ); 44 | } 45 | -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/modifier.currency.php: -------------------------------------------------------------------------------- 1 | 12 | * Name: currency
13 | * Purpose: Formats a number as a currency string, with the given currency symbol 14 | * @param float 15 | * @param string currency (default EUR) 16 | * @return string 17 | */ 18 | function smarty_modifier_currency($amount, $currency='EUR', $tag='') 19 | { 20 | $currency_symbols = array( 21 | 'EUR' => '€', 22 | 'GBP' => '£', 23 | 'USD' => '$' 24 | ); 25 | 26 | if ( array_key_exists( $currency, $currency_symbols ) ) 27 | { 28 | $currency_symbol = $currency_symbols[$currency]; 29 | } 30 | else 31 | { 32 | $currency_symbol = $currency; 33 | } 34 | 35 | if ( !empty( $tag ) ) 36 | { 37 | $currency_symbol = '<'.$tag.'>'.$currency_symbol.''; 38 | } 39 | 40 | switch( $currency ) 41 | { 42 | case 'USD': 43 | case 'GBP': 44 | { 45 | return $currency_symbol.number_format($amount,2,'.',','); 46 | } 47 | 48 | default: 49 | { 50 | return number_format($amount,2,',','.').$currency_symbol; 51 | } 52 | } 53 | } 54 | 55 | ?> 56 | -------------------------------------------------------------------------------- /src/Twig-sifo-plugins/filter.time_format.php: -------------------------------------------------------------------------------- 1 | getLanguage()); 13 | $locale = localeconv(); 14 | setlocale(LC_NUMERIC, null); 15 | $thousand_separator = ($locale['thousands_sep'] == '') ? '.' : $locale['thousands_sep']; 16 | $decimal_separator = $locale['decimal_point']; 17 | 18 | if (null === $decimals) 19 | { 20 | $decimals = 0; 21 | } 22 | 23 | $time *= 1000; 24 | 25 | if ($time < 100) 26 | { 27 | // Miliseconds. 28 | $formatted_time = number_format($time, $decimals, $decimal_separator, $thousand_separator) . ' milisec'; 29 | } 30 | else 31 | { 32 | // Seconds. 33 | $formatted_time = number_format($time / 1000, $decimals, $decimal_separator, $thousand_separator) . ' sec'; 34 | } 35 | 36 | return $formatted_time; 37 | } 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Sifo PHP 2 | ======== 3 | 4 | [SIFO] is a battle-tested open source Legacy PHP framework currently running on several production 5 | sites since more than 7 years, from small installations to large websites with multiple servers. 6 | 7 | --- 8 | 9 | ## Installation 10 | 11 | ```bash 12 | composer require sifophp/sifo sifophp/sifo-common-instance 13 | ``` 14 | 15 | ## Future of Sifo Framework 16 | 17 | ### Support 18 | 19 | * Sifo is actively maintained cost it is used by some companies in production 20 | * Fill free to open issue or a pull request for any kind of fix or improvement 21 | 22 | ### New Features 23 | 24 | * Although, the framework is actively maintained, we aren't go to add any new feature, 25 | Sifo has a lot of features that we are trying to remove in order to archieve a more cleaner integration between the 26 | framework and the business code. 27 | 28 | ### Deprecations 29 | 30 | * Use only classes located inner `Sifo\` namespace every other library included will be deleted in future releases 31 | 32 | ### Maybe 33 | 34 | * Allow Framework Agnostic Controllers 35 | * Clean package without external libraries 36 | 37 | --- 38 | 39 | More documentation in the *official site*: [https://web.archive.org/web/20180809060838/http://sifo.me/] [SIFO] 40 | 41 | [SIFO]: https://web.archive.org/web/20180809060838/http://sifo.me/ 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/Twig-sifo-plugins/filter.create_links.php: -------------------------------------------------------------------------------- 1 | ()\[\]\{\}\s\x7F-\\xFF]* 40 | ( 41 | [.!,?]+ [^.!,?"\\'<>()\\[\\]\{\\}\s\\x7F-\\xFF]+ 42 | )* 43 | )? 44 | }ix 45 | REGEXP; 46 | } 47 | 48 | return preg_replace($regexp, '\1\4', $string); 49 | } 50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /src/Sifo/Cache/Memcache.php: -------------------------------------------------------------------------------- 1 | set( 'a', 'my value' ); // Stores in the key 'a' the value 'my value' 13 | * 14 | * This class is based on Memcache object implementation: http://www.php.net/manual/en/book.memcache.php 15 | * 16 | */ 17 | namespace Sifo; 18 | 19 | /** 20 | * Wrapper for the PECL Memcache extension. 21 | * 22 | * @see http://www.php.net/manual/en/memcache.installation.php 23 | */ 24 | class CacheMemcache extends CacheBase 25 | { 26 | protected $cache_object = null; 27 | 28 | /** 29 | * Returns an instance of the Memcache object with the configured servers. 30 | */ 31 | public function __construct() 32 | { 33 | try 34 | { 35 | $servers = \Sifo\Config::getInstance()->getConfig( 'cache', 'servers' ); 36 | } 37 | catch ( \Sifo\Exception_Configuration $e ) 38 | { 39 | // Default memcached address and listening port. 40 | $servers = array( array( '127.0.0.1' => 11211 ) ); 41 | } 42 | 43 | $this->cache_object = new \CacheMemcacheAdapter(); 44 | 45 | foreach ( $servers[0] as $server => $port ) 46 | { 47 | $this->cache_object->addServer( $server, $port ); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/modifier.time_format.php: -------------------------------------------------------------------------------- 1 | 14 | * Name: time_format
15 | * Purpose: format times directly from DB. 16 | * 17 | * @param integer $time Time given in ms. 18 | * @param integer $decimals Number of decimals. 19 | * @return string 20 | */ 21 | function smarty_modifier_time_format( $time, $decimals=3 ) 22 | { 23 | // Numeric locale vars. 24 | // Remember to change the number_format modifier if you change the locales management here. 25 | setlocale( LC_NUMERIC, \Sifo\Domains::getInstance()->getLanguage() ); 26 | $locale = localeconv(); 27 | setlocale( LC_NUMERIC, null ); 28 | $thousand_separator = ( $locale['thousands_sep'] == '' ) ? '.' : $locale['thousands_sep']; 29 | $decimal_separator = $locale['decimal_point']; 30 | 31 | if ( is_null( $decimals ) ) 32 | { 33 | $decimals = 0; 34 | } 35 | 36 | $time = $time*1000; 37 | 38 | if ( $time < 100 ) 39 | { 40 | // Miliseconds. 41 | $formatted_time = number_format( $time, $decimals, $decimal_separator, $thousand_separator ).' milisec'; 42 | } 43 | else 44 | { 45 | // Seconds. 46 | $formatted_time = number_format( ( $time / 1000 ), $decimals, $decimal_separator, $thousand_separator ).' sec'; 47 | } 48 | 49 | return $formatted_time; 50 | } 51 | 52 | /* vim: set expandtab: */ 53 | 54 | ?> 55 | -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/function.pagelink.php: -------------------------------------------------------------------------------- 1 | getString( 'QUERY_STRING' ); 22 | $_current_path = \Sifo\FilterServer::getInstance()->getString( 'REQUEST_URI' ); 23 | 24 | if ( !empty( $_current_querystring ) ) 25 | { 26 | $_current_querystring = '?' . $_current_querystring; 27 | $_current_path = str_replace( $_current_querystring, '', $_current_path ); 28 | } 29 | 30 | $_current_url = array_reverse( explode( $_delimiter, $_current_path ) ); 31 | 32 | if ( is_numeric( $_current_url[0] ) ) 33 | { 34 | $_current_page = ( int )array_shift( $_current_url ); 35 | } 36 | else 37 | { 38 | $_current_page = 1; 39 | } 40 | 41 | $_current_url = implode( $_delimiter, array_reverse( $_current_url ) ); 42 | 43 | if ( !isset( $params['page'] ) ) 44 | { 45 | trigger_error( "pagelink: You should provide the destination pagelink." ); 46 | } 47 | else 48 | { 49 | if ( $params['page'] > 1 ) 50 | { 51 | return $_current_url . $_delimiter . $params['page']; 52 | } 53 | else 54 | { 55 | return $_current_url; 56 | } 57 | } 58 | } 59 | 60 | /* vim: set expandtab: */ 61 | 62 | ?> 63 | -------------------------------------------------------------------------------- /src/Sifo/Cache/Memcached.php: -------------------------------------------------------------------------------- 1 | cache_object = new \Memcached(); 38 | 39 | try 40 | { 41 | $servers = Config::getInstance()->getConfig( 'cache', 'servers' ); 42 | } 43 | catch ( Exception_Configuration $e ) 44 | { 45 | // Default memcached address and listening port. 46 | $servers = array( array( '127.0.0.1' => 11211 ) ); 47 | } 48 | 49 | foreach ( $servers[0] as $server => $port ) 50 | { 51 | $this->cache_object->addServer( $server, $port ); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Sifo/Keyspace.php: -------------------------------------------------------------------------------- 1 | getConfig( 'keyspace' ); 33 | } 34 | 35 | if ( !isset( self::$keyspace[$key_name] ) ) 36 | { 37 | throw new KeySpace_Exception( "Key named '$key_name' is not available in the key space." ); 38 | } 39 | 40 | 41 | $key = self::$keyspace[$key_name]; 42 | 43 | if ( is_array( $parameters ) ) 44 | { 45 | foreach ( $parameters as $tag => $value ) 46 | { 47 | $tag = preg_quote( $tag, '/' ); 48 | $key = preg_replace( "/<($tag)>/", $value, $key); 49 | } 50 | } 51 | 52 | // Remove any missing parameters: 53 | if ( false !== strpos( $key, '<' ) ) 54 | { 55 | throw new KeySpace_Exception( "The key contains undeclared parameters for replacement" ); 56 | } 57 | 58 | return $key; 59 | } 60 | 61 | } 62 | 63 | class KeySpace_Exception extends \Exception 64 | { 65 | 66 | } -------------------------------------------------------------------------------- /src/Sifo/CssPacker.php: -------------------------------------------------------------------------------- 1 | 12 | * Name: create_links
13 | * Purpose: create HTML markup for links
14 | * Input:
15 | * - string: text you want to search for links into 16 | * Params:
17 | * - string $regexp Optional in case you want to define a different regexp for URLs (like only internal links). 18 | * 19 | * @author Manuel Fernandez 20 | * @return string 21 | */ 22 | function smarty_modifier_create_links($string,$regexp = '') 23 | { 24 | if ( empty( $regexp ) ) 25 | { 26 | $regexp = <<()\[\]\{\}\s\x7F-\\xFF]* 54 | ( 55 | [.!,?]+ [^.!,?"\\'<>()\\[\\]\{\\}\s\\x7F-\\xFF]+ 56 | )* 57 | )? 58 | }ix 59 | REGEXP; 60 | } 61 | 62 | return preg_replace( $regexp, '\1\4', $string ); 63 | } 64 | 65 | /* vim: set expandtab: */ 66 | 67 | ?> 68 | -------------------------------------------------------------------------------- /src/Sifo/Cache/MemcacheAdapter.php: -------------------------------------------------------------------------------- 1 | getLanguage()); 13 | $locale = localeconv(); 14 | setlocale(LC_NUMERIC, null); 15 | $thousand_separator = ($locale['thousands_sep'] == '') ? '.' : $locale['thousands_sep']; 16 | $decimal_separator = $locale['decimal_point']; 17 | 18 | if ($size < 1024) 19 | { 20 | if (null === $decimals) 21 | { 22 | $decimals = 0; 23 | } 24 | // Kilobytes. 25 | $formatted_size = number_format($size, $decimals, $decimal_separator, $thousand_separator) . ' B'; 26 | } 27 | elseif ($size < 1048576) 28 | { 29 | if (null === $decimals) 30 | { 31 | $decimals = 0; 32 | } 33 | // Kylobytes. 34 | $formatted_size = number_format(($size / 1024), $decimals, $decimal_separator, $thousand_separator) . ' KB'; 35 | } 36 | elseif ($size < 1073741824) 37 | { 38 | if (null === $decimals) 39 | { 40 | $decimals = 1; 41 | } 42 | // Megabytes. 43 | $formatted_size = number_format(($size / 1048576), $decimals, $decimal_separator, $thousand_separator) . ' MB'; 44 | } 45 | else 46 | { 47 | if (null === $decimals) 48 | { 49 | $decimals = 1; 50 | } 51 | // Gigabytes. 52 | $formatted_size = number_format(($size / 1073741824), $decimals, $decimal_separator, $thousand_separator) . ' GB'; 53 | } 54 | 55 | return $formatted_size; 56 | } 57 | ); 58 | } 59 | -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/modifier.size_format.php: -------------------------------------------------------------------------------- 1 | 14 | * Name: size_format
15 | * Purpose: format sizes directly from DB. 16 | * 17 | * @param integer $size Size of a file. 18 | * @param integer $decimals Number of decimals. 19 | * @return string 20 | */ 21 | function smarty_modifier_size_format( $size, $decimals=null ) 22 | { 23 | // Numeric locale vars. 24 | // Remember to change the number_format modifier if you change the locales management here. 25 | setlocale( LC_NUMERIC, \Sifo\Domains::getInstance()->getLanguage() ); 26 | $locale = localeconv(); 27 | setlocale( LC_NUMERIC, null ); 28 | $thousand_separator = ( $locale['thousands_sep'] == '' ) ? '.' : $locale['thousands_sep']; 29 | $decimal_separator = $locale['decimal_point']; 30 | 31 | if ( $size < 1024 ) 32 | { 33 | if ( is_null( $decimals ) ) 34 | { 35 | $decimals = 0; 36 | } 37 | // Kilobytes. 38 | $formatted_size = number_format( $size, $decimals, $decimal_separator, $thousand_separator ).' B'; 39 | } 40 | elseif ( $size < 1048576 ) 41 | { 42 | if ( is_null( $decimals ) ) 43 | { 44 | $decimals = 0; 45 | } 46 | // Kylobytes. 47 | $formatted_size = number_format( ( $size / 1024 ), $decimals, $decimal_separator, $thousand_separator ).' KB'; 48 | } 49 | elseif ( $size < 1073741824 ) 50 | { 51 | if ( is_null( $decimals ) ) 52 | { 53 | $decimals = 1; 54 | } 55 | // Megabytes. 56 | $formatted_size = number_format( ( $size / 1048576 ), $decimals, $decimal_separator, $thousand_separator ).' MB'; 57 | } 58 | else 59 | { 60 | if ( is_null( $decimals ) ) 61 | { 62 | $decimals = 1; 63 | } 64 | // Gigabytes. 65 | $formatted_size = number_format( ( $size / 1073741824 ), $decimals, $decimal_separator, $thousand_separator ).' GB'; 66 | 67 | } 68 | 69 | return $formatted_size; 70 | } 71 | 72 | /* vim: set expandtab: */ 73 | 74 | ?> 75 | -------------------------------------------------------------------------------- /src/Twig-sifo-plugins/function.pagelink.php: -------------------------------------------------------------------------------- 1 | getString('QUERY_STRING'); 16 | $current_path = \Sifo\FilterServer::getInstance()->getString('REQUEST_URI'); 17 | $current_host = \Sifo\Urls::$base_url; 18 | } 19 | else 20 | { 21 | $current_querystring = $_SERVER['QUERY_STRING']; 22 | $current_path = $_SERVER['REQUEST_URI']; 23 | $current_host = ($_SERVER['HTTPS'] ? 'https://' : 'http://') . $_SERVER['HTTP_HOST']; 24 | } 25 | 26 | // Clean querystring always. The URL could eventually include an empty "?". 27 | $current_path = str_ireplace('?' . $current_querystring, '', $current_path); 28 | 29 | $current_url = array_reverse(explode($delimiter, $current_path)); 30 | 31 | if (isset($args[0]['base_url'])) 32 | { 33 | $current_url = $args[0]['base_url']; 34 | } 35 | else 36 | { 37 | $current_url = implode($delimiter, array_reverse($current_url)); 38 | 39 | if (isset($args[0]['absolute'])) 40 | { 41 | $current_url = $current_host . $current_url; 42 | } 43 | } 44 | 45 | if (!isset($args[0]['page'])) 46 | { 47 | trigger_error('pagelink: You should provide the destination pagelink. Params: ' . json_encode($args[0]), E_USER_WARNING); 48 | } 49 | else 50 | { 51 | if ($args[0]['page'] > 1 || (isset($args[0]['force_first_page']) && $args[0]['force_first_page'] == true)) 52 | { 53 | return $current_url . $delimiter . $args[0]['page']; 54 | } 55 | 56 | return $current_url; 57 | } 58 | }, ['is_variadic' => true] 59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /src/Sifo/Model.php: -------------------------------------------------------------------------------- 1 | init(); 28 | return Database::getInstance(); 29 | } 30 | 31 | /** 32 | * Use this method as constructor in chidren. 33 | */ 34 | protected function init() 35 | { 36 | return true; 37 | } 38 | 39 | /** 40 | * Returns an element in the registry. 41 | * 42 | * @param string $key 43 | * @return mixed 44 | */ 45 | protected function inRegistry( $key ) 46 | { 47 | $reg = Registry::getInstance(); 48 | if ( $reg->keyExists( $key ) ) 49 | { 50 | return $reg->get( $key ); 51 | } 52 | 53 | return false; 54 | } 55 | 56 | /** 57 | * Stores in the registry a value with the given key. 58 | * 59 | * @param string $key 60 | * @param mixed $value 61 | */ 62 | protected function storeInRegistry( $key, $value ) 63 | { 64 | $reg = Registry::getInstance()->set( $key, $value ); 65 | } 66 | 67 | /** 68 | * Returns the translation of a string 69 | * 70 | * @param string $subject 71 | * @param string $var_1 72 | * @param string $var2 73 | * @param string $var_n 74 | * @return string 75 | */ 76 | public function translate( $subject, $var_1 = '', $var2 = '', $var_n = '' ) 77 | { 78 | $args = func_get_args(); 79 | $variables = array(); 80 | if ( 1 < count( $args ) ) 81 | { 82 | foreach ( $args as $key => $value ) 83 | { 84 | $variables['%'.$key] = $value; 85 | } 86 | 87 | } 88 | 89 | unset( $variables['%0'] ); 90 | return I18N::getInstance( 'messages', Domains::getInstance()->getLanguage() )->getTranslation( $subject, $variables ); 91 | } 92 | 93 | /** 94 | * When Database response is bad you can use $this->CacheExecute($seconds, "SELECT..'");. Writes to /cache are done. 95 | */ 96 | } 97 | -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/function.filln.php: -------------------------------------------------------------------------------- 1 | 13 | * Name: fill
14 | * Input:
15 | * - [any] (required) - string 16 | * - subject (required) - string 17 | * - delimiter (optional, defaults to '%' ) - string 18 | * Purpose: Fills the variables found in 'subject' with the paramaters passed. The variables are any word surrounded by two delimiters. 19 | * 20 | * Examples of usage: 21 | * 22 | * {fill subject="http://domain.com/profile/%username%" username='fred'} 23 | * Output: http://domain.com/profile/fred 24 | * 25 | * {fill subject="Hello %user%, welcome aboard!" user=Fred} 26 | * Outputs: Hello Fred, welcome aboard 27 | * 28 | * {fill subject="http://||subdomain||.domain.com/||page||/||action||" subdomain='www' page='my-first-post' action='vote' delimiter='||'} 29 | * Outputs: http://www.domain.com/my-first-post/vote 30 | * 31 | * @link http://www.harecoded.com/fill-smarty-php-plugin-311577 32 | * @author Albert Lombarte 33 | * @param array 34 | * @param Smarty 35 | * @return string 36 | */ 37 | function smarty_function_filln($params, &$smarty) 38 | { 39 | 40 | if (isset($params['delimiter'])) { 41 | $_delimiter = $params['delimiter']; 42 | unset($params['delimiter']); 43 | } else { 44 | $_delimiter = '%'; 45 | } 46 | 47 | if (false !== strpos($_delimiter, '$')) { 48 | trigger_error("fill: The delimiter '$' is banned in function {url}", E_USER_NOTICE); 49 | } 50 | 51 | if (!isset($params['subject']) || count($params) < 2) { 52 | trigger_error("fill: The attribute 'subject' and at least one parameter is needed in function {url}", E_USER_NOTICE); 53 | } 54 | 55 | $_html_result = $params['subject']; 56 | $_tmp_result = $_html_result; 57 | 58 | unset($params['subject']); 59 | 60 | foreach ($params as $_key => $_val) 61 | { 62 | $_val = (string)$_val; 63 | $_tmp_result = str_replace($_delimiter . $_key . $_delimiter, $_val, $_tmp_result); 64 | 65 | $normalized_url = \Sifo\Urls::normalize($_val); 66 | $_html_result = str_replace($_delimiter . $_key . $_delimiter, $normalized_url, $_html_result); 67 | } 68 | 69 | return $_html_result; 70 | 71 | } 72 | 73 | /* vim: set expandtab: */ 74 | 75 | ?> 76 | -------------------------------------------------------------------------------- /src/Sifo/Crypt.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/modifier.time_since.php: -------------------------------------------------------------------------------- 1 | 16 | * Name: size_format
17 | * Purpose: format sizes directly from DB. 18 | * 19 | * @param integer $size Size of a file. 20 | * @param integer $decimals Number of decimals. 21 | * @return string 22 | */ 23 | function smarty_modifier_time_since( $diff_time ) 24 | { 25 | if ( !is_numeric ( $diff_time ) ) 26 | $diff_time = strtotime( date("Y-m-d H:i:s") ) - strtotime($diff_time); 27 | 28 | if ( floor($diff_time/(60*60*24)) >= 365 ) 29 | { 30 | $value[0] = floor($diff_time/(60*60*24*365)); 31 | if ( 1 == $value[0] ) 32 | $value[1] = \Sifo\I18N::getTranslation("year"); 33 | else 34 | $value[1] = \Sifo\I18N::getTranslation("years"); 35 | } 36 | elseif ( floor($diff_time/(60*60*24)) >= 30 ) 37 | { 38 | $value[0] = floor($diff_time/(60*60*24*30)); 39 | if ( 1 == $value[0] ) 40 | $value[1] = \Sifo\I18N::getTranslation("month"); 41 | else 42 | $value[1] = \Sifo\I18N::getTranslation("months"); 43 | } 44 | elseif ( floor($diff_time/(60*60*24)) >= 7 ) 45 | { 46 | $value[0] = floor($diff_time/(60*60*24*7)); 47 | if ( 1 == $value[0] ) 48 | $value[1] = \Sifo\I18N::getTranslation("week"); 49 | else 50 | $value[1] = \Sifo\I18N::getTranslation("weeks"); 51 | } 52 | elseif ( floor($diff_time/(60*60)) >= 24 ) 53 | { 54 | $value[0] = floor($diff_time/(60*60*24)); 55 | if ( 1 == $value[0] ) 56 | $value[1] = \Sifo\I18N::getTranslation("day"); 57 | else 58 | $value[1] = \Sifo\I18N::getTranslation("days"); 59 | }elseif ( floor($diff_time/(60)) >= 60 ) 60 | { 61 | $value[0] = floor($diff_time/(60*60)); 62 | if ( 1 == $value[0] ) 63 | $value[1] = \Sifo\I18N::getTranslation("hour"); 64 | else 65 | $value[1] = \Sifo\I18N::getTranslation("hours"); 66 | } 67 | elseif ( floor($diff_time/(60)) >= 1 ) 68 | { 69 | $value[0] = floor($diff_time/(60)); 70 | if ( 1 == $value[0] ) 71 | $value[1] = \Sifo\I18N::getTranslation("minute"); 72 | else 73 | $value[1] = \Sifo\I18N::getTranslation("minutes"); 74 | } 75 | else 76 | { 77 | $value[0] = false; 78 | $value[1] = \Sifo\I18N::getTranslation("just some seconds"); 79 | } 80 | 81 | $final_string = ($value > 0) ? $value[0] .' ' . $value[1] : $value[1]; 82 | 83 | return \Sifo\I18N::getTranslation('%1 ago', ['%1' => $final_string]); 84 | } 85 | -------------------------------------------------------------------------------- /src/Sifo/JsPacker.php: -------------------------------------------------------------------------------- 1 | instance_static_host}", 76 | Hash = window.Hash ? window.Hash : "unset", 77 | sInstance = window.sInstance ? window.sInstance : '', 78 | basePathConfig = {\n\t 79 | CODE; 80 | foreach ( $media_list as $group => $media_data ) 81 | { 82 | $base_array[] = "\t'$group': sHostStatic + '/{$this->generated_files_public_path}/' + sInstance + '$group.js?rev=' + Hash"; 83 | } 84 | 85 | $base_code .= implode( ",\n", $base_array ) . "\n\t};\n"; 86 | 87 | return $base_code; 88 | 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /src/Twig-sifo-plugins/function.filln.php: -------------------------------------------------------------------------------- 1 | getString( 41 | 'SCRIPT_URI' 42 | ), 43 | E_USER_WARNING 44 | ); 45 | } 46 | 47 | $subject = $args[0]['subject']; 48 | $tmp_result = $subject; 49 | 50 | foreach ($args[0] as $key => $current_value) 51 | { 52 | $current_value = (string) $current_value; 53 | $tmp_result = str_replace($delimiter . $key . $delimiter, $current_value, $tmp_result); 54 | 55 | if (method_exists('\Verticalroot\UrlsManagement', 'normalize')) 56 | { 57 | $urlized_val = \Verticalroot\UrlsManagement::normalize($current_value, $strict_params_normalize); 58 | $subject = str_replace($delimiter . $key . $delimiter, $urlized_val, $subject); 59 | } 60 | else if (method_exists('Urls', 'normalize')) 61 | { 62 | $urlized_val = \Sifo\Urls::normalize($current_value); 63 | $subject = str_replace($delimiter . $key . $delimiter, $urlized_val, $subject); 64 | } 65 | else 66 | { 67 | $subject = $tmp_result; 68 | } 69 | } 70 | 71 | return $subject; 72 | }, ['is_variadic' => true] 73 | ); 74 | } 75 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | $PROJECT_DIR$/composer.json 15 | 16 | 17 | 18 | 20 | 21 | 23 | 24 | 25 | 28 | 42 | 43 | 44 | 45 | 46 | 1681212321240 47 | 52 | 53 | 54 | 55 | 57 | -------------------------------------------------------------------------------- /src/Twig-sifo-plugins/function.fill.php: -------------------------------------------------------------------------------- 1 | escape_html; 43 | if (isset($args[0]['escapevar'])) 44 | { 45 | $escapevar = ($twig->escape_html && ($args[0]['escapevar'] != 'no')); 46 | unset($args[0]['escapevar']); 47 | } 48 | 49 | $html_result = $args[0]['subject']; 50 | $tmp_result = $html_result; 51 | unset($args[0]['subject']); 52 | 53 | foreach ($args[0] as $key => $_val) 54 | { 55 | if ($escapevar) 56 | { 57 | $_val = htmlspecialchars($_val, ENT_QUOTES, SMARTY_RESOURCE_CHAR_SET); 58 | } 59 | $_val = (string) $_val; 60 | $tmp_result = str_replace($delimiter . $key . $delimiter, (string) $_val, $tmp_result); 61 | 62 | // The UrlParse::normalize, amongs other things lowers the string. Check if plugin calls with lower=no to skip: 63 | if ($normalize && true === \Sifo\Urls::$normalize_values && (!isset($args[0]['lower']) || $args[0]['lower'] != 'no')) 64 | { 65 | $html_result = str_replace($delimiter . $key . $delimiter, \Sifo\Urls::normalize((string) $_val), $html_result); 66 | } 67 | else 68 | { 69 | $html_result = $tmp_result; 70 | } 71 | } 72 | 73 | if (false !== strpos(urldecode($html_result), $delimiter)) 74 | { 75 | trigger_error("fill: There are still parameters to replace, because the '$delimiter' delimiter was found in $html_result"); 76 | } 77 | 78 | return $html_result; 79 | }, ['is_variadic' => true] 80 | ); 81 | } 82 | -------------------------------------------------------------------------------- /src/Sifo/Cache/Lock.php: -------------------------------------------------------------------------------- 1 | lock_id = uniqid(); 49 | $this->key = $key; 50 | $this->cache_object = $cache_instance; 51 | } 52 | 53 | /** 54 | * @param string $original_key 55 | * @param CacheBase $cache_instance 56 | * 57 | * @return CacheLock 58 | */ 59 | public static function getInstance( $original_key, $cache_instance ) 60 | { 61 | $key = self::KEY_PREFIX . $original_key; 62 | 63 | if ( !isset( self::$instances[$key] ) ) 64 | { 65 | self::$instances[$key] = new self( $key, $cache_instance ); 66 | } 67 | 68 | return self::$instances[$key]; 69 | } 70 | 71 | /** 72 | * Returns if another cache calculation is in progress. 73 | * 74 | * @return boolean 75 | */ 76 | public function isLocked() 77 | { 78 | // The flow is not locked if the current process is the lock holder. 79 | return ( ( $value = $this->cache_object->get( $this->key ) ) && ( $value != $this->lock_id ) ); 80 | } 81 | 82 | 83 | /** 84 | * Acquire lock. 85 | * 86 | * @return boolean 87 | */ 88 | public function acquire() 89 | { 90 | $this->cache_object->set( $this->key, $this->lock_id, self::TTL ); 91 | } 92 | 93 | /** 94 | * Releases the lock. 95 | * 96 | * @return boolean 97 | */ 98 | public function release() 99 | { 100 | unset( self::$instances[$this->key] ); 101 | return $this->cache_object->delete( $this->key ); 102 | } 103 | 104 | /** 105 | * Release cache lock before object's destruction. 106 | * 107 | * If Exceptions, reDispatch, exit() or other hacks interfere with the normal workflow 108 | * the cache locks have to be released. 109 | */ 110 | public function __destruct() 111 | { 112 | if ( !empty( self::$instances[$this->key] ) ) 113 | { 114 | $this->release(); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/Twig-sifo-plugins/filter.time_since.php: -------------------------------------------------------------------------------- 1 | = 365) 15 | { 16 | $value[0] = floor($diff_time / (60 * 60 * 24 * 365)); 17 | if (1 == $value[0]) 18 | { 19 | $value[1] = \Sifo\I18N::getTranslation("year"); 20 | } 21 | else 22 | { 23 | $value[1] = \Sifo\I18N::getTranslation("years"); 24 | } 25 | } 26 | elseif (floor($diff_time / (60 * 60 * 24)) >= 30) 27 | { 28 | $value[0] = floor($diff_time / (60 * 60 * 24 * 30)); 29 | if (1 == $value[0]) 30 | { 31 | $value[1] = \Sifo\I18N::getTranslation("month"); 32 | } 33 | else 34 | { 35 | $value[1] = \Sifo\I18N::getTranslation("months"); 36 | } 37 | } 38 | elseif (floor($diff_time / (60 * 60 * 24)) >= 7) 39 | { 40 | $value[0] = floor($diff_time / (60 * 60 * 24 * 7)); 41 | if (1 == $value[0]) 42 | { 43 | $value[1] = \Sifo\I18N::getTranslation("week"); 44 | } 45 | else 46 | { 47 | $value[1] = \Sifo\I18N::getTranslation("weeks"); 48 | } 49 | } 50 | elseif (floor($diff_time / (60 * 60)) >= 24) 51 | { 52 | $value[0] = floor($diff_time / (60 * 60 * 24)); 53 | if (1 == $value[0]) 54 | { 55 | $value[1] = \Sifo\I18N::getTranslation("day"); 56 | } 57 | else 58 | { 59 | $value[1] = \Sifo\I18N::getTranslation("days"); 60 | } 61 | } 62 | elseif (floor($diff_time / (60)) >= 60) 63 | { 64 | $value[0] = floor($diff_time / (60 * 60)); 65 | if (1 == $value[0]) 66 | { 67 | $value[1] = \Sifo\I18N::getTranslation("hour"); 68 | } 69 | else 70 | { 71 | $value[1] = \Sifo\I18N::getTranslation("hours"); 72 | } 73 | } 74 | elseif (floor($diff_time / (60)) >= 1) 75 | { 76 | $value[0] = floor($diff_time / (60)); 77 | if (1 == $value[0]) 78 | { 79 | $value[1] = \Sifo\I18N::getTranslation("minute"); 80 | } 81 | else 82 | { 83 | $value[1] = \Sifo\I18N::getTranslation("minutes"); 84 | } 85 | } 86 | else 87 | { 88 | $value[0] = false; 89 | $value[1] = \Sifo\I18N::getTranslation("just some seconds"); 90 | } 91 | 92 | $final_string = ($value > 0) ? $value[0] . ' ' . $value[1] : $value[1]; 93 | 94 | return \Sifo\I18N::getTranslation('%1 ago', ['%1' => $final_string]); 95 | } 96 | ); 97 | } 98 | -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/function.email_obfuscator.php: -------------------------------------------------------------------------------- 1 | . 18 | * @param string Email to obfuscate (received automatically). 19 | * @param string Text to show instead of the email. 20 | * @return string JavaScript to show the obfuscated email. 21 | */ 22 | function smarty_function_email_obfuscator($params, &$smarty) 23 | { 24 | 25 | // email address to obfuscate. 26 | $email = ( isset( $params['email'] ) ) ? $params['email'] : ''; 27 | // optional text to show instead the email 28 | $linktext = ( isset( $params['text'] ) ) ? $params['text'] : ''; 29 | // style information via class. 30 | $style_class = ( isset( $params['class'] ) ) ? ' class=\"' . $params['class'] . '\" ' : ''; 31 | // style information via id. 32 | $style_id = ( isset( $params['id'] ) ) ? ' id=\"' . $params['id'] . '\" ' : ''; 33 | 34 | // Getting the extra params for the case of %1, %2, etc in the linktext. Using ; like separator. 35 | $extra_params = array(); 36 | if ( isset( $params['extra'] ) ) { 37 | $extra_params = explode( ';', $params['extra'] ); 38 | } 39 | 40 | // Translating linktext 41 | $textbefore = ''; 42 | $textafter = ''; 43 | if ( !empty( $linktext ) ) 44 | { 45 | $calling_class = get_called_class(); 46 | $obj = new $calling_class(); 47 | $temp = smarty_block_t( $extra_params, $linktext, $obj); 48 | // If the email is inside the text string 49 | $email_position = strpos( $temp, $email ); 50 | if ( $email_position ) 51 | { 52 | // If the email is inside the string we make the link only in the email address 53 | $textbefore = substr( $temp, 0, $email_position ); 54 | $textafter = substr( $temp, strpos( $temp, $email ) + strlen( $email ) ); 55 | $linktext = ''; 56 | } 57 | else 58 | { 59 | // Else the link is all the string 60 | $linktext = $temp; 61 | } 62 | } 63 | 64 | $character_set = '+-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'; 65 | $key = str_shuffle( $character_set ); 66 | $cipher_text = ''; 67 | $id = 'e'.rand( 1, 999999999 ); 68 | for ( $i = 0; $i < strlen( $email ); $i += 1 ) 69 | { 70 | $cipher_text.= $key[ strpos( $character_set, $email[ $i ] ) ]; 71 | } 72 | $script = 'var namex="' . $linktext . '";var a="' . $key . '";var b=a.split("").sort().join("");var c="' . $cipher_text . '";var d="";'; 73 | $script .= 'for(var e=0;e"+linktext+"<\/a>"+textafter'; 75 | $script = "eval(\"".str_replace(array("\\",'"'),array("\\\\",'\"'), $script)."\")"; 76 | $script = ''; 77 | return '[javascript protected email address]' . $script; 78 | } 79 | ?> 80 | -------------------------------------------------------------------------------- /src/Twig-sifo-plugins/function.email_obfuscator.php: -------------------------------------------------------------------------------- 1 | "+linktext+"<\/a>"+textafter'; 60 | $script = "eval(\"" . str_replace(array("\\", '"'), array("\\\\", '\"'), $script) . "\")"; 61 | $script = ''; 62 | 63 | return '[javascript protected email address]' . $script; 64 | }, ['is_variadic' => true] 65 | ); 66 | } 67 | -------------------------------------------------------------------------------- /src/Sifo/MysqlModel.php: -------------------------------------------------------------------------------- 1 | keyExists( $key ) ) 45 | { 46 | return $reg->get( $key ); 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Stores in the registry a value with the given key. 54 | * 55 | * @param string $key 56 | * @param mixed $value 57 | */ 58 | protected function storeInRegistry( $key, $value ) 59 | { 60 | Registry::getInstance()->set( $key, $value ); 61 | } 62 | 63 | /** 64 | * Returns the translation of a string 65 | * 66 | * @param string $subject 67 | * @param string $var_1 68 | * @param string $var2 69 | * @param string $var_n 70 | * @return string 71 | */ 72 | public function translate( $subject, $var_1 = '', $var2 = '', $var_n = '' ) 73 | { 74 | $args = func_get_args(); 75 | $variables = array(); 76 | if ( 1 < count( $args ) ) 77 | { 78 | foreach ( $args as $key => $value ) 79 | { 80 | $variables['%'.$key] = $value; 81 | } 82 | 83 | } 84 | 85 | unset( $variables['%0'] ); 86 | return I18N::getInstance( 'messages', Domains::getInstance()->getLanguage() )->getTranslation( $subject, $variables ); 87 | } 88 | 89 | /** 90 | * Returns the Database connection object. 91 | * 92 | * @param string $profile The profile to be used in the database connection. 93 | * @return Mysql|MysqlDebug 94 | */ 95 | protected function connectDb( $profile = 'default' ) 96 | { 97 | if ( Domains::getInstance()->getDebugMode() !== true ) 98 | { 99 | return Mysql::getInstance( $profile ); 100 | } 101 | 102 | return DebugMysql::getInstance( $profile ); 103 | } 104 | 105 | /** 106 | * Magic method to retrieve table names from a configuration file. 107 | * 108 | * @param string $attribute 109 | * 110 | * @return string 111 | */ 112 | public function __get( $attribute ) 113 | { 114 | $tablenames = Config::getInstance()->getConfig( 'tablenames' ); 115 | 116 | $domain = Domains::getInstance()->getDomain(); 117 | 118 | if ( isset( $tablenames['names'][$domain][$attribute] ) ) 119 | { 120 | return $tablenames['names'][$domain][$attribute]; 121 | } 122 | elseif ( isset( $tablenames['names']['default'][$attribute] ) ) 123 | { 124 | return $tablenames['names']['default'][$attribute]; 125 | } 126 | 127 | return $attribute; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/Sifo/Mail.php: -------------------------------------------------------------------------------- 1 | getConfig('mail'); 57 | 58 | $this->mail = new PHPMailer(); 59 | $this->mail->CharSet = $config['CharSet']; 60 | $this->mail->From = $config['From']; 61 | $this->mail->FromName = $config['FromName']; 62 | 63 | foreach ($config as $property => $value) 64 | { 65 | $this->mail->$property = $value; 66 | } 67 | 68 | return $this->mail; 69 | } 70 | 71 | 72 | /** 73 | * Calls the PHPmailer methods. 74 | * 75 | * @param string $method 76 | * @param mixed $args 77 | * 78 | * @return mixed 79 | */ 80 | public function __call($method, $args) 81 | { 82 | return call_user_func_array(array($this->mail, $method), $args); 83 | } 84 | 85 | /** 86 | * Get any phpmailer attribute. 87 | * 88 | * @param string $property 89 | */ 90 | public function __get($property) 91 | { 92 | return $this->mail->$property; 93 | } 94 | 95 | /** 96 | * Set any phpmailer attribute. 97 | * 98 | * @param string $property 99 | * @param mixed $value 100 | */ 101 | public function __set($property, $value) 102 | { 103 | $this->mail->$property = $value; 104 | } 105 | 106 | 107 | /** 108 | * Send an email. 109 | * 110 | * @param string $to 111 | * @param string $subject 112 | * @param string $body 113 | * 114 | * @return boolean 115 | */ 116 | public function send($to, $subject, $body) 117 | { 118 | $this->mail->Subject = $subject; 119 | $this->mail->AltBody = strip_tags($body); 120 | $this->mail->AddAddress($to); 121 | $this->mail->MsgHTML($body); 122 | 123 | if (!$this->mail->Send()) 124 | { 125 | trigger_error($this->mail->ErrorInfo); 126 | 127 | return false; 128 | } 129 | 130 | $this->mail->ClearAddresses(); 131 | 132 | return true; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/Sifo/Benchmark.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Sifo/FlashMessages.php: -------------------------------------------------------------------------------- 1 | keyExists( 'flash_messages' ) ) 60 | { 61 | $flash_messages = $registry->get( 'flash_messages' ); 62 | } 63 | 64 | if ( is_array( $message ) ) // Dump of errors. 65 | { 66 | $flash_messages[$type] = $message; 67 | } 68 | else 69 | { 70 | $flash_messages[$type][] = $message; 71 | } 72 | $registry->set( "flash_messages", $flash_messages ); 73 | } 74 | 75 | /** 76 | * Returns the messages stack. 77 | */ 78 | static public function get( $type = null, $storage_engine = self::STORAGE_REGISTRY ) 79 | { 80 | $messages = array(); 81 | $existing_messages = self::_getMsgs( $storage_engine ); 82 | 83 | if ( null === $type ) 84 | { 85 | return $existing_messages; 86 | } 87 | else 88 | { 89 | if ( isset( $existing_messages[$type] ) ) 90 | { 91 | return $existing_messages[$type]; 92 | } 93 | return false; 94 | } 95 | } 96 | 97 | /** 98 | * Get the messages stack. 99 | * 100 | * @param integer $storage_engine The storage engine to retrieve the msgs. 101 | * @return array 102 | */ 103 | static private function _getMsgs( $storage_engine ) 104 | { 105 | $registry = self::_getStorageEngine( $storage_engine ); 106 | 107 | $msgs = $registry->get( 'flash_messages' ); 108 | if ( $msgs && $storage_engine === self::STORAGE_SESSION ) 109 | { 110 | $registry->delete( 'flash_messages' ); 111 | } 112 | 113 | if ( $msgs ) 114 | { 115 | return $msgs; 116 | } 117 | 118 | return array(); 119 | } 120 | 121 | static private function _getStorageEngine( $engine ) 122 | { 123 | switch ( $engine ) 124 | { 125 | case self::STORAGE_SESSION: 126 | return Session::getInstance(); 127 | case self::STORAGE_REGISTRY: 128 | return Registry::getInstance(); 129 | default: 130 | throw new Exception_503( 'Invalid storage type.' ); 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /src/Sifo/View.php: -------------------------------------------------------------------------------- 1 | template_path = $template; 40 | 41 | $this->chooseTemplatingEngine(); 42 | $this->assignVariables(); 43 | 44 | return $this->templating_engine->fetch($this->template_path); 45 | } 46 | 47 | public function assign($variable_name, $value) 48 | { 49 | $this->variables[$variable_name] = $value; 50 | } 51 | 52 | public function getTemplateVars() 53 | { 54 | return $this->variables; 55 | } 56 | 57 | private function assignVariables() 58 | { 59 | foreach ($this->variables as $variable => $value) 60 | { 61 | $this->templating_engine->assign($variable, $value); 62 | } 63 | } 64 | 65 | private function chooseTemplatingEngine() 66 | { 67 | $file_extension = pathinfo($this->template_path, PATHINFO_EXTENSION); 68 | 69 | if ('twig' != $file_extension) 70 | { 71 | $this->setSmartyTemplatingEngine(); 72 | } 73 | else 74 | { 75 | $this->setTwigTemplatingEngine(); 76 | } 77 | } 78 | 79 | private function setSmartyTemplatingEngine() 80 | { 81 | if ($this->templating_engine instanceof ViewSmarty) 82 | { 83 | return; 84 | } 85 | 86 | $this->templating_engine = new ViewSmarty(); 87 | } 88 | 89 | private function setTwigTemplatingEngine() 90 | { 91 | if ($this->templating_engine instanceof ViewTwig) 92 | { 93 | return; 94 | } 95 | 96 | $this->templating_engine = new ViewTwig(); 97 | } 98 | 99 | public static function customErrorHandler($errno, $errstr, $errfile, $errline) 100 | { 101 | $error_has_been_silented = (0 === error_reporting()); 102 | if ($error_has_been_silented) 103 | { 104 | return false; 105 | } 106 | 107 | $error_friendly = Debug::friendlyErrorType($errno); 108 | $error_string = "[{$error_friendly}] {$errstr} in {$errfile}:{$errline}"; 109 | 110 | if (Domains::getInstance()->getDebugMode()) 111 | { 112 | Debug::subSet('smarty_errors', $errfile, '
' . $error_string . '
', true); 113 | } 114 | 115 | // Smarty only write PHP USER errors to log: 116 | if (($raw_url = Urls::$actual_url)) 117 | { 118 | error_log("URL '{$raw_url}' launched the following Smarty error: {$error_string}"); 119 | 120 | return true; 121 | } 122 | 123 | // Follow the error handling flow: 124 | return false; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/Sifo/View/Smarty.php: -------------------------------------------------------------------------------- 1 | smarty = new \Smarty(); 13 | 14 | $this->smarty->inheritance_merge_compiled_includes = false; 15 | 16 | // Get the instances inheritance. 17 | $instance_inheritance = \Sifo\Domains::getInstance()->getInstanceInheritance(); 18 | 19 | // If there is inheritance. 20 | if (is_array($instance_inheritance)) 21 | { 22 | // First the child instance, last the parent instance. 23 | $instance_inheritance = array_reverse($instance_inheritance); 24 | foreach ($instance_inheritance as $current_instance) 25 | { 26 | $this->smarty->addPluginsDir(ROOT_PATH . '/instances/' . $current_instance . '/templates/_smarty/plugins'); 27 | } 28 | } 29 | else 30 | { 31 | $this->smarty->addPluginsDir(ROOT_PATH . '/instances/' . Bootstrap::$instance . '/templates/_smarty/plugins'); 32 | } 33 | // Last path is the default smarty plugins directory. 34 | $this->smarty->addPluginsDir(ROOT_PATH . '/vendor/sifophp/sifo/src/Smarty-sifo-plugins'); 35 | 36 | $this->smarty->setTemplateDir(ROOT_PATH . '/'); // The templates are taken using the templates.config.php mappings, under the variable $_tpls. 37 | 38 | // Paths definition: 39 | $templates_path = ROOT_PATH . '/instances/' . Bootstrap::$instance . '/templates/'; 40 | $this->smarty->setCompileDir($templates_path . '_smarty/compile/'); 41 | $this->smarty->setConfigDir($templates_path . '_smarty/configs/'); 42 | $this->smarty->setCacheDir($templates_path . '_smarty/cache/'); 43 | 44 | if (($view_setting = Config::getInstance()->getConfig('views')) && (isset($view_setting['smarty']))) 45 | { 46 | $smarty_settings = $view_setting['smarty']; 47 | 48 | if (isset($smarty_settings['custom_plugins_dir'])) 49 | { 50 | // If is set, this path will be the default smarty plugins directory. 51 | $this->smarty->addPluginsDir($smarty_settings['custom_plugins_dir']); 52 | } 53 | // Set this to false to avoid magical parsing of literal blocks without the {literal} tags. 54 | $this->smarty->auto_literal = $smarty_settings['auto_literal']; 55 | $this->smarty->escape_html = $smarty_settings['escape_html']; 56 | } 57 | } 58 | 59 | 60 | public function fetch($template) 61 | { 62 | $this->template_path = $template; 63 | 64 | set_error_handler(array(View::class, "customErrorHandler")); 65 | \Smarty::muteExpectedErrors(); 66 | 67 | try 68 | { 69 | $result = $this->smarty->fetch( 70 | $template, 71 | $cache_id = null, 72 | $compile_id = null, 73 | $parent = null, 74 | $display = false, 75 | $merge_tpl_vars = true, 76 | $no_output_filter = false 77 | ); 78 | } 79 | catch (\Exception $e) 80 | { 81 | trigger_error($e->getMessage(), E_USER_ERROR); 82 | $result = null; 83 | } 84 | 85 | // The current method launch an set_error_handler but inside self::muteExpectedErrors() ther is one more. 86 | // We need launch two restores to turn back to the preview expected behaviour. 87 | restore_error_handler(); 88 | restore_error_handler(); 89 | 90 | return $result; 91 | } 92 | 93 | public function assign($variable_name, $value) 94 | { 95 | $this->smarty->assign($variable_name, $value); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/Sifo/CLBootstrap.php: -------------------------------------------------------------------------------- 1 | timingStart(); 35 | self::dispatch( $controller_name ); 36 | Benchmark::getInstance()->timingStop(); 37 | } 38 | 39 | /** 40 | * Sets the controller and view properties and executes the controller, sending the output buffer. 41 | * 42 | * @param string $controller Dispatches a specific controller. Defaults to null for compatibility with Bootstrap::dispatch 43 | */ 44 | public static function dispatch( $controller = null, $container = null ) 45 | { 46 | // Set Timezone as required by php 5.1+ 47 | date_default_timezone_set('Europe/Madrid'); 48 | 49 | self::$language = 'en_US'; 50 | 51 | // This is the controller to use: 52 | $ctrl = self::invokeController( $controller, $container ); 53 | $ctrl->setContainer(static::$container); 54 | self::$controller = $controller; 55 | $ctrl->build(); 56 | 57 | // Debug: 58 | if ( Domains::getInstance()->getDebugMode() ) 59 | { 60 | $ctrl_debug = self::invokeController( 'DebugCommandLineDebug' ); 61 | $ctrl_debug->build(); 62 | } 63 | } 64 | 65 | public static function is_domain( $var ) 66 | { 67 | return ( false !== strpos( $var, "." ) ); 68 | } 69 | 70 | public static function get_available_domains() 71 | { 72 | $domain_configuration = Config::getInstance()->getConfig( 'domains' ); 73 | $configuration_keys = array_keys( $domain_configuration ); 74 | $available_domains = array_filter( $configuration_keys, "self::is_domain"); 75 | 76 | return $available_domains; 77 | } 78 | 79 | } 80 | 81 | // Disable whatever buffering default config. 82 | @ob_end_flush(); 83 | 84 | // Instance name (folder under instances): 85 | preg_match("/\/([^\/]+)\/([^\/]+)\/[^\/]+$/", $_SERVER['PHP_SELF'], $matchs); 86 | 87 | // Set the real and active instance name. 88 | CLBootstrap::$instance = $matchs[1]; 89 | 90 | if ( extension_loaded( 'newrelic' ) && isset( CLBootstrap::$instance ) ) 91 | { 92 | newrelic_set_appname( ucfirst( CLBootstrap::$instance ) ); 93 | } 94 | 95 | if (false === isset($argv)) { 96 | $argv = $_SERVER['argv'] ?? []; 97 | } 98 | 99 | if ( !isset( $argv[1] ) || ( '-h' == $argv[1] ) || ( '--help' == $argv[1] ) ) 100 | { 101 | // Dump help info: 102 | require_once ROOT_PATH . '/vendor/sifophp/sifo-common-instance/controllers/shared/commandLine.php'; 103 | 104 | echo PHP_EOL . "Execute 'php $argv[0] --help' to read the help information." . PHP_EOL . PHP_EOL; 105 | echo "Your available domains:" . PHP_EOL; 106 | $available_domains = CLBootstrap::get_available_domains(); 107 | echo implode(PHP_EOL, $available_domains); 108 | die; 109 | } 110 | CLBootstrap::$command_line_params = $argv; 111 | 112 | // Setting the domain. 113 | FilterServer::getInstance()->setHost( $argv[1] ); 114 | -------------------------------------------------------------------------------- /src/Sifo/Cache.php: -------------------------------------------------------------------------------- 1 | isActive() ) 88 | { 89 | trigger_error( 'Memcached is down! Falling back to Disk cache if available...' ); 90 | 91 | // Use cache disk instead: 92 | $cache_object = new CacheDisk(); 93 | self::$cache_type = self::CACHE_TYPE_DISK; 94 | } 95 | 96 | $cache_object->use_locking = (bool) $lock_enabled; 97 | self::$instance[$type][$lock_enabled] = $cache_object; 98 | 99 | return self::$instance[$type][$lock_enabled]; 100 | } 101 | 102 | /** 103 | * Reads from configuration files the cache type this project is using by default. 104 | * 105 | * @return string Cache type. 106 | */ 107 | static protected function discoverCacheType() 108 | { 109 | $cache_config = Config::getInstance()->getConfig( 'cache' ); 110 | 111 | if ( true !== $cache_config['active'] || !isset( $cache_config['client'] ) ) 112 | { 113 | return self::CACHE_TYPE_DISK; 114 | } 115 | 116 | if ( 'Memcached' === $cache_config['client'] ) 117 | { 118 | return self::CACHE_TYPE_MEMCACHED; 119 | } 120 | 121 | if ( 'Memcache' === $cache_config['client'] ) 122 | { 123 | return self::CACHE_TYPE_MEMCACHE; 124 | } 125 | 126 | return 'unknown'; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/Sifo/Registry.php: -------------------------------------------------------------------------------- 1 | array( $subkey => $value ) ) 112 | * 113 | * @param string $key Name you want to store the value with. 114 | * @param mixed $value The object to store in the array. 115 | * @return void 116 | */ 117 | public static function subSet( $key, $sub_key, $value ) 118 | { 119 | self::$storage[$key][$sub_key] = $value; 120 | } 121 | 122 | /** 123 | * Adds another element to the end of the array. 124 | * 125 | * @param string $key 126 | * @param mixed $value 127 | * @return int New number of elements in the array. 128 | */ 129 | public static function push( $key, $value ) 130 | { 131 | if ( !self::keyExists( $key ) ) 132 | { 133 | self::$storage[$key] = array(); 134 | } 135 | 136 | if ( !is_array( self::$storage[$key] ) ) 137 | { 138 | throw new Exception_Registry( 'Failed to PUSH an element in the registry because the given key is not an array.' ); 139 | } 140 | 141 | return array_push( self::$storage[$key], $value ); 142 | } 143 | 144 | /** 145 | * @param string $index 146 | * @returns boolean 147 | * 148 | */ 149 | public static function keyExists( $key ) 150 | { 151 | return array_key_exists( $key, self::$storage ); 152 | } 153 | 154 | } 155 | 156 | class Exception_Registry extends \Exception {}; 157 | -------------------------------------------------------------------------------- /src/Sifo/imageController.php: -------------------------------------------------------------------------------- 1 | is_gif || $this->is_jpeg || $this->is_png || $this->is_bmp || $this->is_ico ) || ( $this->is_gif + $this->is_jpeg + $this->is_png + $this->is_bmp + $this->is_ico ) > 1 ) 63 | { 64 | throw new Exception_500( "Please do the favour of use one (and only one) image content_type helper!" ); 65 | } 66 | 67 | if ( $this->is_gif ) 68 | { 69 | $content_type ='Content-type: image/gif'; 70 | } 71 | 72 | if ( $this->is_jpeg ) 73 | { 74 | $content_type ='Content-type: image/jpeg'; 75 | } 76 | 77 | if ( $this->is_png ) 78 | { 79 | $content_type ='Content-type: image/png'; 80 | } 81 | 82 | if ( $this->is_bmp ) 83 | { 84 | $content_type ='Content-type: image/bmp'; 85 | } 86 | 87 | if ( $this->is_ico ) 88 | { 89 | $content_type ='Content-type: image/x-icon'; 90 | } 91 | 92 | Headers::set( 'Content-type', $content_type ); 93 | } 94 | 95 | /** 96 | * Returns tha contents in cache or false. 97 | * 98 | * @return mixed 99 | */ 100 | protected function grabCache() 101 | { 102 | if ( Domains::getInstance()->getDevMode() && ( FilterCookie::getInstance()->getInteger( 'rebuild_all' ) || FilterGet::getInstance()->getInteger( 'rebuild' ) ) ) 103 | { 104 | return false; 105 | } 106 | 107 | $cache_key = $this->parseCache(); 108 | 109 | // Controller does not use cache: 110 | if ( !$cache_key ) 111 | { 112 | return false; 113 | } 114 | 115 | $cache = new CacheDisk(); 116 | $content = $cache->get( $cache_key['name'] ); 117 | 118 | return ( $content ? $content : false ); 119 | } 120 | 121 | /** 122 | * Dispatch the controller. 123 | */ 124 | public function dispatch() 125 | { 126 | $this->customizeHeader(); 127 | 128 | $this->preDispatch(); 129 | $cached_content = $this->grabCache(); 130 | if ( false !== $cached_content ) 131 | { 132 | echo $cached_content; 133 | $this->postDispatch(); 134 | return; 135 | } 136 | $cache_key = $this->parseCache(); 137 | 138 | $content = $this->build(); 139 | 140 | if ( false !== $cache_key ) 141 | { 142 | $cache = new CacheDisk(); 143 | $cache->set( $cache_key['name'], $content, $cache_key['expiration'] ); 144 | } 145 | 146 | $this->postDispatch(); 147 | echo $content; 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /src/Sifo/RedisModel.php: -------------------------------------------------------------------------------- 1 | getConfig( 'redis', 'default' ); 59 | } 60 | catch( Exception_Configuration $e ) 61 | { 62 | // Connection taken from domains.config.php: 63 | $db_params = Domains::getInstance()->getParam( 'redis' ); 64 | } 65 | 66 | } 67 | else // Advanced configuration taken from redis.config.php 68 | { 69 | $db_params = Config::getInstance()->getConfig( 'redis', $profile ); 70 | } 71 | 72 | self::$connected_client[$profile] = PredisProxyClient::getInstance( $db_params ); 73 | $this->profile = $profile; 74 | } 75 | 76 | return self::$connected_client[$profile]; 77 | } 78 | 79 | /** 80 | * Disconnect from server and reset the static object for reconnection. 81 | */ 82 | public function disconnect() 83 | { 84 | self::$connected_client[$this->profile]->disconnect(); 85 | self::$connected_client[$this->profile] = null; 86 | } 87 | 88 | /** 89 | * Disconnect clients on object destruction. 90 | */ 91 | public function __destruct() 92 | { 93 | foreach ( self::$connected_client as $client ) 94 | { 95 | $client->disconnect(); 96 | } 97 | } 98 | } 99 | 100 | class PredisProxyClient 101 | { 102 | static protected $instance; 103 | 104 | protected $client; 105 | protected $connection_params; 106 | 107 | public static function getInstance( Array $connection_params ) 108 | { 109 | asort( $connection_params ); 110 | 111 | $key = md5( serialize( $connection_params ) ); 112 | if ( isset( self::$instance[$key] ) ) 113 | { 114 | return self::$instance[$key]; 115 | } 116 | 117 | if ( true !== Domains::getInstance()->getDebugMode() ) 118 | { 119 | self::$instance[$key] = new self( $connection_params ); 120 | } 121 | else 122 | { 123 | self::$instance[$key] = new DebugPredisProxyClient( $connection_params ); 124 | } 125 | 126 | return self::$instance[$key]; 127 | } 128 | 129 | protected function __construct( Array $connection_params ) 130 | { 131 | $this->connection_params = $connection_params; 132 | $this->client = new \Predis\Client( $connection_params ); 133 | } 134 | 135 | public function __call( $method, $args ) 136 | { 137 | if ( is_object( $this->client ) ) 138 | { 139 | return call_user_func_array( array( $this->client, $method ), $args ); 140 | } 141 | 142 | return null; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/Sifo/MediaPacker.php: -------------------------------------------------------------------------------- 1 | working_instance = Config::getInstance()->getInstanceName(); 67 | $this->instance_static_host = Domains::getInstance()->getStaticHost(); 68 | 69 | // Contents will be accessible by static server under this path: 70 | $this->generated_files_public_path = $this->media_type . '/generated'; 71 | 72 | // Packed contents will be stored under this filesystem path. You can overwrite this property: 73 | $this->generated_files_folder = ROOT_PATH . '/instances/' . $this->working_instance . '/public/static/' . $this->generated_files_public_path; 74 | 75 | 76 | } 77 | 78 | /** 79 | * Takes all the available combinations of media files and creates all the packs. 80 | */ 81 | public function packMedia() 82 | { 83 | $media = Config::getInstance()->getConfig( $this->media_type ); 84 | 85 | foreach ( $media as $group => $media_name ) 86 | { 87 | ksort( $media[$group] ); // Reorder elements by priority key, no matter how the array was created. 88 | $file = $this->generated_files_folder . '/' . $group . '.' . $this->media_type; 89 | 90 | // Add the basepath definition at the beginning of the 'default' JS file: 91 | $prepend_string = ( 'default' == $group && 'js' == $this->media_type ? $this->getBasePathConfig( $media ) : '' ); 92 | 93 | $content = $this->getPackedContent( $media[$group], $prepend_string ); 94 | 95 | // Create subdirs if needed: 96 | $file_info = pathinfo( $file ); 97 | if ( !is_dir( $file_info['dirname'] ) ) 98 | { 99 | // Create directory recursively if does not exist yet. 100 | mkdir( $file_info['dirname'], 0755, true ); 101 | } 102 | 103 | // Write packed file to disk: 104 | file_put_contents( $file, $content ); 105 | } 106 | } 107 | 108 | /** 109 | * Sets the directory where you want to write the generated files to. 110 | * 111 | * @param $path Real path to the directory storing 112 | * 113 | * @throws \RuntimeException 114 | */ 115 | public function setGeneratedFolder( $path ) 116 | { 117 | if ( is_dir( $path ) ) 118 | { 119 | $this->generated_files_folder = $path; 120 | } 121 | else 122 | { 123 | throw new \RuntimeException( 'Path given to store generated content is not a valid dir.' ); 124 | } 125 | 126 | } 127 | 128 | } -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/block.t.php: -------------------------------------------------------------------------------- 1 | escape_html ) ) 60 | { 61 | // In the don't protected configuration, the expectd behaviour is escapeing html: 62 | $escape = ( isset($params['escape'] ) )? $params['escape'] : "html"; 63 | unset($params['escape']); 64 | 65 | if( isset( $params['escapevar'] ) ) 66 | { 67 | // Option not available when escape_html is false. You could use $var|escape 68 | unset( $params['escapevar'] ); 69 | } 70 | } 71 | else 72 | { 73 | $escape = false; 74 | if ( isset($params['escape'] ) ) 75 | { 76 | // (escape) Escape param is not available when escape_html is set to true. 77 | unset($params['escape']); 78 | } 79 | 80 | // set escape_var mode 81 | if ( ( !isset( $params['escapevar'] ) ) || ( $params['escapevar']!='no') ) 82 | { 83 | foreach( $params as &$param ) 84 | { 85 | $param = htmlspecialchars($param, ENT_QUOTES, SMARTY_RESOURCE_CHAR_SET ); 86 | } 87 | } 88 | elseif( isset( $params['escapevar'] ) ) 89 | { 90 | unset( $params['escapevar'] ); 91 | } 92 | } 93 | 94 | // set plural version 95 | if (isset($params['plural'])) { 96 | $plural = $params['plural']; 97 | unset($params['plural']); 98 | 99 | // set count 100 | if (isset($params['count']) && ( 1 != $params['count'] ) ) { 101 | $text = $plural; 102 | unset($params['count']); 103 | } 104 | } 105 | 106 | $text = \Sifo\I18N::getTranslation( $text ); 107 | 108 | // run strarg if there are parameters 109 | if (count($params)) { 110 | $text = smarty_gettext_strarg($text, $params); 111 | } 112 | 113 | switch ($escape) { 114 | case 'html': 115 | $text = nl2br(htmlspecialchars($text)); 116 | break; 117 | case 'javascript': 118 | case 'js': 119 | // javascript escape 120 | $text = str_replace('\'', '\\\'', stripslashes($text)); 121 | break; 122 | case 'url': 123 | // url escape 124 | $text = urlencode($text); 125 | break; 126 | } 127 | 128 | return $text; 129 | } 130 | 131 | ?> 132 | -------------------------------------------------------------------------------- /src/Sifo/Dir.php: -------------------------------------------------------------------------------- 1 | Filename or Dirname 44 | * "relative" => Path relative to the starting point 45 | * "absolute" => Absolute path 46 | * "folder" => Parent folder 47 | * 48 | * @param string $base_path Path to starting directory. 49 | * @param string $relative_path Relative path added to base_path. If you have /path/to/dir and specify "dir" as relative_path then will list files in /path/to as dir/file1, dir/file2 ... 50 | */ 51 | public function getFileListRecursive( $base_path, $relative_path = "" ) 52 | { 53 | // If base path ends in / remove it. 54 | if ( substr( $base_path, -1, 1 ) == "/" ) 55 | { 56 | $base_path = substr( $base_path, 0, -1 ); 57 | } 58 | // If relative path starts in / remove it. 59 | if ( substr( $relative_path, 0, 1 ) == "/" ) 60 | { 61 | $relative_path = substr( $relative_path, 1 ); 62 | } 63 | 64 | $path = $base_path . "/" . $relative_path; 65 | 66 | if ( !is_dir( $path ) ) 67 | { 68 | return false; 69 | } 70 | 71 | $list = array(); 72 | 73 | $directory = opendir( "$path" ); 74 | 75 | while ( $file = readdir( $directory ) ) 76 | { 77 | if ( !in_array( $file, $this->ignored_files ) ) 78 | { 79 | $f = $path . "/" . $file; 80 | $f = preg_replace( '/(\/){2,}/', '/', $f ); // Replace double slashes. 81 | if ( is_file( $f ) ) 82 | { 83 | $list[] = array( "filename" => $file, "relative" => $relative_path . "/$file", "absolute" => $f, "folder"=> $relative_path ); 84 | } 85 | 86 | if ( is_dir( $f ) ) // Ignore _smarty dir 87 | { 88 | $list = array_merge( $list, $this->getFileListRecursive( $base_path, $relative_path . "/$file" ) ); // Recursive call. 89 | } 90 | } 91 | } 92 | closedir( $directory ); 93 | sort( $list ); 94 | return $list ; 95 | } 96 | 97 | /** 98 | * Get subdirs 99 | * 100 | * @param string $path 101 | * @param string $relative_path 102 | * @return array 103 | */ 104 | public function getDirs( $path ) 105 | { 106 | if ( !is_dir( $path ) ) 107 | { 108 | return false; 109 | } 110 | 111 | $list = array(); 112 | 113 | $directory = opendir( "$path" ); 114 | 115 | while ( $file = readdir( $directory ) ) 116 | { 117 | if ( !in_array( $file, $this->ignored_files ) ) 118 | { 119 | $f = $path . "/" . $file; 120 | $f = preg_replace( '/(\/){2,}/', '/', $f ); // Replace double slashes. 121 | 122 | if ( is_dir( $f ) ) 123 | { 124 | $list[] = $file; 125 | } 126 | } 127 | } 128 | closedir( $directory ); 129 | sort( $list ); 130 | 131 | return $list; 132 | } 133 | 134 | public function setIgnore( Array $ignored_files ) 135 | { 136 | $this->ignored_files = $ignored_files; 137 | } 138 | 139 | } 140 | ?> -------------------------------------------------------------------------------- /src/Smarty-sifo-plugins/function.fill.php: -------------------------------------------------------------------------------- 1 | 13 | * Name: fill
14 | * Input:
15 | * - [any] (required) - string 16 | * - subject (required) - string 17 | * - delimiter (optional, defaults to '%' ) - string 18 | * - lower (optional, set to lower=no if you don't want lowercase) - string 19 | * - normalize (optional, set to normalize=no to override \Sifo\Urls::$normalize_values setting and disable it) - string 20 | * - escapevar (Set to no for avoid html escaping when the smarty escape_html attribute is true). 21 | * Purpose: Fills the variables found in 'subject' with the paramaters passed. The variables are any word surrounded by two delimiters. 22 | * 23 | * Examples of usage: 24 | * 25 | * {fill subject="http://domain.com/profile/%username%" username='fred'} 26 | * Output: http://domain.com/profile/fred 27 | * 28 | * {fill subject="Hello %user%, welcome aboard!" user=Fred} 29 | * Outputs: Hello Fred, welcome aboard 30 | * 31 | * {fill subject="http://||subdomain||.domain.com/||page||/||action||" subdomain='www' page='my-first-post' action='vote' delimiter='||'} 32 | * Outputs: http://www.domain.com/my-first-post/vote 33 | * 34 | * @link http://www.harecoded.com/fill-smarty-php-plugin-311577 35 | * @author Albert Lombarte 36 | * @param array 37 | * @param Smarty 38 | * @return string 39 | */ 40 | function smarty_function_fill($params, &$smarty) 41 | { 42 | 43 | if ( isset($params['delimiter']) ) 44 | { 45 | $_delimiter = $params['delimiter']; 46 | unset($params['delimiter']); 47 | } else { 48 | $_delimiter = '%'; 49 | } 50 | 51 | $_normalize = true; 52 | 53 | if ( isset($params['normalize']) ) 54 | { 55 | switch( $params['normalize'] ) 56 | { 57 | case 'no': 58 | case '0': 59 | case 'false': 60 | $_normalize = false; 61 | break; 62 | default: 63 | $_normalize = true; 64 | } 65 | } 66 | else 67 | { 68 | $params['normalize'] = true; 69 | } 70 | 71 | 72 | if ( false !== strpos($_delimiter, '$' ) ) 73 | { 74 | trigger_error("fill: The delimiter '$' is banned in function {url}", E_USER_NOTICE); 75 | } 76 | 77 | if (!isset($params['subject']) || count($params)<2) { 78 | trigger_error("fill: The attribute 'subject' and at least one parameter is needed in function {url}", E_USER_NOTICE); 79 | } 80 | 81 | $escapevar = $smarty->escape_html; 82 | if ( isset( $params['escapevar'] ) ) 83 | { 84 | $escapevar = ( $smarty->escape_html && ( $params['escapevar'] != 'no') ); 85 | unset( $params['escapevar'] ); 86 | } 87 | 88 | $_html_result = $params['subject']; 89 | $_tmp_result = $_html_result; 90 | unset( $params['subject'] ); 91 | 92 | foreach( $params as $_key => $_val ) 93 | { 94 | if( $escapevar ) 95 | { 96 | $_val = htmlspecialchars($_val, ENT_QUOTES, SMARTY_RESOURCE_CHAR_SET ); 97 | } 98 | $_val = (string)$_val; 99 | $_tmp_result = str_replace( $_delimiter . $_key . $_delimiter, (string)$_val, $_tmp_result); 100 | 101 | // The UrlParse::normalize, amongs other things lowers the string. Check if plugin calls with lower=no to skip: 102 | if ( $_normalize && true === \Sifo\Urls::$normalize_values && ( !isset($params['lower'] ) || $params['lower'] != 'no' ) ) 103 | { 104 | $_html_result = str_replace( $_delimiter . $_key . $_delimiter, \Sifo\Urls::normalize( (string)$_val ), $_html_result); 105 | } 106 | else 107 | { 108 | $_html_result = $_tmp_result; 109 | } 110 | } 111 | 112 | if ( false !== strpos(urldecode($_html_result), $_delimiter) ) 113 | { 114 | trigger_error("fill: There are still parameters to replace, because the '$_delimiter' delimiter was found in $_html_result"); 115 | } 116 | 117 | return $_html_result; 118 | 119 | } 120 | 121 | /* vim: set expandtab: */ 122 | 123 | ?> 124 | -------------------------------------------------------------------------------- /src/Sifo/Debug/Sphinxql.php: -------------------------------------------------------------------------------- 1 | timingStart( 'sphinxql' ); 46 | $sphinx_results = parent::multiQuery( $tag ); 47 | $sphinx_time = Benchmark::getInstance()->timingCurrentToRegistry( 'sphinxql' ); 48 | 49 | foreach( $this->queries as $key => $query ) 50 | { 51 | $query_info['query'] = $query['query']; 52 | $query_info['tag'] = $query['tag']; 53 | $query_info['resultset'] = ( !empty( $sphinx_results[$key] ) ) ? $sphinx_results[$key] : array(); 54 | $query_info['returned_rows'] = ( !empty( $sphinx_results[$key] ) ) ? count( $query_info['resultset'] ) : 0; 55 | $this->query_debug['queries'][] = $query_info; 56 | } 57 | 58 | $this->query_debug['backtrace'] = $this->getCallerClass(); 59 | $this->query_debug['time'] = $sphinx_time; 60 | $this->query_debug['error'] = ( $this->sphinxql->errno ) ? $this->sphinxql->error : ''; 61 | $this->query_debug['tag'] = $tag; 62 | $this->query_debug['connection_data'] = $this->sphinx_config; 63 | 64 | Debug::push( 'sphinxql', $this->query_debug ); 65 | 66 | if ( $this->sphinxql->errno ) 67 | { 68 | Debug::push( 'sphinxql_errors', $this->sphinxql->error ); 69 | } 70 | 71 | unset( $this->query_debug ); 72 | unset( $this->queries ); 73 | 74 | return $sphinx_results; 75 | } 76 | 77 | /** 78 | * Redefines addQuery method adding debug information. 79 | * @param $query 80 | * @param null $tag 81 | * @param array $parameters 82 | * 83 | * @return string The query after being prepared. 84 | */ 85 | public function addQuery( $query, $tag = null, $parameters = array() ) 86 | { 87 | $prepared_query = parent::addQuery( $query, $tag, $parameters ); 88 | $this->queries[] = array( 'query' => $prepared_query . ';', 'tag' => $tag ); 89 | 90 | return $prepared_query; 91 | } 92 | 93 | /** 94 | * Build the caller classes stack. 95 | * @return string 96 | */ 97 | public function getCallerClass() 98 | { 99 | $array_debug = debug_backtrace(); 100 | 101 | $trace = array(); 102 | $step = 0; 103 | foreach ( array_reverse( $array_debug ) as $debug_step ) 104 | { 105 | if ( !isset( $debug_step['class'] ) ) 106 | { 107 | $debug_step['class'] = ''; 108 | } 109 | if ( !isset( $debug_step['function'] ) ) 110 | { 111 | $debug_step['function'] = ''; 112 | } 113 | if ( !isset( $debug_step['file'] ) ) 114 | { 115 | $debug_step['file'] = ''; 116 | } 117 | if ( !isset( $debug_step['line'] ) ) 118 | { 119 | $debug_step['line'] = ''; 120 | } 121 | 122 | ++$step; 123 | $trace[] = "$step > ".$debug_step['class'].'::'.$debug_step['function'] 124 | .' - '.basename ( $debug_step['file'] ) 125 | .':'.$debug_step['line']." [".dirname( $debug_step['file'] )."]"; 126 | 127 | if ( in_array( $debug_step['function'], array( 'query', 'multiQuery' ) ) ) 128 | { 129 | break; 130 | } 131 | } 132 | 133 | return $trace; 134 | } 135 | 136 | /** 137 | * Redefines logError class. Errors will be shown on debug. 138 | * @param $error 139 | */ 140 | protected function logError( $error ) 141 | {} 142 | } -------------------------------------------------------------------------------- /src/Sifo/Cookie.php: -------------------------------------------------------------------------------- 1 | request[$key] = $value; 33 | } 34 | 35 | static public function deleteCookie( $key ) 36 | { 37 | unset( self::getInstance()->request[$key] ); 38 | } 39 | } 40 | 41 | class Cookie 42 | { 43 | 44 | static protected $cookies; 45 | static private $domain; 46 | static private $path; 47 | 48 | static private function _initDomain() 49 | { 50 | self::$cookies = array( ); 51 | // Take domain from configuration to allow multiple subdomain compatibility with cookies. 52 | self::$domain = Domains::getInstance()->getDomain(); 53 | self::$path = '/'; 54 | } 55 | 56 | static public function set( $name, $value, $days = 14, $domain = false, $secure = false, $httpOnly = false, string $samesite = null ) 57 | { 58 | $domain ?: self::_initDomain(); 59 | 60 | $expires = 0 == $days ? 0 : time() + ( 86400 * $days ); 61 | 62 | $result = static::setCookie( $name, $value, $expires, self::$path, self::$domain, $secure, $httpOnly, $samesite ); 63 | 64 | if ( !$result ) 65 | { 66 | trigger_error( "COOKIE WRITE FAIL: Tried to write '$name' with value '$value' but failed." ); 67 | return false; 68 | } 69 | 70 | // Filter runtime update: 71 | FilterCookieRuntime::setCookie( $name, $value ); 72 | 73 | return true; 74 | } 75 | 76 | static public function delete( $name ) 77 | { 78 | self::_initDomain(); 79 | $result = static::setCookie( $name, '', time() - 3600, self::$path, self::$domain); 80 | if ( !$result ) 81 | { 82 | trigger_error( "COOKIE DELETE FAIL: Tried to delete '$name' but failed." ); 83 | return false; 84 | } 85 | 86 | // Filter runtime update: 87 | FilterCookieRuntime::deleteCookie( $name ); 88 | 89 | return true; 90 | } 91 | 92 | /** 93 | * Read one (string) or several (array) cookies and returns it with a simple sanitization of the content. 94 | * 95 | * @deprecated The Cookie::get from FilterCookie::getString. 96 | * @param string|array $cookie 97 | * @return string|false 98 | */ 99 | static public function get( $cookies ) 100 | { 101 | trigger_error( "'Cookie::get' is deprecated, please use 'FilterCookie'. Ex: FilterCookie::getInstance()->getString( 'cookie_key' );" ); 102 | 103 | if ( is_array( $cookies ) ) 104 | { 105 | foreach ( $cookies as $cookie ) 106 | { 107 | $values[$cookie] = self::_sanitizeCookie( $cookie ); 108 | } 109 | 110 | if ( !isset( $values ) ) 111 | { 112 | return false; 113 | } 114 | 115 | return $values; 116 | } 117 | else 118 | { 119 | return self::_sanitizeCookie( $cookies ); 120 | } 121 | } 122 | 123 | /** 124 | * Returns a sanitized Cookie. 125 | * 126 | * @param array $cookies 127 | * @return string|false 128 | */ 129 | static private function _sanitizeCookie( $cookie ) 130 | { 131 | if ( FilterCookie::getInstance()->isSent( $cookie ) ) 132 | { 133 | return FilterCookie::getInstance()->getString( $cookie ); 134 | } 135 | 136 | return false; 137 | } 138 | 139 | static protected function setCookie(string $name, $value = "", $expires = 0, $path = "", $domain = "", $secure = false, $httponly = false, string $samesite = null): bool 140 | { 141 | $options = [ 142 | 'expires' => $expires, 143 | 'path' => $path, 144 | 'domain' => $domain, 145 | 'secure' => $secure, 146 | 'httponly' => $httponly, 147 | ]; 148 | 149 | if ( $samesite !== null) { 150 | $options['samesite'] = $samesite; 151 | } 152 | 153 | return setcookie( $name, $value, $options ); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/Sifo/Session.php: -------------------------------------------------------------------------------- 1 | getDomain() ); 35 | } 36 | 37 | if ( !isset( $_SESSION ) ) 38 | { 39 | if ( headers_sent ( ) ) 40 | { 41 | trigger_error( "Session: The session was not started before the sending of the headers." ); 42 | return; 43 | } 44 | 45 | if ($session_name instanceof SessionNameStrategy) { 46 | $session_name->set(); 47 | } 48 | 49 | // Session init. 50 | session_start(); 51 | } 52 | } 53 | 54 | /** 55 | * Singleton 56 | * 57 | * @static 58 | * @return Session 59 | */ 60 | public static function getInstance() 61 | { 62 | if ( !isset( self::$instance ) ) 63 | { 64 | $session_name_environment = FilterEnv::getInstance()->getString('SESSION_NAME'); 65 | 66 | switch ($session_name_environment) { 67 | case 'environment_and_vertical': 68 | $session_name_strategy = new SessionEnvironmentStrategy(); 69 | break; 70 | default: 71 | $session_name_strategy = null; 72 | } 73 | 74 | self::$instance = new self($session_name_strategy); 75 | } 76 | return self::$instance; 77 | } 78 | 79 | /** 80 | * Use it to set a single var like $ses->set( 'name', 'val' ); or an array of pairs key-value like $ses->set( array( 'key' => 'val' ) ); 81 | * 82 | * @param string|array $name 83 | * @param string|null $value 84 | * @return boolean 85 | */ 86 | public function set( $name, $value = null ) 87 | { 88 | if ( is_array( $name ) && null === $value ) 89 | { 90 | foreach ( $name as $key => $val ) 91 | { 92 | $_SESSION[$key] = $val; 93 | } 94 | } 95 | elseif ( !isset( $name ) || !isset( $value ) ) 96 | { 97 | trigger_error( 'Session: Missing parameter or parameters.', E_USER_WARNING); 98 | return false; 99 | } 100 | else 101 | { 102 | $_SESSION[$name] = $value; 103 | } 104 | 105 | return true; 106 | } 107 | 108 | public function get( $name ) 109 | { 110 | if ( !isset( $_SESSION[$name] ) ) 111 | { 112 | return null; 113 | } 114 | 115 | return $_SESSION[$name]; 116 | } 117 | 118 | public function getId() 119 | { 120 | if ( !isset( $_SESSION ) ) 121 | { 122 | return null; 123 | } 124 | 125 | return session_id(); 126 | } 127 | 128 | public function delete( $name ) 129 | { 130 | if ( !isset( $_SESSION[$name] ) ) 131 | { 132 | trigger_error( "Session: $name variable does not exist.", E_USER_WARNING ); 133 | return false; 134 | } 135 | else 136 | { 137 | unset( $_SESSION[$name] ); 138 | return true; 139 | } 140 | } 141 | 142 | /** 143 | * @param string $index 144 | * @returns boolean 145 | * 146 | */ 147 | public static function keyExists( $key ) 148 | { 149 | return isset( $_SESSION[$key] ); 150 | } 151 | 152 | /** 153 | * Remove all the session saved data. And the Session continue started. 154 | * 155 | * @return bool 156 | */ 157 | public function reset() 158 | { 159 | $this->destroy(); 160 | session_start(); 161 | 162 | return true; 163 | } 164 | 165 | public function destroy() 166 | { 167 | if ( isset( $_SESSION ) ) 168 | { 169 | unset( $_SESSION ); 170 | $_SESSION = array( ); 171 | session_destroy(); 172 | } 173 | 174 | return true; 175 | } 176 | 177 | /** 178 | * Ends the current session and store session data. 179 | */ 180 | public function writeClose() 181 | { 182 | session_write_close(); 183 | } 184 | 185 | public static function setExpirationTime( $time ) 186 | { 187 | ini_set( 'session.cache_expire', $time ); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/Sifo/Images.php: -------------------------------------------------------------------------------- 1 | $resizeUp, 56 | 'preserveAlpha' => $transparency, 57 | 'preserveTransparency' => $transparency, 58 | 'jpegQuality' => $quality, 59 | ] 60 | ); 61 | 62 | if (self::isCropRequired($crop)) { 63 | $thumb->adaptiveResize($width, $height, $crop['x'], $crop['y']); 64 | } else { 65 | $thumb->resize($width, $height); 66 | } 67 | 68 | $thumb->save($to, $fileinfo['extension']); 69 | 70 | return true; 71 | } 72 | 73 | /** 74 | * Crop an image using specific points where the crop have to begin. 75 | * 76 | * @param string $from Origin file name 77 | * @param string $to Final file name 78 | * @param $startX X point where the crop have to begin. 79 | * @param $startY Y point where the crop have to begin. 80 | * @param $width Final width. 81 | * @param $height Final height 82 | * @param bool $resizeUp 83 | * @param bool $transparency 84 | * @param int $quality 85 | * @return bool 86 | */ 87 | static public function cropAndSave( 88 | string $from, 89 | string $to, 90 | int $startX, 91 | int $startY, 92 | int $width, 93 | int $height, 94 | bool $resizeUp = false, 95 | bool $transparency = false, 96 | int $quality = 100 97 | ) { 98 | $fileInfo = pathinfo($to); 99 | 100 | $thumb = \PhpThumbFactory::create( 101 | $from, 102 | [ 103 | 'resizeUp' => $resizeUp, 104 | 'preserveAlpha' => $transparency, 105 | 'preserveTransparency' => $transparency, 106 | 'jpegQuality' => $quality, 107 | ] 108 | ); 109 | 110 | $thumb->crop($startX, $startY, $width, $height); 111 | 112 | $thumb->save($to, $fileInfo['extension']); 113 | 114 | return true; 115 | } 116 | 117 | /** 118 | * Upload and resize an image. 119 | * 120 | * @param file $from 121 | * @param file $to 122 | * @param integer $width 123 | * @param integer $height 124 | * @param boolean $crop 125 | * @return boolean 126 | */ 127 | static public function uploadResizeAndSave( 128 | array $post_file, 129 | string $destination, 130 | int $width, 131 | int $height, 132 | array $crop = [], 133 | bool $resizeUp = false, 134 | bool $transparency = false 135 | ) { 136 | $old_name = $post_file['tmp_name']; 137 | $upload_info = pathinfo( $old_name ); 138 | $new_name = $upload_info['dirname'].'/'.$post_file['name']; 139 | static::moveFile($old_name, $new_name); 140 | 141 | self::resizeAndSave($new_name, $destination, $width, $height, (array)$crop, $resizeUp, $transparency); 142 | 143 | return true; 144 | } 145 | 146 | private static function isCropRequired(array $crop): bool 147 | { 148 | return array_key_exists('x', $crop) 149 | && is_int($crop['x']) 150 | && array_key_exists('y', $crop) 151 | && is_int($crop['y']); 152 | } 153 | 154 | protected static function moveFile(string $from, string $to): void 155 | { 156 | move_uploaded_file($from, $to); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/Sifo/API/Youtube.php: -------------------------------------------------------------------------------- 1 | getVideoData( $video_url ); 35 | * 36 | * The format of the returned data is an array with these keys: 37 | * [video_id] => ybNJb6EuU1Y 38 | * [url_player] => http://www.youtube.com/watch?v=ybNJb6EuU1Y&feature=youtube_gdata 39 | * [title] => Video title 40 | * [description] => Video description 41 | * [keywords] => Array 42 | * ( 43 | * [0] => keyword1 44 | * [1] => keyword2 45 | * ... 46 | * [N] => keywordN 47 | * ) 48 | * [url_embed] => http://www.youtube.com/v/ybNJb6EuU1Y?f=videos&app=youtube_gdata 49 | * [duration] => Duration (in seconds) 50 | * [thumbnails] => Array 51 | * ( 52 | * [0] => http://i.ytimg.com/vi/ybNJb6EuU1Y/2.jpg 53 | * [1] => http://i.ytimg.com/vi/ybNJb6EuU1Y/1.jpg 54 | * [2] => http://i.ytimg.com/vi/ybNJb6EuU1Y/3.jpg 55 | * ) 56 | */ 57 | class APIYoutube 58 | { 59 | /** 60 | * Youtube API url to retreive data. 61 | * 62 | * @var string 63 | */ 64 | protected $api_url = 'http://gdata.youtube.com/feeds/api/videos/'; 65 | 66 | /** 67 | * Media namespace to format the XML. 68 | * 69 | * @var string 70 | */ 71 | protected $media_namespace = 'http://search.yahoo.com/mrss/'; 72 | 73 | /** 74 | * Get video data from Youtube API. 75 | * 76 | * @param string $video_url Video URL or video ID. 77 | * @return array 78 | */ 79 | public function getVideoData( $video_url ) 80 | { 81 | $video_id = $this->_getVideoId( $video_url ); 82 | 83 | $multi_curl = EpiCurl::getInstance(); 84 | $curl = curl_init( $this->api_url . $video_id ); 85 | curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 ); 86 | $response = $multi_curl->addCurl( $curl ); 87 | 88 | if ( 200 !== $response->code ) 89 | { 90 | return false; 91 | } 92 | 93 | try 94 | { 95 | $xml_data = @new SimpleXMLElement( $response->data ); 96 | } 97 | catch( \Exception $e ) 98 | { 99 | if ( 'Invalid id' === $response->data ) 100 | { 101 | return false; 102 | } 103 | } 104 | 105 | $video_data['video_id'] = $video_id; 106 | $video_data['url_player'] = ( string ) $xml_data->link[0]->attributes()->href[0]; 107 | 108 | $media_group = $xml_data->children( $this->media_namespace ); 109 | $video_data['title'] = ( string ) $media_group->group->title; 110 | $video_data['description'] = ( string ) $media_group->group->description; 111 | $video_data['keywords'] = explode( ',', ( string ) $media_group->group->keywords ); 112 | 113 | if ( !isset( $media_group->group->content[0] ) ) 114 | { 115 | return false; 116 | } 117 | 118 | $content_attrs = $media_group->group->content[0]->attributes(); 119 | $video_data['url_embed'] = ( string ) $content_attrs['url']; 120 | $video_data['duration'] = ( int ) $content_attrs['duration']; 121 | 122 | foreach ( $media_group->group->thumbnail as $key => $val ) 123 | { 124 | $thumb_attrs = $val->attributes(); 125 | $thumb_width = ( int ) $thumb_attrs['width']; 126 | if ( $thumb_width == 120 ) 127 | { 128 | $video_data['thumbnails'][] = ( string ) $thumb_attrs['url']; 129 | } 130 | } 131 | 132 | return $video_data; 133 | } 134 | 135 | /** 136 | * Get video ID from URL. 137 | * 138 | * @param string $video_url Video URL or video ID. 139 | * @return string 140 | */ 141 | private function _getVideoId( $video_url ) 142 | { 143 | $video_id = ''; 144 | $url_parts = parse_url( $video_url ); 145 | if ( !isset( $url_parts['query'] ) ) 146 | { 147 | $video_id = $video_url; 148 | } 149 | else 150 | { 151 | parse_str( $url_parts['query'], $query_parts ); 152 | if ( isset( $query_parts['v'] ) ) 153 | { 154 | $video_id = $query_parts['v']; 155 | } 156 | } 157 | 158 | return $video_id; 159 | } 160 | } 161 | 162 | ?> 163 | -------------------------------------------------------------------------------- /src/Sifo/LoadBalancer.php: -------------------------------------------------------------------------------- 1 | load_balancer_cache_key = $this->load_balancer_cache_key 66 | . '_' . Bootstrap::$instance 67 | . '_' . (Domains::getInstance()->getDevMode() ? 'dev' : 'prod'); 68 | } 69 | 70 | /** 71 | * Sets the nodes to work with. 72 | * @param array $nodes 73 | * @throws Exception_500 74 | * @return integer Number of nodes added. 75 | */ 76 | public function setNodes( array $nodes ) 77 | { 78 | $cache = Cache::getInstance(); 79 | $available_servers = trim( $cache->get( $this->load_balancer_cache_key ) ); // CacheDisk returns " " when no cache. 80 | 81 | if ( empty( $available_servers ) ) 82 | { 83 | foreach( $nodes as $key => $node_properties ) 84 | { 85 | $this->addNodeIfAvailable( $key, $node_properties ); 86 | } 87 | 88 | // Save in cache available servers (even if none): 89 | $serialized_nodes = serialize( array( 'nodes' => $this->nodes, 'total_weights' => $this->total_weights ) ); 90 | $cache->set( $this->load_balancer_cache_key, $serialized_nodes, self::CACHE_EXPIRATION ); 91 | } 92 | else 93 | { 94 | $available_servers = unserialize( $available_servers ); 95 | $this->nodes = $available_servers['nodes']; 96 | $this->total_weights = $available_servers['total_weights']; 97 | } 98 | 99 | $num_nodes = count( $this->nodes ); 100 | 101 | if ( 1 > $num_nodes ) 102 | { 103 | // This exception will be shown for CACHE_EXPIRATION seconds until servers are up again. 104 | throw new Exception_500( '[LOAD BALANCER] No available servers in profile' ); 105 | } 106 | 107 | return $num_nodes; 108 | 109 | 110 | } 111 | 112 | /** 113 | * Adds a server to the battery of available. 114 | * @param integer $index Number of server. 115 | * @param integer $weight Weight of this server. 116 | * 117 | * @return integer Position in battery 118 | */ 119 | protected function addServer( $index, $weight ) 120 | { 121 | $x = (!is_array($this->nodes)) ? 0 : count( $this->nodes ); 122 | $this->nodes[$x] = new \stdClass; 123 | $this->nodes[$x]->index = $index; 124 | $this->total_weights += ( $this->nodes[$x]->weight = abs( $weight ) ); 125 | 126 | return $x; 127 | } 128 | 129 | /** 130 | * Retrieves a random node, the more weight, the more chances to be the picked. 131 | */ 132 | public function get() 133 | { 134 | if ( !isset( $this->nodes ) ) 135 | { 136 | throw new LoadBalancer_Exception( "There aren't any nodes set in the balancer. Have you called setNodes( Array nodes ) ?" ); 137 | } 138 | 139 | $x = round( mt_rand( 0, $this->total_weights ) ); 140 | 141 | $max = ( $i = 0 ); 142 | do 143 | { 144 | $max += $this->nodes[ $i++ ]->weight; 145 | } 146 | while ( $x > $max ); 147 | 148 | return $this->nodes[ ( $i-1 ) ]->index; 149 | } 150 | 151 | /** 152 | * Removes a server from the list of availables. 153 | * 154 | * @param integer $index 155 | */ 156 | public function removeServer( $index ) 157 | { 158 | if ( isset( $this->nodes[$index] ) ) 159 | { 160 | $this->total_weights -= $this->nodes[$index]->weight; 161 | unset( $this->nodes[$index]); 162 | $this->nodes = array_values( $this->nodes ); 163 | } 164 | } 165 | } 166 | 167 | class LoadBalancer_Exception extends \Exception {} -------------------------------------------------------------------------------- /src/Sifo/Metadata.php: -------------------------------------------------------------------------------- 1 | assign( 'metadata', Metadata::get() ); 33 | * 34 | * metadata_es_ES.config.php: 35 | * $config['test'] = array( 36 | * 'title' => "%name% - %section%. YourBrandName", 37 | * 'description' => "Description of %name% - %section%", 38 | * 'keywords' => "%name%,%section%" 39 | * ); 40 | * 41 | * FINALLY, THE RESULT IS: 42 | * 43 | * $config['test'] = array( 44 | * 'title' => "Test name - Test section. YourBrandName", 45 | * 'description' => "Description of Test name - Test section", 46 | * 'keywords' => "Test name,Test section" 47 | * ); 48 | * 49 | */ 50 | class Metadata 51 | { 52 | /** 53 | * Store metadata key. It's not mandatory define a key. If you don't set a key the metadata key will be the URL path. 54 | * 55 | * @param string $key This key should be defined in the metadata_lang.config.php 56 | */ 57 | static public function setKey( $key ) 58 | { 59 | self::set( null, $key, true ); 60 | } 61 | 62 | /** 63 | * Store values to do a replacement in the metadata definition. If an array is passed 64 | * in the values the var_name is ignored. Keys are used as var_names. 65 | * 66 | * @param string $var_name Var name defined in the metadata config. 67 | * @param string|array $value Value or values to replace in the metadata config (as string or key=>value). 68 | */ 69 | static public function setValues( $var_name, $value ) 70 | { 71 | if ( is_array( $value ) ) 72 | { 73 | foreach ( $value as $key => $val ) 74 | { 75 | self::set( "%$key%", $val ); 76 | } 77 | } 78 | else 79 | { 80 | self::set( "%$var_name%", $value ); 81 | } 82 | } 83 | 84 | /** 85 | * Get metadata. It uses the metadata key or path to return the metadata. 86 | * 87 | * @return array 88 | */ 89 | static public function get() 90 | { 91 | $metadata_info = self::_getMetadataInformation(); 92 | $metadata_raw = Config::getInstance()->getConfig( 'lang/metadata_' . Domains::getInstance()->getLanguage() ); 93 | $metadata = $metadata_raw['default']; 94 | 95 | if ( isset( $metadata_info['metadata_key'] ) ) 96 | { 97 | $metadata = $metadata_raw[ $metadata_info['metadata_key'] ]; 98 | } 99 | else 100 | { 101 | $reversal_path = Router::getReversalRoute( Urls::getInstance( Bootstrap::$instance )->getPath() ); 102 | if( $reversal_path && isset( $metadata_raw[ $reversal_path ] ) ) 103 | { 104 | $metadata = $metadata_raw[ $reversal_path ]; 105 | } 106 | } 107 | 108 | return self::_replaceVars( $metadata, $metadata_info ); 109 | } 110 | 111 | /** 112 | * Replace Metadata vars in the metadata defined in metadata config. 113 | * 114 | * @param array $metadata Metadata get it of metadat config. 115 | * @param array $metadata_info Metadata info with the vars to do the replacement. 116 | * @return array 117 | */ 118 | static private function _replaceVars( $metadata, $metadata_info ) 119 | { 120 | if ( isset( $metadata_info['vars'] ) && is_array( $metadata ) ) 121 | { 122 | foreach ( $metadata as $name => $value ) 123 | { 124 | $metadata[ $name ] = strtr( $metadata[ $name ], $metadata_info['vars'] ); 125 | } 126 | } 127 | 128 | return $metadata; 129 | } 130 | 131 | /** 132 | * Store metadata information in registry. 133 | * 134 | * @param string $key Variable name. 135 | * @param string $value Variable value. 136 | * @param boolean $is_metadata_key If it's the metadata key this value is true, others false. 137 | */ 138 | static public function set( $key, $value, $is_metadata_key = false ) 139 | { 140 | $registry = Registry::getInstance(); 141 | if ( $registry->keyExists( 'metadata_information' ) ) 142 | { 143 | $metadata_information = $registry->get( 'metadata_information' ); 144 | } 145 | 146 | if ( $is_metadata_key ) 147 | { 148 | $metadata_information['metadata_key'] = $value; 149 | } 150 | else 151 | { 152 | $metadata_information['vars'][$key] = $value; 153 | } 154 | 155 | $registry->set( 'metadata_information', $metadata_information ); 156 | } 157 | 158 | /** 159 | * Get the metadata information. 160 | * 161 | * @return array 162 | */ 163 | static private function _getMetadataInformation() 164 | { 165 | $msgs = Registry::getInstance()->get( 'metadata_information'); 166 | 167 | if ( $msgs ) 168 | { 169 | return $msgs; 170 | } 171 | 172 | return array(); 173 | } 174 | } -------------------------------------------------------------------------------- /src/RSS_PHP/rss_php.php: -------------------------------------------------------------------------------- 1 | 8 | Published: 200801 :: blacknet :: via rssphp.net 9 | 10 | RSS_PHP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. 11 | 12 | Usage: 13 | See the documentation at http://rssphp.net/documentation 14 | Examples: 15 | Can be found online at http://rssphp.net/examples 16 | */ 17 | 18 | class rss_php { 19 | 20 | public $document; 21 | public $channel; 22 | public $items; 23 | 24 | /**************************** 25 | public load methods 26 | ***/ 27 | # load RSS by URL 28 | public function load($url=false, $unblock=true) { 29 | if($url) { 30 | if($unblock) { 31 | $this->loadParser(file_get_contents($url, false, $this->randomContext())); 32 | } else { 33 | $this->loadParser(file_get_contents($url)); 34 | } 35 | } 36 | } 37 | # load raw RSS data 38 | public function loadRSS($rawxml=false) { 39 | if($rawxml) { 40 | $this->loadParser($rawxml); 41 | } 42 | } 43 | 44 | /**************************** 45 | public load methods 46 | @param $includeAttributes BOOLEAN 47 | return array; 48 | ***/ 49 | # return full rss array 50 | public function getRSS($includeAttributes=false) { 51 | if($includeAttributes) { 52 | return $this->document; 53 | } 54 | return $this->valueReturner(); 55 | } 56 | # return channel data 57 | public function getChannel($includeAttributes=false) { 58 | if($includeAttributes) { 59 | return $this->channel; 60 | } 61 | return $this->valueReturner($this->channel); 62 | } 63 | # return rss items 64 | public function getItems($includeAttributes=false) { 65 | if($includeAttributes) { 66 | return $this->items; 67 | } 68 | return $this->valueReturner($this->items); 69 | } 70 | 71 | /**************************** 72 | internal methods 73 | ***/ 74 | private function loadParser($rss=false) { 75 | if($rss) { 76 | $this->document = array(); 77 | $this->channel = array(); 78 | $this->items = array(); 79 | $DOMDocument = new DOMDocument; 80 | $DOMDocument->strictErrorChecking = false; 81 | $DOMDocument->loadXML($rss); 82 | $this->document = $this->extractDOM($DOMDocument->childNodes); 83 | } 84 | } 85 | 86 | private function valueReturner($valueBlock=false) { 87 | if(!$valueBlock) { 88 | $valueBlock = $this->document; 89 | } 90 | foreach($valueBlock as $valueName => $values) { 91 | if(isset($values['value'])) { 92 | $values = $values['value']; 93 | } 94 | if(is_array($values)) { 95 | $valueBlock[$valueName] = $this->valueReturner($values); 96 | } else { 97 | $valueBlock[$valueName] = $values; 98 | } 99 | } 100 | return $valueBlock; 101 | } 102 | 103 | private function extractDOM($nodeList,$parentNodeName=false) { 104 | $itemCounter = 0; 105 | foreach($nodeList as $values) { 106 | if(substr($values->nodeName,0,1) != '#') { 107 | if($values->nodeName == 'item') { 108 | $nodeName = $values->nodeName.':'.$itemCounter; 109 | $itemCounter++; 110 | } else { 111 | $nodeName = $values->nodeName; 112 | } 113 | $tempNode[$nodeName] = array(); 114 | if($values->attributes) { 115 | for($i=0;$values->attributes->item($i);$i++) { 116 | $tempNode[$nodeName]['properties'][$values->attributes->item($i)->nodeName] = $values->attributes->item($i)->nodeValue; 117 | } 118 | } 119 | if(!$values->firstChild) { 120 | $tempNode[$nodeName]['value'] = $values->textContent; 121 | } else { 122 | $tempNode[$nodeName]['value'] = $this->extractDOM($values->childNodes, $values->nodeName); 123 | } 124 | if(in_array($parentNodeName, array('channel','rdf:RDF'))) { 125 | if($values->nodeName == 'item') { 126 | $this->items[] = $tempNode[$nodeName]['value']; 127 | } elseif(!in_array($values->nodeName, array('rss','channel'))) { 128 | $this->channel[$values->nodeName] = $tempNode[$nodeName]; 129 | } 130 | } 131 | } elseif(substr($values->nodeName,1) == 'text') { 132 | $tempValue = trim(preg_replace('/\s\s+/',' ',str_replace("\n",' ', $values->textContent))); 133 | if($tempValue) { 134 | $tempNode = $tempValue; 135 | } 136 | } elseif(substr($values->nodeName,1) == 'cdata-section'){ 137 | $tempNode = $values->textContent; 138 | } 139 | } 140 | return $tempNode; 141 | } 142 | 143 | private function randomContext() { 144 | $headerstrings = array(); 145 | $headerstrings['User-Agent'] = 'Mozilla/5.0 (Windows; U; Windows NT 5.'.rand(0,2).'; en-US; rv:1.'.rand(2,9).'.'.rand(0,4).'.'.rand(1,9).') Gecko/2007'.rand(10,12).rand(10,30).' Firefox/2.0.'.rand(0,1).'.'.rand(1,9); 146 | $headerstrings['Accept-Charset'] = rand(0,1) ? 'en-gb,en;q=0.'.rand(3,8) : 'en-us,en;q=0.'.rand(3,8); 147 | $headerstrings['Accept-Language'] = 'en-us,en;q=0.'.rand(4,6); 148 | $setHeaders = 'Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5'."\r\n". 149 | 'Accept-Charset: '.$headerstrings['Accept-Charset']."\r\n". 150 | 'Accept-Language: '.$headerstrings['Accept-Language']."\r\n". 151 | 'User-Agent: '.$headerstrings['User-Agent']."\r\n"; 152 | $contextOptions = array( 153 | 'http'=>array( 154 | 'method'=>"GET", 155 | 'header'=>$setHeaders 156 | ) 157 | ); 158 | return stream_context_create($contextOptions); 159 | } 160 | 161 | } 162 | 163 | ?> 164 | -------------------------------------------------------------------------------- /src/Sifo/Router.php: -------------------------------------------------------------------------------- 1 | getString( 'HTTPS' ) == 'on' || $server->getString( 'HTTP_X_FORWARDED_PROTO' ) == 'https' ) 46 | { 47 | $used_url .= "s"; 48 | } 49 | $used_url .= "://"; 50 | 51 | if ( $server->getString( 'HTTP_HOST' ) ) 52 | { 53 | $hostname = $server->getString( 'HTTP_HOST' ); 54 | } 55 | else 56 | { 57 | $hostname = $server->getString( "SERVER_NAME" ); 58 | } 59 | 60 | if ( $server->getString( 'SERVER_PORT' ) != "80" ) 61 | { 62 | $used_url .= $hostname . ":" . $server->getString( 'SERVER_PORT' ) . $server->getString( "REQUEST_URI" ); 63 | } 64 | else 65 | { 66 | $used_url .= $hostname . $server->getString( "REQUEST_URI" ); 67 | } 68 | 69 | return $used_url; 70 | } 71 | 72 | /** 73 | * Looks if the path has a known pattern handled by a controller. 74 | */ 75 | public function __construct( $path, $instance, $subdomain = false, $language = false, $www_mode = false ) 76 | { 77 | // Look for routes: 78 | $routes = Config::getInstance( $instance )->getConfig( 'router' ); 79 | 80 | // Failed to parse routes file. 81 | if ( !$routes ) 82 | { 83 | throw new Exception_500( "Failed opening router conifiguration file" ); 84 | } 85 | 86 | if ( $language ) 87 | { 88 | try 89 | { 90 | self::$routes_for_this_language = Config::getInstance( $instance )->getConfig( 'lang/router_' . $language ); 91 | 92 | 93 | // Translation of URLs: 94 | foreach ( self::$routes_for_this_language as $translated_route => $destiny ) 95 | { 96 | if ( isset( $routes[$translated_route] ) && $translated_route != $destiny ) 97 | { 98 | // Replace a translation of the URL by the english entry. 99 | $routes[$destiny] = $routes[$translated_route]; 100 | 101 | // Delete the English entry. 102 | unset( $routes[$translated_route] ); 103 | } 104 | 105 | 106 | // Create a mapping table with the association translated => original 107 | self::$reversal_map[$destiny] = $translated_route; 108 | } 109 | } 110 | catch ( Exception_Configuration $e ) 111 | { 112 | // trigger_error( "Failed to load url config profile for language '$language'" ); 113 | } 114 | } 115 | 116 | foreach ( $routes as $route => $controller ) 117 | { 118 | // The subdomain can define the controller to use. 119 | if ( $subdomain == $route ) 120 | { 121 | $this->main_controller = $controller; 122 | return; 123 | } 124 | // No valid subdomain for controller, use path to define controller instead: 125 | elseif ( $path == $route ) 126 | { 127 | $this->main_controller = $controller; 128 | return; 129 | } 130 | } 131 | 132 | // The controller cannot be determined by parsing the path or the subdomain, is a home? 133 | if ( !isset( $this->main_controller ) ) 134 | { 135 | if ( ( strlen( $path ) == 0 ) && !( ( $subdomain != "www" && true == $www_mode || strlen( $subdomain ) > 0 && false == $www_mode) ) ) 136 | { 137 | $this->main_controller = $routes['__HOME__']; 138 | } 139 | else 140 | { 141 | if ( $rules_301 = Config::getInstance( $instance )->getConfig( '301_rules' ) ) 142 | { 143 | $used_url = self::getUsedUrl(); 144 | foreach ( $rules_301 as $regexp => $replacement ) 145 | { 146 | $destiny = preg_replace( $regexp, $replacement, $used_url, -1, $count ); 147 | 148 | // $count indicates the replaces. If $count gt 0 means that was matchs. 149 | if ( $count ) 150 | { 151 | throw new Exception_301( $destiny ); 152 | } 153 | } 154 | } 155 | // No route found, use default. 156 | $this->main_controller = $routes['__NO_ROUTE_FOUND__']; 157 | } 158 | } 159 | } 160 | 161 | public function getController() 162 | { 163 | return $this->main_controller; 164 | } 165 | 166 | /** 167 | * Returns the key associated to a translated route. Or same string if no reversal found. 168 | * 169 | * For instance, if you pass 'ayuda' should return 'help'. 170 | * 171 | * @param string $translated_route 172 | * @return string 173 | */ 174 | static public function getReversalRoute( $translated_route ) 175 | { 176 | if ( isset( self::$reversal_map[$translated_route] ) ) 177 | { 178 | // The path has translation: 179 | return self::$reversal_map[$translated_route]; 180 | } 181 | 182 | if ( !isset( self::$routes_for_this_language[ $translated_route ] ) ) 183 | { 184 | // There are not available translation for this route. 185 | return $translated_route; 186 | } 187 | 188 | return false; 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/Sifo/Cache/Disk.php: -------------------------------------------------------------------------------- 1 | cache_object = &$this; 37 | return $this; 38 | } 39 | 40 | /** 41 | * Stores variable "var" with "key" only if such key doesn't exist at the server yet. 42 | * 43 | * @param string $key 44 | * @param mixed $var 45 | * @param integer $expire Seconds until this item will expire. Zero for persistent caching (never expire). 46 | * 47 | * @return bool 48 | */ 49 | public function add( $key, $var, $expire = 0 ) 50 | { 51 | if ( false != $this->get( $key ) ) 52 | { 53 | return false; 54 | } 55 | return $this->set( $key, $var, $expire ); 56 | } 57 | 58 | 59 | /** 60 | * Increment an existing integer value 61 | * 62 | * @param string $key 63 | * @param integer $value 64 | * @param integer $expire Seconds until this item will expire. Zero for persistent caching (never expire). 65 | * 66 | * @return bool 67 | */ 68 | public function increment( $key, $value = 1, $expire = 0 ) 69 | { 70 | if ( !is_numeric( $current_value = $this->get( $key ) ) ) 71 | { 72 | return false; 73 | } 74 | 75 | $new_value = $current_value + $value; 76 | return ( $this->set( $key, $new_value, $expire ) ? $new_value : false ); 77 | } 78 | 79 | /** 80 | * Increment an existing integer value 81 | * 82 | * @param string $key 83 | * @param integer $value 84 | * @param integer $expire Seconds until this item will expire. Zero for persistent caching (never expire). 85 | * @return bool 86 | */ 87 | public function decrement( $key, $value = 1, $expire = 0 ) 88 | { 89 | if ( !is_numeric( $current_value = $this->get( $key ) ) ) 90 | { 91 | return false; 92 | } 93 | 94 | $new_value = $current_value - $value; 95 | return ( $this->set( $key, $new_value, $expire ) ? $new_value : false ); 96 | } 97 | 98 | /** 99 | * Write content in cache 100 | * 101 | * @param string $key 102 | * @param string $contents 103 | * @param integer $expire Seconds until this item will expire. Zero for persistent caching (never expire). 104 | * 105 | * @return boolean 106 | */ 107 | public function set( $key, $contents, $expire = 0 ) 108 | { 109 | $source_file = $this->getCacheFilename( $key ); 110 | 111 | $cache_content = array( 112 | 'key' => $key, 113 | 'expiration' => $expire, 114 | 'content' => $contents 115 | ); 116 | return file_put_contents( $source_file, var_export( $cache_content, true ) ); 117 | } 118 | 119 | /** 120 | * Returns the content associated to that key or FALSE. 121 | * 122 | * Also deletes the cache file if has expired when checking it. 123 | * 124 | * @param string $key 125 | * 126 | * @return mixed Cached content or FALSE. 127 | */ 128 | public function get( $key ) 129 | { 130 | if ( $this->hasRebuild() ) 131 | { 132 | return false; 133 | } 134 | 135 | $source_file = $this->getCacheFilename( $key ); 136 | 137 | $file_content = @file_get_contents( $source_file ); 138 | if ( !$file_content ) 139 | { 140 | return false; 141 | } 142 | 143 | $cache_content = eval( 'return ' . $file_content . ';' ); 144 | 145 | if ( !isset( $cache_content['expiration'] ) || !isset( $cache_content['content'] ) ) 146 | { 147 | return false; 148 | } 149 | 150 | // Check if content has expired (expiration=0 means persistent cache): 151 | if ( $cache_content['expiration'] > 0 ) 152 | { 153 | $mtime = filemtime( $source_file ); 154 | if ( ( $mtime + $cache_content['expiration'] ) < time() ) 155 | { 156 | // Delete the file. 157 | @unlink( $source_file ); 158 | return false; 159 | } 160 | } 161 | 162 | return $cache_content['content']; 163 | 164 | 165 | } 166 | 167 | /** 168 | * Deletes the cache key. 169 | * 170 | * @param $key 171 | * 172 | * @return bool 173 | */ 174 | public function delete( $key ) 175 | { 176 | return @unlink( $this->getCacheFilename( $key ) ); 177 | } 178 | 179 | 180 | /** 181 | * Check if cache to Disk will work. 182 | * 183 | * @return integer 184 | */ 185 | public function isActive() 186 | { 187 | $cache_path = $this->getPathBase(); 188 | return is_writable( $cache_path ) && is_readable( $cache_path ); 189 | } 190 | 191 | 192 | /** 193 | * Returns the full path to the cache filename related to the given key. 194 | * 195 | * @param $key 196 | * 197 | * @return string 198 | */ 199 | private function getCacheFilename( $key ) 200 | { 201 | $hash = sha1( $key ); 202 | return $this->getPathBase() . "{$hash}.cache"; 203 | } 204 | 205 | /** 206 | * Returns the base folder where cache will be stored. 207 | * 208 | * @return string 209 | */ 210 | private function getPathBase() 211 | { 212 | return ROOT_PATH . '/instances/' . Bootstrap::$instance . '/templates/_smarty/cache/'; 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /src/Sifo/Exceptions.php: -------------------------------------------------------------------------------- 1 | = $current_exception_code ) ) 60 | { 61 | $this->redirect = true; 62 | } 63 | 64 | if ( isset( Headers::$http_codes[$current_exception_code] ) ) 65 | { 66 | $this->http_code = $current_exception_code; 67 | $this->http_code_msg = Headers::$http_codes[$current_exception_code]; 68 | } 69 | else 70 | { 71 | // The passed exception is not in the list. Pass a 500 error. 72 | $this->http_code = 500; 73 | $this->http_code_msg = 'Internal Server Error'; 74 | } 75 | 76 | // Set internal exception vars if they are empty (non declared in constructor). 77 | // This allows usage of methods as $e->getMessage() or $e->getCode() 78 | if ( 0 == $this->code ) 79 | { 80 | $this->code = $this->http_code; 81 | } 82 | 83 | if ( null === $this->message ) 84 | { 85 | $this->message = $this->http_code_msg; 86 | } 87 | } 88 | 89 | /** 90 | * Raises a Sifo exceptions based on the given HTTP status code 91 | * @param string $message Reason 92 | * @param int $code HTTP status code 93 | */ 94 | public static function raise( $message, $code ) 95 | { 96 | if ( isset( Headers::$http_codes[$code] ) ) 97 | { 98 | $exception = '\Sifo\Exception_' . $code; 99 | throw new $exception( $message ); 100 | } 101 | else 102 | { 103 | // Unknown status code. 104 | throw new Exception_500( $message, $code ); 105 | } 106 | } 107 | 108 | /** http://fabien.potencier.org/php-serialization-stack-traces-and-exceptions.html */ 109 | public function serialize() 110 | { 111 | return serialize( array( $this->code, $this->message, $this->http_code, $this->http_code_msg, $this->redirect ) ); 112 | } 113 | 114 | public function unserialize($serialized) 115 | { 116 | list( $this->code, $this->message, $this->http_code, $this->http_code_msg, $this->redirect ) = unserialize( $serialized ); 117 | } 118 | } 119 | 120 | /** 121 | * Redirect (Moved permanently). 122 | */ 123 | class Exception_301 extends SEO_Exception{} 124 | 125 | /** 126 | * Found (redirection). 127 | */ 128 | class Exception_302 extends SEO_Exception{} 129 | 130 | /** 131 | * See other. 132 | */ 133 | class Exception_303 extends SEO_Exception{} 134 | 135 | /** 136 | * Not modified headers. TODO, implement Etag. 137 | */ 138 | class Exception_304 extends SEO_Exception{} 139 | 140 | /* 141 | * Temporary redirect 142 | */ 143 | class Exception_307 extends SEO_Exception{} 144 | 145 | /** 146 | * Bad request 147 | */ 148 | class Exception_400 extends SEO_Exception{} 149 | 150 | /** 151 | * Unauthorized Exception. 152 | */ 153 | class Exception_401 extends SEO_Exception{} 154 | 155 | /** 156 | * Forbidden. 157 | */ 158 | class Exception_403 extends SEO_Exception{} 159 | 160 | /** 161 | * Not found. 162 | */ 163 | class Exception_404 extends SEO_Exception{} 164 | 165 | /** 166 | * Method not allowed. 167 | */ 168 | class Exception_405 extends SEO_Exception{} 169 | 170 | /** 171 | * Oooops. Internal server error. 172 | */ 173 | class Exception_500 extends SEO_Exception{} 174 | 175 | /** 176 | * Service unavailable. 177 | */ 178 | class Exception_503 extends SEO_Exception{} 179 | 180 | /* Not so common status codes */ 181 | class Exception_100 extends SEO_Exception{} 182 | class Exception_101 extends SEO_Exception{} 183 | class Exception_201 extends SEO_Exception{} 184 | class Exception_202 extends SEO_Exception{} 185 | class Exception_203 extends SEO_Exception{} 186 | class Exception_204 extends SEO_Exception{} 187 | class Exception_205 extends SEO_Exception{} 188 | class Exception_206 extends SEO_Exception{} 189 | class Exception_300 extends SEO_Exception{} 190 | class Exception_305 extends SEO_Exception{} 191 | class Exception_402 extends SEO_Exception{} 192 | class Exception_406 extends SEO_Exception{} 193 | class Exception_407 extends SEO_Exception{} 194 | class Exception_408 extends SEO_Exception{} 195 | class Exception_409 extends SEO_Exception{} 196 | class Exception_410 extends SEO_Exception{} 197 | class Exception_411 extends SEO_Exception{} 198 | class Exception_412 extends SEO_Exception{} 199 | class Exception_413 extends SEO_Exception{} 200 | class Exception_414 extends SEO_Exception{} 201 | class Exception_415 extends SEO_Exception{} 202 | class Exception_416 extends SEO_Exception{} 203 | class Exception_417 extends SEO_Exception{} 204 | class Exception_501 extends SEO_Exception{} 205 | class Exception_502 extends SEO_Exception{} 206 | class Exception_504 extends SEO_Exception{} 207 | class Exception_505 extends SEO_Exception{} 208 | -------------------------------------------------------------------------------- /src/Sifo/Search.php: -------------------------------------------------------------------------------- 1 | sphinx_config = $this->getConnectionParams( $profile ); 52 | 53 | // Check if Sphinx is enabled by configuration: 54 | if ( true === $this->sphinx_config['active'] ) 55 | { 56 | self::$search_engine = 'Sphinx'; 57 | $this->sphinx = self::connect( $this->sphinx_config ); 58 | } 59 | } 60 | 61 | /** 62 | * Singleton get instance. Return one search engine object. 63 | * 64 | * @param string $profile 65 | * @return object Config 66 | */ 67 | public static function getInstance( $profile = 'default' ) 68 | { 69 | if ( !isset ( self::$instance[$profile] ) ) 70 | { 71 | if ( Domains::getInstance()->getDebugMode() !== true ) 72 | { 73 | self::$instance[$profile] = new Search( $profile ); 74 | } 75 | else 76 | { 77 | self::$instance[$profile] = new DebugSearch( $profile ); 78 | } 79 | } 80 | 81 | return self::$instance[$profile]; 82 | } 83 | 84 | /** 85 | * Get Sphinx connection params from config files. 86 | * 87 | * @param $profile 88 | * @throws Exception_500 89 | * @return array 90 | */ 91 | protected function getConnectionParams( $profile ) 92 | { 93 | // The domains.config file has priority, let's fetch it. 94 | $sphinx_config = \Sifo\Domains::getInstance()->getParam( 'sphinx' ); 95 | 96 | if ( empty( $sphinx_config ) ) 97 | { 98 | try 99 | { 100 | // If the domains.config doesn't define the params, we use the sphinx.config. 101 | $sphinx_config = Config::getInstance()->getConfig( 'sphinx' ); 102 | 103 | if ( isset( $sphinx_config[$profile] ) ) 104 | { 105 | $sphinx_config = $this->checkBalancedProfile( $sphinx_config[$profile] ); 106 | } 107 | elseif ( isset( $sphinx_config['default'] ) ) 108 | { 109 | // Is using profiles but there isn't the required one. 110 | throw new \Sifo\Exception_500( "Expected sphinx settings not defined for profile {$profile} in sphinx.config." ); 111 | } 112 | // Deprecated: 113 | else 114 | { 115 | if ( Domains::getInstance()->getDebugMode() === true ) 116 | { 117 | trigger_error( "DEPRECATED: You aren't using profiles for your sphinx.config file. Please, define at least the 'default' one. (This message is only readable with the debug flag enabled)", E_USER_DEPRECATED ); 118 | } 119 | } 120 | $sphinx_config['config_file'] = 'sphinx'; 121 | } 122 | catch ( Exception_Configuration $e ) 123 | { 124 | throw new \Sifo\Exception_500( 'You must define the connection params in sphinx.config or domains.config file' ); 125 | } 126 | } 127 | else 128 | { 129 | $sphinx_config['config_file'] = 'domains'; 130 | } 131 | 132 | return $sphinx_config; 133 | } 134 | 135 | /** 136 | * Check if one profile has balanced servers or single server. Returns the connection to use. 137 | * @param $sphinx_config 138 | * @return array 139 | */ 140 | private function checkBalancedProfile( $sphinx_config ) 141 | { 142 | if ( isset( $sphinx_config[0] ) && is_array( $sphinx_config[0] ) ) 143 | { 144 | $lb = new LoadBalancerSearch(); 145 | $lb->setNodes( $sphinx_config ); 146 | $selected_server = $lb->get(); 147 | $sphinx_config = $sphinx_config[$selected_server]; 148 | } 149 | 150 | return $sphinx_config; 151 | } 152 | 153 | /** 154 | * Delegate all calls to the proper class. 155 | * 156 | * @param string $method 157 | * @param mixed $args 158 | * @return mixed 159 | */ 160 | function __call( $method, $args ) 161 | { 162 | if ( is_object( $this->sphinx ) ) 163 | { 164 | return call_user_func_array( array( $this->sphinx, $method ), $args ); 165 | } 166 | return null; 167 | } 168 | 169 | /** 170 | * Use this method to connect to Sphinx. 171 | * @param $node_properties 172 | * @return \SphinxClient 173 | * @throws Exception_500 174 | */ 175 | static function connect( $node_properties ) 176 | { 177 | if ( true === $node_properties['active'] ) 178 | { 179 | $sphinx = new \SphinxClient(); 180 | $sphinx->SetServer( $node_properties['server'], $node_properties['port'] ); 181 | 182 | // If it's defined a time out connection in config file: 183 | if( isset( $node_properties['time_out'] ) ) 184 | { 185 | $sphinx->SetConnectTimeout( $node_properties['time_out'] ); 186 | } 187 | 188 | // Check if Sphinx is listening: 189 | if ( false === $sphinx->Status() ) 190 | { 191 | throw new \Sifo\Exception_500( 'Sphinx (' . $node_properties['server'] . ':' . $node_properties['port'] . ') is down!' ); 192 | } 193 | } 194 | 195 | return $sphinx; 196 | } 197 | } 198 | 199 | class LoadBalancerSearch extends LoadBalancer 200 | { 201 | /** 202 | * Name of the cache where the results of server status are stored. 203 | * @var string 204 | */ 205 | protected $load_balancer_cache_key = 'BalancedNodesSearch'; 206 | 207 | protected function addNodeIfAvailable( $index, $node_properties ) 208 | { 209 | try 210 | { 211 | Search::connect( $node_properties ); 212 | $this->addServer( $index, $node_properties['weight'] ); 213 | } 214 | catch( \Sifo\Exception_500 $e ) 215 | { 216 | trigger_error('[SEARCH LOAD BALANCER] ' . $e->getMessage(), E_USER_WARNING); 217 | } 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /src/Sifo/Config.php: -------------------------------------------------------------------------------- 1 | instance_name = $instance_name; 69 | if ( $instance_name === 'tests' ) 70 | { 71 | $this->config_path = ROOT_PATH . '/' . $instance_name ."/config/"; 72 | } 73 | else 74 | { 75 | $this->config_path = ROOT_PATH . "/instances/" . $instance_name ."/config/"; 76 | } 77 | 78 | include( $this->config_path . $this->configuration_files ); 79 | $this->paths_to_configs = $config; 80 | 81 | $env_file = (isset($_SERVER['APP_ENV']) && $_SERVER['APP_ENV'] === 'test') ? '.env.test' : '.env'; 82 | $dotenv = new Dotenv(); 83 | 84 | try { 85 | $dotenv->load(ROOT_PATH . "/$env_file"); 86 | } catch (PathException $exception) { 87 | return; 88 | } 89 | } 90 | 91 | /** 92 | * Singleton of config class. 93 | * 94 | * @param string $instance_name Instance Name, needed to determine correct paths. 95 | * @return Config 96 | */ 97 | public static function getInstance( $instance_name = null, $force = false ) 98 | { 99 | // Load instance from bootsrap 100 | if ( !isset( $instance_name ) ) 101 | { 102 | $instance_name = Bootstrap::$instance; 103 | } 104 | 105 | if ( !isset ( self::$instance[$instance_name] ) || $force === true ) 106 | { 107 | self::$instance[$instance_name] = new self( $instance_name ); 108 | } 109 | 110 | return self::$instance[$instance_name]; 111 | } 112 | 113 | /** 114 | * Loads the desired config file for a given valid 'profile'. 115 | * 116 | * @param string $profile The requested profile. 117 | * @throws Exception_Configuration When isn't set the self::PROFILE_NAME_FOR_CONFIG_FILES section or the desired profile. 118 | * @return boolean 119 | */ 120 | protected function loadConfig( $profile ) 121 | { 122 | if( !isset( $this->paths_to_configs[$profile] ) ) 123 | { 124 | throw new Exception_Configuration( "The profile '$profile' was not found" ); 125 | } 126 | else 127 | { 128 | if ( !include( ROOT_PATH . '/' . $this->paths_to_configs[$profile] ) ) 129 | { 130 | throw new Exception_Configuration( "Failed to include file " . ROOT_PATH . '/' . $this->paths_to_configs[$profile] , E_USER_ERROR ); 131 | } 132 | else 133 | { 134 | // The file was correctly included. We include the variable $config found. 135 | if ( !isset( $config ) ) 136 | { 137 | throw new Exception_Configuration( 'The configuration files must have a variable named $config' ); 138 | } 139 | 140 | return $config; 141 | } 142 | } 143 | } 144 | 145 | /** 146 | * Gets the profile config variables for the desired profile. 147 | * 148 | * @param string $profile The requested profile. 149 | * @param string $group The requested group inside the profile. 150 | * @throws Exception_Configuration When the selected group or profile doesn't exist. 151 | * @return mixed $config_values The config values in the config file of the current profile. 152 | */ 153 | public function getConfig( $profile, $group = null ) 154 | { 155 | if ( !isset( $this->config_values[$profile] ) ) 156 | { 157 | $this->config_values[$profile] = $this->loadConfig( $profile ); 158 | } 159 | 160 | if ( is_null( $group ) ) 161 | { 162 | return $this->config_values[$profile]; 163 | } 164 | if ( isset( $this->config_values[$profile][$group] ) ) 165 | { 166 | return $this->config_values[$profile][$group]; 167 | } 168 | 169 | throw new Exception_Configuration( "The group '$group' for profile '$profile' was never set.", E_USER_ERROR ); 170 | } 171 | 172 | /** 173 | * Instance name. 174 | * 175 | * @return string 176 | */ 177 | public function getInstanceName() 178 | { 179 | return $this->instance_name; 180 | } 181 | 182 | /** 183 | * Returns the library assigned to the given alias. 184 | * 185 | * @param string $alias Alias of the library, e.g: 'smarty' 186 | * @return string Effective name of the folder with the library 187 | */ 188 | public function getLibrary( $alias ) 189 | { 190 | $libraries = $this->getConfig( 'libraries', 'default' ); 191 | 192 | // User requested a different profile, combine with default for missing attributes. 193 | if ( self::$libraries_profile != 'default' ) 194 | { 195 | $libraries = array_merge( $libraries, $this->getConfig( 'libraries', self::$libraries_profile ) ); 196 | } 197 | 198 | if ( !isset( $libraries[$alias] ) ) 199 | { 200 | throw new Exception_Configuration( "The library '$alias' you are loading is not set in profile " . self::$libraries_profile ); 201 | } 202 | 203 | return $libraries[$alias]; 204 | } 205 | } 206 | 207 | /** 208 | * Exception for the process. 209 | */ 210 | class Exception_Configuration extends \Exception 211 | { 212 | } 213 | 214 | ?> 215 | -------------------------------------------------------------------------------- /src/Sifo/DirectoryList.php: -------------------------------------------------------------------------------- 1 | getRecursiveList( $path ); 37 | * 38 | * // Recursive list of PHP and HTML files (hiding dirs) 39 | * $iterator = $dir->getRecursiveList( $path, false, array( 'php', 'html' ) ); 40 | * 41 | * // List of immediate files and dirs (non recursive): 42 | * $iterator = $dir->getList( $path ); 43 | * 44 | * 45 | * Then you can iterate the result $iterator in a foreach ( $path => $DirectoryIterator ) 46 | * where $DirectoryIterator has many interesting methods such as: 47 | * ->getATime() 48 | * ->getBasename ( $ending_part_to_remove ) 49 | * ->getCTime() 50 | * ->getExtension() 51 | * ->getFilename() 52 | * ->getGroup() 53 | * ->getInode() 54 | * ->getMTime() 55 | * ->getOwner() 56 | * ->getPath() 57 | * ->getPathname() 58 | * ->getPerms() 59 | * ->getSize() 60 | * ->getType() 61 | * ->isDir() 62 | * ->isDot() 63 | * ->isExecutable() 64 | * ->isFile() 65 | * ->isLink() 66 | * ->isReadable() 67 | * ->isWritable() 68 | * ->valid() 69 | * 70 | * @see http://www.php.net/manual/en/spl.iterators.php 71 | */ 72 | class DirectoryList 73 | { 74 | 75 | /** 76 | * Returns the list of *immediate* files [isFile()] and folders [isDir()] on the given path. 77 | * 78 | * Non-recursive function. 79 | * 80 | * @param string $path Directory where you want to start parsing. 81 | * @param array $valid_extensions 82 | * @return \IteratorIterator 83 | */ 84 | public function getList( $path, $valid_extensions = array( ) ) 85 | { 86 | // Using RecursiveDirectoryIterator because compared to DirectoryIterator this one removes dot folders: 87 | $recursive_dir_iterator = new \RecursiveDirectoryIterator( $path ); 88 | $recursive_dir_iterator->setFlags( \RecursiveDirectoryIterator::SKIP_DOTS ); 89 | 90 | if ( !empty( $valid_extensions ) ) 91 | { 92 | return new FilterFilesByExtensionIterator( 93 | new \IteratorIterator( $recursive_dir_iterator ), 94 | $valid_extensions ); 95 | } 96 | else 97 | { 98 | 99 | return new \IteratorIterator( $recursive_dir_iterator ); 100 | } 101 | 102 | } 103 | 104 | /** 105 | * Recursive listing of directory, files and dirs. If a set of extensions is 106 | * passed only matching files will be returned (do not pass the dot in the extensions) 107 | * 108 | * @param string $path Directory where you want to start parsing. 109 | * @param bool $accept_directories 110 | * @param array $valid_extensions List of accepted extensions in the list, empty array for no filtering. 111 | * @return \RecursiveIteratorIterator|\Sifo\FilterFilesByExtensionIterator ratorIterator of RecursiveDirectoryIterator 112 | */ 113 | public function getRecursiveList( $path, $accept_directories = true, $valid_extensions = array( ) ) 114 | { 115 | $mode = $this->_getIteratorMode( $accept_directories ); 116 | $recursive_dir_iterator = new \RecursiveDirectoryIterator( $path ); 117 | $recursive_dir_iterator->setFlags( \RecursiveDirectoryIterator::SKIP_DOTS ); 118 | 119 | if ( !empty( $valid_extensions ) ) 120 | { 121 | return new FilterFilesByExtensionIterator( 122 | new \RecursiveIteratorIterator( 123 | $recursive_dir_iterator, 124 | $mode, \RecursiveIteratorIterator::CATCH_GET_CHILD 125 | ), 126 | $valid_extensions ); 127 | } 128 | else 129 | { 130 | return new \RecursiveIteratorIterator( $recursive_dir_iterator, $mode, \RecursiveIteratorIterator::CATCH_GET_CHILD ); 131 | } 132 | 133 | } 134 | 135 | private function _getIteratorMode( $accept_directories ) 136 | { 137 | /** 138 | * Available modes for RecursiveIteratorIterator: 139 | * 140 | * RecursiveIteratorIterator::LEAVES_ONLY (don't show folders, default) 141 | * RecursiveIteratorIterator::SELF_FIRST (show parent folders before children) 142 | * RecursiveIteratorIterator::CHILD_FIRST (show parent folders after children, unusual) 143 | * 144 | * Flags (set in flags, not in mode): 145 | * RecursiveIteratorIterator::CATCH_GET_CHILD = Catches exceptions in getChildren() call 146 | */ 147 | return ( $accept_directories ? 148 | \RecursiveIteratorIterator::SELF_FIRST : 149 | \RecursiveIteratorIterator::LEAVES_ONLY 150 | ); 151 | 152 | } 153 | 154 | } 155 | 156 | /** 157 | * Filters out unwanted files from the iterator. Pass an array with the list of 158 | * extensions you want to accept. 159 | */ 160 | class FilterFilesByExtensionIterator extends \FilterIterator 161 | { 162 | 163 | protected $allowed_extensions; 164 | 165 | public function __construct( \Iterator $iterator, Array $allowed_extensions ) 166 | { 167 | $this->allowed_extensions = $allowed_extensions; 168 | parent::__construct( $iterator ); 169 | 170 | } 171 | 172 | /** 173 | * Checks if current file matches the allowed extension or not. If directories 174 | * are passed will be accepted. 175 | * 176 | * @return boolean 177 | */ 178 | public function accept() 179 | { 180 | // If directories are passed, we accept them. Is duty of the calling function: 181 | 182 | if ( $this->current()->isDir() ) 183 | { 184 | return true; 185 | } 186 | 187 | if ( !empty( $this->allowed_extensions ) ) 188 | { 189 | foreach ( $this->allowed_extensions as $ext ) 190 | { 191 | if ( pathinfo( $this->getBaseName(), PATHINFO_EXTENSION ) == $ext ) 192 | { 193 | return true; 194 | } 195 | } 196 | return false; 197 | } 198 | 199 | return true; 200 | 201 | } 202 | 203 | } -------------------------------------------------------------------------------- /src/Core-js/classes/modals.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @depracated It will be deleted cost is part of a third party library. 3 | */ 4 | CORE.classes.modal = { 5 | oDefault : { 6 | sUrl : '#', // Default URL to open 7 | filters: [], // List of filters used 8 | callbacks: { // Sepcific callbacks 9 | beforeShowCont: function() { 10 | width = $('.nyroModalCont').width(); 11 | height = $('.nyroModalCont').height(); 12 | $('.nyroModalCont iframe').css('width', width); 13 | $('.nyroModalCont iframe').css('height', height); 14 | } 15 | }, 16 | anims: {}, // Sepcific animations functions 17 | loadFilter: undefined, // Name of the filter used for loading 18 | 19 | modal: false, // Indicates if it's a modal window or not 20 | closeOnEscape: true, // Indicates if the modal should close on Escape key 21 | closeOnClick: true, // Indicates if a click on the background should close the modal 22 | useKeyHandler: false, // Indicates if the modal has to handle key down event 23 | 24 | showCloseButton: true, // Indicates if the closeButonn should be added 25 | closeButton: 'Close', // Close button HTML 26 | 27 | stack: false, // Indicates if links automatically binded inside the modal should stack or not 28 | nonStackable: 'form', // Filter to not stack DOM element 29 | 30 | header: undefined, // header include in every modal 31 | footer: undefined, // footer include in every modal 32 | 33 | // Specific confirguation for gallery filter 34 | galleryLoop: true, // Indicates if the gallery should loop 35 | galleryCounts: true, // Indicates if the gallery counts should be shown 36 | ltr: true, // Left to Right by default. Put to false for Hebrew or Right to Left language. Used in gallery filter 37 | 38 | // Specific confirguation for DOM filter 39 | domCopy: false, // Indicates if DOM element should be copied or moved 40 | 41 | // Specific confirguation for link and form filters 42 | ajax: {}, // Ajax options to be used in link and form filter 43 | 44 | // Specific confirguation for image filter 45 | imageRegex: '[^\.]\.(jpg|jpeg|png|tiff|gif|bmp)\s*$', // Regex used to detect image link 46 | 47 | selIndicator: 'nyroModalSel', // Value added when a form or Ajax is sent with a filter content 48 | 49 | swfObjectId: undefined, // Object id for swf object 50 | swf: { // Default SWF attributes 51 | allowFullScreen: 'true', 52 | allowscriptaccess: 'always', 53 | wmode: 'transparent' 54 | }, 55 | 56 | store: {}, // Storage object for filters. 57 | errorMsg: 'An error occured', // Error message 58 | elts: { // HTML elements for the modal 59 | all: undefined, 60 | bg: undefined, 61 | load: undefined, 62 | cont: undefined, 63 | hidden: undefined 64 | }, 65 | sizes: { // Size information 66 | initW: undefined, // Initial width 67 | initH: undefined, // Initial height 68 | w: undefined, // width 69 | h: undefined, // height 70 | minW: undefined, // minimum Width 71 | minH: undefined, // minimum height 72 | wMargin: undefined, // Horizontal margin 73 | hMargin: undefined // Vertical margin 74 | }, 75 | anim: { // Animation names to use 76 | def: undefined, // Default animation set to use if sspecific are not defined or doesn't exist 77 | showBg: undefined, // Set to use for showBg animation 78 | hideBg: undefined, // Set to use for hideBg animation 79 | showLoad: undefined, // Set to use for showLoad animation 80 | hideLoad: undefined, // Set to use for hideLoad animation 81 | showCont: undefined, // Set to use for showCont animation 82 | hideCont: undefined, // Set to use for hideCont animation 83 | showTrans: undefined, // Set to use for showTrans animation 84 | hideTrans: undefined, // Set to use for hideTrans animation 85 | resize: undefined // Set to use for resize animation 86 | }, 87 | 88 | _open: false, // Indicates if the modal is open 89 | _bgReady: false, // Indicates if the background is ready 90 | _opened: false, // Indicates if the modal was opened (useful for stacking) 91 | _loading: false, // Indicates if the loading is shown 92 | _animated: false, // Indicates if the modal is currently animated 93 | _transition: false, //Indicates if the modal is in transition 94 | _nmOpener: undefined, // nmObj of the modal that opened the current one in non stacking mode 95 | _nbContentLoading: 0, // Counter for contentLoading call 96 | _scripts: '', // Scripts tags to be included 97 | _scriptsShown: '' //Scripts tags to be included once the modal is swhon 98 | } 99 | }; 100 | 101 | CORE.classes.modal.init = function (oOptions){ 102 | 103 | var self = this; 104 | var Cm = CORE.modules; 105 | var Cc = CORE.classes; 106 | var Cg = CORE.globals; 107 | var oSettings = self.oDefault; 108 | var key = ''; 109 | 110 | for ( key in oOptions ) { 111 | if(oOptions.hasOwnProperty(key)) { 112 | oSettings[key] = oOptions[key]; 113 | } 114 | } 115 | 116 | // Load the CSS 117 | if (oSettings.pathCss) { 118 | // Load the nyroModal Css 119 | //console.log (oSettings.pathCss); 120 | $(document.body).append(''); 121 | } 122 | 123 | if (Cg.isIE6) { 124 | 125 | $LAB.script(Cm.nyromodal_ie).wait( function() { 126 | Cc.modal.load(oSettings); 127 | }); 128 | 129 | } 130 | else 131 | { 132 | Cc.modal.bind(oSettings); 133 | } 134 | 135 | }; 136 | 137 | CORE.classes.modal.autobind = function (oTarget){ 138 | 139 | $(oTarget).nyroModal(); 140 | 141 | }; 142 | 143 | CORE.classes.modal.open = function (oOptions){ 144 | 145 | var self = this; 146 | var oSettings = self.oDefault; 147 | 148 | if (oOptions === undefined) 149 | { 150 | var oOptions = {}; 151 | } 152 | 153 | for ( key in oOptions ) { 154 | if(oOptions.hasOwnProperty(key)) { 155 | oSettings[key] = oOptions[key]; 156 | } 157 | } 158 | 159 | 160 | if(oSettings.sUrl !== undefined || oSettings.sUrl !== '#') { 161 | $.nmManual(oSettings.sUrl, oSettings); 162 | } 163 | 164 | }; 165 | 166 | CORE.classes.modal.close = function(){ 167 | $.nmTop().close(); 168 | }; --------------------------------------------------------------------------------