Merge pull request #10551 from annando/profiler

Support for stacked profiler analysis
This commit is contained in:
Hypolite Petovan 2021-07-27 09:59:53 -04:00 committed by GitHub
commit 71a0c52dc3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 813 additions and 633 deletions

View file

@ -22,7 +22,6 @@
use Friendica\App; use Friendica\App;
use Friendica\Content\ContactSelector; use Friendica\Content\ContactSelector;
use Friendica\Content\Feature; use Friendica\Content\Feature;
use Friendica\Content\Text\BBCode;
use Friendica\Core\Hook; use Friendica\Core\Hook;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Core\Protocol; use Friendica\Core\Protocol;
@ -34,7 +33,6 @@ use Friendica\DI;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\Item; use Friendica\Model\Item;
use Friendica\Model\Post; use Friendica\Model\Post;
use Friendica\Model\Profile;
use Friendica\Model\Tag; use Friendica\Model\Tag;
use Friendica\Model\Verb; use Friendica\Model\Verb;
use Friendica\Object\Post as PostObject; use Friendica\Object\Post as PostObject;
@ -56,6 +54,7 @@ use Friendica\Util\XML;
*/ */
function localize_item(&$item) function localize_item(&$item)
{ {
DI::profiler()->startRecording('rendering');
/// @todo The following functionality needs to be cleaned up. /// @todo The following functionality needs to be cleaned up.
if (!empty($item['verb'])) { if (!empty($item['verb'])) {
$activity = DI::activity(); $activity = DI::activity();
@ -65,9 +64,11 @@ function localize_item(&$item)
if (stristr($item['verb'], Activity::POKE)) { if (stristr($item['verb'], Activity::POKE)) {
$verb = urldecode(substr($item['verb'], strpos($item['verb'],'#') + 1)); $verb = urldecode(substr($item['verb'], strpos($item['verb'],'#') + 1));
if (!$verb) { if (!$verb) {
DI::profiler()->stopRecording();
return; return;
} }
if ($item['object-type'] == "" || $item['object-type'] !== Activity\ObjectType::PERSON) { if ($item['object-type'] == "" || $item['object-type'] !== Activity\ObjectType::PERSON) {
DI::profiler()->stopRecording();
return; return;
} }
@ -120,6 +121,7 @@ function localize_item(&$item)
'verb', 'object-type', 'resource-id', 'body', 'plink']; 'verb', 'object-type', 'resource-id', 'body', 'plink'];
$obj = Post::selectFirst($fields, ['uri' => $item['parent-uri']]); $obj = Post::selectFirst($fields, ['uri' => $item['parent-uri']]);
if (!DBA::isResult($obj)) { if (!DBA::isResult($obj)) {
DI::profiler()->stopRecording();
return; return;
} }
@ -177,6 +179,7 @@ function localize_item(&$item)
'network' => $item['author-network'], 'url' => $item['author-link']]; 'network' => $item['author-network'], 'url' => $item['author-link']];
$item['plink'] = Contact::magicLinkByContact($author, $item['plink']); $item['plink'] = Contact::magicLinkByContact($author, $item['plink']);
} }
DI::profiler()->stopRecording();
} }
/** /**
@ -263,6 +266,7 @@ function conv_get_blocklist()
*/ */
function conversation(App $a, array $items, $mode, $update, $preview = false, $order = 'commented', $uid = 0) function conversation(App $a, array $items, $mode, $update, $preview = false, $order = 'commented', $uid = 0)
{ {
DI::profiler()->startRecording('rendering');
$page = DI::page(); $page = DI::page();
$page->registerFooterScript(Theme::getPathForFile('asset/typeahead.js/dist/typeahead.bundle.js')); $page->registerFooterScript(Theme::getPathForFile('asset/typeahead.js/dist/typeahead.bundle.js'));
@ -603,6 +607,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o
'$dropping' => ($page_dropping ? DI::l10n()->t('Delete Selected Items') : False), '$dropping' => ($page_dropping ? DI::l10n()->t('Delete Selected Items') : False),
]); ]);
DI::profiler()->stopRecording();
return $o; return $o;
} }
@ -616,6 +621,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o
* @return array items with parents and comments * @return array items with parents and comments
*/ */
function conversation_fetch_comments($thread_items, bool $pinned, array $activity) { function conversation_fetch_comments($thread_items, bool $pinned, array $activity) {
DI::profiler()->startRecording('rendering');
$comments = []; $comments = [];
while ($row = Post::fetch($thread_items)) { while ($row = Post::fetch($thread_items)) {
@ -693,6 +699,7 @@ function conversation_fetch_comments($thread_items, bool $pinned, array $activit
DBA::close($thread_items); DBA::close($thread_items);
DI::profiler()->stopRecording();
return $comments; return $comments;
} }
@ -711,6 +718,7 @@ function conversation_fetch_comments($thread_items, bool $pinned, array $activit
* @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/ */
function conversation_add_children(array $parents, $block_authors, $order, $uid) { function conversation_add_children(array $parents, $block_authors, $order, $uid) {
DI::profiler()->startRecording('rendering');
if (count($parents) > 1) { if (count($parents) > 1) {
$max_comments = DI::config()->get('system', 'max_comments', 100); $max_comments = DI::config()->get('system', 'max_comments', 100);
} else { } else {
@ -753,6 +761,7 @@ function conversation_add_children(array $parents, $block_authors, $order, $uid)
$items = conv_sort($items, $order); $items = conv_sort($items, $order);
DI::profiler()->stopRecording();
return $items; return $items;
} }
@ -768,6 +777,7 @@ function conversation_add_children(array $parents, $block_authors, $order, $uid)
* @return array * @return array
*/ */
function conversation_fetch_items(array $parent, array $items, array $condition, bool $block_authors, array $params, array $activity) { function conversation_fetch_items(array $parent, array $items, array $condition, bool $block_authors, array $params, array $activity) {
DI::profiler()->startRecording('rendering');
if ($block_authors) { if ($block_authors) {
$condition[0] .= " AND NOT `author-hidden`"; $condition[0] .= " AND NOT `author-hidden`";
} }
@ -779,11 +789,13 @@ function conversation_fetch_items(array $parent, array $items, array $condition,
if (count($comments) != 0) { if (count($comments) != 0) {
$items = array_merge($items, $comments); $items = array_merge($items, $comments);
} }
DI::profiler()->stopRecording();
return $items; return $items;
} }
function item_photo_menu($item) function item_photo_menu($item)
{ {
DI::profiler()->startRecording('rendering');
$sub_link = ''; $sub_link = '';
$poke_link = ''; $poke_link = '';
$contact_url = ''; $contact_url = '';
@ -882,6 +894,7 @@ function item_photo_menu($item)
$o .= '<li role="menuitem"><a href="' . $v . '">' . $k . '</a></li>' . PHP_EOL; $o .= '<li role="menuitem"><a href="' . $v . '">' . $k . '</a></li>' . PHP_EOL;
} }
} }
DI::profiler()->stopRecording();
return $o; return $o;
} }
@ -980,6 +993,7 @@ function builtin_activity_puller(array $activity, array &$conv_responses)
* @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/ */
function format_activity(array $links, $verb, $id) { function format_activity(array $links, $verb, $id) {
DI::profiler()->startRecording('rendering');
$o = ''; $o = '';
$expanded = ''; $expanded = '';
$phrase = ''; $phrase = '';
@ -1059,11 +1073,13 @@ function format_activity(array $links, $verb, $id) {
]); ]);
$o .= $expanded; $o .= $expanded;
DI::profiler()->stopRecording();
return $o; return $o;
} }
function status_editor(App $a, $x, $notes_cid = 0, $popup = false) function status_editor(App $a, $x, $notes_cid = 0, $popup = false)
{ {
DI::profiler()->startRecording('rendering');
$o = ''; $o = '';
$geotag = !empty($x['allow_location']) ? Renderer::replaceMacros(Renderer::getMarkupTemplate('jot_geotag.tpl'), []) : ''; $geotag = !empty($x['allow_location']) ? Renderer::replaceMacros(Renderer::getMarkupTemplate('jot_geotag.tpl'), []) : '';
@ -1151,6 +1167,7 @@ function status_editor(App $a, $x, $notes_cid = 0, $popup = false)
$o = '<div id="jot-popup" style="display: none;">' . $o . '</div>'; $o = '<div id="jot-popup" style="display: none;">' . $o . '</div>';
} }
DI::profiler()->stopRecording();
return $o; return $o;
} }
@ -1164,6 +1181,7 @@ function status_editor(App $a, $x, $notes_cid = 0, $popup = false)
*/ */
function get_item_children(array &$item_list, array $parent, $recursive = true) function get_item_children(array &$item_list, array $parent, $recursive = true)
{ {
DI::profiler()->startRecording('rendering');
$children = []; $children = [];
foreach ($item_list as $i => $item) { foreach ($item_list as $i => $item) {
if ($item['gravity'] != GRAVITY_PARENT) { if ($item['gravity'] != GRAVITY_PARENT) {
@ -1185,6 +1203,7 @@ function get_item_children(array &$item_list, array $parent, $recursive = true)
} }
} }
} }
DI::profiler()->stopRecording();
return $children; return $children;
} }
@ -1196,6 +1215,7 @@ function get_item_children(array &$item_list, array $parent, $recursive = true)
*/ */
function sort_item_children(array $items) function sort_item_children(array $items)
{ {
DI::profiler()->startRecording('rendering');
$result = $items; $result = $items;
usort($result, 'sort_thr_received_rev'); usort($result, 'sort_thr_received_rev');
foreach ($result as $k => $i) { foreach ($result as $k => $i) {
@ -1203,6 +1223,7 @@ function sort_item_children(array $items)
$result[$k]['children'] = sort_item_children($result[$k]['children']); $result[$k]['children'] = sort_item_children($result[$k]['children']);
} }
} }
DI::profiler()->stopRecording();
return $result; return $result;
} }
@ -1240,7 +1261,9 @@ function add_children_to_list(array $children, array &$item_list)
*/ */
function smart_flatten_conversation(array $parent) function smart_flatten_conversation(array $parent)
{ {
DI::profiler()->startRecording('rendering');
if (!isset($parent['children']) || count($parent['children']) == 0) { if (!isset($parent['children']) || count($parent['children']) == 0) {
DI::profiler()->stopRecording();
return $parent; return $parent;
} }
@ -1251,6 +1274,7 @@ function smart_flatten_conversation(array $parent)
if (isset($child['children']) && count($child['children'])) { if (isset($child['children']) && count($child['children'])) {
// This helps counting only the regular posts // This helps counting only the regular posts
$count_post_closure = function($var) { $count_post_closure = function($var) {
DI::profiler()->stopRecording();
return $var['verb'] === Activity::POST; return $var['verb'] === Activity::POST;
}; };
@ -1276,6 +1300,7 @@ function smart_flatten_conversation(array $parent)
} }
} }
DI::profiler()->stopRecording();
return $parent; return $parent;
} }
@ -1293,9 +1318,11 @@ function smart_flatten_conversation(array $parent)
*/ */
function conv_sort(array $item_list, $order) function conv_sort(array $item_list, $order)
{ {
DI::profiler()->startRecording('rendering');
$parents = []; $parents = [];
if (!(is_array($item_list) && count($item_list))) { if (!(is_array($item_list) && count($item_list))) {
DI::profiler()->stopRecording();
return $parents; return $parents;
} }
@ -1355,6 +1382,7 @@ function conv_sort(array $item_list, $order)
} }
} }
DI::profiler()->stopRecording();
return $parents; return $parents;
} }

