@ -1,67 +1,67 @@ | |||
{ | |||
"name": "friendica/friendica", | |||
"description": "A decentralized social network part of The Federation", | |||
"type": "project", | |||
"keywords": [ | |||
"social network", | |||
"dfrn", | |||
"ostatus", | |||
"diaspora" | |||
], | |||
"license": "AGPL-3.0+", | |||
"support": { | |||
"issues": "https://github.com/friendica/friendica/issues" | |||
}, | |||
"require": { | |||
"php": ">5.6", | |||
"ext-xml": "*", | |||
"ezyang/htmlpurifier": "~4.7.0", | |||
"league/html-to-markdown": "~4.4.1", | |||
"lightopenid/lightopenid": "dev-master", | |||
"michelf/php-markdown": "^1.7", | |||
"mobiledetect/mobiledetectlib": "2.8.*", | |||
"paragonie/random_compat": "^2.0", | |||
"pear/Text_LanguageDetect": "1.*", | |||
"pear/Text_Highlighter": "dev-master", | |||
"smarty/smarty": "^3.1", | |||
"fxp/composer-asset-plugin": "~1.3", | |||
"bower-asset/base64": "^1.0", | |||
"bower-asset/Chart-js": "^2.7", | |||
"bower-asset/perfect-scrollbar": "^0.6", | |||
"npm-asset/jquery": "^2.0", | |||
"npm-asset/jquery-colorbox": "^1.6", | |||
"npm-asset/jquery-datetimepicker": "^2.4.0", | |||
"npm-asset/jgrowl": "^1.4", | |||
"npm-asset/fullcalendar": "^3.0.1" | |||
}, | |||
"repositories": [ | |||
{ | |||
"type": "vcs", | |||
"url": "https://github.com/pear/Text_Highlighter" | |||
} | |||
], | |||
"autoload": { | |||
"psr-4": { | |||
"Friendica\\": "src/" | |||
}, | |||
"psr-0": { | |||
"": "library/" | |||
} | |||
}, | |||
"config": { | |||
"autoloader-suffix": "Friendica", | |||
"optimize-autoloader": true, | |||
"preferred-install": "dist", | |||
"fxp-asset": { | |||
"installer-paths": { | |||
"npm-asset-library": "vendor/asset", | |||
"bower-asset-library": "vendor/asset" | |||
} | |||
} | |||
}, | |||
"archive": { | |||
"exclude": [ | |||
"log", "cache", "/photo", "/proxy" | |||
] | |||
} | |||
} | |||
{ | |||
"name": "friendica/friendica", | |||
"description": "A decentralized social network part of The Federation", | |||
"type": "project", | |||
"keywords": [ | |||
"social network", | |||
"dfrn", | |||
"ostatus", | |||
"diaspora" | |||
], | |||
"license": "AGPL-3.0+", | |||
"support": { | |||
"issues": "https://github.com/friendica/friendica/issues" | |||
}, | |||
"require": { | |||
"php": ">5.6", | |||
"ext-xml": "*", | |||
"ezyang/htmlpurifier": "~4.7.0", | |||
"league/html-to-markdown": "~4.4.1", | |||
"lightopenid/lightopenid": "dev-master", | |||
"michelf/php-markdown": "^1.7", | |||
"mobiledetect/mobiledetectlib": "2.8.*", | |||
"paragonie/random_compat": "^2.0", | |||
"pear/Text_LanguageDetect": "1.*", | |||
"pear/Text_Highlighter": "dev-master", | |||
"smarty/smarty": "^3.1", | |||
"fxp/composer-asset-plugin": "~1.3", | |||
"bower-asset/base64": "^1.0", | |||
"bower-asset/Chart-js": "^2.7", | |||
"bower-asset/perfect-scrollbar": "^0.6", | |||
"npm-asset/jquery": "^2.0", | |||
"npm-asset/jquery-colorbox": "^1.6", | |||
"npm-asset/jquery-datetimepicker": "^2.4.0", | |||
"npm-asset/jgrowl": "^1.4", | |||
"npm-asset/fullcalendar": "^3.0.1" | |||
}, | |||
"repositories": [ | |||
{ | |||
"type": "vcs", | |||
"url": "https://github.com/pear/Text_Highlighter" | |||
} | |||
], | |||
"autoload": { | |||
"psr-4": { | |||
"Friendica\\": "src/" | |||
}, | |||
"psr-0": { | |||
"": "library/" | |||
} | |||
}, | |||
"config": { | |||
"autoloader-suffix": "Friendica", | |||
"optimize-autoloader": true, | |||
"preferred-install": "dist", | |||
"fxp-asset": { | |||
"installer-paths": { | |||
"npm-asset-library": "vendor/asset", | |||
"bower-asset-library": "vendor/asset" | |||
} | |||
} | |||
}, | |||
"archive": { | |||
"exclude": [ | |||
"log", "cache", "/photo", "/proxy" | |||
] | |||
} | |||
} |
@ -1,60 +1,60 @@ | |||
<?php | |||
namespace Friendica; | |||
/** | |||
* All modules in Friendica should extend BaseModule, although not all modules | |||
* need to extend all the methods described here | |||
* | |||
* @author Hypolite Petovan mrpetovan@gmail.com | |||
*/ | |||
abstract class BaseModule extends BaseObject | |||
{ | |||
/** | |||
* @brief Initialization method common to both content() and post() | |||
* | |||
* Extend this method if you need to do any shared processing before both | |||
* content() or post() | |||
*/ | |||
public static function init() | |||
{ | |||
} | |||
/** | |||
* @brief Module GET method to display any content | |||
* | |||
* Extend this method if the module is supposed to return any display | |||
* through a GET request. It can be an HTML page through templating or a | |||
* XML feed or a JSON output. | |||
* | |||
* @return string | |||
*/ | |||
public static function content() | |||
{ | |||
$o = ''; | |||
return $o; | |||
} | |||
/** | |||
* @brief Module POST method to process submitted data | |||
* | |||
* Extend this method if the module is supposed to process POST requests. | |||
* Doesn't display any content | |||
*/ | |||
public static function post() | |||
{ | |||
// goaway('module'); | |||
} | |||
/** | |||
* @brief Called after post() | |||
* | |||
* Unknown purpose | |||
*/ | |||
public static function afterpost() | |||
{ | |||
} | |||
} | |||
<?php | |||
namespace Friendica; | |||
/** | |||
* All modules in Friendica should extend BaseModule, although not all modules | |||
* need to extend all the methods described here | |||
* | |||
* @author Hypolite Petovan mrpetovan@gmail.com | |||
*/ | |||
abstract class BaseModule extends BaseObject | |||
{ | |||
/** | |||
* @brief Initialization method common to both content() and post() | |||
* | |||
* Extend this method if you need to do any shared processing before both | |||
* content() or post() | |||
*/ | |||
public static function init() | |||
{ | |||
} | |||
/** | |||
* @brief Module GET method to display any content | |||
* | |||
* Extend this method if the module is supposed to return any display | |||
* through a GET request. It can be an HTML page through templating or a | |||
* XML feed or a JSON output. | |||
* | |||
* @return string | |||
*/ | |||
public static function content() | |||
{ | |||
$o = ''; | |||
return $o; | |||
} | |||
/** | |||
* @brief Module POST method to process submitted data | |||
* | |||
* Extend this method if the module is supposed to process POST requests. | |||
* Doesn't display any content | |||
*/ | |||
public static function post() | |||
{ | |||
// goaway('module'); | |||
} | |||
/** | |||
* @brief Called after post() | |||
* | |||
* Unknown purpose | |||
*/ | |||
public static function afterpost() | |||
{ | |||
} | |||
} |
@ -1,39 +1,39 @@ | |||
<?php | |||
/** | |||
* @file src/Content/Text/Markdown.php | |||
*/ | |||
namespace Friendica\Content\Text; | |||
use Friendica\BaseObject; | |||
use Michelf\MarkdownExtra; | |||
/** | |||
* Friendica-specific usage of Markdown | |||
* | |||
* @author Hypolite Petovan <mrpetovan@gmail.com> | |||
*/ | |||
class Markdown extends BaseObject | |||
{ | |||
/** | |||
* Converts a Markdown string into HTML. The hardwrap parameter maximizes | |||
* compatibility with Diaspora in spite of the Markdown standard. | |||
* | |||
* @brief Converts a Markdown string into HTML | |||
* @param string $text | |||
* @param bool $hardwrap | |||
* @return string | |||
*/ | |||
public static function convert($text, $hardwrap = true) { | |||
$stamp1 = microtime(true); | |||
$MarkdownParser = new MarkdownExtra(); | |||
$MarkdownParser->hard_wrap = $hardwrap; | |||
$html = $MarkdownParser->transform($text); | |||
self::getApp()->save_timestamp($stamp1, "parser"); | |||
return $html; | |||
} | |||
} | |||
<?php | |||
/** | |||
* @file src/Content/Text/Markdown.php | |||
*/ | |||
namespace Friendica\Content\Text; | |||
use Friendica\BaseObject; | |||
use Michelf\MarkdownExtra; | |||
/** | |||
* Friendica-specific usage of Markdown | |||
* | |||
* @author Hypolite Petovan <mrpetovan@gmail.com> | |||
*/ | |||
class Markdown extends BaseObject | |||
{ | |||
/** | |||
* Converts a Markdown string into HTML. The hardwrap parameter maximizes | |||
* compatibility with Diaspora in spite of the Markdown standard. | |||
* | |||
* @brief Converts a Markdown string into HTML | |||
* @param string $text | |||
* @param bool $hardwrap | |||
* @return string | |||
*/ | |||
public static function convert($text, $hardwrap = true) { | |||
$stamp1 = microtime(true); | |||
$MarkdownParser = new MarkdownExtra(); | |||
$MarkdownParser->hard_wrap = $hardwrap; | |||
$html = $MarkdownParser->transform($text); | |||
self::getApp()->save_timestamp($stamp1, "parser"); | |||
return $html; | |||
} | |||
} |
@ -1,162 +1,162 @@ | |||
<?php | |||
/* | |||
* @file src/Content/Widget/TagCloud.php | |||
*/ | |||
namespace Friendica\Content\Widget; | |||
use dba; | |||
use Friendica\Core\L10n; | |||
use Friendica\Core\System; | |||
use Friendica\Database\DBM; | |||
require_once 'include/dba.php'; | |||
require_once 'include/security.php'; | |||
/** | |||
* TagCloud widget | |||
* | |||
* @author Rabuzarus | |||
*/ | |||
class TagCloud | |||
{ | |||
/** | |||
* Construct a tag/term cloud block for an user. | |||
* | |||
* @brief Construct a tag/term cloud block for an user. | |||
* @param int $uid The user ID. | |||
* @param int $count Max number of displayed tags/terms. | |||
* @param int $owner_id The contact ID of the owner of the tagged items. | |||
* @param string $flags Special item flags. | |||
* @param int $type The tag/term type. | |||
* | |||
* @return string HTML formatted output. | |||
*/ | |||
public static function getHTML($uid, $count = 0, $owner_id = 0, $flags = '', $type = TERM_HASHTAG) | |||
{ | |||
$o = ''; | |||
$r = self::tagadelic($uid, $count, $owner_id, $flags, $type); | |||
if (count($r)) { | |||
$contact = dba::selectFirst('contact', ['url'], ['uid' => $uid, 'self' => true]); | |||
$url = System::removedBaseUrl($contact['url']); | |||
foreach ($r as $rr) { | |||
$tag['level'] = $rr[2]; | |||
$tag['url'] = $url . '?tag=' . urlencode($rr[0]); | |||
$tag['name'] = $rr[0]; | |||
$tags[] = $tag; | |||
} | |||
$tpl = get_markup_template('tagblock_widget.tpl'); | |||
$o = replace_macros($tpl, [ | |||
'$title' => L10n::t('Tags'), | |||
'$tags' => $tags | |||
]); | |||
} | |||
return $o; | |||
} | |||
/** | |||
* Get alphabetical sorted array of used tags/terms of an user including | |||
* a weighting by frequency of use. | |||
* | |||
* @brief Get alphabetical sorted array of used tags/terms of an user including | |||
* a weighting by frequency of use. | |||
* @param int $uid The user ID. | |||
* @param int $count Max number of displayed tags/terms. | |||
* @param int $owner_id The contact id of the owner of the tagged items. | |||
* @param string $flags Special item flags. | |||
* @param int $type The tag/term type. | |||
* | |||
* @return arr Alphabetical sorted array of used tags of an user. | |||
*/ | |||
private static function tagadelic($uid, $count = 0, $owner_id = 0, $flags = '', $type = TERM_HASHTAG) | |||
{ | |||
$item_condition = item_condition(); | |||
$sql_options = item_permissions_sql($uid); | |||
$limit = $count ? sprintf('LIMIT %d', intval($count)) : ''; | |||
if ($flags) { | |||
if ($flags === 'wall') { | |||
$sql_options .= ' AND `item`.`wall` '; | |||
} | |||
} | |||
if ($owner_id) { | |||
$sql_options .= ' AND `item`.`owner-id` = ' . intval($owner_id) . ' '; | |||
} | |||
// Fetch tags | |||
$r = dba::p("SELECT `term`, COUNT(`term`) AS `total` FROM `term` | |||
LEFT JOIN `item` ON `term`.`oid` = `item`.`id` | |||
WHERE `term`.`uid` = ? AND `term`.`type` = ? | |||
AND `term`.`otype` = ? | |||
AND $item_condition $sql_options | |||
GROUP BY `term` ORDER BY `total` DESC $limit", | |||
$uid, | |||
$type, | |||
TERM_OBJ_POST | |||
); | |||
if (!DBM::is_result($r)) { | |||
return []; | |||
} | |||
return self::tagCalc($r); | |||
} | |||
/** | |||
* Calculate weighting of tags according to the frequency of use. | |||
* | |||
* @brief Calculate weighting of tags according to the frequency of use. | |||
* @param array $arr Array of tags/terms with tag/term name and total count of use. | |||
* @return array Alphabetical sorted array of used tags/terms of an user. | |||
*/ | |||
private static function tagCalc($arr) | |||
{ | |||
$tags = []; | |||
$min = 1e9; | |||
$max = -1e9; | |||
$x = 0; | |||
if (!$arr) { | |||
return []; | |||
} | |||
foreach ($arr as $rr) { | |||
$tags[$x][0] = $rr['term']; | |||
$tags[$x][1] = log($rr['total']); | |||
$tags[$x][2] = 0; | |||
$min = min($min, $tags[$x][1]); | |||
$max = max($max, $tags[$x][1]); | |||
$x ++; | |||
} | |||
usort($tags, 'self::tagsSort'); | |||
$range = max(.01, $max - $min) * 1.0001; | |||
for ($x = 0; $x < count($tags); $x ++) { | |||
$tags[$x][2] = 1 + floor(9 * ($tags[$x][1] - $min) / $range); | |||
} | |||
return $tags; | |||
} | |||
/** | |||
* Compare function to sort tags/terms alphabetically. | |||
* | |||
* @brief Compare function to sort tags/terms alphabetically. | |||
* @param type $a | |||
* @param type $b | |||
* | |||
* @return int | |||
*/ | |||
private static function tagsSort($a, $b) | |||
{ | |||
if (strtolower($a[0]) == strtolower($b[0])) { | |||
return 0; | |||
} | |||
return ((strtolower($a[0]) < strtolower($b[0])) ? -1 : 1); | |||
} | |||
} | |||
<?php | |||
/* | |||
* @file src/Content/Widget/TagCloud.php | |||
*/ | |||
namespace Friendica\Content\Widget; | |||
use dba; | |||
use Friendica\Core\L10n; | |||
use Friendica\Core\System; | |||
use Friendica\Database\DBM; | |||
require_once 'include/dba.php'; | |||
require_once 'include/security.php'; | |||
/** | |||
* TagCloud widget | |||
* | |||
* @author Rabuzarus | |||
*/ | |||
class TagCloud | |||
{ | |||
/** | |||
* Construct a tag/term cloud block for an user. | |||
* | |||
* @brief Construct a tag/term cloud block for an user. | |||
* @param int $uid The user ID. | |||
* @param int $count Max number of displayed tags/terms. | |||
* @param int $owner_id The contact ID of the owner of the tagged items. | |||
* @param string $flags Special item flags. | |||
* @param int $type The tag/term type. | |||
* | |||
* @return string HTML formatted output. | |||
*/ | |||
public static function getHTML($uid, $count = 0, $owner_id = 0, $flags = '', $type = TERM_HASHTAG) | |||
{ | |||
$o = ''; | |||
$r = self::tagadelic($uid, $count, $owner_id, $flags, $type); | |||
if (count($r)) { | |||
$contact = dba::selectFirst('contact', ['url'], ['uid' => $uid, 'self' => true]); | |||
$url = System::removedBaseUrl($contact['url']); | |||
foreach ($r as $rr) { | |||
$tag['level'] = $rr[2]; | |||
$tag['url'] = $url . '?tag=' . urlencode($rr[0]); | |||
$tag['name'] = $rr[0]; | |||
$tags[] = $tag; | |||
} | |||
$tpl = get_markup_template('tagblock_widget.tpl'); | |||
$o = replace_macros($tpl, [ | |||
'$title' => L10n::t('Tags'), | |||
'$tags' => $tags | |||
]); | |||
} | |||
return $o; | |||
} | |||
/** | |||
* Get alphabetical sorted array of used tags/terms of an user including | |||
* a weighting by frequency of use. | |||
* | |||
* @brief Get alphabetical sorted array of used tags/terms of an user including | |||
* a weighting by frequency of use. | |||
* @param int $uid The user ID. | |||
* @param int $count Max number of displayed tags/terms. | |||
* @param int $owner_id The contact id of the owner of the tagged items. | |||
* @param string $flags Special item flags. | |||
* @param int $type The tag/term type. | |||
* | |||
* @return arr Alphabetical sorted array of used tags of an user. | |||
*/ | |||
private static function tagadelic($uid, $count = 0, $owner_id = 0, $flags = '', $type = TERM_HASHTAG) | |||
{ | |||
$item_condition = item_condition(); | |||
$sql_options = item_permissions_sql($uid); | |||
$limit = $count ? sprintf('LIMIT %d', intval($count)) : ''; | |||
if ($flags) { | |||
if ($flags === 'wall') { | |||
$sql_options .= ' AND `item`.`wall` '; | |||
} | |||
} | |||
if ($owner_id) { | |||
$sql_options .= ' AND `item`.`owner-id` = ' . intval($owner_id) . ' '; | |||
} | |||
// Fetch tags | |||
$r = dba::p("SELECT `term`, COUNT(`term`) AS `total` FROM `term` | |||
LEFT JOIN `item` ON `term`.`oid` = `item`.`id` | |||
WHERE `term`.`uid` = ? AND `term`.`type` = ? | |||
AND `term`.`otype` = ? | |||
AND $item_condition $sql_options | |||
GROUP BY `term` ORDER BY `total` DESC $limit", | |||
$uid, | |||
$type, | |||
TERM_OBJ_POST | |||
); | |||
if (!DBM::is_result($r)) { | |||
return []; | |||
} | |||
return self::tagCalc($r); | |||
} | |||
/** | |||
* Calculate weighting of tags according to the frequency of use. | |||
* | |||
* @brief Calculate weighting of tags according to the frequency of use. | |||
* @param array $arr Array of tags/terms with tag/term name and total count of use. | |||
* @return array Alphabetical sorted array of used tags/terms of an user. | |||
*/ | |||
private static function tagCalc($arr) | |||
{ | |||
$tags = []; | |||
$min = 1e9; | |||
$max = -1e9; | |||
$x = 0; | |||
if (!$arr) { | |||
return []; | |||
} | |||
foreach ($arr as $rr) { | |||
$tags[$x][0] = $rr['term']; | |||
$tags[$x][1] = log($rr['total']); | |||
$tags[$x][2] = 0; | |||
$min = min($min, $tags[$x][1]); | |||
$max = max($max, $tags[$x][1]); | |||
$x ++; | |||
} | |||
usort($tags, 'self::tagsSort'); | |||
$range = max(.01, $max - $min) * 1.0001; | |||
for ($x = 0; $x < count($tags); $x ++) { | |||
$tags[$x][2] = 1 + floor(9 * ($tags[$x][1] - $min) / $range); | |||
} | |||
return $tags; | |||
} | |||
/** | |||
* Compare function to sort tags/terms alphabetically. | |||
* | |||
* @brief Compare function to sort tags/terms alphabetically. | |||
* @param type $a | |||
* @param type $b | |||
* | |||
* @return int | |||
*/ | |||
private static function tagsSort($a, $b) | |||
{ | |||
if (strtolower($a[0]) == strtolower($b[0])) { | |||
return 0; | |||
} | |||
return ((strtolower($a[0]) < strtolower($b[0])) ? -1 : 1); | |||
} | |||
} |
@ -1,57 +1,57 @@ | |||
<?php | |||
/** | |||
* @file src/Core/Session.php | |||
*/ | |||
namespace Friendica\Core; | |||
use Friendica\Core\Session\DatabaseSessionHandler; | |||
use Friendica\Core\Session\MemcacheSessionHandler; | |||
/** | |||
* High-level Session service class | |||
* | |||
* @author Hypolite Petovan <mrpetovan@gmail.com> | |||
*/ | |||
class Session | |||
{ | |||
public static $exists = false; | |||
public static $expire = 180000; | |||
public static function init() | |||
{ | |||
ini_set('session.gc_probability', 50); | |||
ini_set('session.use_only_cookies', 1); | |||
ini_set('session.cookie_httponly', 1); | |||
if (Config::get('system', 'ssl_policy') == SSL_POLICY_FULL) { | |||
ini_set('session.cookie_secure', 1); | |||
} | |||
if (!Config::get('system', 'disable_database_session')) { | |||
$memcache = Cache::memcache(); | |||
if (is_object($memcache)) { | |||
$SessionHandler = new MemcacheSessionHandler($memcache); | |||
} else { | |||
$SessionHandler = new DatabaseSessionHandler(); | |||
} | |||
session_set_save_handler($SessionHandler); | |||
} | |||
} | |||
public static function exists($name) | |||
{ | |||
return isset($_SESSION[$name]); | |||
} | |||
public static function get($name) | |||
{ | |||
return defaults($_SESSION, $name, null); | |||
} | |||
public static function set($name, $value) | |||
{ | |||
$_SESSION[$name] = $value; | |||
} | |||
} | |||
<?php | |||
/** | |||
* @file src/Core/Session.php | |||
*/ | |||
namespace Friendica\Core; | |||
use Friendica\Core\Session\DatabaseSessionHandler; | |||
use Friendica\Core\Session\MemcacheSessionHandler; | |||
/** | |||
* High-level Session service class | |||
* | |||
* @author Hypolite Petovan <mrpetovan@gmail.com> | |||
*/ | |||
class Session | |||
{ | |||
public static $exists = false; | |||
public static $expire = 180000; | |||
public static function init() | |||
{ | |||
ini_set('session.gc_probability', 50); | |||
ini_set('session.use_only_cookies', 1); | |||
ini_set('session.cookie_httponly', 1); | |||
if (Config::get('system', 'ssl_policy') == SSL_POLICY_FULL) { | |||
ini_set('session.cookie_secure', 1); | |||
} | |||
if (!Config::get('system', 'disable_database_session')) { | |||
$memcache = Cache::memcache(); | |||
if (is_object($memcache)) { | |||
$SessionHandler = new MemcacheSessionHandler($memcache); | |||
} else { | |||
$SessionHandler = new DatabaseSessionHandler(); | |||
} | |||
session_set_save_handler($SessionHandler); | |||
} | |||
} | |||
public static function exists($name) | |||
{ | |||
return isset($_SESSION[$name]); | |||
} | |||
public static function get($name) | |||
{ | |||
return defaults($_SESSION, $name, null); | |||
} | |||
public static function set($name, $value) | |||
{ | |||
$_SESSION[$name] = $value; | |||
} | |||
} |
@ -1,95 +1,95 @@ | |||
<?php | |||
namespace Friendica\Core\Session; | |||
use Friendica\BaseObject; | |||
use Friendica\Core\Session; | |||
use Friendica\Database\DBM; | |||
use SessionHandlerInterface; | |||
use dba; | |||
require_once 'boot.php'; | |||
require_once 'include/dba.php'; | |||
require_once 'include/text.php'; | |||
/** | |||
* SessionHandler using database | |||
* | |||
* @author Hypolite Petovan <mrpetovan@gmail.com> | |||
*/ | |||
class DatabaseSessionHandler extends BaseObject implements SessionHandlerInterface | |||
{ | |||
public function open($save_path, $session_name) | |||
{ | |||
return true; | |||
} | |||
public function read($session_id) | |||
{ | |||
if (!x($session_id)) { | |||
return ''; | |||
} | |||
$session = dba::selectFirst('session', ['data'], ['sid' => $session_id]); | |||
if (DBM::is_result($session)) { | |||
Session::$exists = true; | |||
return $session['data']; | |||
} | |||
logger("no data for session $session_id", LOGGER_TRACE); | |||
return ''; | |||
} | |||
/** | |||
* @brief Standard PHP session write callback | |||
* | |||
* This callback updates the DB-stored session data and/or the expiration depending | |||
* on the case. Uses the Session::expire global for existing session, 5 minutes | |||
* for newly created session. | |||
* | |||
* @param string $session_id Session ID with format: [a-z0-9]{26} | |||
* @param string $session_data Serialized session data | |||
* @return boolean Returns false if parameters are missing, true otherwise | |||
*/ | |||
public function write($session_id, $session_data) | |||
{ | |||
if (!$session_id) { | |||
return false; | |||
} | |||
if (!$session_data) { | |||
return true; | |||
} | |||
$expire = time() + Session::$expire; | |||
$default_expire = time() + 300; | |||
if (Session::$exists) { | |||
$fields = ['data' => $session_data, 'expire' => $expire]; | |||
$condition = ["`sid` = ? AND (`data` != ? OR `expire` != ?)", $session_id, $session_data, $expire]; | |||
dba::update('session', $fields, $condition); | |||
} else { | |||
$fields = ['sid' => $session_id, 'expire' => $default_expire, 'data' => $session_data]; | |||
dba::insert('session', $fields); | |||
} | |||
return true; | |||
} | |||
public function close() | |||
{ | |||
return true; | |||
} | |||
public function destroy($id) | |||
{ | |||
dba::delete('session', ['sid' => $id]); | |||
return true; | |||
} | |||
public function gc($maxlifetime) | |||
{ | |||
dba::delete('session', ["`expire` < ?", time()]); | |||
return true; | |||
} | |||
} | |||
<?php | |||
namespace Friendica\Core\Session; | |||
use Friendica\BaseObject; | |||
use Friendica\Core\Session; | |||
use Friendica\Database\DBM; | |||
use SessionHandlerInterface; | |||
use dba; | |||
require_once 'boot.php'; | |||
require_once 'include/dba.php'; | |||
require_once 'include/text.php'; | |||
/** | |||
* SessionHandler using database | |||
* | |||
* @author Hypolite Petovan <mrpetovan@gmail.com> | |||
*/ | |||
class DatabaseSessionHandler extends BaseObject implements SessionHandlerInterface | |||
{ | |||
public function open($save_path, $session_name) | |||
{ | |||
return true; | |||
} | |||
public function read($session_id) | |||
{ | |||
if (!x($session_id)) { | |||
return ''; | |||
} | |||
$session = dba::selectFirst('session', ['data'], ['sid' => $session_id]); | |||
if (DBM::is_result($session)) { | |||
Session::$exists = true; | |||
return $session['data']; | |||
} | |||
logger("no data for session $session_id", LOGGER_TRACE); | |||
return ''; | |||
} | |||
/** | |||
* @brief Standard PHP session write callback | |||
* | |||
* This callback updates the DB-stored session data and/or the expiration depending | |||
* on the case. Uses the Session::expire global for existing session, 5 minutes | |||
* for newly created session. | |||
* | |||
* @param string $session_id Session ID with format: [a-z0-9]{26} | |||
* @param string $session_data Serialized session data | |||
* @return boolean Returns false if parameters are missing, true otherwise | |||
*/ | |||
public function write($session_id, $session_data) | |||
{ | |||
if (!$session_id) { | |||
return false; | |||
} | |||
if (!$session_data) { | |||
return true; | |||
} | |||
$expire = time() + Session::$expire; | |||
$default_expire = time() + 300; | |||
if (Session::$exists) { | |||
$fields = ['data' => $session_data, 'expire' => $expire]; | |||
$condition = ["`sid` = ? AND (`data` != ? OR `expire` != ?)", $session_id, $session_data, $expire]; | |||
dba::update('session', $fields, $condition); | |||
} else { | |||
$fields = ['sid' => $session_id, 'expire' => $default_expire, 'data' => $session_data]; | |||
dba::insert('session', $fields); | |||
} | |||
return true; | |||
} | |||
public function close() | |||
{ | |||
return true; | |||
} | |||
public function destroy($id) | |||
{ | |||
dba::delete('session', ['sid' => $id]); | |||
return true; | |||
} | |||
public function gc($maxlifetime) | |||
{ | |||
dba::delete('session', ["`expire` < ?", time()]); | |||
return true; | |||
} | |||
} |
@ -1,102 +1,102 @@ | |||
<?php | |||
namespace Friendica\Core\Session; | |||
use Friendica\BaseObject; | |||
use Friendica\Core\Session; | |||
use SessionHandlerInterface; | |||
use Memcache; | |||
require_once 'boot.php'; | |||
require_once 'include/text.php'; | |||
/** | |||
* SessionHandler using Memcache | |||
* | |||
* @author Hypolite Petovan <mrpetovan@gmail.com> | |||
*/ | |||
class MemcacheSessionHandler extends BaseObject implements SessionHandlerInterface | |||
{ | |||
/** | |||
* @var Memcache | |||
*/ | |||
private $memcache = null; | |||
/** | |||
* | |||
* @param Memcache $memcache | |||
*/ | |||
public function __construct(Memcache $memcache) | |||
{ | |||
$this->memcache = $memcache; | |||
} | |||
public function open($save_path, $session_name) | |||
{ | |||
return true; | |||
} | |||
public function read($session_id) | |||
{ | |||
if (!x($session_id)) { | |||
return ''; | |||
} | |||
$data = $this->memcache->get(self::getApp()->get_hostname() . ":session:" . $session_id); | |||
if (!is_bool($data)) { | |||
Session::$exists = true; | |||
return $data; | |||
} | |||
logger("no data for session $session_id", LOGGER_TRACE); | |||
return ''; | |||
} | |||
/** | |||
* @brief Standard PHP session write callback | |||
* | |||
* This callback updates the stored session data and/or the expiration depending | |||
* on the case. Uses the Session::expire for existing session, 5 minutes | |||
* for newly created session. | |||
* | |||
* @param string $session_id Session ID with format: [a-z0-9]{26} | |||
* @param string $session_data Serialized session data | |||
* @return boolean Returns false if parameters are missing, true otherwise | |||
*/ | |||
public function write($session_id, $session_data) | |||
{ | |||
if (!$session_id) { | |||
return false; | |||
} | |||
if (!$session_data) { | |||
return true; | |||
} | |||
$expire = time() + Session::$expire; | |||
$this->memcache->set( | |||
self::getApp()->get_hostname() . ":session:" . $session_id, | |||
$session_data, | |||
MEMCACHE_COMPRESSED, | |||
$expire | |||
); | |||
return true; | |||
} | |||
public function close() | |||
{ | |||
return true; | |||
} | |||
public function destroy($id) | |||
{ | |||
$this->memcache->delete(self::getApp()->get_hostname() . ":session:" . $id); | |||
return true; | |||
} | |||
public function gc($maxlifetime) | |||
{ | |||
return true; | |||
} | |||
} | |||
<?php | |||
namespace Friendica\Core\Session; | |||
use Friendica\BaseObject; | |||
use Friendica\Core\Session; | |||
use SessionHandlerInterface; | |||
use Memcache; | |||
require_once 'boot.php'; | |||
require_once 'include/text.php'; | |||
/** | |||
* SessionHandler using Memcache | |||
* | |||
* @author Hypolite Petovan <mrpetovan@gmail.com> | |||
*/ | |||
class MemcacheSessionHandler extends BaseObject implements SessionHandlerInterface | |||
{ | |||
/** | |||
* @var Memcache | |||
*/ | |||
private $memcache = null; | |||
/** | |||
* | |||
* @param Memcache $memcache | |||
*/ | |||
public function __construct(Memcache $memcache) | |||
{ | |||
$this->memcache = $memcache; | |||
} | |||
public function open($save_path, $session_name) | |||
{ | |||
return true; | |||
} | |||
public function read($session_id) | |||
{ | |||
if (!x($session_id)) { | |||
return ''; | |||
} | |||
$data = $this->memcache->get(self::getApp()->get_hostname() . ":session:" . $session_id); | |||
if (!is_bool($data)) { | |||
Session::$exists = true; | |||
return $data; | |||
} | |||
logger("no data for session $session_id", LOGGER_TRACE); | |||
return ''; | |||
} | |||
/** | |||
* @brief Standard PHP session write callback | |||
* | |||
* This callback updates the stored session data and/or the expiration depending | |||
* on the case. Uses the Session::expire for existing session, 5 minutes | |||
* for newly created session. | |||
* | |||
* @param string $session_id Session ID with format: [a-z0-9]{26} | |||
* @param string $session_data Serialized session data | |||
* @return boolean Returns false if parameters are missing, true otherwise | |||
*/ | |||
public function write($session_id, $session_data) | |||
{ | |||
if (!$session_id) { | |||
return false; | |||
} | |||
if (!$session_data) { | |||
return true; | |||
} | |||
$expire = time() + Session::$expire; | |||
$this->memcache->set( | |||
self::getApp()->get_hostname() . ":session:" . $session_id, | |||
$session_data, | |||
MEMCACHE_COMPRESSED, | |||
$expire | |||
); | |||
return true; | |||
} | |||
public function close() | |||
{ | |||
return true; | |||
} | |||
public function destroy($id) | |||
{ | |||
$this->memcache->delete(self::getApp()->get_hostname() . ":session:" . $id); | |||
return true; | |||
} | |||
public function gc($maxlifetime) | |||
{ | |||
return true; | |||
} | |||
} |
@ -1,189 +1,189 @@ | |||
<?php | |||
/** | |||
* @file src/Core/Theme.php | |||
*/ | |||
namespace Friendica\Core; | |||
use Friendica\Core\System; | |||
require_once 'boot.php'; | |||
/** | |||
* Some functions to handle themes | |||
*/ | |||
class Theme | |||
{ | |||
/** | |||
* @brief Parse theme comment in search of theme infos. | |||
* | |||
* like | |||
* \code | |||
* ..* Name: My Theme | |||
* * Description: My Cool Theme | |||
* . * Version: 1.2.3 | |||
* * Author: John <profile url> | |||
* * Maintainer: Jane <profile url> | |||
* * | |||
* \endcode | |||
* @param string $theme the name of the theme | |||
* @return array | |||
*/ | |||
public static function getInfo($theme) | |||
{ | |||
$info=[ | |||
'name' => $theme, | |||
'description' => "", | |||
'author' => [], | |||
'maintainer' => [], | |||
'version' => "", | |||
'credits' => "", | |||
'experimental' => false, | |||
'unsupported' => false | |||
]; | |||
if (file_exists("view/theme/$theme/experimental")) | |||
$info['experimental'] = true; | |||
if (file_exists("view/theme/$theme/unsupported")) | |||
$info['unsupported'] = true; | |||
if (!is_file("view/theme/$theme/theme.php")) return $info; | |||
$a = get_app(); | |||
$stamp1 = microtime(true); | |||
$f = file_get_contents("view/theme/$theme/theme.php"); | |||
$a->save_timestamp($stamp1, "file"); | |||
$r = preg_match("|/\*.*\*/|msU", $f, $m); | |||
if ($r) { | |||
$ll = explode("\n", $m[0]); | |||
foreach ( $ll as $l ) { | |||
$l = trim($l,"\t\n\r */"); | |||
if ($l != "") { | |||
list($k, $v) = array_map("trim", explode(":", $l, 2)); | |||
$k= strtolower($k); | |||
if ($k == "author") { | |||
$r=preg_match("|([^<]+)<([^>]+)>|", $v, $m); | |||
if ($r) { | |||
$info['author'][] = ['name'=>$m[1], 'link'=>$m[2]]; | |||
} else { | |||
$info['author'][] = ['name'=>$v]; | |||
} | |||
} elseif ($k == "maintainer") { | |||
$r=preg_match("|([^<]+)<([^>]+)>|", $v, $m); | |||
if ($r) { | |||
$info['maintainer'][] = ['name'=>$m[1], 'link'=>$m[2]]; | |||
} else { | |||
$info['maintainer'][] = ['name'=>$v]; | |||
} | |||
} else { | |||
if (array_key_exists($k, $info)) { | |||
$info[$k] = $v; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
return $info; | |||
} | |||
/** | |||
* @brief Returns the theme's screenshot. | |||
* | |||
* The screenshot is expected as view/theme/$theme/screenshot.[png|jpg]. | |||
* | |||
* @param sring $theme The name of the theme | |||
* @return string | |||
*/ | |||
public static function getScreenshot($theme) | |||
{ | |||
$exts = ['.png','.jpg']; | |||
foreach ($exts as $ext) { | |||
if (file_exists('view/theme/' . $theme . '/screenshot' . $ext)) { | |||
return(System::baseUrl() . '/view/theme/' . $theme . '/screenshot' . $ext); | |||
} | |||
} | |||
return(System::baseUrl() . '/images/blank.png'); | |||
} | |||
// install and uninstall theme | |||
public static function uninstall($theme) | |||
{ | |||
logger("Addons: uninstalling theme " . $theme); | |||
include_once("view/theme/$theme/theme.php"); | |||
if (function_exists("{$theme}_uninstall")) { | |||
$func = "{$theme}_uninstall"; | |||
$func(); | |||
} | |||
} | |||
public static function install($theme) | |||
{ | |||
// silently fail if theme was removed | |||
if (! file_exists("view/theme/$theme/theme.php")) { | |||
return false; | |||
} | |||
logger("Addons: installing theme $theme"); | |||
include_once("view/theme/$theme/theme.php"); | |||
if (function_exists("{$theme}_install")) { | |||
$func = "{$theme}_install"; | |||
$func(); | |||
return true; | |||
} else { | |||
logger("Addons: FAILED installing theme $theme"); | |||
return false; | |||
} | |||
} | |||
/** | |||
* @brief Get the full path to relevant theme files by filename | |||
* | |||
* This function search in the theme directory (and if not present in global theme directory) | |||
* if there is a directory with the file extension and for a file with the given | |||
* filename. | |||
* | |||
* @param string $file Filename | |||
* @param string $root Full root path | |||
* @return string Path to the file or empty string if the file isn't found | |||
*/ | |||
public static function getPathForFile($file, $root = '') | |||
{ | |||
$file = basename($file); | |||
// Make sure $root ends with a slash / if it's not blank | |||
if ($root !== '' && $root[strlen($root)-1] !== '/') { | |||
$root = $root . '/'; | |||
} | |||
$theme_info = get_app()->theme_info; | |||
if (is_array($theme_info) && array_key_exists('extends',$theme_info)) { | |||
$parent = $theme_info['extends']; | |||
} else { | |||
$parent = 'NOPATH'; | |||
} | |||
$theme = current_theme(); | |||
$thname = $theme; | |||
$ext = substr($file,strrpos($file,'.')+1); | |||
$paths = [ | |||
"{$root}view/theme/$thname/$ext/$file", | |||
"{$root}view/theme/$parent/$ext/$file", | |||
"{$root}view/$ext/$file", | |||
]; | |||
foreach ($paths as $p) { | |||
// strpos() is faster than strstr when checking if one string is in another (http://php.net/manual/en/function.strstr.php) | |||
if (strpos($p,'NOPATH') !== false) { | |||
continue; | |||
} elseif (file_exists($p)) { | |||
return $p; | |||
} | |||
} | |||
return ''; | |||
} | |||
} | |||
<?php | |||
/** | |||
* @file src/Core/Theme.php | |||
*/ | |||
namespace Friendica\Core; | |||
use Friendica\Core\System; | |||
require_once 'boot.php'; | |||
/** | |||
* Some functions to handle themes | |||
*/ | |||
class Theme | |||
{ | |||
/** | |||
* @brief Parse theme comment in search of theme infos. | |||
* | |||
* like | |||
* \code | |||
* ..* Name: My Theme | |||
* * Description: My Cool Theme | |||
* . * Version: 1.2.3 | |||
* * Author: John <profile url> | |||
* * Maintainer: Jane <profile url> | |||
* * | |||
* \endcode | |||
* @param string $theme the name of the theme | |||
* @return array | |||
*/ | |||
public static function getInfo($theme) | |||
{ | |||
$info=[ | |||
'name' => $theme, | |||
'description' => "", | |||
'author' => [], | |||
'maintainer' => [], | |||
'version' => "", | |||
'credits' => "", | |||
'experimental' => false, | |||
'unsupported' => false | |||
]; | |||
if (file_exists("view/theme/$theme/experimental")) | |||
$info['experimental'] = true; | |||
if (file_exists("view/theme/$theme/unsupported")) | |||
$info['unsupported'] = true; | |||
if (!is_file("view/theme/$theme/theme.php")) return $info; | |||
$a = get_app(); | |||
$stamp1 = microtime(true); | |||
$f = file_get_contents("view/theme/$theme/theme.php"); | |||
$a->save_timestamp($stamp1, "file"); | |||
$r = preg_match("|/\*.*\*/|msU", $f, $m); | |||
if ($r) { | |||
$ll = explode("\n", $m[0]); | |||
foreach ( $ll as $l ) { | |||
$l = trim($l,"\t\n\r */"); | |||
if ($l != "") { | |||
list($k, $v) = array_map("trim", explode(":", $l, 2)); | |||
$k= strtolower($k); | |||
if ($k == "author") { | |||
$r=preg_match("|([^<]+)<([^>]+)>|", $v, $m); | |||
if ($r) { | |||
$info['author'][] = ['name'=>$m[1], 'link'=>$m[2]]; | |||
} else { | |||
$info['author'][] = ['name'=>$v]; | |||
} | |||
} elseif ($k == "maintainer") { | |||
$r=preg_match("|([^<]+)<([^>]+)>|", $v, $m); | |||
if ($r) { | |||
$info['maintainer'][] = ['name'=>$m[1], 'link'=>$m[2]]; | |||
} else { | |||
$info['maintainer'][] = ['name'=>$v]; | |||
} | |||
} else { | |||
if (array_key_exists($k, $info)) { | |||
$info[$k] = $v; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
return $info; | |||
} | |||
/** | |||
* @brief Returns the theme's screenshot. | |||
* | |||
* The screenshot is expected as view/theme/$theme/screenshot.[png|jpg]. | |||
* | |||
* @param sring $theme The name of the theme | |||
* @return string | |||
*/ | |||
public static function getScreenshot($theme) | |||
{ | |||
$exts = ['.png','.jpg']; | |||
foreach ($exts as $ext) { | |||
if (file_exists('view/theme/' . $theme . '/screenshot' . $ext)) { | |||
return(System::baseUrl() . '/view/theme/' . $theme . '/screenshot' . $ext); | |||
} | |||
} | |||
return(System::baseUrl() . '/images/blank.png'); | |||
} | |||
// install and uninstall theme | |||
public static function uninstall($theme) | |||
{ | |||
logger("Addons: uninstalling theme " . $theme); | |||
include_once("view/theme/$theme/theme.php"); | |||
if (function_exists("{$theme}_uninstall")) { | |||
$func = "{$theme}_uninstall"; | |||
$func(); | |||
} | |||
} | |||
public static function install($theme) | |||
{ | |||
// silently fail if theme was removed | |||
if (! file_exists("view/theme/$theme/theme.php")) { | |||
return false; | |||
} | |||
logger("Addons: installing theme $theme"); | |||
include_once("view/theme/$theme/theme.php"); | |||
if (function_exists("{$theme}_install")) { | |||
$func = "{$theme}_install"; | |||
$func(); | |||
return true; | |||
} else { | |||
logger("Addons: FAILED installing theme $theme"); | |||
return false; | |||
} | |||
} | |||
/** | |||
* @brief Get the full path to relevant theme files by filename | |||
* | |||
* This function search in the theme directory (and if not present in global theme directory) | |||
* if there is a directory with the file extension and for a file with the given | |||
* filename. | |||
* | |||
* @param string $file Filename | |||
* @param string $root Full root path | |||
* @return string Path to the file or empty string if the file isn't found | |||
*/ | |||
public static function getPathForFile($file, $root = '') | |||
{ | |||
$file = basename($file); | |||
// Make sure $root ends with a slash / if it's not blank | |||
if ($root !== '' && $root[strlen($root)-1] !== '/') { | |||
$root = $root . '/'; | |||
} | |||
$theme_info = get_app()->theme_info; | |||
if (is_array($theme_info) && array_key_exists('extends',$theme_info)) { | |||
$parent = $theme_info['extends']; | |||
} else { | |||
$parent = 'NOPATH'; | |||
} | |||
$theme = current_theme(); | |||
$thname = $theme; | |||
$ext = substr($file,strrpos($file,'.')+1); | |||
$paths = [ | |||
"{$root}view/theme/$thname/$ext/$file", | |||
"{$root}view/theme/$parent/$ext/$file", | |||
"{$root}view/$ext/$file", | |||
]; | |||
foreach ($paths as $p) { | |||
// strpos() is faster than strstr when checking if one string is in another (http://php.net/manual/en/function.strstr.php) | |||
if (strpos($p,'NOPATH') !== false) { | |||
continue; | |||
} elseif (file_exists($p)) { | |||
return $p; | |||
} | |||
} | |||
return ''; | |||
} | |||
} |
@ -1,273 +1,273 @@ | |||
<?php | |||
/** | |||
* @file src/Database/PostUpdate.php | |||
*/ | |||
namespace Friendica\Database; | |||
use Friendica\Core\Config; | |||
use Friendica\Database\DBM; | |||
use Friendica\Model\Contact; | |||
use Friendica\Model\GContact; | |||
use dba; | |||
require_once 'include/dba.php'; | |||
/** | |||
* Post update functions | |||
*/ | |||
class PostUpdate | |||
{ | |||
/** | |||
* @brief Calls the post update functions | |||
*/ | |||
public static function update() | |||
{ | |||
if (!self::update1192()) { | |||
return; | |||
} | |||
if (!self::update1194()) { | |||
return; | |||
} | |||
if (!self::update1198()) { | |||
return; | |||
} | |||
if (!self::update1206()) { | |||
return; | |||
} | |||
} | |||
/** | |||
* @brief set the gcontact-id in all item entries | |||
* | |||
* This job has to be started multiple times until all entries are set. | |||
* It isn't started in the update function since it would consume too much time and can be done in the background. | |||
* | |||
* @return bool "true" when the job is done | |||
*/ | |||
private static function update1192() | |||
{ | |||
// Was the script completed? | |||
if (Config::get("system", "post_update_version") >= 1192) { | |||
return true; | |||
} | |||
// Check if the first step is done (Setting "gcontact-id" in the item table) | |||
$r = dba::select('item', ['author-link', 'author-name', 'author-avatar', 'uid', 'network'], ['gcontact-id' => 0], ['limit' => 1000]); | |||
if (!$r) { | |||
// Are there unfinished entries in the thread table? | |||
$r = q("SELECT COUNT(*) AS `total` FROM `thread` | |||
INNER JOIN `item` ON `item`.`id` =`thread`.`iid` | |||
WHERE `thread`.`gcontact-id` = 0 AND | |||
(`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)"); | |||
if ($r && ($r[0]["total"] == 0)) { | |||
Config::set("system", "post_update_version", 1192); | |||
return true; | |||
} | |||
// Update the thread table from the item table | |||
q("UPDATE `thread` INNER JOIN `item` ON `item`.`id`=`thread`.`iid` | |||
SET `thread`.`gcontact-id` = `item`.`gcontact-id` | |||
WHERE `thread`.`gcontact-id` = 0 AND | |||
(`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)"); | |||
return false; | |||
} | |||
$item_arr = []; | |||
foreach ($r as $item) { | |||
$index = $item["author-link"]."-".$item["uid"]; | |||
$item_arr[$index] = ["author-link" => $item["author-link"], | |||
"uid" => $item["uid"], | |||
"network" => $item["network"]]; | |||
} | |||
// Set the "gcontact-id" in the item table and add a new gcontact entry if needed | |||
foreach ($item_arr as $item) { | |||
$gcontact_id = GContact::getId(["url" => $item['author-link'], "network" => $item['network'], | |||
"photo" => $item['author-avatar'], "name" => $item['author-name']]); | |||
dba::update('item', ['gcontact-id' => $gcontact_id], ['uid' => $item['uid'], 'author-link' => $item['author-link'], 'gcontact-id' => 0]); | |||
} | |||
return false; | |||
} | |||
/** | |||
* @brief Updates the "global" field in the item table | |||
* | |||
* @return bool "true" when the job is done | |||
*/ | |||
private static function update1194() | |||
{ | |||
// Was the script completed? | |||
if (Config::get("system", "post_update_version") >= 1194) { | |||
return true; | |||
} | |||
logger("Start", LOGGER_DEBUG); | |||
$end_id = Config::get("system", "post_update_1194_end"); | |||
if (!$end_id) { | |||
$r = q("SELECT `id` FROM `item` WHERE `uid` != 0 ORDER BY `id` DESC LIMIT 1"); | |||
if ($r) { | |||
Config::set("system", "post_update_1194_end", $r[0]["id"]); | |||
$end_id = Config::get("system", "post_update_1194_end"); | |||
} | |||
} | |||
logger("End ID: ".$end_id, LOGGER_DEBUG); | |||