$val) {
if($val[$field] == $value) {
return $val;
}
}
return $default_value;
}
/**
* Search for the key of the first item with value $value for field $field in a 2D array.
* @return The matching key or -1
*/
function multiarray_search_key($field, $value, $array) {
foreach($array as $key=>$val) {
if($val[$field] == $value) {
return $key;
}
}
return -1;
}
/**
* Filters a 2D array returning all the entries where $field is not equal to $value.
* @return The filtered array.
*/
function multiarray_filter($field, $value, $array) {
$return = array();
foreach($array as $key=>$val) {
if($val[$field] != $value) {
$return[] = $val;
}
}
return $return;
}
/**
* Check that $haystack starts with $needle.
*/
function startswith($haystack, $needle) {
$length = strlen($needle);
return (substr($haystack, 0, $length) === $needle);
}
/**
* Check that $haystack ends with $needle.
*/
function endswith($haystack, $needle) {
$length = strlen($needle);
if ($length == 0) {
return true;
}
return (substr($haystack, -$length) === $needle);
}
/**
* Replace only the first occurrence of $needle in $haystack by $replace.
*/
function str_replace_first($needle, $replace, $haystack) {
$pos = strpos($haystack, $needle);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
}
}
/**
* List all available templates.
* @return An array {path, name, current} where path is the template path, name is the template name and current is true if this is the current template, false otherwise.
*/
function list_templates() {
global $config;
$paths = array_filter(scandir(TPL_DIR), function($item) { return is_dir(TPL_DIR.$item) && !startswith($item, '.'); });
$names = array_map('ucfirst', $paths);
$templates = array();
foreach($paths as $key=>$path) {
$path .= '/';
$templates[] = array(
'path'=>$path,
'name'=>$names[$key],
'current'=>$path == $config->template
);
}
return $templates;
}
/**
* Get the total generation time.
* @param $start_generation_time is a milliseconds timestamp
* @return Generation time as a string, with units (seconds or milliseconds)
*/
function get_generation_time($start_generation_time) {
$round = round(microtime(true) - (float)$start_generation_time, 2).'s';
if($round == '0s') {
$round = round((microtime(true) - $start_generation_time)*1000, 3).'ms';
}
return $round;
}
/**
* Returns the global category of a MIME-TYPE
* @param $mime_type, a MIME-TYPE
*/
function get_category_mime_type($mime_type) {
$end = strpos($mime_type, '/');
if ($end === false) {
return false;
}
$category = substr($mime_type, 0, $end);
$available_categories = array('application', 'audio', 'example', 'image', 'message', 'model', 'multipart', 'text', 'video');
$end = in_array($category, $available_categories);
if ($end !== false) {
return $category;
}
else {
return false;
}
}
/**
* Downloads all the urls in the array $urls and returns an array with the results and the http status_codes.
*
* Mostly inspired by blogotext by timovn : https://github.com/timovn/blogotext/blob/master/inc/fich.php
*
* Note: If open_basedir or safe_mode, Curl will not follow redirections :
* https://stackoverflow.com/questions/24687145/curlopt-followlocation-and-curl-multi-and-safe-mode
*
* @param an array $urls of associative arrays {'url', 'post'} for each URL. 'post' is a JSON array of data to send _via_ POST.
* @return an array {'results', 'status_code'}, results being an array of the retrieved contents, indexed by URLs, and 'status_codes' being an array of status_code, indexed by URL.
*/
function curl_downloader($urls, $fetch_content=true, $verbose=true) {
$chunks = array_chunk($urls, 40, true); // Chunks of 40 urls because curl has problems with too big "multi" requests
$results = array();
$status_codes = array();
$content_types = array();
$command_line = is_command_line();
if (ini_get('open_basedir') == '' && ini_get('safe_mode') === false) { // Disable followlocation option if this is activated, to avoid warnings
$follow_redirect = true;
}
else {
$follow_redirect = false;
}
if ($verbose) {
if (function_exists('apache_setenv')) {
/* Selon l'hébergeur la fonction peut être désactivée. Alors Php
arrête le programme avec l'erreur :
"PHP Fatal error: Call to undefined function apache_setenv()".
*/
@apache_setenv('no-gzip', 1);
}
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);
for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
ob_implicit_flush(1);
if ($command_line) {
$backspace = PHP_EOL;
$span_start = '';
$span_end = '';
}
else {
$backspace = '
';
$span_start = '';
$span_end = '';
}
}
foreach ($chunks as $chunk) {
$multihandler = curl_multi_init();
$handlers = array();
$total_feed_chunk = count($chunk) + count($results);
foreach ($chunk as $i=>$url_array) {
set_time_limit(20); // Reset max execution time
$url = $url_array['url'];
$handlers[$i] = curl_init($url);
curl_setopt_array($handlers[$i], array(
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 15,
CURLOPT_FOLLOWLOCATION => $follow_redirect,
CURLOPT_MAXREDIRS => 5,
CURLOPT_USERAGENT => (!empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''), // Add a user agent to prevent problems with some feeds
CURLOPT_HEADER => $fetch_content ? FALSE : TRUE,
CURLOPT_NOBODY => $fetch_content ? FALSE : TRUE,
));
if (!empty($url_array['post'])) {
curl_setopt($handlers[$i], CURLOPT_POST, true);
curl_setopt($handlers[$i], CURLOPT_POSTFIELDS, json_decode($url_array['post'], true));
}
if ($verbose) {
echo str_replace('CLASS', 'class="refreshed-feed-tmp"', $span_start).'Starting to download '.$url.'…'.$backspace.$span_end;
}
curl_multi_add_handle($multihandler, $handlers[$i]);
}
do {
curl_multi_exec($multihandler, $active);
curl_multi_select($multihandler);
} while ($active > 0);
if ($verbose && !$command_line) {
echo '';
}
foreach ($chunk as $i=>$url_array) {
$url = $url_array['url'];
$results[$url] = curl_multi_getcontent($handlers[$i]);
$status_codes[$url] = curl_getinfo($handlers[$i], CURLINFO_HTTP_CODE);
$content_types[$url] = curl_getinfo($handlers[$i], CURLINFO_CONTENT_TYPE);
curl_multi_remove_handle($multihandler, $handlers[$i]);
curl_close($handlers[$i]);
if ($verbose && !$command_line) {
echo str_replace('CLASS', '', $span_start).'Starting to download '.$url.'… Done.'.$backspace.$span_end;
}
}
curl_multi_close($multihandler);
}
return array('results'=>$results, 'status_codes'=>$status_codes, 'content_types'=>$content_types);
}
/**
* Clean the rainTPL cache
* @param (optional) $folder, folder with the rainTPL cache, default to tmp
*/
function clean_cache($folder='tmp/') {
$folder_handler = opendir(ROOT_DIR.$folder);
while ($file = readdir($folder_handler)) {
if ($file == '.' || $file == '..') {
continue;
}
unlink(ROOT_DIR.$folder.'/'.$file);
}
closedir($folder_handler);
}
/**
* Check if the script is run from the command line or not
* @return true if script is run from command line, false otherwise
*/
function is_command_line() {
return 'cli' == php_sapi_name();
}
/**
* Check if url_rewriting is available
* @return 1 if available, 0 otherwise
*/
function get_url_rewriting() {
if (function_exists('apache_get_modules')) {
return (int) in_array('mod_rewrite', apache_get_modules());
}
else {
return getenv('HTTP_MOD_REWRITE')=='On' ? 1 : 0;
}
}
/**
* Check if curl is available
* @return null or an array of disabled functions.
*/
function check_curl_availability() {
$curl_functions = array(
'curl_multi_init', 'curl_init', 'curl_setopt_array',
'curl_setopt', 'curl_multi_add_handle',
'curl_multi_exec', 'curl_multi_select',
'curl_multi_getcontent', 'curl_getinfo',
'curl_multi_remove_handle', 'curl_close',
'curl_multi_close' );
$curl_disabled_functions = array();
foreach($curl_functions as $curl_function)
if (! function_exists ($curl_function))
$curl_disabled_functions[] = $curl_function;
if (count ($curl_disabled_functions) > 0)
return $curl_disabled_functions;
return null;
}
/**
* Check if pdo_sqlite is available
* @return true if available, false otherwise
*/
function is_pdo_sqlite_available() {
return in_array('pdo_sqlite', get_loaded_extensions());
}
/**
* Format date for pretty printing
* @param $timestamp: date in timestamp format.
*/
function format_date($timestamp) {
$now = time();
$diff = $now - $timestamp;
if ($diff < 60) {
return $diff.'s ago';
} else if ($diff < 300) {
return round($diff / 60).'min ago';
} else if ($diff < 3600) {
return (round($diff / 300) * 5).'min ago';
} else if (floor($now/86400) == floor($timestamp/86400)) {
return 'Today, '.date('H:i', $timestamp);
} else if (floor($now/86400) == floor($timestamp/86400) + 1) {
return 'Yesterday, '.date('H:i', $timestamp);
} else if (date('Y:W', $now) == date('Y:W', $timestamp)) {
return date('l, H:i', $timestamp);
} else if (date('Y',$now) == date('Y',$timestamp)) {
return date('F d, H:i', $timestamp);
} else {
return date('F d, Y, H:i', $timestamp);
}
}