View file

@ -152,6 +152,7 @@ class BBCode
*/ */
public static function getAttachmentData($body) public static function getAttachmentData($body)
{ {
DI::profiler()->startRecording('rendering');
$data = [ $data = [
'type' => '', 'type' => '',
'text' => '', 'text' => '',
@ -167,6 +168,7 @@ class BBCode
]; ];
if (!preg_match("/(.*)\[attachment(.*?)\](.*?)\[\/attachment\](.*)/ism", $body, $match)) { if (!preg_match("/(.*)\[attachment(.*?)\](.*?)\[\/attachment\](.*)/ism", $body, $match)) {
DI::profiler()->stopRecording();
return self::getOldAttachmentData($body); return self::getOldAttachmentData($body);
} }
@ -211,6 +213,7 @@ class BBCode
} }
if (!in_array($data['type'], ['link', 'audio', 'photo', 'video'])) { if (!in_array($data['type'], ['link', 'audio', 'photo', 'video'])) {
DI::profiler()->stopRecording();
return []; return [];
} }
@ -232,6 +235,7 @@ class BBCode
} }
} }
DI::profiler()->stopRecording();
return $data; return $data;
} }
@ -247,6 +251,7 @@ class BBCode
- (thumbnail) - (thumbnail)
*/ */
DI::profiler()->startRecording('rendering');
$has_title = !empty($item['title']); $has_title = !empty($item['title']);
$plink = $item['plink'] ?? ''; $plink = $item['plink'] ?? '';
$post = self::getAttachmentData($body); $post = self::getAttachmentData($body);
@ -398,6 +403,7 @@ class BBCode
} }
} }
DI::profiler()->stopRecording();
return $post; return $post;
} }
@ -434,6 +440,7 @@ class BBCode
*/ */
public static function toPlaintext($text, $keep_urls = true) public static function toPlaintext($text, $keep_urls = true)
{ {
DI::profiler()->startRecording('rendering');
// Remove pictures in advance to avoid unneeded proxy calls // Remove pictures in advance to avoid unneeded proxy calls
$text = preg_replace("/\[img\=(.*?)\](.*?)\[\/img\]/ism", ' $2 ', $text); $text = preg_replace("/\[img\=(.*?)\](.*?)\[\/img\]/ism", ' $2 ', $text);
$text = preg_replace("/\[img.*?\[\/img\]/ism", ' ', $text); $text = preg_replace("/\[img.*?\[\/img\]/ism", ' ', $text);
@ -443,6 +450,7 @@ class BBCode
$naked_text = HTML::toPlaintext(self::convert($text, false, 0, true), 0, !$keep_urls); $naked_text = HTML::toPlaintext(self::convert($text, false, 0, true), 0, !$keep_urls);
DI::profiler()->stopRecording();
return $naked_text; return $naked_text;
} }
@ -468,6 +476,7 @@ class BBCode
*/ */
public static function scaleExternalImages(string $srctext) public static function scaleExternalImages(string $srctext)
{ {
DI::profiler()->startRecording('rendering');
$s = $srctext; $s = $srctext;
// Simplify image links // Simplify image links
@ -517,6 +526,7 @@ class BBCode
} }
} }
DI::profiler()->stopRecording();
return $s; return $s;
} }
@ -532,6 +542,7 @@ class BBCode
*/ */
public static function limitBodySize($body) public static function limitBodySize($body)
{ {
DI::profiler()->startRecording('rendering');
$maxlen = DI::config()->get('config', 'max_import_size', 0); $maxlen = DI::config()->get('config', 'max_import_size', 0);
// If the length of the body, including the embedded images, is smaller // If the length of the body, including the embedded images, is smaller
@ -603,8 +614,10 @@ class BBCode
$new_body = $new_body . $orig_body; $new_body = $new_body . $orig_body;
} }
DI::profiler()->stopRecording();
return $new_body; return $new_body;
} else { } else {
DI::profiler()->stopRecording();
return $body; return $body;
} }
} }
@ -624,13 +637,13 @@ class BBCode
*/ */
public static function convertAttachment($text, $simplehtml = self::INTERNAL, $tryoembed = true, array $data = [], $uriid = 0) public static function convertAttachment($text, $simplehtml = self::INTERNAL, $tryoembed = true, array $data = [], $uriid = 0)
{ {
DI::profiler()->startRecording('rendering');
$data = $data ?: self::getAttachmentData($text); $data = $data ?: self::getAttachmentData($text);
if (empty($data) || empty($data['url'])) { if (empty($data) || empty($data['url'])) {
DI::profiler()->stopRecording();
return $text; return $text;
} }
$stamp1 = microtime(true);
if (isset($data['title'])) { if (isset($data['title'])) {
$data['title'] = strip_tags($data['title']); $data['title'] = strip_tags($data['title']);
$data['title'] = str_replace(['http://', 'https://'], '', $data['title']); $data['title'] = str_replace(['http://', 'https://'], '', $data['title']);
@ -688,17 +701,20 @@ class BBCode
} }
} }
DI::profiler()->saveTimestamp($stamp1, 'rendering'); DI::profiler()->stopRecording();
return trim(($data['text'] ?? '') . ' ' . $return . ' ' . ($data['after'] ?? '')); return trim(($data['text'] ?? '') . ' ' . $return . ' ' . ($data['after'] ?? ''));
} }
public static function removeShareInformation($Text, $plaintext = false, $nolink = false) public static function removeShareInformation($Text, $plaintext = false, $nolink = false)
{ {
DI::profiler()->startRecording('rendering');
$data = self::getAttachmentData($Text); $data = self::getAttachmentData($Text);
if (!$data) { if (!$data) {
DI::profiler()->stopRecording();
return $Text; return $Text;
} elseif ($nolink) { } elseif ($nolink) {
DI::profiler()->stopRecording();
return $data['text'] . ($data['after'] ?? ''); return $data['text'] . ($data['after'] ?? '');
} }
@ -712,11 +728,13 @@ class BBCode
} }
if (empty($data['text']) && !empty($data['title']) && empty($data['url'])) { if (empty($data['text']) && !empty($data['title']) && empty($data['url'])) {
DI::profiler()->stopRecording();
return $data['title'] . $data['after']; return $data['title'] . $data['after'];
} }
// If the link already is included in the post, don't add it again // If the link already is included in the post, don't add it again
if (!empty($data['url']) && strpos($data['text'], $data['url'])) { if (!empty($data['url']) && strpos($data['text'], $data['url'])) {
DI::profiler()->stopRecording();
return $data['text'] . $data['after']; return $data['text'] . $data['after'];
} }
@ -728,6 +746,7 @@ class BBCode
$text .= "\n[url]" . $data['url'] . '[/url]'; $text .= "\n[url]" . $data['url'] . '[/url]';
} }
DI::profiler()->stopRecording();
return $text . "\n" . $data['after']; return $text . "\n" . $data['after'];
} }
@ -821,6 +840,7 @@ class BBCode
*/ */
public static function getTagPosition($text, $name, $occurrences = 0) public static function getTagPosition($text, $name, $occurrences = 0)
{ {
DI::profiler()->startRecording('rendering');
if ($occurrences < 0) { if ($occurrences < 0) {
$occurrences = 0; $occurrences = 0;
} }
@ -833,6 +853,7 @@ class BBCode
} }
if ($start_open === false) { if ($start_open === false) {
DI::profiler()->stopRecording();
return false; return false;
} }
@ -840,6 +861,7 @@ class BBCode
$start_close = strpos($text, ']', $start_open); $start_close = strpos($text, ']', $start_open);
if ($start_close === false) { if ($start_close === false) {
DI::profiler()->stopRecording();
return false; return false;
} }
@ -848,6 +870,7 @@ class BBCode
$end_open = strpos($text, '[/' . $name . ']', $start_close); $end_open = strpos($text, '[/' . $name . ']', $start_close);
if ($end_open === false) { if ($end_open === false) {
DI::profiler()->stopRecording();
return false; return false;
} }
@ -866,6 +889,7 @@ class BBCode
$res['start']['equal'] = $start_equal + 1; $res['start']['equal'] = $start_equal + 1;
} }
DI::profiler()->stopRecording();
return $res; return $res;
} }
@ -880,6 +904,7 @@ class BBCode
*/ */
public static function pregReplaceInTag($pattern, $replace, $name, $text) public static function pregReplaceInTag($pattern, $replace, $name, $text)
{ {
DI::profiler()->startRecording('rendering');
$occurrences = 0; $occurrences = 0;
$pos = self::getTagPosition($text, $name, $occurrences); $pos = self::getTagPosition($text, $name, $occurrences);
while ($pos !== false && $occurrences++ < 1000) { while ($pos !== false && $occurrences++ < 1000) {
@ -896,6 +921,7 @@ class BBCode
$pos = self::getTagPosition($text, $name, $occurrences); $pos = self::getTagPosition($text, $name, $occurrences);
} }
DI::profiler()->stopRecording();
return $text; return $text;
} }
@ -964,12 +990,14 @@ class BBCode
*/ */
public static function fetchShareAttributes($text) public static function fetchShareAttributes($text)
{ {
DI::profiler()->startRecording('rendering');
// See Issue https://github.com/friendica/friendica/issues/10454 // See Issue https://github.com/friendica/friendica/issues/10454
// Hashtags in usernames are expanded to links. This here is a quick fix. // Hashtags in usernames are expanded to links. This here is a quick fix.
$text = preg_replace('/([@!#])\[url\=.*?\](.*?)\[\/url\]/ism', '$1$2', $text); $text = preg_replace('/([@!#])\[url\=.*?\](.*?)\[\/url\]/ism', '$1$2', $text);
$attributes = []; $attributes = [];
if (!preg_match("/(.*?)\[share(.*?)\](.*)\[\/share\]/ism", $text, $matches)) { if (!preg_match("/(.*?)\[share(.*?)\](.*)\[\/share\]/ism", $text, $matches)) {
DI::profiler()->stopRecording();
return $attributes; return $attributes;
} }
@ -978,6 +1006,7 @@ class BBCode
preg_match("/$field=(['\"])(.+?)\\1/ism", $attribute_string, $matches); preg_match("/$field=(['\"])(.+?)\\1/ism", $attribute_string, $matches);
$attributes[$field] = html_entity_decode($matches[2] ?? '', ENT_QUOTES, 'UTF-8'); $attributes[$field] = html_entity_decode($matches[2] ?? '', ENT_QUOTES, 'UTF-8');
} }
DI::profiler()->stopRecording();
return $attributes; return $attributes;
} }
@ -1002,6 +1031,7 @@ class BBCode
*/ */
public static function convertShare($text, callable $callback, int $uriid = 0) public static function convertShare($text, callable $callback, int $uriid = 0)
{ {
DI::profiler()->startRecording('rendering');
$return = preg_replace_callback( $return = preg_replace_callback(
"/(.*?)\[share(.*?)\](.*)\[\/share\]/ism", "/(.*?)\[share(.*?)\](.*)\[\/share\]/ism",
function ($match) use ($callback, $uriid) { function ($match) use ($callback, $uriid) {
@ -1033,6 +1063,7 @@ class BBCode
$text $text
); );
DI::profiler()->stopRecording();
return $return; return $return;
} }
@ -1052,6 +1083,7 @@ class BBCode
*/ */
private static function convertShareCallback(array $attributes, array $author_contact, $content, $is_quote_share, $simplehtml) private static function convertShareCallback(array $attributes, array $author_contact, $content, $is_quote_share, $simplehtml)
{ {
DI::profiler()->startRecording('rendering');
$mention = Protocol::formatMention($attributes['profile'], $attributes['author']); $mention = Protocol::formatMention($attributes['profile'], $attributes['author']);
switch ($simplehtml) { switch ($simplehtml) {
@ -1247,19 +1279,23 @@ class BBCode
public static function cleanPictureLinks($text) public static function cleanPictureLinks($text)
{ {
DI::profiler()->startRecording('rendering');
$return = preg_replace_callback("&\[url=([^\[\]]*)\]\[img=(.*)\](.*)\[\/img\]\[\/url\]&Usi", 'self::cleanPictureLinksCallback', $text); $return = preg_replace_callback("&\[url=([^\[\]]*)\]\[img=(.*)\](.*)\[\/img\]\[\/url\]&Usi", 'self::cleanPictureLinksCallback', $text);
$return = preg_replace_callback("&\[url=([^\[\]]*)\]\[img\](.*)\[\/img\]\[\/url\]&Usi", 'self::cleanPictureLinksCallback', $return); $return = preg_replace_callback("&\[url=([^\[\]]*)\]\[img\](.*)\[\/img\]\[\/url\]&Usi", 'self::cleanPictureLinksCallback', $return);
DI::profiler()->stopRecording();
return $return; return $return;
} }
public static function removeLinks(string $bbcode) public static function removeLinks(string $bbcode)
{ {
DI::profiler()->startRecording('rendering');
$bbcode = preg_replace("/\[img\=(.*?)\](.*?)\[\/img\]/ism", ' $1 ', $bbcode); $bbcode = preg_replace("/\[img\=(.*?)\](.*?)\[\/img\]/ism", ' $1 ', $bbcode);
$bbcode = preg_replace("/\[img.*?\[\/img\]/ism", ' ', $bbcode); $bbcode = preg_replace("/\[img.*?\[\/img\]/ism", ' ', $bbcode);
$bbcode = preg_replace('/[@!#]\[url\=.*?\].*?\[\/url\]/ism', '', $bbcode); $bbcode = preg_replace('/[@!#]\[url\=.*?\].*?\[\/url\]/ism', '', $bbcode);
$bbcode = preg_replace("/\[url=[^\[\]]*\](.*)\[\/url\]/Usi", ' $1 ', $bbcode); $bbcode = preg_replace("/\[url=[^\[\]]*\](.*)\[\/url\]/Usi", ' $1 ', $bbcode);
$bbcode = preg_replace('/[@!#]?\[url.*?\[\/url\]/ism', '', $bbcode); $bbcode = preg_replace('/[@!#]?\[url.*?\[\/url\]/ism', '', $bbcode);
DI::profiler()->stopRecording();
return $bbcode; return $bbcode;
} }
@ -1271,8 +1307,11 @@ class BBCode
*/ */
public static function setMentionsToNicknames(string $body):string public static function setMentionsToNicknames(string $body):string
{ {
DI::profiler()->startRecording('rendering');
$regexp = "/([@!])\[url\=([^\[\]]*)\].*?\[\/url\]/ism"; $regexp = "/([@!])\[url\=([^\[\]]*)\].*?\[\/url\]/ism";
return preg_replace_callback($regexp, ['self', 'mentionCallback'], $body); $body = preg_replace_callback($regexp, ['self', 'mentionCallback'], $body);
DI::profiler()->stopRecording();
return $body;
} }
/** /**
@ -1360,6 +1399,8 @@ class BBCode
return ''; return '';
} }
DI::profiler()->startRecording('rendering');
Hook::callAll('bbcode', $text); Hook::callAll('bbcode', $text);
$a = DI::app(); $a = DI::app();
@ -1979,6 +2020,7 @@ class BBCode
); );
$text = HTML::purify($text, $allowedIframeDomains); $text = HTML::purify($text, $allowedIframeDomains);
DI::profiler()->stopRecording();
return trim($text); return trim($text);
} }
@ -1991,9 +2033,11 @@ class BBCode
*/ */
public static function stripAbstract($text) public static function stripAbstract($text)
{ {
DI::profiler()->startRecording('rendering');
$text = preg_replace("/[\s|\n]*\[abstract\].*?\[\/abstract\][\s|\n]*/ism", '', $text); $text = preg_replace("/[\s|\n]*\[abstract\].*?\[\/abstract\][\s|\n]*/ism", '', $text);
$text = preg_replace("/[\s|\n]*\[abstract=.*?\].*?\[\/abstract][\s|\n]*/ism", '', $text); $text = preg_replace("/[\s|\n]*\[abstract=.*?\].*?\[\/abstract][\s|\n]*/ism", '', $text);
DI::profiler()->stopRecording();
return $text; return $text;
} }
@ -2006,6 +2050,7 @@ class BBCode
*/ */
public static function getAbstract($text, $addon = '') public static function getAbstract($text, $addon = '')
{ {
DI::profiler()->startRecording('rendering');
$abstract = ''; $abstract = '';
$abstracts = []; $abstracts = [];
$addon = strtolower($addon); $addon = strtolower($addon);
@ -2024,6 +2069,7 @@ class BBCode
$abstract = $result[1]; $abstract = $result[1];
} }
DI::profiler()->stopRecording();
return $abstract; return $abstract;
} }
@ -2062,6 +2108,7 @@ class BBCode
*/ */
public static function toMarkdown($text, $for_diaspora = true) public static function toMarkdown($text, $for_diaspora = true)
{ {
DI::profiler()->startRecording('rendering');
$original_text = $text; $original_text = $text;
// Since Diaspora is creating a summary for links, this function removes them before posting // Since Diaspora is creating a summary for links, this function removes them before posting
@ -2106,13 +2153,9 @@ class BBCode
// Maybe we should make this newline at every time before a quote. // Maybe we should make this newline at every time before a quote.
$text = str_replace(['</a><blockquote>'], ['</a><br><blockquote>'], $text); $text = str_replace(['</a><blockquote>'], ['</a><br><blockquote>'], $text);
$stamp1 = microtime(true);
// Now convert HTML to Markdown // Now convert HTML to Markdown
$text = HTML::toMarkdown($text); $text = HTML::toMarkdown($text);
DI::profiler()->saveTimestamp($stamp1, "parser");
// Libertree has a problem with escaped hashtags. // Libertree has a problem with escaped hashtags.
$text = str_replace(['\#'], ['#'], $text); $text = str_replace(['\#'], ['#'], $text);
@ -2131,6 +2174,7 @@ class BBCode
Hook::callAll('bb2diaspora', $text); Hook::callAll('bb2diaspora', $text);
DI::profiler()->stopRecording();
return $text; return $text;
} }
@ -2149,6 +2193,7 @@ class BBCode
*/ */
public static function getTags($string) public static function getTags($string)
{ {
DI::profiler()->startRecording('rendering');
$ret = []; $ret = [];
self::performWithEscapedTags($string, ['noparse', 'pre', 'code', 'img'], function ($string) use (&$ret) { self::performWithEscapedTags($string, ['noparse', 'pre', 'code', 'img'], function ($string) use (&$ret) {
@ -2199,6 +2244,7 @@ class BBCode
} }
}); });
DI::profiler()->stopRecording();
return array_unique($ret); return array_unique($ret);
} }
@ -2258,6 +2304,7 @@ class BBCode
*/ */
public static function setMentions($body, $profile_uid = 0, $network = '') public static function setMentions($body, $profile_uid = 0, $network = '')
{ {
DI::profiler()->startRecording('rendering');
self::performWithEscapedTags($body, ['noparse', 'pre', 'code', 'img'], function ($body) use ($profile_uid, $network) { self::performWithEscapedTags($body, ['noparse', 'pre', 'code', 'img'], function ($body) use ($profile_uid, $network) {
$tags = self::getTags($body); $tags = self::getTags($body);
@ -2289,6 +2336,7 @@ class BBCode
return $body; return $body;
}); });
DI::profiler()->stopRecording();
return $body; return $body;
} }
@ -2304,6 +2352,7 @@ class BBCode
*/ */
public static function getShareOpeningTag(string $author, string $profile, string $avatar, string $link, string $posted, string $guid = null) public static function getShareOpeningTag(string $author, string $profile, string $avatar, string $link, string $posted, string $guid = null)
{ {
DI::profiler()->startRecording('rendering');
$header = "[share author='" . str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $author) . $header = "[share author='" . str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $author) .
"' profile='" . str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $profile) . "' profile='" . str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $profile) .
"' avatar='" . str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $avatar) . "' avatar='" . str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $avatar) .
@ -2316,6 +2365,7 @@ class BBCode
$header .= "']"; $header .= "']";
DI::profiler()->stopRecording();
return $header; return $header;
} }
@ -2337,6 +2387,7 @@ class BBCode
*/ */
public static function embedURL(string $url, bool $tryAttachment = true, string $title = null, string $description = null, string $tags = null): string public static function embedURL(string $url, bool $tryAttachment = true, string $title = null, string $description = null, string $tags = null): string
{ {
DI::profiler()->startRecording('rendering');
DI::logger()->info($url); DI::logger()->info($url);
// If there is already some content information submitted we don't // If there is already some content information submitted we don't
@ -2358,6 +2409,7 @@ class BBCode
DI::logger()->info('(unparsed): returns: ' . $result); DI::logger()->info('(unparsed): returns: ' . $result);
DI::profiler()->stopRecording();
return $result; return $result;
} }
@ -2376,6 +2428,7 @@ class BBCode
break; break;
} }
DI::profiler()->stopRecording();
return $bbcode; return $bbcode;
} }
@ -2383,10 +2436,13 @@ class BBCode
// Bypass attachment if parse url for a comment // Bypass attachment if parse url for a comment
if (!$tryAttachment) { if (!$tryAttachment) {
DI::profiler()->stopRecording();
return "\n" . '[url=' . $url . ']' . $siteinfo['title'] . '[/url]'; return "\n" . '[url=' . $url . ']' . $siteinfo['title'] . '[/url]';
} }
// Format it as BBCode attachment // Format it as BBCode attachment
return "\n" . PageInfo::getFooterFromData($siteinfo); $bbcode = "\n" . PageInfo::getFooterFromData($siteinfo);
DI::profiler()->stopRecording();
return $bbcode;
} }
} }

