JavaScript addon hooks
---
+#### PHP part
+Make sure your JavaScript addon file (addon/*addon_name*/*addon_name*.js) is listed in the document response.
+
+In your addon install function, add:
+
+ Addon::registerHook('template_vars', 'addon/<addon_name>/<addon_name>.php', '<addon_name>_template_vars');
+
+In your addon uninstall function, add:
+
+ Addon::unregisterHook('template_vars', 'addon/<addon_name>/<addon_name>.php', '<addon_name>_template_vars');
+
+Then, add your addon name to the *addon_hooks* template variable array:
+
+ function <addon_name>_template_vars($a, &$arr)
+ {
+ if (!array_key_exists('addon_hooks',$arr['vars']))
+ {
+ $arr['vars']['addon_hooks'] = array();
+ }
+ $arr['vars']['addon_hooks'][] = "<addon_name>";
+ }
+
+#### JavaScript part
Register your addon hooks in file 'addon/*addon_name*/*addon_name*.js'.
Addon_registerHook(type,hookfnstr);
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]'
);
- $body = L10n::t('Full Name: %1$s\nSite Location: %2$s\nLogin Name: %3$s ' . "\x28" . '%4$s' . "\x29",
+ $body = L10n::t("Full Name: %s\nSite Location: %s\nLogin Name: %s (%s)",
$params['source_name'],
$siteurl, $params['source_mail'],
$params['source_nick']
}
}
- // textversion keeps linebreaks
- $textversion = strip_tags(str_replace("<br>", "\n", html_entity_decode(BBCode::convert(stripslashes(str_replace(["\\r\\n", "\\r", "\\n"], "\n",
- $body))),ENT_QUOTES, 'UTF-8')));
- $htmlversion = html_entity_decode(BBCode::convert(stripslashes(str_replace(["\\r\\n", "\\r", "\\n\\n", "\\n"],
- "<br />\n", $body))), ENT_QUOTES, 'UTF-8');
+ $textversion = BBCode::toPlaintext($body);
+ $htmlversion = BBCode::convert($body);
$datarray = [];
$datarray['banner'] = $banner;
'itemurl' => (($rr['addr'] != "") ? $rr['addr'] : $rr['url']),
'url' => $url,
'network' => ContactSelector::networkToName($rr['network'], $rr['url']),
+ 'nick' => htmlentities($rr['nick']),
];
}
switch ($it['label']) {
case 'friend_suggestion':
$notif_content[] = replace_macros($sugg, [
- '$str_notifytype' => L10n::t('Notification type: '),
+ '$type' => $it['label'],
+ '$str_notifytype' => L10n::t('Notification type:'),
'$notify_type' => $it['notify_type'],
'$intro_id' => $it['intro_id'],
- '$madeby' => L10n::t('suggested by %s', $it['madeby']),
- '$contact_id' => $it['contact-id'],
+ '$lbl_madeby' => L10n::t('Suggested by:'),
+ '$madeby' => $it['madeby'],
+ '$madeby_url' => $it['madeby_url'],
+ '$madeby_zrl' => $it['madeby_zrl'],
+ '$madeby_addr' => $it['madeby_addr'],
+ '$contact_id' => $it['contact_id'],
'$photo' => $it['photo'],
'$fullname' => $it['name'],
'$url' => $it['url'],
+ '$zrl' => $it['zrl'],
+ '$lbl_url' => L10n::t('Profile URL'),
+ '$addr' => $it['addr'],
'$hidden' => ['hidden', L10n::t('Hide this contact from others'), ($it['hidden'] == 1), ''],
'$knowyou' => $it['knowyou'],
}
$notif_content[] = replace_macros($tpl, [
+ '$type' => $it['label'],
'$header' => htmlentities($header),
- '$str_notifytype' => L10n::t('Notification type: '),
+ '$str_notifytype' => L10n::t('Notification type:'),
'$notify_type' => $it['notify_type'],
'$dfrn_text' => $dfrn_text,
'$dfrn_id' => $it['dfrn_id'],
'guid', 'created', 'plink', 'title'];
$item = Item::selectFirst(local_user(), $fields, ['id' => $post_id]);
- if (!DBM::is_result($item) || $item['private']) {
+ if (!DBM::is_result($item) || $item['private'] == 1) {
killme();
}
if ($cat === 'config') {
$this->config[$k] = $value;
} else {
+ if (!isset($this->config[$cat])) {
+ $this->config[$cat] = [];
+ }
+
$this->config[$cat][$k] = $value;
}
}
// Only arrays are serialized in database, so we have to unserialize sparingly
$value = is_string($v) && preg_match("|^a:[0-9]+:{.*}$|s", $v) ? unserialize($v) : $v;
+ if (!isset($this->config[$uid])) {
+ $this->config[$uid] = [];
+ }
+
+ if (!isset($this->config[$uid][$cat])) {
+ $this->config[$uid][$cat] = [];
+ }
+
$this->config[$uid][$cat][$k] = $value;
}
return $params;
}
+
+ /**
+ * Copied from http://php.net/manual/en/function.str-replace.php#88569
+ * Modified for camel caps: renamed stro_replace -> strOrigReplace
+ *
+ * When using str_replace(...), values that did not exist in the original string (but were put there by previous
+ * replacements) will be replaced continuously. This string replacement function is designed to replace the values
+ * in $search with those in $replace while not factoring in prior replacements. Note that this function will
+ * always look for the longest possible match first and then work its way down to individual characters.
+ *
+ * @param array $search list of strings or characters that need to be replaced
+ * @param array $replace list of strings or characters that will replace the corresponding values in $search
+ * @param string $subject the string on which this operation is being performed
+ *
+ * @return string $subject with all substrings in the $search array replaced by the values in the $replace array
+ */
+ private static function strOrigReplace($search, $replace, $subject)
+ {
+ return strtr($subject, array_combine($search, $replace));
+ }
+
/**
* @brief Replaces text emoticons with graphical images
*
}
} else {
$params['string'] = preg_replace_callback('/<(3+)/', 'self::pregHeart', $params['string']);
- $s = str_replace($params['texts'], $params['icons'], $params['string']);
+ $s = self::strOrigReplace($params['texts'], $params['icons'], $params['string']);
}
$s = preg_replace_callback('/<pre>(.*?)<\/pre>/ism', 'self::decode', $s);
/// @todo Fetch contact details by "Contact::getDetailsByUrl" instead of queries to contact, fcontact and gcontact
$r = q(
"SELECT `intro`.`id` AS `intro_id`, `intro`.*, `contact`.*,
- `fcontact`.`name` AS `fname`, `fcontact`.`url` AS `furl`,
+ `fcontact`.`name` AS `fname`, `fcontact`.`url` AS `furl`, `fcontact`.`addr` AS `faddr`,
`fcontact`.`photo` AS `fphoto`, `fcontact`.`request` AS `frequest`,
`gcontact`.`location` AS `glocation`, `gcontact`.`about` AS `gabout`,
`gcontact`.`keywords` AS `gkeywords`, `gcontact`.`gender` AS `ggender`,
'notify_type' => L10n::t('Friend Suggestion'),
'intro_id' => $it['intro_id'],
'madeby' => $it['name'],
+ 'madeby_url' => $it['url'],
+ 'madeby_zrl' => Contact::magicLink($it['url']),
+ 'madeby_addr' => $it['addr'],
'contact_id' => $it['contact-id'],
'photo' => ((x($it, 'fphoto')) ? proxy_url($it['fphoto'], false, PROXY_SIZE_SMALL) : "images/person-175.jpg"),
'name' => $it['fname'],
- 'url' => Contact::magicLink($it['furl']),
+ 'url' => $it['furl'],
+ 'zrl' => Contact::magicLink($it['furl']),
'hidden' => $it['hidden'] == 1,
'post_newfriend' => (intval(PConfig::get(local_user(), 'system', 'post_newfriend')) ? '1' : 0),
'knowyou' => $knowyou,
<div class="intro-wrapper" >
<p class="intro-desc">{{$str_notifytype}} {{$notify_type}}</p>
-<div class="intro-madeby">{{$madeby}}</div>
+{{if $madeby}}<div class="intro-madeby">{{$lbl_madeby}} {{$madeby}}</div>{{/if}}
<div class="intro-fullname" >{{$fullname}}</div>
<a class="intro-url-link" href="{{$url}}" ><img class="intro-photo lframe" src="{{$photo}}" width="175" height="175" title="{{$fullname|escape:'html'}}" alt="{{$fullname|escape:'html'}}" /></a>
<div class="intro-note" >{{$note}}</div>
#adminpage, .delegate-content-wrapper, .uexport-content-wrapper,
.viewcontacts-content-wrapper, .dfrn_request-content-wrapper,
.friendica-content-wrapper, .credits-content-wrapper, .nogroup-content-wrapper,
-.profperm-content-wrapper, .invite-content-wrapper, .tos-content-wrapper {
+.profperm-content-wrapper, .invite-content-wrapper, .tos-content-wrapper,
+.fsuggest-content-wrapper {
min-height: calc(100vh - 150px);
padding: 15px;
padding-bottom: 20px;
}
.intro-desc-label, .intro-url-label, .intro-network-label,
.intro-location-label, .intro-gender-label, .intro-keywords-label,
-.intro-about-label, .intro-knowyou-label {
+.intro-about-label, .intro-knowyou-label, .intro-madeby-label {
font-weight: bold;
}
.intro-contact-info.xs .intro-url-label, .intro-contact-info.xs .intro-network-label,
--- /dev/null
+
+/**
+ * @brief Javascript for the notifications module
+ */
+
+// Catch the intro ID from the URL
+var introID = location.pathname.split("/").pop();
+
+$(document).ready(function(){
+ // Since only the DIV's inside the notification-list are marked
+ // with the class "unseen", we need some js to transfer this class
+ // to the parent li list-elements.
+ if($(".notif-item").hasClass("unseen")) {
+ $(".notif-item.unseen").parent("li").addClass("unseen");
+ }
+});
+
+$(window).load(function(){
+ // Scroll to the intro by its intro ID.
+ if (isIntroID()) {
+ scrollToItem('intro-' + introID);
+ }
+});
+
+// Check if it is a real introduction ID.
+function isIntroID() {
+ // Check for the correct path.
+ if (window.location.href.indexOf("/notifications/intros/") !== -1) {
+ // Make sure the introID is a positive Integer value.
+ var intVal = Number(introID);
+ if (Math.floor(intVal) !== Infinity && String(intVal) === introID && intVal > 0) {
+ return true;
+ }
+ }
+ return false;
+}
this.attr('autocomplete','off');
var a = this.textcomplete([contacts], {className:'accontacts', appendTo: '#contact-list'});
+ if(autosubmit) {
+ a.on('textComplete:select', function(e,value,strategy) {submit_form(this);});
+ }
+
a.on('textComplete:select', function(e, value, strategy) {
$(".dropdown-menu.textcomplete-dropdown.media-list").show();
});
-<div class="intro-wrapper media" id="intro-{{$contact_id}}" >
+{{* template incomming contact request and suggested contacts *}}
+
+<div class="intro-wrapper media" id="intro-{{$intro_id}}" >
{{* Contact Photo *}}
<div class="intro-photo-wrapper dropdown pull-left" >
- <img id="photo-{{$contact_id}}" class="intro-photo media-object" src="{{$photo}}" title="{{$fullname|escape:'html'}}" alt="{{$fullname|escape:'html'}}" />
+ <img id="photo-{{$intro_id}}" class="intro-photo media-object" src="{{$photo}}" title="{{$fullname|escape:'html'}}" alt="{{$fullname|escape:'html'}}" />
</div>
<div class="media-body">
{{* The intro actions like approve, ignore, discard intro*}}
<div class="intro-actions pull-right nav-pills preferences">
- <button class="btn-link intro-action-link" onclick="addElmToModal('#intro-approve-wrapper-{{$contact_id}}');" aria-label="{{$approve|escape:'html'}}" title="{{$approve|escape:'html'}}" data-toggle="tooltip"><i class="fa fa-check" aria-hidden="true"></i></button>
+ <button class="btn-link intro-action-link" onclick="addElmToModal('#intro-approve-wrapper-{{$intro_id}}');" aria-label="{{$approve|escape:'html'}}" title="{{$approve|escape:'html'}}" data-toggle="tooltip"><i class="fa fa-check" aria-hidden="true"></i></button>
<form class="intro-form" action="notifications/{{$intro_id}}" method="post">
<button class="btn-link intro-submit-ignore intro-action-link" type="submit" name="submit" value="{{$ignore|escape:'html'}}" aria-label="{{$ignore|escape:'html'}}" title="{{$ignore|escape:'html'}}" data-toggle="tooltip"><i class="fa fa-ban" aria-hidden="true"></i></button>
</form>
</div>
<div class='intro-enty-name'><h4 class="media-heading"><a href="{{$zrl}}">{{$fullname}}</a></h4></div>
- <div class="intro-desc"><span class="intro-desc-label">{{$str_notifytype}}</span>{{$notify_type}}</div>
+ <div class="intro-desc"><span class="intro-desc-label">{{$str_notifytype}}</span> {{$notify_type}}</div>
+ {{* if the contact was suggestested by another contact, the contact who made the suggestion is displayed*}}
+ {{if $madeby}}<div class="intro-madeby"><span class="intro-madeby-label">{{$lbl_madeby}}</span> <a href="{{$madeby_zrl}}">{{$madeby}}</a></div>{{/if}}
{{* Additional information of the contact *}}
<div class="intro-contact-info hidden-xs">
{{if $keywords}}<div class="intro-keywords"><span class="intro-keywords-label">{{$lbl_keywords}}</span> {{$keywords}}</div>{{/if}}
{{if $about}}<div class="intro-about"><span class="intro-about-label">{{$lbl_about}}</span> {{$about}}</div>{{/if}}
<div class="intro-knowyou"><span class="intro-knowyou-label">{{$lbl_knowyou}}</span>{{$knowyou}}</div>
- <div class="intro-note intro-note-{{$contact_id}}">{{$note}}</div>
+ <div class="intro-note intro-note-{{$intro_id}}">{{$note}}</div>
</div>
{{* Additional information of the contact for mobile view *}}
{{if $keywords}}<div class="intro-keywords"><span class="intro-keywords-label">{{$lbl_keywords}}</span>{{$keywords}}</div>{{/if}}
{{if $about}}<div class="intro-about"><span class="intro-about-label">{{$lbl_about}}</span>{{$about}}</div>{{/if}}
<div class="intro-knowyou"><span class="intro-knowyou-label">{{$lbl_knowyou}}</span>{{$knowyou}}</div>
- <div class="intro-note intro-note-{{$contact_id}}">{{$note}}</div>
+ <div class="intro-note intro-note-{{$intro_id}}">{{$note}}</div>
</div>
{{* This sections contains special settings for contact approval. We hide it by default and load this section in
a bootstrap modal in the case of approval *}}
- <div id="intro-approve-wrapper-{{$contact_id}}" style="display: none;">
+ <div id="intro-approve-wrapper-{{$intro_id}}" style="display: none;">
<h3 class="heading">{{$fullname}}{{if $addr}} ({{$addr}}){{/if}}</h3>
- <form class="intro-approve-form" action="dfrn_confirm" method="post">
+ <form class="intro-approve-form" {{if $request}}action="{{$request}}" method="get"{{else}}action="dfrn_confirm" method="post"{{/if}}>
{{include file="field_checkbox.tpl" field=$hidden}}
+ {{if $type != "friend_suggestion"}}
<input type="hidden" name="dfrn_id" value="{{$dfrn_id}}" >
<input type="hidden" name="intro_id" value="{{$intro_id}}" >
<input type="hidden" name="contact_id" value="{{$contact_id}}" >
+ {{/if}}
{{$dfrn_text}}
<button class="btn btn-small btn-default intro-submit-ignore" type="submit" name="submit" value="{{$ignore|escape:'html'}}">{{$ignore|escape:'html'}}</button>
{{if $discard}}<button class="btn btn-small btn-default intro-submit-discard" type="submit" name="submit" value="{{$discard|escape:'html'}}">{{$discard|escape:'html'}}</button> {{/if}}
</form>
- <button class="btn btn-small btn-primary intro-submit-approve pull-right" onclick="addElmToModal('#intro-approve-wrapper-{{$contact_id}}')">{{$approve|escape:'html'}}</button>
+ <button class="btn btn-small btn-primary intro-submit-approve pull-right" onclick="addElmToModal('#intro-approve-wrapper-{{$intro_id}}')">{{$approve|escape:'html'}}</button>
</div>
<div class="clear"></div>
{{/if}}
+<script type="text/javascript" src="view/theme/frio/frameworks/jquery-color/jquery.color.js"></script>
+<script type="text/javascript" src="view/theme/frio/js/mod_notifications.js"></script>
<div class="generic-page-wrapper">
{{include file="section_title.tpl" title=$notif_header}}
{{* The pager *}}
{{$notif_paginate}}
</div>
-
-{{* Since only the DIV's inside the notification-list are marked with the class "unseen",
-we need some js to transfer this class to the parent li list-elements *}}
-<script type="text/javascript">
-$(document).ready(function(){
- if( $(".notif-item").hasClass("unseen")) {
- $(".notif-item.unseen").parent("li").addClass("unseen");
- }
-});
-</script>
\ No newline at end of file
--- /dev/null
+
+{{include file="intros.tpl"}}
\ No newline at end of file