]> git.mxchange.org Git - friendica.git/commitdiff
Merge pull request #5773 from MrPetovan/task/rewrite-js-hooks
authorMichael Vogel <icarus@dabo.de>
Mon, 1 Oct 2018 17:10:30 +0000 (17:10 +0000)
committerGitHub <noreply@github.com>
Mon, 1 Oct 2018 17:10:30 +0000 (17:10 +0000)
Rewrite JS hooks

1  2 
include/conversation.php
include/text.php
mod/contacts.php
mod/editpost.php
mod/events.php
mod/message.php
mod/videos.php
src/App.php
view/js/main.js
view/templates/head.tpl
view/theme/frio/templates/head.tpl

diff --combined include/conversation.php
index e41b697b547824d869ad487107b05503bb80e956,d791fa41419fec39bd8b1659379ce06577fe0ef5..59ee5ed8248cbdd4b2b7be65c74c6b3382bc2182
@@@ -229,12 -229,12 +229,12 @@@ function localize_item(&$item
                $xmlhead = "<" . "?xml version='1.0' encoding='UTF-8' ?" . ">";
  
                $obj = XML::parseString($xmlhead.$item['object']);
 -              $links = XML::parseString($xmlhead."<links>".unxmlify($obj->link)."</links>");
  
                $Bname = $obj->title;
 -              $Blink = "";
 +              $Blink = $obj->id;
                $Bphoto = "";
 -              foreach ($links->link as $l) {
 +
 +              foreach ($obj->link as $l) {
                        $atts = $l->attributes();
                        switch ($atts['rel']) {
                                case "alternate": $Blink = $atts['href'];
@@@ -1091,21 -1091,6 +1091,6 @@@ function status_editor(App $a, $x, $not
                '$delitems'  => L10n::t("Delete item\x28s\x29?")
        ]);
  
-       $tpl = get_markup_template('jot-end.tpl');
-       $a->page['end'] .= replace_macros($tpl, [
-               '$newpost'   => 'true',
-               '$baseurl'   => System::baseUrl(true),
-               '$geotag'    => $geotag,
-               '$nickname'  => $x['nickname'],
-               '$ispublic'  => L10n::t('Visible to <strong>everybody</strong>'),
-               '$linkurl'   => L10n::t('Please enter a link URL:'),
-               '$vidurl'    => L10n::t("Please enter a video link/URL:"),
-               '$audurl'    => L10n::t("Please enter an audio link/URL:"),
-               '$term'      => L10n::t('Tag term:'),
-               '$fileas'    => L10n::t('Save to Folder:'),
-               '$whereareu' => L10n::t('Where are you right now?')
-       ]);
        $jotplugins = '';
        Addon::callHooks('jot_tool', $jotplugins);
  
@@@ -1454,7 -1439,7 +1439,7 @@@ function get_responses(array $conv_resp
        $ret = [];
        foreach ($response_verbs as $v) {
                $ret[$v] = [];
 -              $ret[$v]['count'] = defaults($conv_responses[$v], $item['uri'], '');
 +              $ret[$v]['count'] = defaults($conv_responses[$v], $item['uri'], 0);
                $ret[$v]['list']  = defaults($conv_responses[$v], $item['uri'] . '-l', []);
                $ret[$v]['self']  = defaults($conv_responses[$v], $item['uri'] . '-self', '0');
                if (count($ret[$v]['list']) > MAX_LIKERS) {
diff --combined include/text.php
index 97baee7f60b551a76089ba31efbd66e573bb3412,53b806122148b686670a5888f41fb01a434d709b..7013c2c91b493baeba1d2cb8b22e7e08e6a37573
@@@ -1191,9 -1191,6 +1191,6 @@@ function prepare_body(array &$item, $at
                                $a->page['htmlhead'] .= replace_macros(get_markup_template('videos_head.tpl'), [
                                        '$baseurl' => System::baseUrl(),
                                ]);
-                               $a->page['end'] .= replace_macros(get_markup_template('videos_end.tpl'), [
-                                       '$baseurl' => System::baseUrl(),
-                               ]);
                        }
  
                        $url_parts = explode('/', $the_url);
@@@ -1911,3 -1908,58 +1908,3 @@@ function format_network_name($network, 
                return $network_name;
        }
  }
 -
 -/**
 - * @brief Syntax based code highlighting for popular languages.
 - * @param string $s Code block
 - * @param string $lang Programming language
 - * @return string Formated html
 - */
 -function text_highlight($s, $lang) {
 -      if ($lang === 'js') {
 -              $lang = 'javascript';
 -      }
 -
 -      if ($lang === 'bash') {
 -              $lang = 'sh';
 -      }
 -
 -      // @TODO: Replace Text_Highlighter_Renderer_Html by scrivo/highlight.php
 -
 -      // Autoload the library to make constants available
 -      class_exists('Text_Highlighter_Renderer_Html');
 -
 -      $options = [
 -              'numbers' => HL_NUMBERS_LI,
 -              'tabsize' => 4,
 -      ];
 -
 -      $tag_added = false;
 -      $s = trim(html_entity_decode($s, ENT_COMPAT));
 -      $s = str_replace('    ', "\t", $s);
 -
 -      /*
 -       * The highlighter library insists on an opening php tag for php code blocks. If
 -       * it isn't present, nothing is highlighted. So we're going to see if it's present.
 -       * If not, we'll add it, and then quietly remove it after we get the processed output back.
 -       */
 -      if ($lang === 'php' && strpos($s, '<?php') !== 0) {
 -              $s = '<?php' . "\n" . $s;
 -              $tag_added = true;
 -      }
 -
 -      $renderer = new Text_Highlighter_Renderer_Html($options);
 -      $factory = new Text_Highlighter();
 -      $hl = $factory->factory($lang);
 -      $hl->setRenderer($renderer);
 -      $o = $hl->highlight($s);
 -      $o = str_replace("\n", '', $o);
 -
 -      if ($tag_added) {
 -              $b = substr($o, 0, strpos($o, '<li>'));
 -              $e = substr($o, strpos($o, '</li>'));
 -              $o = $b . $e;
 -      }
 -
 -      return '<code>' . $o . '</code>';
 -}
diff --combined mod/contacts.php
index 1604f0b6605ec43d6f0e936972ad2394a45c11f2,86d7e2ac659e01d639cb8d9feb3ac644ad832381..68dbbd59ddbb4e904ed5b57f087c9751be8a177b
@@@ -47,11 -47,6 +47,11 @@@ function contacts_init(App $a
                if (!DBA::isResult($contact)) {
                        $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => 0]);
                }
 +
 +              // Don't display contacts that are about to be deleted
 +              if ($contact['network'] == Protocol::PHANTOM) {
 +                      $contact = false;
 +              }
        }
  
        if (DBA::isResult($contact)) {
                '$baseurl' => System::baseUrl(true),
                '$base' => $base
        ]);
-       $tpl = get_markup_template("contacts-end.tpl");
-       $a->page['end'] .= replace_macros($tpl, [
-               '$baseurl' => System::baseUrl(true),
-               '$base' => $base
-       ]);
  }
  
  function contacts_batch_actions(App $a)
  {
 -      $contacts_id = $_POST['contact_batch'];
 -      if (!is_array($contacts_id)) {
 +      if (empty($_POST['contact_batch']) || !is_array($_POST['contact_batch'])) {
                return;
        }
  
 +      $contacts_id = $_POST['contact_batch'];
 +
        $orig_records = q("SELECT * FROM `contact` WHERE `id` IN (%s) AND `uid` = %d AND `self` = 0",
                implode(",", $contacts_id),
                intval(local_user())
@@@ -373,7 -361,7 +367,7 @@@ function _contact_drop($orig_record
                return;
        }
  
 -      Contact::terminateFriendship($r[0], $orig_record);
 +      Contact::terminateFriendship($r[0], $orig_record, true);
        Contact::remove($orig_record['id']);
  }
  
@@@ -509,9 -497,6 +503,6 @@@ function contacts_content(App $a, $upda
                $a->page['htmlhead'] .= replace_macros(get_markup_template('contact_head.tpl'), [
                        '$baseurl' => System::baseUrl(true),
                ]);
-               $a->page['end'] .= replace_macros(get_markup_template('contact_end.tpl'), [
-                       '$baseurl' => System::baseUrl(true),
-               ]);
  
                $contact['blocked'] = Contact::isBlockedByUser($contact['id'], local_user());
                $contact['readonly'] = Contact::isIgnoredByUser($contact['id'], local_user());
                /// @todo Only show the following link with DFRN when the remote version supports it
                $follow = '';
                $follow_text = '';
 -              if (in_array($contact['network'], [Protocol::DIASPORA, Protocol::OSTATUS, Protocol::DFRN])) {
 -                      if (in_array($contact['rel'], [Contact::FRIEND, Contact::SHARING])) {
 +              if (in_array($contact['rel'], [Contact::FRIEND, Contact::SHARING])) {
 +                      if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) {
                                $follow = System::baseUrl(true) . "/unfollow?url=" . urlencode($contact["url"]);
                                $follow_text = L10n::t("Disconnect/Unfollow");
 -                      } else {
 -                              $follow = System::baseUrl(true) . "/follow?url=" . urlencode($contact["url"]);
 -                              $follow_text = L10n::t("Connect/Follow");
                        }
 -              }
 -
 -              if ($contact['uid'] == 0) {
 +              } else {
                        $follow = System::baseUrl(true) . "/follow?url=" . urlencode($contact["url"]);
                        $follow_text = L10n::t("Connect/Follow");
                }
                $sql_extra = " AND `blocked` = 0 ";
        }
  
 +      $sql_extra .= sprintf(" AND `network` != '%s' ", Protocol::PHANTOM);
 +
        $search = x($_GET, 'search') ? notags(trim($_GET['search'])) : '';
        $nets   = x($_GET, 'nets'  ) ? notags(trim($_GET['nets']))   : '';
  
diff --combined mod/editpost.php
index 9f4aee31d6c63421a2692990b123a3926ac17ec8,b8ccff470e5fd2fd7dc1873899bcaca4e1d25acb..d6493b3c0c1a8aa34f4d9c547ca1688fe3ca8759
@@@ -21,18 -21,12 +21,18 @@@ function editpost_content(App $a
        }
  
        $post_id = (($a->argc > 1) ? intval($a->argv[1]) : 0);
 +      $return_url = (($a->argc > 2) ? base64_decode($a->argv[2]) : '');
  
        if (!$post_id) {
                notice(L10n::t('Item not found') . EOL);
                return;
        }
  
 +      // Fallback to SESSION return_path
 +      if (empty($return_url)) {
 +              $return_url = $_SESSION['return_url'];
 +      }
 +
        $fields = ['allow_cid', 'allow_gid', 'deny_cid', 'deny_gid',
                'type', 'body', 'title', 'file', 'wall', 'post-type'];
  
                '$nickname' => $a->user['nickname']
        ]);
  
-       $tpl = get_markup_template('jot-end.tpl');
-       $a->page['end'] .= replace_macros($tpl, [
-               '$baseurl' => System::baseUrl(),
-               '$ispublic' => '&nbsp;', // L10n::t('Visible to <strong>everybody</strong>'),
-               '$geotag' => $geotag,
-               '$nickname' => $a->user['nickname']
-       ]);
        $tpl = get_markup_template("jot.tpl");
  
        if (strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) {
  
        $o .= replace_macros($tpl, [
                '$is_edit' => true,
 -              '$return_path' => $_SESSION['return_url'],
 +              '$return_path' => $return_url,
                '$action' => 'item',
                '$share' => L10n::t('Save'),
                '$upload' => L10n::t('Upload photo'),
diff --combined mod/events.php
index 38b632cf49e46d9a0fa0eda12966d61c0235af06,fd658a9cef1c08c8bdf75895b5a07d456a9ed3c3..d04aac3761267d05515e61d7d1d5e51a16e7b4ea
@@@ -20,8 -20,7 +20,8 @@@ use Friendica\Util\Temporal
  
  require_once 'include/items.php';
  
 -function events_init(App $a) {
 +function events_init(App $a)
 +{
        if (!local_user()) {
                return;
        }
@@@ -43,8 -42,7 +43,8 @@@
        return;
  }
  
 -function events_post(App $a) {
 +function events_post(App $a)
 +{
  
        logger('post: ' . print_r($_REQUEST, true), LOGGER_DATA);
  
                return;
        }
  
 -      $event_id = (x($_POST, 'event_id') ? intval($_POST['event_id']) : 0);
 -      $cid = (x($_POST, 'cid') ? intval($_POST['cid']) : 0);
 +      $event_id = !empty($_POST['event_id']) ? intval($_POST['event_id']) : 0;
 +      $cid = !empty($_POST['cid']) ? intval($_POST['cid']) : 0;
        $uid = local_user();
  
 -      $start_text  = escape_tags($_REQUEST['start_text']);
 -      $finish_text = escape_tags($_REQUEST['finish_text']);
 +      $start_text  = escape_tags(defaults($_REQUEST, 'start_text', ''));
 +      $finish_text = escape_tags(defaults($_REQUEST, 'finish_text', ''));
  
 -      $adjust   = intval($_POST['adjust']);
 -      $nofinish = intval($_POST['nofinish']);
 +      $adjust   = intval(defaults($_POST, 'adjust', 0));
 +      $nofinish = intval(defaults($_POST, 'nofinish', 0));
  
        // The default setting for the `private` field in event_store() is false, so mirror that
        $private_event = false;
@@@ -93,9 -91,9 +93,9 @@@
        // and we'll waste a bunch of time responding to it. Time that
        // could've been spent doing something else.
  
 -      $summary  = escape_tags(trim($_POST['summary']));
 -      $desc     = escape_tags(trim($_POST['desc']));
 -      $location = escape_tags(trim($_POST['location']));
 +      $summary  = escape_tags(trim(defaults($_POST, 'summary', '')));
 +      $desc     = escape_tags(trim(defaults($_POST, 'desc', '')));
 +      $location = escape_tags(trim(defaults($_POST, 'location', '')));
        $type     = 'event';
  
        $action = ($event_id == '') ? 'new' : "event/" . $event_id;
                goaway($onerror_url);
        }
  
 -      $share = (intval($_POST['share']) ? intval($_POST['share']) : 0);
 +      $share = intval(defaults($_POST, 'share', 0));
  
        $c = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1",
                intval(local_user())
                $str_contact_deny  = !empty($_POST['contact_deny'])  ? perms2str($_POST['contact_deny'])  : '';
  
                // Undo the pseudo-contact of self, since there are real contacts now
 -              if (strpos($str_contact_allow, '<' . $self . '>') !== false ) {
 +              if (strpos($str_contact_allow, '<' . $self . '>') !== false) {
                        $str_contact_allow = str_replace('<' . $self . '>', '', $str_contact_allow);
                }
                // Make sure to set the `private` field as true. This is necessary to
        goaway($_SESSION['return_url']);
  }
  
 -function events_content(App $a) {
 -
 +function events_content(App $a)
 +{
        if (!local_user()) {
                notice(L10n::t('Permission denied.') . EOL);
                return;
                '$i18n' => $i18n,
        ]);
  
-       $etpl = get_markup_template('event_end.tpl');
-       $a->page['end'] .= replace_macros($etpl, [
-               '$baseurl' => System::baseUrl(),
-       ]);
        $o = '';
        $tabs = '';
        // tabs
        $mode = 'view';
        $y = 0;
        $m = 0;
 -      $ignored = (x($_REQUEST, 'ignored') ? intval($_REQUEST['ignored']) : 0);
 +      $ignored = !empty($_REQUEST['ignored']) ? intval($_REQUEST['ignored']) : 0;
  
        if ($a->argc > 1) {
                if ($a->argc > 2 && $a->argv[1] == 'event') {
  
        // The view mode part is similiar to /mod/cal.php
        if ($mode == 'view') {
 -
                $thisyear  = DateTimeFormat::localNow('Y');
                $thismonth = DateTimeFormat::localNow('m');
                if (!$y) {
                $finish = sprintf('%d-%d-%d %d:%d:%d', $y, $m, $dim, 23, 59, 59);
  
                if ($a->argc > 1 && $a->argv[1] === 'json') {
 -                      if (x($_GET, 'start')) {
 -                              $start  = $_GET['start'];
 +                      if (!empty($_GET['start'])) {
 +                              $start = $_GET['start'];
                        }
 -                      if (x($_GET, 'end'))   {
 +                      if (!empty($_GET['end'])) {
                                $finish = $_GET['end'];
                        }
                }
                        $r = Event::sortByDate($r);
                        foreach ($r as $rr) {
                                $j = $rr['adjust'] ? DateTimeFormat::local($rr['start'], 'j') : DateTimeFormat::utc($rr['start'], 'j');
 -                              if (!x($links,$j)) {
 +                              if (empty($links[$j])) {
                                        $links[$j] = System::baseUrl() . '/' . $a->cmd . '#link-' . $j;
                                }
                        }
                        $events = Event::prepareListForTemplate($r);
                }
  
 -              if ($a->argc > 1 && $a->argv[1] === 'json'){
 +              if ($a->argc > 1 && $a->argv[1] === 'json') {
                        echo json_encode($events);
                        killme();
                }
  
 -              if (x($_GET, 'id')) {
 +              if (!empty($_GET['id'])) {
                        $tpl = get_markup_template("event.tpl");
                } else {
                        $tpl = get_markup_template("events_js.tpl");
                foreach ($events as $key => $event) {
                        $event_item = [];
                        foreach ($event['item'] as $k => $v) {
 -                              $k = str_replace('-' ,'_', $k);
 +                              $k = str_replace('-''_', $k);
                                $event_item[$k] = $v;
                        }
                        $events[$key]['item'] = $event_item;
                        '$list'  => L10n::t('list'),
                ]);
  
 -              if (x($_GET, 'id')) {
 +              if (!empty($_GET['id'])) {
                        echo $o;
                        killme();
                }
                }
  
                // In case of an error the browser is redirected back here, with these parameters filled in with the previous values
 -              if (x($_REQUEST, 'nofinish'))    {$orig_event['nofinish']    = $_REQUEST['nofinish'];}
 -              if (x($_REQUEST, 'adjust'))      {$orig_event['adjust']      = $_REQUEST['adjust'];}
 -              if (x($_REQUEST, 'summary'))     {$orig_event['summary']     = $_REQUEST['summary'];}
 -              if (x($_REQUEST, 'description')) {$orig_event['description'] = $_REQUEST['description'];}
 -              if (x($_REQUEST, 'location'))    {$orig_event['location']    = $_REQUEST['location'];}
 -              if (x($_REQUEST, 'start'))       {$orig_event['start']       = $_REQUEST['start'];}
 -              if (x($_REQUEST, 'finish'))      {$orig_event['finish']      = $_REQUEST['finish'];}
 -              if (x($_REQUEST,'finish')) $orig_event['finish'] = $_REQUEST['finish'];
 -
 -              $n_checked = ((x($orig_event) && $orig_event['nofinish']) ? ' checked="checked" ' : '');
 -              $a_checked = ((x($orig_event) && $orig_event['adjust'])   ? ' checked="checked" ' : '');
 -
 -              $t_orig = (x($orig_event) ? $orig_event['summary']  : '');
 -              $d_orig = (x($orig_event) ? $orig_event['desc']     : '');
 -              $l_orig = (x($orig_event) ? $orig_event['location'] : '');
 -              $eid    = (x($orig_event) ? $orig_event['id']       : 0);
 -              $cid    = (x($orig_event) ? $orig_event['cid']      : 0);
 -              $uri    = (x($orig_event) ? $orig_event['uri']      : '');
 +              if (!empty($_REQUEST['nofinish']))    {$orig_event['nofinish']    = $_REQUEST['nofinish'];}
 +              if (!empty($_REQUEST['adjust']))      {$orig_event['adjust']      = $_REQUEST['adjust'];}
 +              if (!empty($_REQUEST['summary']))     {$orig_event['summary']     = $_REQUEST['summary'];}
 +              if (!empty($_REQUEST['description'])) {$orig_event['description'] = $_REQUEST['description'];}
 +              if (!empty($_REQUEST['location']))    {$orig_event['location']    = $_REQUEST['location'];}
 +              if (!empty($_REQUEST['start']))       {$orig_event['start']       = $_REQUEST['start'];}
 +              if (!empty($_REQUEST['finish']))      {$orig_event['finish']      = $_REQUEST['finish'];}
 +
 +              $n_checked = (!empty($orig_event['nofinish']) ? ' checked="checked" ' : '');
 +              $a_checked = (!empty($orig_event['adjust'])   ? ' checked="checked" ' : '');
 +
 +              $t_orig = !empty($orig_event) ? $orig_event['summary']  : '';
 +              $d_orig = !empty($orig_event) ? $orig_event['desc']     : '';
 +              $l_orig = !empty($orig_event) ? $orig_event['location'] : '';
 +              $eid = !empty($orig_event) ? $orig_event['id']  : 0;
 +              $cid = !empty($orig_event) ? $orig_event['cid'] : 0;
 +              $uri = !empty($orig_event) ? $orig_event['uri'] : '';
  
                $sh_disabled = '';
 -              $sh_checked  = '';
 +              $sh_checked = '';
  
 -              if (x($orig_event)) {
 -                      $sh_checked = (($orig_event['allow_cid'] === '<' . local_user() . '>' && !$orig_event['allow_gid'] && !$orig_event['deny_cid'] && !$orig_event['deny_gid']) ? '' : ' checked="checked" ');
 +              if (!empty($orig_event)
 +                      && ($orig_event['allow_cid'] !== '<' . local_user() . '>'
 +                      || $orig_event['allow_gid']
 +                      || $orig_event['deny_cid']
 +                      || $orig_event['deny_gid']))
 +              {
 +                      $sh_checked = ' checked="checked" ';
                }
  
                if ($cid || $mode === 'edit') {
                        $sh_disabled = 'disabled="disabled"';
                }
  
 -              $sdt = (x($orig_event) ? $orig_event['start']  : 'now');
 -              $fdt = (x($orig_event) ? $orig_event['finish'] : 'now');
 +              $sdt = !empty($orig_event) ? $orig_event['start']  : 'now';
 +              $fdt = !empty($orig_event) ? $orig_event['finish'] : 'now';
  
                $tz = date_default_timezone_get();
 -              if (x($orig_event)) {
 +              if (!empty($orig_event)) {
                        $tz = ($orig_event['adjust'] ? date_default_timezone_get() : 'UTC');
                }
  
                $smonth = DateTimeFormat::convert($sdt, $tz, 'UTC', 'm');
                $sday   = DateTimeFormat::convert($sdt, $tz, 'UTC', 'd');
  
 -              $shour   = (x($orig_event) ? DateTimeFormat::convert($sdt, $tz, 'UTC', 'H') : '00');
 -              $sminute = (x($orig_event) ? DateTimeFormat::convert($sdt, $tz, 'UTC', 'i') : '00');
 +              $shour   = !empty($orig_event) ? DateTimeFormat::convert($sdt, $tz, 'UTC', 'H') : '00';
 +              $sminute = !empty($orig_event) ? DateTimeFormat::convert($sdt, $tz, 'UTC', 'i') : '00';
  
                $fyear  = DateTimeFormat::convert($fdt, $tz, 'UTC', 'Y');
                $fmonth = DateTimeFormat::convert($fdt, $tz, 'UTC', 'm');
                $fday   = DateTimeFormat::convert($fdt, $tz, 'UTC', 'd');
  
 -              $fhour   = (x($orig_event) ? DateTimeFormat::convert($fdt, $tz, 'UTC', 'H') : '00');
 -              $fminute = (x($orig_event) ? DateTimeFormat::convert($fdt, $tz, 'UTC', 'i') : '00');
 +              $fhour   = !empty($orig_event) ? DateTimeFormat::convert($fdt, $tz, 'UTC', 'H') : '00';
 +              $fminute = !empty($orig_event) ? DateTimeFormat::convert($fdt, $tz, 'UTC', 'i') : '00';
  
                $perms = ACL::getDefaultUserPermissions($orig_event);
  
 -              if ($mode === 'new' || $mode === 'copy') {
 -                      $acl = ($cid ? '' : ACL::getFullSelectorHTML($a->user, false, $orig_event));
 +              if (!$cid && in_array($mode, ['new', 'copy'])) {
 +                      $acl = ACL::getFullSelectorHTML($a->user, false, $orig_event);
 +              } else {
 +                      $acl = '';
                }
  
                // If we copy an old event, we need to remove the ID and URI
  
                $tpl = get_markup_template('event_form.tpl');
  
 -              $o .= replace_macros($tpl,[
 +              $o .= replace_macros($tpl, [
                        '$post' => System::baseUrl() . '/events',
                        '$eid'  => $eid,
                        '$cid'  => $cid,
                        '$title' => L10n::t('Event details'),
                        '$desc' => L10n::t('Starting date and Title are required.'),
                        '$s_text' => L10n::t('Event Starts:') . ' <span class="required" title="' . L10n::t('Required') . '">*</span>',
 -                      '$s_dsel' => Temporal::getDateTimeField(new DateTime(), DateTime::createFromFormat('Y', $syear+5), DateTime::createFromFormat('Y-m-d H:i', "$syear-$smonth-$sday $shour:$sminute"), L10n::t('Event Starts:'), 'start_text', true, true, '', '', true),
 +                      '$s_dsel' => Temporal::getDateTimeField(
 +                              new DateTime(),
 +                              DateTime::createFromFormat('Y', $syear+5),
 +                              DateTime::createFromFormat('Y-m-d H:i', "$syear-$smonth-$sday $shour:$sminute"),
 +                              L10n::t('Event Starts:'),
 +                              'start_text',
 +                              true,
 +                              true,
 +                              '',
 +                              '',
 +                              true
 +                      ),
                        '$n_text' => L10n::t('Finish date/time is not known or not relevant'),
                        '$n_checked' => $n_checked,
                        '$f_text' => L10n::t('Event Finishes:'),
 -                      '$f_dsel' => Temporal::getDateTimeField(new DateTime(), DateTime::createFromFormat('Y', $fyear+5), DateTime::createFromFormat('Y-m-d H:i', "$fyear-$fmonth-$fday $fhour:$fminute"), L10n::t('Event Finishes:'), 'finish_text', true, true, 'start_text'),
 +                      '$f_dsel' => Temporal::getDateTimeField(
 +                              new DateTime(),
 +                              DateTime::createFromFormat('Y', $fyear+5),
 +                              DateTime::createFromFormat('Y-m-d H:i', "$fyear-$fmonth-$fday $fhour:$fminute"),
 +                              L10n::t('Event Finishes:'),
 +                              'finish_text',
 +                              true,
 +                              true,
 +                              'start_text'
 +                      ),
                        '$a_text' => L10n::t('Adjust for viewer timezone'),
                        '$a_checked' => $a_checked,
                        '$d_text' => L10n::t('Description:'),
                        '$basic' => L10n::t('Basic'),
                        '$advanced' => L10n::t('Advanced'),
                        '$permissions' => L10n::t('Permissions'),
 -
                ]);
  
                return $o;
diff --combined mod/message.php
index d0a583967b047c3a61a6261f5dd10f9f6657693c,23d528a8aa32d984d032e2840b5ba0dd6144d399..7dc42177635fcf6885dafb843c843738b4970062
@@@ -46,12 -46,6 +46,6 @@@ function message_init(App $a
                '$baseurl' => System::baseUrl(true),
                '$base' => $base
        ]);
-       $end_tpl = get_markup_template('message-end.tpl');
-       $a->page['end'] .= replace_macros($end_tpl, [
-               '$baseurl' => System::baseUrl(true),
-               '$base' => $base
-       ]);
  }
  
  function message_post(App $a)
@@@ -92,7 -86,7 +86,7 @@@
                $a->argc = 2;
                $a->argv[1] = 'new';
        } else {
 -              goaway($_SESSION['return_url']);
 +              goaway($a->cmd . '/' . $ret);
        }
  }
  
@@@ -199,13 -193,6 +193,6 @@@ function message_content(App $a
                        '$linkurl' => L10n::t('Please enter a link URL:')
                ]);
  
-               $tpl = get_markup_template('msg-end.tpl');
-               $a->page['end'] .= replace_macros($tpl, [
-                       '$baseurl' => System::baseUrl(true),
-                       '$nickname' => $a->user['nickname'],
-                       '$linkurl' => L10n::t('Please enter a link URL:')
-               ]);
                $preselect = isset($a->argv[2]) ? [$a->argv[2]] : [];
  
                $prename = $preurl = $preid = '';
                        '$linkurl' => L10n::t('Please enter a link URL:')
                ]);
  
-               $tpl = get_markup_template('msg-end.tpl');
-               $a->page['end'] .= replace_macros($tpl, [
-                       '$baseurl' => System::baseUrl(true),
-                       '$nickname' => $a->user['nickname'],
-                       '$linkurl' => L10n::t('Please enter a link URL:')
-               ]);
                $mails = [];
                $seen = 0;
                $unknown = false;
@@@ -488,7 -468,7 +468,7 @@@ function render_messages(array $msg, $t
                        '$id' => $rr['id'],
                        '$from_name' => $participants,
                        '$from_url' => Contact::magicLink($rr['url']),
 -                      '$from_addr' => $contact['addr'],
 +                      '$from_addr' => defaults($contact, 'addr', ''),
                        '$sparkle' => ' sparkle',
                        '$from_photo' => ProxyUtils::proxifyUrl($from_photo, false, ProxyUtils::SIZE_THUMB),
                        '$subject' => $subject_e,
diff --combined mod/videos.php
index e00df10a24b48d171fa05287c7456b86875a795d,4bd0ab4f3262431f6f7b0fee5f347a1247ba226e..a0c9d0d16edfeb8cd4e761a2784f02104b212799
@@@ -105,12 -105,6 +105,6 @@@ function videos_init(App $a
                $a->page['htmlhead'] .= replace_macros($tpl,[
                        '$baseurl' => System::baseUrl(),
                ]);
-               $tpl = get_markup_template("videos_end.tpl");
-               $a->page['end'] .= replace_macros($tpl,[
-                       '$baseurl' => System::baseUrl(),
-               ]);
        }
  
        return;
@@@ -367,12 -361,11 +361,12 @@@ function videos_content(App $a
                foreach ($r as $rr) {
                        $alt_e = $rr['filename'];
                        /// @todo The album isn't part of the above query. This seems to be some unfinished code that needs to be reworked completely.
 +                      $rr['album'] = '';
                        $name_e = $rr['album'];
  
                        $videos[] = [
                                'id'       => $rr['id'],
 -                              'link'     => System::baseUrl() . '/videos/' . $a->data['user']['nickname'] . '/video/' . $rr['resource-id'],
 +                              'link'     => System::baseUrl() . '/videos/' . $a->data['user']['nickname'] . '/video/' . $rr['hash'],
                                'title'    => L10n::t('View Video'),
                                'src'      => System::baseUrl() . '/attach/' . $rr['id'] . '?attachment=0',
                                'alt'      => $alt_e,
diff --combined src/App.php
index 0dc4b86b95f6520f14bb966e45f552ff6e8ad511,3761004575a8157c38b107a556204f30b5140afb..7622a1a0ce3aacb5e2795fbdd6b9c1e7b572e78e
@@@ -96,6 -96,41 +96,41 @@@ class Ap
        public $force_max_items = 0;
        public $theme_events_in_profile = true;
  
+       public $stylesheets = [];
+       public $footerScripts = [];
+       /**
+        * Register a stylesheet file path to be included in the <head> tag of every page.
+        * Inclusion is done in App->initHead().
+        * The path can be absolute or relative to the Friendica installation base folder.
+        *
+        * @see App->initHead()
+        *
+        * @param string $path
+        */
+       public function registerStylesheet($path)
+       {
+               $url = str_replace($this->get_basepath() . DIRECTORY_SEPARATOR, '', $path);
+               $this->stylesheets[] = trim($url, '/');
+       }
+       /**
+        * Register a javascript file path to be included in the <footer> tag of every page.
+        * Inclusion is done in App->initFooter().
+        * The path can be absolute or relative to the Friendica installation base folder.
+        *
+        * @see App->initFooter()
+        *
+        * @param string $path
+        */
+       public function registerFooterScript($path)
+       {
+               $url = str_replace($this->get_basepath() . DIRECTORY_SEPARATOR, '', $path);
+               $this->footerScripts[] = trim($url, '/');
+       }
        /**
         * @brief An array for all theme-controllable parameters
         *
                        'aside' => '',
                        'bottom' => '',
                        'content' => '',
-                       'end' => '',
                        'footer' => '',
                        'htmlhead' => '',
                        'nav' => '',
                }
  
                if (file_exists($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php')) {
 -                      $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php');
 +                      $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php', true);
                }
        }
  
        /**
         * Tries to load the specified configuration file into the App->config array.
 -       * Overwrites previously set values.
 +       * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config.
         *
         * The config format is INI and the template for configuration files is the following:
         *
         * // Keep this line
         *
         * @param type $filepath
 +       * @param bool $overwrite Force value overwrite if the config key already exists
         * @throws Exception
         */
 -      public function loadConfigFile($filepath)
 +      public function loadConfigFile($filepath, $overwrite = false)
        {
                if (!file_exists($filepath)) {
                        throw new Exception('Error parsing non-existent config file ' . $filepath);
  
                foreach ($config as $category => $values) {
                        foreach ($values as $key => $value) {
 -                              $this->setConfigValue($category, $key, $value);
 +                              if ($overwrite) {
 +                                      $this->setConfigValue($category, $key, $value);
 +                              } else {
 +                                      $this->setDefaultConfigValue($category, $key, $value);
 +                              }
                        }
                }
        }
  
                // Load the local addon config file to overwritten default addon config values
                if (file_exists($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'addon.ini.php')) {
 -                      $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'addon.ini.php');
 +                      $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'addon.ini.php', true);
                }
        }
  
                $this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage'];
        }
  
-       public function init_pagehead()
+       /**
+        * Initializes App->page['htmlhead'].
+        *
+        * Includes:
+        * - Page title
+        * - Favicons
+        * - Registered stylesheets (through App->registerStylesheet())
+        * - Infinite scroll data
+        * - head.tpl template
+        */
+       public function initHead()
        {
                $interval = ((local_user()) ? PConfig::get(local_user(), 'system', 'update_interval') : 40000);
  
                        $this->page['title'] = $this->config['sitename'];
                }
  
-               /* put the head template at the beginning of page['htmlhead']
-                * since the code added by the modules frequently depends on it
-                * being first
-                */
-               if (!isset($this->page['htmlhead'])) {
-                       $this->page['htmlhead'] = '';
-               }
-               // If we're using Smarty, then doing replace_macros() will replace
-               // any unrecognized variables with a blank string. Since we delay
-               // replacing $stylesheet until later, we need to replace it now
-               // with another variable name
-               if ($this->theme['template_engine'] === 'smarty3') {
-                       $stylesheet = $this->get_template_ldelim('smarty3') . '$stylesheet' . $this->get_template_rdelim('smarty3');
+               if (!empty($this->theme['stylesheet'])) {
+                       $stylesheet = $this->theme['stylesheet'];
                } else {
-                       $stylesheet = '$stylesheet';
+                       $stylesheet = $this->getCurrentThemeStylesheetPath();
                }
  
+               $this->registerStylesheet($stylesheet);
                $shortcut_icon = Config::get('system', 'shortcut_icon');
                if ($shortcut_icon == '') {
                        $shortcut_icon = 'images/friendica-32.png';
                }
  
                // get data wich is needed for infinite scroll on the network page
-               $invinite_scroll = infinite_scroll_data($this->module);
+               $infinite_scroll = infinite_scroll_data($this->module);
+               Core\Addon::callHooks('head', $this->page['htmlhead']);
  
                $tpl = get_markup_template('head.tpl');
+               /* put the head template at the beginning of page['htmlhead']
+                * since the code added by the modules frequently depends on it
+                * being first
+                */
                $this->page['htmlhead'] = replace_macros($tpl, [
                        '$baseurl'         => $this->get_baseurl(),
                        '$local_user'      => local_user(),
                        '$update_interval' => $interval,
                        '$shortcut_icon'   => $shortcut_icon,
                        '$touch_icon'      => $touch_icon,
-                       '$stylesheet'      => $stylesheet,
-                       '$infinite_scroll' => $invinite_scroll,
+                       '$infinite_scroll' => $infinite_scroll,
                        '$block_public'    => intval(Config::get('system', 'block_public')),
+                       '$stylesheets'     => $this->stylesheets,
                ]) . $this->page['htmlhead'];
        }
  
-       public function init_page_end()
+       /**
+        * Initializes App->page['footer'].
+        *
+        * Includes:
+        * - Javascript homebase
+        * - Mobile toggle link
+        * - Registered footer scripts (through App->registerFooterScript())
+        * - footer.tpl template
+        */
+       public function initFooter()
        {
-               if (!isset($this->page['end'])) {
-                       $this->page['end'] = '';
+               // If you're just visiting, let javascript take you home
+               if (!empty($_SESSION['visitor_home'])) {
+                       $homebase = $_SESSION['visitor_home'];
+               } elseif (local_user()) {
+                       $homebase = 'profile/' . $this->user['nickname'];
+               }
+               if (isset($homebase)) {
+                       $this->page['footer'] .= '<script>var homebase="' . $homebase . '";</script>' . "\n";
                }
-               $tpl = get_markup_template('end.tpl');
-               $this->page['end'] = replace_macros($tpl, [
-                       '$baseurl' => $this->get_baseurl()
-               ]) . $this->page['end'];
+               /*
+                * Add a "toggle mobile" link if we're using a mobile device
+                */
+               if ($this->is_mobile || $this->is_tablet) {
+                       if (isset($_SESSION['show-mobile']) && !$_SESSION['show-mobile']) {
+                               $link = 'toggle_mobile?address=' . curPageURL();
+                       } else {
+                               $link = 'toggle_mobile?off=1&address=' . curPageURL();
+                       }
+                       $this->page['footer'] .= replace_macros(get_markup_template("toggle_mobile_footer.tpl"), [
+                               '$toggle_link' => $link,
+                               '$toggle_text' => Core\L10n::t('toggle mobile')
+                       ]);
+               }
+               Core\Addon::callHooks('footer', $this->page['footer']);
+               $tpl = get_markup_template('footer.tpl');
+               $this->page['footer'] = replace_macros($tpl, [
+                       '$baseurl' => $this->get_baseurl(),
+                       '$footerScripts' => $this->footerScripts,
+               ]) . $this->page['footer'];
        }
  
        public function set_curl_code($code)
  
                $meminfo = [];
                foreach ($memdata as $line) {
 -                      list($key, $val) = explode(':', $line);
 +                      $data = explode(':', $line);
 +                      if (count($data) != 2) {
 +                              continue;
 +                      }
 +                      list($key, $val) = $data;
                        $meminfo[$key] = (int) trim(str_replace('kB', '', $val));
                        $meminfo[$key] = (int) ($meminfo[$key] / 1024);
                }
                return $return;
        }
  
 +      /**
 +       * Sets a default value in the config cache. Ignores already existing keys.
 +       *
 +       * @param string $cat Config category
 +       * @param string $k   Config key
 +       * @param mixed  $v   Default value to set
 +       */
 +      private function setDefaultConfigValue($cat, $k, $v)
 +      {
 +              if (!isset($this->config[$cat][$k])) {
 +                      $this->setConfigValue($cat, $k, $v);
 +              }
 +      }
 +
        /**
         * Sets a value in the config cache. Accepts raw output from the config table
         *
diff --combined view/js/main.js
index 83086c82b037b4f322bf832b98e233fcde979f18,b41750b6a56dad16722e51779d32db74ec79857e..7e726248d3fd0f3c939dc7957a407ec4a266cbee
@@@ -81,11 -81,6 +81,11 @@@ $(function() 
                        Dialog.doImageBrowser("comment", id);
                        return;
                }
 +
 +              if (bbcode == "imgprv") {
 +                      bbcode = "img";
 +              }
 +
                insertFormatting(bbcode, id);
        });
  
        // Asynchronous calls are deferred until the very end of the page load to ease on slower connections
        window.addEventListener("load", function(){
                NavUpdate();
 -              acl.get(0, 100);
 +              if (typeof acl !== 'undefined') {
 +                      acl.get(0, 100);
 +              }
        });
  
        // Allow folks to stop the ajax page updates with the pause/break key
@@@ -485,14 -478,12 +485,12 @@@ function liveUpdate(src) 
                $('.wall-item-body', data).imagesLoaded(function() {
                        updateConvItems(data);
  
+                       document.dispatchEvent(new Event('postprocess_liveupdate'));
                        // Update the scroll position.
                        $(window).scrollTop($(window).scrollTop() + $("section").height() - orgHeight);
                });
-               callAddonHooks("postprocess_liveupdate");
        });
  }
  
  function imgbright(node) {
@@@ -676,6 -667,7 +674,7 @@@ function preview_post() 
                        if (data.preview) {
                                $("#jot-preview-content").html(data.preview);
                                $("#jot-preview-content" + " a").click(function() {return false;});
+                               document.dispatchEvent(new Event('postprocess_liveupdate'));
                        }
                },
                "json"
@@@ -742,6 -734,8 +741,8 @@@ function loadScrollContent() 
                } else {
                        $("#scroll-end").fadeIn('normal');
                }
+               document.dispatchEvent(new Event('postprocess_liveupdate'));
        });
  }
  
diff --combined view/templates/head.tpl
index 7da270d3ff1ed8b6a0b59905178766ee874a7f43,6c08bc8e452870f8fffbad9360ea81cc08d3a67d..6c55f99771e63beb58ed9f61852136bfb32f896e
@@@ -7,13 -7,12 +7,11 @@@
  <link rel="stylesheet" href="view/asset/jgrowl/jquery.jgrowl.min.css" type="text/css" media="screen" />
  <link rel="stylesheet" href="view/asset/jquery-datetimepicker/build/jquery.datetimepicker.min.css" type="text/css" media="screen" />
  <link rel="stylesheet" href="view/asset/perfect-scrollbar/css/perfect-scrollbar.min.css" type="text/css" media="screen" />
 -<link rel="stylesheet" href="vendor/pear/text_highlighter/sample.css" type="text/css" media="screen" />
  
- <link rel="stylesheet" type="text/css" href="{{$stylesheet}}" media="all" />
+ {{foreach $stylesheets as $stylesheetUrl}}
+ <link rel="stylesheet" href="{{$stylesheetUrl}}" type="text/css" media="screen" />
+ {{/foreach}}
  
- <!--
- <link rel="shortcut icon" href="images/friendica-32.png" />
- <link rel="apple-touch-icon" href="images/friendica-128.png"/>
- -->
  <link rel="shortcut icon" href="{{$shortcut_icon}}" />
  <link rel="apple-touch-icon" href="{{$touch_icon}}"/>
  
  <script type="text/javascript" src="view/asset/imagesloaded/imagesloaded.pkgd.min.js"></script>
  <script type="text/javascript" src="view/js/acl.js" ></script>
  <script type="text/javascript" src="view/asset/base64/base64.min.js" ></script>
- <script type="text/javascript" src="view/js/addon-hooks.js" ></script>
- {{if is_array($addon_hooks)}}
- {{foreach $addon_hooks as $addon_hook}}
- <script type="text/javascript" src="addon/{{$addon_hook}}/{{$addon_hook}}.js"></script>
- {{/foreach}}
- {{/if}}
  <script type="text/javascript" src="view/js/main.js" ></script>
  <script>
  
index 9d26a61b45595fa204124ebb52f8ec8fe9bb7baf,b68dde506f46cead6387836ed71a42ba9ade1ba7..d8f8b1d82dc531bc1e7906d81eb534226e1606fc
@@@ -12,6 -12,7 +12,6 @@@
  <link rel="stylesheet" href="view/asset/jgrowl/jquery.jgrowl.min.css" type="text/css" media="screen" />
  <link rel="stylesheet" href="view/asset/jquery-datetimepicker/build/jquery.datetimepicker.min.css" type="text/css" media="screen" />
  <link rel="stylesheet" href="view/asset/perfect-scrollbar/css/perfect-scrollbar.min.css" type="text/css" media="screen" />
 -<link rel="stylesheet" href="vendor/pear/text_highlighter/sample.css" type="text/css" media="screen" />
  
  <link rel="stylesheet" href="view/theme/frio/frameworks/bootstrap/css/bootstrap.min.css" type="text/css" media="screen"/>
  <link rel="stylesheet" href="view/theme/frio/frameworks/bootstrap/css/bootstrap-theme.min.css" type="text/css" media="screen"/>
  <link rel="stylesheet" href="view/theme/frio/frameworks/bootstrap-toggle/css/bootstrap-toggle.min.css" type="text/css" media="screen"/>
  <link rel="stylesheet" href="view/theme/frio/font/open_sans/open-sans.css" type="text/css" media="screen"/>
  
- {{* The own style.css *}}
- <link rel="stylesheet" type="text/css" href="{{$stylesheet}}" media="all" />
+ {{foreach $stylesheets as $stylesheetUrl}}
+ <link rel="stylesheet" href="{{$stylesheetUrl}}" type="text/css" media="screen" />
+ {{/foreach}}
  
  {{* own css files *}}
  <link rel="stylesheet" href="view/theme/frio/css/hovercard.css" type="text/css" media="screen"/>
  <link rel="stylesheet" href="view/theme/frio/css/font-awesome.custom.css" type="text/css" media="screen"/>
  
- <!--
- <link rel="shortcut icon" href="images/friendica-32.png" />
- <link rel="apple-touch-icon" href="images/friendica-128.png"/>
- -->
  <link rel="shortcut icon" href="{{$shortcut_icon}}" />
  <link rel="apple-touch-icon" href="{{$touch_icon}}"/>
  
  <script type="text/javascript" src="view/asset/imagesloaded/imagesloaded.pkgd.min.js"></script>
  <script type="text/javascript" src="view/js/acl.js"></script>
  <script type="text/javascript" src="view/asset/base64/base64.min.js"></script>
- <script type="text/javascript" src="view/js/addon-hooks.js" ></script>
- {{if is_array($addon_hooks)}}
- {{foreach $addon_hooks as $addon_hook}}
- <script type="text/javascript" src="addon/{{$addon_hook}}/{{$addon_hook}}.js"></script>
- {{/foreach}}
- {{/if}}
  <script type="text/javascript" src="view/js/main.js"></script>
  
  <script type="text/javascript" src="view/theme/frio/frameworks/bootstrap/js/bootstrap.min.js"></script>