View file

@ -143,6 +143,7 @@ class HTML
*/ */
public static function toBBCode($message, $basepath = '') public static function toBBCode($message, $basepath = '')
{ {
DI::profiler()->startRecording('rendering');
$message = str_replace("\r", "", $message); $message = str_replace("\r", "", $message);
$message = Strings::performWithEscapedBlocks($message, '#<pre><code.*</code></pre>#iUs', function ($message) { $message = Strings::performWithEscapedBlocks($message, '#<pre><code.*</code></pre>#iUs', function ($message) {
@ -396,6 +397,7 @@ class HTML
$message = self::qualifyURLs($message, $basepath); $message = self::qualifyURLs($message, $basepath);
} }
DI::profiler()->stopRecording();
return $message; return $message;
} }
@ -585,6 +587,7 @@ class HTML
*/ */
public static function toPlaintext(string $html, $wraplength = 75, $compact = false) public static function toPlaintext(string $html, $wraplength = 75, $compact = false)
{ {
DI::profiler()->startRecording('rendering');
$message = str_replace("\r", "", $html); $message = str_replace("\r", "", $html);
$doc = new DOMDocument(); $doc = new DOMDocument();
@ -593,6 +596,7 @@ class HTML
$message = mb_convert_encoding($message, 'HTML-ENTITIES', "UTF-8"); $message = mb_convert_encoding($message, 'HTML-ENTITIES', "UTF-8");
if (empty($message)) { if (empty($message)) {
DI::profiler()->stopRecording();
return ''; return '';
} }
@ -606,6 +610,7 @@ class HTML
$urls = self::collectURLs($message); $urls = self::collectURLs($message);
if (empty($message)) { if (empty($message)) {
DI::profiler()->stopRecording();
return ''; return '';
} }
@ -689,6 +694,7 @@ class HTML
$message = self::quoteLevel(trim($message), $wraplength); $message = self::quoteLevel(trim($message), $wraplength);
DI::profiler()->stopRecording();
return trim($message); return trim($message);
} }
@ -701,9 +707,11 @@ class HTML
*/ */
public static function toMarkdown($html) public static function toMarkdown($html)
{ {
DI::profiler()->startRecording('rendering');
$converter = new HtmlConverter(['hard_break' => true]); $converter = new HtmlConverter(['hard_break' => true]);
$markdown = $converter->convert($html); $markdown = $converter->convert($html);
DI::profiler()->stopRecording();
return $markdown; return $markdown;
} }

View file

@ -21,7 +21,6 @@
namespace Friendica\Content\Text; namespace Friendica\Content\Text;
use Friendica\Core\System;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Contact; use Friendica\Model\Contact;
@ -40,7 +39,7 @@ class Markdown
* @return string * @return string
*/ */
public static function convert($text, $hardwrap = true, $baseuri = null) { public static function convert($text, $hardwrap = true, $baseuri = null) {
$stamp1 = microtime(true); DI::profiler()->startRecording('rendering');
$MarkdownParser = new MarkdownParser(); $MarkdownParser = new MarkdownParser();
$MarkdownParser->code_class_prefix = 'language-'; $MarkdownParser->code_class_prefix = 'language-';
@ -57,7 +56,7 @@ class Markdown
$html = $MarkdownParser->transform($text); $html = $MarkdownParser->transform($text);
DI::profiler()->saveTimestamp($stamp1, "parser"); DI::profiler()->stopRecording();
return $html; return $html;
} }
@ -109,6 +108,8 @@ class Markdown
*/ */
public static function toBBCode($s) public static function toBBCode($s)
{ {
DI::profiler()->startRecording('rendering');
// The parser cannot handle paragraphs correctly // The parser cannot handle paragraphs correctly
$s = str_replace(['</p>', '<p>', '<p dir="ltr">'], ['<br>', '<br>', '<br>'], $s); $s = str_replace(['</p>', '<p>', '<p dir="ltr">'], ['<br>', '<br>', '<br>'], $s);
@ -134,6 +135,7 @@ class Markdown
// Don't show link to full picture (until it is fixed) // Don't show link to full picture (until it is fixed)
$s = BBCode::scaleExternalImages($s); $s = BBCode::scaleExternalImages($s);
DI::profiler()->stopRecording();
return $s; return $s;
} }
} }

View file

@ -236,9 +236,9 @@ class Addon
return $info; return $info;
} }
$stamp1 = microtime(true); DI::profiler()->startRecording('file');
$f = file_get_contents("addon/$addon/$addon.php"); $f = file_get_contents("addon/$addon/$addon.php");
DI::profiler()->saveTimestamp($stamp1, "file"); DI::profiler()->stopRecording();
$r = preg_match("|/\*.*\*/|msU", $f, $m); $r = preg_match("|/\*.*\*/|msU", $f, $m);

View file

@ -52,11 +52,11 @@ class ProfilerCache implements ICache, IMemoryCache
*/ */
public function getAllKeys($prefix = null) public function getAllKeys($prefix = null)
{ {
$time = microtime(true); $this->profiler->startRecording('cache');
$return = $this->cache->getAllKeys($prefix); $return = $this->cache->getAllKeys($prefix);
$this->profiler->saveTimestamp($time, 'cache'); $this->profiler->stopRecording();
return $return; return $return;
} }
@ -66,11 +66,11 @@ class ProfilerCache implements ICache, IMemoryCache
*/ */
public function get($key) public function get($key)
{ {
$time = microtime(true); $this->profiler->startRecording('cache');
$return = $this->cache->get($key); $return = $this->cache->get($key);
$this->profiler->saveTimestamp($time, 'cache'); $this->profiler->stopRecording();
return $return; return $return;
} }
@ -80,11 +80,11 @@ class ProfilerCache implements ICache, IMemoryCache
*/ */
public function set($key, $value, $ttl = Duration::FIVE_MINUTES) public function set($key, $value, $ttl = Duration::FIVE_MINUTES)
{ {
$time = microtime(true); $this->profiler->startRecording('cache');
$return = $this->cache->set($key, $value, $ttl); $return = $this->cache->set($key, $value, $ttl);
$this->profiler->saveTimestamp($time, 'cache'); $this->profiler->stopRecording();
return $return; return $return;
} }
@ -94,11 +94,11 @@ class ProfilerCache implements ICache, IMemoryCache
*/ */
public function delete($key) public function delete($key)
{ {
$time = microtime(true); $this->profiler->startRecording('cache');
$return = $this->cache->delete($key); $return = $this->cache->delete($key);
$this->profiler->saveTimestamp($time, 'cache'); $this->profiler->stopRecording();
return $return; return $return;
} }
@ -108,11 +108,11 @@ class ProfilerCache implements ICache, IMemoryCache
*/ */
public function clear($outdated = true) public function clear($outdated = true)
{ {
$time = microtime(true); $this->profiler->startRecording('cache');
$return = $this->cache->clear($outdated); $return = $this->cache->clear($outdated);
$this->profiler->saveTimestamp($time, 'cache'); $this->profiler->stopRecording();
return $return; return $return;
} }
@ -123,11 +123,11 @@ class ProfilerCache implements ICache, IMemoryCache
public function add($key, $value, $ttl = Duration::FIVE_MINUTES) public function add($key, $value, $ttl = Duration::FIVE_MINUTES)
{ {
if ($this->cache instanceof IMemoryCache) { if ($this->cache instanceof IMemoryCache) {
$time = microtime(true); $this->profiler->startRecording('cache');
$return = $this->cache->add($key, $value, $ttl); $return = $this->cache->add($key, $value, $ttl);
$this->profiler->saveTimestamp($time, 'cache'); $this->profiler->stopRecording();
return $return; return $return;
} else { } else {
@ -141,11 +141,11 @@ class ProfilerCache implements ICache, IMemoryCache
public function compareSet($key, $oldValue, $newValue, $ttl = Duration::FIVE_MINUTES) public function compareSet($key, $oldValue, $newValue, $ttl = Duration::FIVE_MINUTES)
{ {
if ($this->cache instanceof IMemoryCache) { if ($this->cache instanceof IMemoryCache) {
$time = microtime(true); $this->profiler->startRecording('cache');
$return = $this->cache->compareSet($key, $oldValue, $newValue, $ttl); $return = $this->cache->compareSet($key, $oldValue, $newValue, $ttl);
$this->profiler->saveTimestamp($time, 'cache'); $this->profiler->stopRecording();
return $return; return $return;
} else { } else {
@ -159,11 +159,11 @@ class ProfilerCache implements ICache, IMemoryCache
public function compareDelete($key, $value) public function compareDelete($key, $value)
{ {
if ($this->cache instanceof IMemoryCache) { if ($this->cache instanceof IMemoryCache) {
$time = microtime(true); $this->profiler->startRecording('cache');
$return = $this->cache->compareDelete($key, $value); $return = $this->cache->compareDelete($key, $value);
$this->profiler->saveTimestamp($time, 'cache'); $this->profiler->stopRecording();
return $return; return $return;
} else { } else {

View file

@ -73,7 +73,7 @@ class Renderer
*/ */
public static function replaceMacros(string $template, array $vars = []) public static function replaceMacros(string $template, array $vars = [])
{ {
$stamp1 = microtime(true); DI::profiler()->startRecording('rendering');
// pass $baseurl to all templates if it isn't set // pass $baseurl to all templates if it isn't set
$vars = array_merge(['$baseurl' => DI::baseUrl()->get(), '$APP' => DI::app()], $vars); $vars = array_merge(['$baseurl' => DI::baseUrl()->get(), '$APP' => DI::app()], $vars);
@ -90,7 +90,7 @@ class Renderer
throw new InternalServerErrorException($message); throw new InternalServerErrorException($message);
} }
DI::profiler()->saveTimestamp($stamp1, "rendering"); DI::profiler()->stopRecording();
return $output; return $output;
} }
@ -106,7 +106,7 @@ class Renderer
*/ */
public static function getMarkupTemplate($file, $subDir = '') public static function getMarkupTemplate($file, $subDir = '')
{ {
$stamp1 = microtime(true); DI::profiler()->startRecording('file');
$t = self::getTemplateEngine(); $t = self::getTemplateEngine();
try { try {
@ -119,7 +119,7 @@ class Renderer
throw new InternalServerErrorException($message); throw new InternalServerErrorException($message);
} }
DI::profiler()->saveTimestamp($stamp1, "file"); DI::profiler()->stopRecording();
return $template; return $template;
} }

View file

@ -88,9 +88,9 @@ class Theme
return $info; return $info;
} }
$stamp1 = microtime(true); DI::profiler()->startRecording('file');
$theme_file = file_get_contents("view/theme/$theme/theme.php"); $theme_file = file_get_contents("view/theme/$theme/theme.php");
DI::profiler()->saveTimestamp($stamp1, "file"); DI::profiler()->stopRecording();
$result = preg_match("|/\*.*\*/|msU", $theme_file, $matches); $result = preg_match("|/\*.*\*/|msU", $theme_file, $matches);

View file

@ -468,6 +468,7 @@ class Database
public function p($sql) public function p($sql)
{ {
$this->profiler->startRecording('database');
$stamp1 = microtime(true); $stamp1 = microtime(true);
$params = DBA::getParam(func_get_args()); $params = DBA::getParam(func_get_args());
@ -695,7 +696,7 @@ class Database
$this->errorno = $errorno; $this->errorno = $errorno;
} }
$this->profiler->saveTimestamp($stamp1, 'database'); $this->profiler->stopRecording();
if ($this->configCache->get('system', 'db_log')) { if ($this->configCache->get('system', 'db_log')) {
$stamp2 = microtime(true); $stamp2 = microtime(true);
@ -727,7 +728,7 @@ class Database
public function e($sql) public function e($sql)
{ {
$stamp = microtime(true); $this->profiler->startRecording('database_write');
$params = DBA::getParam(func_get_args()); $params = DBA::getParam(func_get_args());
@ -779,7 +780,7 @@ class Database
$this->errorno = $errorno; $this->errorno = $errorno;
} }
$this->profiler->saveTimestamp($stamp, "database_write"); $this->profiler->stopRecording();
return $retval; return $retval;
} }
@ -914,7 +915,7 @@ class Database
*/ */
public function fetch($stmt) public function fetch($stmt)
{ {
$stamp1 = microtime(true); $this->profiler->startRecording('database');
$columns = []; $columns = [];
@ -962,7 +963,7 @@ class Database
} }
} }
$this->profiler->saveTimestamp($stamp1, 'database'); $this->profiler->stopRecording();
return $columns; return $columns;
} }
@ -1589,7 +1590,7 @@ class Database
public function close($stmt) public function close($stmt)
{ {
$stamp1 = microtime(true); $this->profiler->startRecording('database');
if (!is_object($stmt)) { if (!is_object($stmt)) {
return false; return false;
@ -1615,7 +1616,7 @@ class Database
break; break;
} }
$this->profiler->saveTimestamp($stamp1, 'database'); $this->profiler->stopRecording();
return $ret; return $ret;
} }

View file

@ -58,7 +58,7 @@ class SessionFactory
*/ */
public function createSession(App\Mode $mode, App\BaseURL $baseURL, IConfig $config, Database $dba, ICache $cache, LoggerInterface $logger, Profiler $profiler, array $server = []) public function createSession(App\Mode $mode, App\BaseURL $baseURL, IConfig $config, Database $dba, ICache $cache, LoggerInterface $logger, Profiler $profiler, array $server = [])
{ {
$stamp1 = microtime(true); $profiler->startRecording('session');
$session = null; $session = null;
try { try {
@ -85,7 +85,7 @@ class SessionFactory
$session = new Session\Native($baseURL, $handler); $session = new Session\Native($baseURL, $handler);
} }
} finally { } finally {
$profiler->saveTimestamp($stamp1, 'parser'); $profiler->stopRecording();
return $session; return $session;
} }
} }

View file

@ -2726,22 +2726,6 @@ class Item
$item['hashtags'] = $tags['hashtags']; $item['hashtags'] = $tags['hashtags'];
$item['mentions'] = $tags['mentions']; $item['mentions'] = $tags['mentions'];
// Compile eventual content filter reasons
$filter_reasons = [];
if (!$is_preview && public_contact() != $item['author-id']) {
if (!empty($item['content-warning']) && (!local_user() || !DI::pConfig()->get(local_user(), 'system', 'disable_cw', false))) {
$filter_reasons[] = DI::l10n()->t('Content warning: %s', $item['content-warning']);
}
$hook_data = [
'item' => $item,
'filter_reasons' => $filter_reasons
];
Hook::callAll('prepare_body_content_filter', $hook_data);
$filter_reasons = $hook_data['filter_reasons'];
unset($hook_data);
}
$body = $item['body'] ?? ''; $body = $item['body'] ?? '';
$shared = BBCode::fetchShareAttributes($body); $shared = BBCode::fetchShareAttributes($body);
if (!empty($shared['guid'])) { if (!empty($shared['guid'])) {
@ -2765,6 +2749,22 @@ class Item
$item['body'] = $body; $item['body'] = $body;
$s = $item["rendered-html"]; $s = $item["rendered-html"];
// Compile eventual content filter reasons
$filter_reasons = [];
if (!$is_preview && public_contact() != $item['author-id']) {
if (!empty($item['content-warning']) && (!local_user() || !DI::pConfig()->get(local_user(), 'system', 'disable_cw', false))) {
$filter_reasons[] = DI::l10n()->t('Content warning: %s', $item['content-warning']);
}
$hook_data = [
'item' => $item,
'filter_reasons' => $filter_reasons
];
Hook::callAll('prepare_body_content_filter', $hook_data);
$filter_reasons = $hook_data['filter_reasons'];
unset($hook_data);
}
$hook_data = [ $hook_data = [
'item' => $item, 'item' => $item,
'html' => $s, 'html' => $s,
@ -2858,7 +2858,7 @@ class Item
*/ */
private static function replaceVisualAttachments(array $attachments, string $body) private static function replaceVisualAttachments(array $attachments, string $body)
{ {
$stamp1 = microtime(true); DI::profiler()->startRecording('rendering');
foreach ($attachments['visual'] as $attachment) { foreach ($attachments['visual'] as $attachment) {
if (!empty($attachment['preview'])) { if (!empty($attachment['preview'])) {
@ -2867,7 +2867,7 @@ class Item
$body = str_replace($attachment['url'], Post\Media::getUrlForId($attachment['id']), $body); $body = str_replace($attachment['url'], Post\Media::getUrlForId($attachment['id']), $body);
} }
} }
DI::profiler()->saveTimestamp($stamp1, 'rendering'); DI::profiler()->stopRecording();
return $body; return $body;
} }
@ -2881,7 +2881,7 @@ class Item
*/ */
private static function addVisualAttachments(array $attachments, array $item, string $content, bool $shared) private static function addVisualAttachments(array $attachments, array $item, string $content, bool $shared)
{ {
$stamp1 = microtime(true); DI::profiler()->startRecording('rendering');
$leading = ''; $leading = '';
$trailing = ''; $trailing = '';
@ -2957,7 +2957,7 @@ class Item
} }
} }
DI::profiler()->saveTimestamp($stamp1, 'rendering'); DI::profiler()->stopRecording();
return $content; return $content;
} }
@ -2973,7 +2973,7 @@ class Item
*/ */
private static function addLinkAttachment(int $uriid, array $attachments, string $body, string $content, bool $shared, array $ignore_links) private static function addLinkAttachment(int $uriid, array $attachments, string $body, string $content, bool $shared, array $ignore_links)
{ {
$stamp1 = microtime(true); DI::profiler()->startRecording('rendering');
// @ToDo Check only for audio and video // @ToDo Check only for audio and video
$preview = empty($attachments['visual']); $preview = empty($attachments['visual']);
@ -3038,7 +3038,7 @@ class Item
} elseif (preg_match("/.*(\[attachment.*?\].*?\[\/attachment\]).*/ism", $body, $match)) { } elseif (preg_match("/.*(\[attachment.*?\].*?\[\/attachment\]).*/ism", $body, $match)) {
$data = BBCode::getAttachmentData($match[1]); $data = BBCode::getAttachmentData($match[1]);
} }
DI::profiler()->saveTimestamp($stamp1, 'rendering'); DI::profiler()->stopRecording();
if (isset($data['url']) && !in_array($data['url'], $ignore_links)) { if (isset($data['url']) && !in_array($data['url'], $ignore_links)) {
if (!empty($data['description']) || !empty($data['image']) || !empty($data['preview'])) { if (!empty($data['description']) || !empty($data['image']) || !empty($data['preview'])) {
@ -3086,7 +3086,7 @@ class Item
*/ */
private static function addNonVisualAttachments(array $attachments, array $item, string $content) private static function addNonVisualAttachments(array $attachments, array $item, string $content)
{ {
$stamp1 = microtime(true); DI::profiler()->startRecording('rendering');
$trailing = ''; $trailing = '';
foreach ($attachments['additional'] as $attachment) { foreach ($attachments['additional'] as $attachment) {
if (strpos($item['body'], $attachment['url'])) { if (strpos($item['body'], $attachment['url'])) {
@ -3112,7 +3112,7 @@ class Item
$content .= '<div class="body-attach">' . $trailing . '<div class="clear"></div></div>'; $content .= '<div class="body-attach">' . $trailing . '<div class="clear"></div></div>';
} }
DI::profiler()->saveTimestamp($stamp1, 'rendering'); DI::profiler()->stopRecording();
return $content; return $content;
} }

View file

@ -72,7 +72,7 @@ class HTTPRequest implements IHTTPRequest
*/ */
public function get(string $url, array $opts = [], &$redirects = 0) public function get(string $url, array $opts = [], &$redirects = 0)
{ {
$stamp1 = microtime(true); $this->profiler->startRecording('network');
if (Network::isLocalLink($url)) { if (Network::isLocalLink($url)) {
$this->logger->info('Local link', ['url' => $url, 'callstack' => System::callstack(20)]); $this->logger->info('Local link', ['url' => $url, 'callstack' => System::callstack(20)]);
@ -80,7 +80,7 @@ class HTTPRequest implements IHTTPRequest
if (strlen($url) > 1000) { if (strlen($url) > 1000) {
$this->logger->debug('URL is longer than 1000 characters.', ['url' => $url, 'callstack' => System::callstack(20)]); $this->logger->debug('URL is longer than 1000 characters.', ['url' => $url, 'callstack' => System::callstack(20)]);
$this->profiler->saveTimestamp($stamp1, 'network'); $this->profiler->stopRecording();
return CurlResult::createErrorCurl(substr($url, 0, 200)); return CurlResult::createErrorCurl(substr($url, 0, 200));
} }
@ -99,14 +99,14 @@ class HTTPRequest implements IHTTPRequest
if (Network::isUrlBlocked($url)) { if (Network::isUrlBlocked($url)) {
$this->logger->info('Domain is blocked.', ['url' => $url]); $this->logger->info('Domain is blocked.', ['url' => $url]);
$this->profiler->saveTimestamp($stamp1, 'network'); $this->profiler->stopRecording();
return CurlResult::createErrorCurl($url); return CurlResult::createErrorCurl($url);
} }
$ch = @curl_init($url); $ch = @curl_init($url);
if (($redirects > 8) || (!$ch)) { if (($redirects > 8) || (!$ch)) {
$this->profiler->saveTimestamp($stamp1, 'network'); $this->profiler->stopRecording();
return CurlResult::createErrorCurl($url); return CurlResult::createErrorCurl($url);
} }
@ -208,13 +208,13 @@ class HTTPRequest implements IHTTPRequest
$redirects++; $redirects++;
$this->logger->notice('Curl redirect.', ['url' => $url, 'to' => $curlResponse->getRedirectUrl()]); $this->logger->notice('Curl redirect.', ['url' => $url, 'to' => $curlResponse->getRedirectUrl()]);
@curl_close($ch); @curl_close($ch);
$this->profiler->saveTimestamp($stamp1, 'network'); $this->profiler->stopRecording();
return $this->get($curlResponse->getRedirectUrl(), $opts, $redirects); return $this->get($curlResponse->getRedirectUrl(), $opts, $redirects);
} }
@curl_close($ch); @curl_close($ch);
$this->profiler->saveTimestamp($stamp1, 'network'); $this->profiler->stopRecording();
return $curlResponse; return $curlResponse;
} }
@ -228,7 +228,7 @@ class HTTPRequest implements IHTTPRequest
*/ */
public function post(string $url, $params, array $headers = [], int $timeout = 0, &$redirects = 0) public function post(string $url, $params, array $headers = [], int $timeout = 0, &$redirects = 0)
{ {
$stamp1 = microtime(true); $this->profiler->startRecording('network');
if (Network::isLocalLink($url)) { if (Network::isLocalLink($url)) {
$this->logger->info('Local link', ['url' => $url, 'callstack' => System::callstack(20)]); $this->logger->info('Local link', ['url' => $url, 'callstack' => System::callstack(20)]);
@ -236,14 +236,14 @@ class HTTPRequest implements IHTTPRequest
if (Network::isUrlBlocked($url)) { if (Network::isUrlBlocked($url)) {
$this->logger->info('Domain is blocked.' . ['url' => $url]); $this->logger->info('Domain is blocked.' . ['url' => $url]);
$this->profiler->saveTimestamp($stamp1, 'network'); $this->profiler->stopRecording();
return CurlResult::createErrorCurl($url); return CurlResult::createErrorCurl($url);
} }
$ch = curl_init($url); $ch = curl_init($url);
if (($redirects > 8) || (!$ch)) { if (($redirects > 8) || (!$ch)) {
$this->profiler->saveTimestamp($stamp1, 'network'); $this->profiler->stopRecording();
return CurlResult::createErrorCurl($url); return CurlResult::createErrorCurl($url);
} }
@ -303,13 +303,13 @@ class HTTPRequest implements IHTTPRequest
$redirects++; $redirects++;
$this->logger->info('Post redirect.', ['url' => $url, 'to' => $curlResponse->getRedirectUrl()]); $this->logger->info('Post redirect.', ['url' => $url, 'to' => $curlResponse->getRedirectUrl()]);
curl_close($ch); curl_close($ch);
$this->profiler->saveTimestamp($stamp1, 'network'); $this->profiler->stopRecording();
return $this->post($curlResponse->getRedirectUrl(), $params, $headers, $redirects, $timeout); return $this->post($curlResponse->getRedirectUrl(), $params, $headers, $redirects, $timeout);
} }
curl_close($ch); curl_close($ch);
$this->profiler->saveTimestamp($stamp1, 'network'); $this->profiler->stopRecording();
// Very old versions of Lighttpd don't like the "Expect" header, so we remove it when needed // Very old versions of Lighttpd don't like the "Expect" header, so we remove it when needed
if ($curlResponse->getReturnCode() == 417) { if ($curlResponse->getReturnCode() == 417) {
@ -358,7 +358,7 @@ class HTTPRequest implements IHTTPRequest
$url = trim($url, "'"); $url = trim($url, "'");
$stamp1 = microtime(true); $this->profiler->startRecording('network');
$ch = curl_init(); $ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_URL, $url);
@ -374,7 +374,7 @@ class HTTPRequest implements IHTTPRequest
$http_code = $curl_info['http_code']; $http_code = $curl_info['http_code'];
curl_close($ch); curl_close($ch);
$this->profiler->saveTimestamp($stamp1, "network"); $this->profiler->stopRecording();
if ($http_code == 0) { if ($http_code == 0) {
return $url; return $url;
@ -403,7 +403,7 @@ class HTTPRequest implements IHTTPRequest
return $url; return $url;
} }
$stamp1 = microtime(true); $this->profiler->startRecording('network');
$ch = curl_init(); $ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_URL, $url);
@ -417,7 +417,7 @@ class HTTPRequest implements IHTTPRequest
$body = curl_exec($ch); $body = curl_exec($ch);
curl_close($ch); curl_close($ch);
$this->profiler->saveTimestamp($stamp1, "network"); $this->profiler->stopRecording();
if (trim($body) == "") { if (trim($body) == "") {
return $url; return $url;

View file

@ -650,9 +650,9 @@ class Image
$string = $this->asString(); $string = $this->asString();
$stamp1 = microtime(true); DI::profiler()->stopRecording('file');
file_put_contents($path, $string); file_put_contents($path, $string);
DI::profiler()->saveTimestamp($stamp1, "file"); DI::profiler()->stopRecording();
} }
/** /**

View file

@ -1557,7 +1557,7 @@ class Transmitter
// The contentMap does contain the unmodified HTML. // The contentMap does contain the unmodified HTML.
$language = self::getLanguage($item); $language = self::getLanguage($item);
if (!empty($language)) { if (!empty($language)) {
$richbody = BBCode::setMentionsToNicknames($item['body']); $richbody = BBCode::setMentionsToNicknames($item['body'] ?? '');
$richbody = BBCode::removeAttachment($richbody); $richbody = BBCode::removeAttachment($richbody);
$data['contentMap'][$language] = BBCode::convertForUriId($item['uri-id'], $richbody, BBCode::EXTERNAL); $data['contentMap'][$language] = BBCode::convertForUriId($item['uri-id'], $richbody, BBCode::EXTERNAL);

View file

@ -59,9 +59,9 @@ class ProfilerLogger implements LoggerInterface
*/ */
public function emergency($message, array $context = array()) public function emergency($message, array $context = array())
{ {
$stamp1 = microtime(true); $this->profiler->startRecording('file');
$this->logger->emergency($message, $context); $this->logger->emergency($message, $context);
$this->profiler->saveTimestamp($stamp1, 'file'); $this->profiler->stopRecording();
} }
/** /**
@ -69,9 +69,9 @@ class ProfilerLogger implements LoggerInterface
*/ */
public function alert($message, array $context = array()) public function alert($message, array $context = array())
{ {
$stamp1 = microtime(true); $this->profiler->startRecording('file');
$this->logger->alert($message, $context); $this->logger->alert($message, $context);
$this->profiler->saveTimestamp($stamp1, 'file'); $this->profiler->stopRecording();
} }
/** /**
@ -79,9 +79,9 @@ class ProfilerLogger implements LoggerInterface
*/ */
public function critical($message, array $context = array()) public function critical($message, array $context = array())
{ {
$stamp1 = microtime(true); $this->profiler->startRecording('file');
$this->logger->critical($message, $context); $this->logger->critical($message, $context);
$this->profiler->saveTimestamp($stamp1, 'file'); $this->profiler->stopRecording();
} }
/** /**
@ -89,9 +89,9 @@ class ProfilerLogger implements LoggerInterface
*/ */
public function error($message, array $context = array()) public function error($message, array $context = array())
{ {
$stamp1 = microtime(true); $this->profiler->startRecording('file');
$this->logger->error($message, $context); $this->logger->error($message, $context);
$this->profiler->saveTimestamp($stamp1, 'file'); $this->profiler->stopRecording();
} }
/** /**
@ -99,9 +99,9 @@ class ProfilerLogger implements LoggerInterface
*/ */
public function warning($message, array $context = array()) public function warning($message, array $context = array())
{ {
$stamp1 = microtime(true); $this->profiler->startRecording('file');
$this->logger->warning($message, $context); $this->logger->warning($message, $context);
$this->profiler->saveTimestamp($stamp1, 'file'); $this->profiler->stopRecording();
} }
/** /**
@ -109,9 +109,9 @@ class ProfilerLogger implements LoggerInterface
*/ */
public function notice($message, array $context = array()) public function notice($message, array $context = array())
{ {
$stamp1 = microtime(true); $this->profiler->startRecording('file');
$this->logger->notice($message, $context); $this->logger->notice($message, $context);
$this->profiler->saveTimestamp($stamp1, 'file'); $this->profiler->stopRecording();
} }
/** /**
@ -119,9 +119,9 @@ class ProfilerLogger implements LoggerInterface
*/ */
public function info($message, array $context = array()) public function info($message, array $context = array())
{ {
$stamp1 = microtime(true); $this->profiler->startRecording('file');
$this->logger->info($message, $context); $this->logger->info($message, $context);
$this->profiler->saveTimestamp($stamp1, 'file'); $this->profiler->stopRecording();
} }
/** /**
@ -129,9 +129,9 @@ class ProfilerLogger implements LoggerInterface
*/ */
public function debug($message, array $context = array()) public function debug($message, array $context = array())
{ {
$stamp1 = microtime(true); $this->profiler->startRecording('file');
$this->logger->debug($message, $context); $this->logger->debug($message, $context);
$this->profiler->saveTimestamp($stamp1, 'file'); $this->profiler->stopRecording();
} }
/** /**
@ -139,8 +139,8 @@ class ProfilerLogger implements LoggerInterface
*/ */
public function log($level, $message, array $context = array()) public function log($level, $message, array $context = array())
{ {
$stamp1 = microtime(true); $this->profiler->startRecording('file');
$this->logger->log($level, $message, $context); $this->logger->log($level, $message, $context);
$this->profiler->saveTimestamp($stamp1, 'file'); $this->profiler->stopRecording();
} }
} }

View file

@ -54,6 +54,8 @@ class Profiler implements ContainerInterface
*/ */
private $rendertime; private $rendertime;
private $timestamps = [];
/** /**
* True, if the Profiler should measure the whole rendertime including functions * True, if the Profiler should measure the whole rendertime including functions
* *
@ -85,6 +87,59 @@ class Profiler implements ContainerInterface
$this->reset(); $this->reset();
} }
/**
* Start a profiler recording
*
* @param string $value
* @return void
*/
public function startRecording(string $value)
{
if (!$this->enabled) {
return;
}
$this->timestamps[] = ['value' => $value, 'stamp' => microtime(true), 'credit' => 0];
}
/**
* Stop a profiler recording
*
* @param string $callstack
* @return void
*/
public function stopRecording(string $callstack = '')
{
if (!$this->enabled || empty($this->timestamps)) {
return;
}
$timestamp = array_pop($this->timestamps);
$duration = floatval(microtime(true) - $timestamp['stamp'] - $timestamp['credit']);
$value = $timestamp['value'];
foreach ($this->timestamps as $key => $stamp) {
$this->timestamps[$key]['credit'] += $duration;
}
$callstack = $callstack ?: System::callstack(4, $value == 'rendering' ? 0 : 1);
if (!isset($this->performance[$value])) {
$this->performance[$value] = 0;
}
$this->performance[$value] += (float) $duration;
$this->performance['marktime'] += (float) $duration;
if (!isset($this->callstack[$value][$callstack])) {
// Prevent ugly E_NOTICE
$this->callstack[$value][$callstack] = 0;
}
$this->callstack[$value][$callstack] += (float) $duration;
}
/** /**
* Saves a timestamp for a value - f.e. a call * Saves a timestamp for a value - f.e. a call
* Necessary for profiling Friendica * Necessary for profiling Friendica
@ -143,7 +198,7 @@ class Profiler implements ContainerInterface
$this->performance['network'] = 0; $this->performance['network'] = 0;
$this->performance['file'] = 0; $this->performance['file'] = 0;
$this->performance['rendering'] = 0; $this->performance['rendering'] = 0;
$this->performance['parser'] = 0; $this->performance['session'] = 0;
$this->performance['marktime'] = 0; $this->performance['marktime'] = 0;
$this->performance['marktime'] = microtime(true); $this->performance['marktime'] = microtime(true);
$this->performance['classcreate'] = 0; $this->performance['classcreate'] = 0;
@ -165,7 +220,7 @@ class Profiler implements ContainerInterface
$this->callstack['network'] = []; $this->callstack['network'] = [];
$this->callstack['file'] = []; $this->callstack['file'] = [];
$this->callstack['rendering'] = []; $this->callstack['rendering'] = [];
$this->callstack['parser'] = []; $this->callstack['session'] = [];
} }
/** /**
@ -228,6 +283,16 @@ class Profiler implements ContainerInterface
} }
} }
if (isset($this->callstack["rendering"])) {
$output .= "\nRendering:\n";
foreach ($this->callstack["rendering"] as $func => $time) {
$time = round($time, 3);
if ($time > $limit) {
$output .= $func . ": " . $time . "\n";
}
}
}
return $output; return $output;
} }

View file

@ -101,6 +101,8 @@ trait AppMockTrait
->andReturn($root->url()); ->andReturn($root->url());
$this->profilerMock = \Mockery::mock(Profiler::class); $this->profilerMock = \Mockery::mock(Profiler::class);
$this->profilerMock->shouldReceive('startRecording');
$this->profilerMock->shouldReceive('stopRecording');
$this->profilerMock->shouldReceive('saveTimestamp'); $this->profilerMock->shouldReceive('saveTimestamp');
$this->dice->shouldReceive('create') $this->dice->shouldReceive('create')
->with(Profiler::class) ->with(Profiler::class)

View file

@ -49,6 +49,8 @@ class DatabaseCacheTest extends CacheTest
{ {
$logger = new NullLogger(); $logger = new NullLogger();
$profiler = Mockery::mock(Profiler::class); $profiler = Mockery::mock(Profiler::class);
$profiler->shouldReceive('startRecording');
$profiler->shouldReceive('stopRecording');
$profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true); $profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true);
// load real config to avoid mocking every config-entry which is related to the Database class // load real config to avoid mocking every config-entry which is related to the Database class

View file

@ -51,6 +51,8 @@ class DatabaseLockDriverTest extends LockTest
{ {
$logger = new NullLogger(); $logger = new NullLogger();
$profiler = Mockery::mock(Profiler::class); $profiler = Mockery::mock(Profiler::class);
$profiler->shouldReceive('startRecording');
$profiler->shouldReceive('stopRecording');
$profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true); $profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true);
// load real config to avoid mocking every config-entry which is related to the Database class // load real config to avoid mocking every config-entry which is related to the Database class

View file

@ -69,6 +69,8 @@ class StorageManagerTest extends DatabaseTest
$this->logger = new NullLogger(); $this->logger = new NullLogger();
$profiler = \Mockery::mock(Profiler::class); $profiler = \Mockery::mock(Profiler::class);
$profiler->shouldReceive('startRecording');
$profiler->shouldReceive('stopRecording');
$profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true); $profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true);
// load real config to avoid mocking every config-entry which is related to the Database class // load real config to avoid mocking every config-entry which is related to the Database class

View file

@ -27,6 +27,8 @@ class ProcessTest extends DatabaseTest
$logger = new NullLogger(); $logger = new NullLogger();
$profiler = \Mockery::mock(Profiler::class); $profiler = \Mockery::mock(Profiler::class);
$profiler->shouldReceive('startRecording');
$profiler->shouldReceive('stopRecording');
$profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true); $profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true);
// load real config to avoid mocking every config-entry which is related to the Database class // load real config to avoid mocking every config-entry which is related to the Database class

View file

@ -51,6 +51,8 @@ class DatabaseStorageTest extends StorageTest
{ {
$logger = new NullLogger(); $logger = new NullLogger();
$profiler = \Mockery::mock(Profiler::class); $profiler = \Mockery::mock(Profiler::class);
$profiler->shouldReceive('startRecording');
$profiler->shouldReceive('stopRecording');
$profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true); $profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true);
// load real config to avoid mocking every config-entry which is related to the Database class // load real config to avoid mocking every config-entry which is related to the Database class

View file

@ -52,6 +52,8 @@ class FilesystemStorageTest extends StorageTest
{ {
$logger = new NullLogger(); $logger = new NullLogger();
$profiler = \Mockery::mock(Profiler::class); $profiler = \Mockery::mock(Profiler::class);
$profiler->shouldReceive('startRecording');
$profiler->shouldReceive('stopRecording');
$profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true); $profiler->shouldReceive('saveTimestamp')->withAnyArgs()->andReturn(true);
/** @var MockInterface|L10n $l10n */ /** @var MockInterface|L10n $l10n */

View file

@ -59,7 +59,9 @@ class ProfilerLoggerTest extends MockedTest
$logger = new ProfilerLogger($this->logger, $this->profiler); $logger = new ProfilerLogger($this->logger, $this->profiler);
$this->logger->shouldReceive($function)->with($message, $context)->once(); $this->logger->shouldReceive($function)->with($message, $context)->once();
$this->profiler->shouldReceive('saveTimestamp')->with(\Mockery::any(), 'file')->once(); $this->profiler->shouldReceive('startRecording')->with('file')->once();
$this->profiler->shouldReceive('stopRecording');
$this->profiler->shouldReceive('saveTimestamp');
$logger->$function($message, $context); $logger->$function($message, $context);
} }
@ -72,7 +74,9 @@ class ProfilerLoggerTest extends MockedTest
$logger = new ProfilerLogger($this->logger, $this->profiler); $logger = new ProfilerLogger($this->logger, $this->profiler);
$this->logger->shouldReceive('log')->with(LogLevel::WARNING, 'test', ['a' => 'context'])->once(); $this->logger->shouldReceive('log')->with(LogLevel::WARNING, 'test', ['a' => 'context'])->once();
$this->profiler->shouldReceive('saveTimestamp')->with(\Mockery::any(), 'file')->once(); $this->profiler->shouldReceive('startRecording')->with('file')->once();
$this->profiler->shouldReceive('stopRecording');
$this->profiler->shouldReceive('saveTimestamp');
$logger->log(LogLevel::WARNING, 'test', ['a' => 'context']); $logger->log(LogLevel::WARNING, 'test', ['a' => 'context']);
} }

View file

@ -99,14 +99,14 @@ class ProfilerTest extends MockedTest
'name' => 'rendering', 'name' => 'rendering',
'functions' => ['test', 'it7'], 'functions' => ['test', 'it7'],
], ],
'parser' => [ 'session' => [
'timestamp' => time(), 'timestamp' => time(),
'name' => 'parser', 'name' => 'session',
'functions' => ['test', 'it8'], 'functions' => ['test', 'it8'],
], ],
'marktime' => [ 'marktime' => [
'timestamp' => time(), 'timestamp' => time(),
'name' => 'parser', 'name' => 'session',
'functions' => ['test'], 'functions' => ['test'],
], ],
// This one isn't set during reset // This one isn't set during reset

File diff suppressed because it is too large Load diff