# skip addon folder
FINDOPTS="( -wholename */addon -or -wholename */addons -or -wholename */addons-extra -or -wholename */smarty3 ) -prune -o"
- F9KVERSION=$(sed -n "s/.*'FRIENDICA_VERSION'.*'\([0-9.]*\)'.*/\1/p" ./boot.php);
+ F9KVERSION=$(cat ./VERSION);
echo "Friendica version $F9KVERSION"
;;
esac
### field_input.tpl
-A single line input field for textual input.
+A single line input field for any type of input.
Field parameter:
0. Name of the field,
3. Help text for the input box,
4. if set to "required" modern browser will check that this input box is filled when submitting the form,
5. if set to "autofocus" modern browser will put the cursur into this box once the page is loaded,
-6. if set to "email" or "url" modern browser will check that the filled in value corresponds to an email address or URL.
+6. if set, it will be used for the input type, default is `text` (possible types: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#%3Cinput%3E_types).
### field_intcheckbox.tpl
if ($orig_post) {
$datarray['edit'] = true;
} else {
+ // If this was a share, add missing data here
+ $datarray = Item::addShareDataFromOriginal($datarray);
+
$datarray['edit'] = false;
}
}
}
- // If this was a share, add missing data here
- $datarray = Item::addShareDataFromOriginal($datarray);
-
$post_id = Item::insert($datarray);
if (!$post_id) {
public static function convertShare($text, callable $callback)
{
$return = preg_replace_callback(
- "/(.*?)\[share(.*?)\](.*?)\[\/share\]/ism",
+ "/(.*?)\[share(.*?)\](.*)\[\/share\]/ism",
function ($match) use ($callback) {
$attribute_string = $match[2];
-
$attributes = [];
- foreach(['author', 'profile', 'avatar', 'link', 'posted'] as $field) {
+ foreach (['author', 'profile', 'avatar', 'link', 'posted'] as $field) {
preg_match("/$field=(['\"])(.+?)\\1/ism", $attribute_string, $matches);
$attributes[$field] = html_entity_decode($matches[2] ?? '', ENT_QUOTES, 'UTF-8');
}
*/
public static function getContactListByUserId(int $user_id)
{
- $acl_contacts = Contact::selectToArray(
- ['id', 'name', 'addr', 'micro'],
- ['uid' => $user_id, 'pending' => false, 'rel' => [Contact::FOLLOWER, Contact::FRIEND]]
+ $fields = ['id', 'name', 'addr', 'micro'];
+ $params = ['order' => ['name']];
+ $acl_contacts = Contact::selectToArray($fields,
+ ['uid' => $user_id, 'self' => false, 'blocked' => false, 'archive' => false, 'deleted' => false,
+ 'pending' => false, 'rel' => [Contact::FOLLOWER, Contact::FRIEND]], $params
);
+
+ $acl_forums = Contact::selectToArray($fields,
+ ['uid' => $user_id, 'self' => false, 'blocked' => false, 'archive' => false, 'deleted' => false,
+ 'pending' => false, 'contact-type' => Contact::TYPE_COMMUNITY], $params
+ );
+
+ $acl_contacts = array_merge($acl_forums, $acl_contacts);
+
array_walk($acl_contacts, function (&$value) {
$value['type'] = 'contact';
});
}
}
- if ($default_permissions['hidewall']) {
+ if (!$default_permissions['hidewall']) {
if ($mail_enabled) {
$jotnets_fields[] = [
'type' => 'checkbox',
if (DBA::isResult($contact)) {
$contact_id = $contact["id"];
- // Update the contact every 7 days
- if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) {
+ // Update the contact every 7 days (Don't update mail or feed contacts)
+ if (in_array($contact['network'], Protocol::FEDERATED)) {
$update_contact = ($contact['updated'] < DateTimeFormat::utc('now -7 days'));
// We force the update if the avatar is empty
if (empty($contact['avatar'])) {
$update_contact = true;
}
- } else {
+ } elseif (empty($default) && in_array($contact['network'], [Protocol::MAIL, Protocol::PHANTOM]) && ($uid == 0)) {
+ // Update public mail accounts via their user's accounts
+ $fields = ['network', 'addr', 'name', 'nick', 'avatar', 'photo', 'thumb', 'micro'];
+ $mailcontact = DBA::selectFirst('contact', $fields, ["`addr` = ? AND `network` = ? AND `uid` != 0", $url, Protocol::MAIL]);
+ if (!DBA::isResult($mailcontact)) {
+ $mailcontact = DBA::selectFirst('contact', $fields, ["`nurl` = ? AND `network` = ? AND `uid` != 0", $url, Protocol::MAIL]);
+ }
+
+ if (DBA::isResult($mailcontact)) {
+ DBA::update('contact', $mailcontact, ['id' => $contact_id]);
+ }
+
$update_contact = false;
}
$sql = "`item`.`uid` = ?";
}
- $contact_field = ($contact["contact-type"] == self::TYPE_COMMUNITY ? 'owner-id' : 'author-id');
+ $contact_field = ((($contact["contact-type"] == self::TYPE_COMMUNITY) || ($contact['network'] == Protocol::MAIL)) ? 'owner-id' : 'author-id');
if ($thread_mode) {
$condition = ["`$contact_field` = ? AND `gravity` = ? AND " . $sql,
$body = $shared_item['body'];
}
- $item['body'] = preg_replace("/(.*?\[share.*?\]\s?).*?(\s?\[\/share\]\s?)/ism", '$1' . $body . '$2', $item['body']);
+ $item['body'] = preg_replace("/\[share ([^\[\]]*)\].*\[\/share\]/ism", '[share $1]' . $body . '[/share]', $item['body']);
unset($shared_item['body']);
return array_merge($item, $shared_item);
'$errors_label' => L10n::tt('Error', 'Errors', count(self::$errors)),
'$errors' => self::$errors,
'$recovery_message' => L10n::t('Don’t have your phone? <a href="%s">Enter a two-factor recovery code</a>', '2fa/recovery'),
- '$verify_code' => ['verify_code', L10n::t('Please enter a code from your authentication app'), '', '', 'required', 'autofocus placeholder="000000"'],
+ '$verify_code' => ['verify_code', L10n::t('Please enter a code from your authentication app'), '', '', 'required', 'autofocus placeholder="000000"', 'number'],
'$verify_label' => L10n::t('Verify code and complete login'),
]);
}
$terms = Term::tagArrayFromItemId($item['id'], [Term::MENTION, Term::IMPLICIT_MENTION]);
- // Directly mention the original author upon a quoted reshare.
- // Else just ensure that the original author receives the reshare.
- $announce = self::getAnnounceArray($item);
- if (!empty($announce['comment'])) {
- $data['to'][] = $announce['actor']['url'];
- } elseif (!empty($announce)) {
- $data['cc'][] = $announce['actor']['url'];
- }
-
if (!$item['private']) {
+ // Directly mention the original author upon a quoted reshare.
+ // Else just ensure that the original author receives the reshare.
+ $announce = self::getAnnounceArray($item);
+ if (!empty($announce['comment'])) {
+ $data['to'][] = $announce['actor']['url'];
+ } elseif (!empty($announce)) {
+ $data['cc'][] = $announce['actor']['url'];
+ }
+
$data = array_merge($data, self::fetchPermissionBlockFromConversation($item));
$data['to'][] = ActivityPub::PUBLIC_COLLECTION;
// Custom visibility tags inputs
let acl_groups = new Bloodhound({
local: {{$acl_groups|@json_encode nofilter}},
- identify: function(obj) { return obj.id; },
+ identify: function(obj) { return obj.type + '-' + obj.id.toString(); },
datumTokenizer: Bloodhound.tokenizers.obj.whitespace(['name']),
queryTokenizer: Bloodhound.tokenizers.whitespace,
});
let acl_contacts = new Bloodhound({
local: {{$acl_contacts|@json_encode nofilter}},
- identify: function(obj) { return obj.id; },
+ identify: function(obj) { return obj.type + '-' + obj.id.toString(); },
datumTokenizer: Bloodhound.tokenizers.obj.whitespace(['name', 'addr']),
queryTokenizer: Bloodhound.tokenizers.whitespace,
});
let acl = new Bloodhound({
local: {{$acl_list|@json_encode nofilter}},
- identify: function(obj) { return obj.id; },
+ identify: function(obj) { return obj.type + '-' + obj.id.toString(); },
datumTokenizer: Bloodhound.tokenizers.obj.whitespace(['name', 'addr']),
queryTokenizer: Bloodhound.tokenizers.whitespace,
});
return 'label label-info';
}
},
- itemValue: 'id',
+ itemValue: function (item) { return item.type + '-' + item.id.toString(); },
itemText: 'name',
itemThumb: 'micro',
itemTitle: function(item) {
return 'label label-info';
}
},
- itemValue: 'id',
+ itemValue: function (item) { return item.type + '-' + item.id.toString(); },
itemText: 'name',
itemThumb: 'micro',
itemTitle: function(item) {
// Import existing ACL into the tags input fields.
- $group_allow_input.val().split(',').forEach(function (val) {
- $acl_allow_input.tagsinput('add', acl_groups.get(val)[0]);
+ $group_allow_input.val().split(',').forEach(function (group_id) {
+ $acl_allow_input.tagsinput('add', acl_groups.get('group-' + group_id)[0]);
});
- $contact_allow_input.val().split(',').forEach(function (val) {
- $acl_allow_input.tagsinput('add', acl_contacts.get(val)[0]);
+ $contact_allow_input.val().split(',').forEach(function (contact_id) {
+ $acl_allow_input.tagsinput('add', acl_contacts.get('contact-' + contact_id)[0]);
});
- $group_deny_input.val().split(',').forEach(function (val) {
- $acl_deny_input.tagsinput('add', acl_groups.get(val)[0]);
+ $group_deny_input.val().split(',').forEach(function (group_id) {
+ $acl_deny_input.tagsinput('add', acl_groups.get('group-' + group_id)[0]);
});
- $contact_deny_input.val().split(',').forEach(function (val) {
- $acl_deny_input.tagsinput('add', acl_contacts.get(val)[0]);
+ $contact_deny_input.val().split(',').forEach(function (contact_id) {
+ $acl_deny_input.tagsinput('add', acl_contacts.get('contact-' + contact_id)[0]);
});
// Anti-duplicate callback + acl fields value generation
- <div class='field input' id='wrapper_{{$field.0}}'>
- <label for='id_{{$field.0}}'>{{$field.1}}</label>
- <input{{if $field.6 eq 'email'}} type='email'{{elseif $field.6 eq 'url'}} type='url'{{else}} type="text"{{/if}} name='{{$field.0}}' id='id_{{$field.0}}' value="{{$field.2 nofilter}}"{{if $field.4 eq 'required'}} required{{/if}}{{if $field.5 eq "autofocus"}} autofocus{{elseif $field.5}} {{$field.5 nofilter}}{{/if}} aria-describedby='{{$field.0}}_tip'>
+ <div class="field input" id="wrapper_{{$field.0}}">
+ <label for="id_{{$field.0}}">{{$field.1}}</label>
+ <input{{if $field.6}} type="{{$field.6}}"{{else}} type="text"{{/if}} name="{{$field.0}}" id="id_{{$field.0}}" value="{{$field.2 nofilter}}"{{if $field.4 eq 'required'}} required{{/if}}{{if $field.5 eq "autofocus"}} autofocus{{elseif $field.5}} {{$field.5 nofilter}}{{/if}} aria-describedby="{{$field.0}}_tip">
{{if $field.3}}
- <span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3 nofilter}}</span>
+ <span class="field_help" role="tooltip" id="{{$field.0}}_tip">{{$field.3 nofilter}}</span>
{{/if}}
</div>
{{if !isset($label) || $label != false }}
<label for="id_{{$field.0}}" id="label_{{$field.0}}">{{$field.1 nofilter}}{{if $field.4}}<span class="required"> {{$field.4}}</span>{{/if}}</label>
{{/if}}
- <input class="form-control" name="{{$field.0}}" id="id_{{$field.0}}"{{if $field.6 eq "email"}} type="email"{{elseif $field.6 eq "url"}} type="url"{{else}} type="text"{{/if}} value="{{$field.2 nofilter}}"{{if $field.4 eq "required"}} required{{/if}}{{if $field.5 eq "autofocus"}} autofocus{{elseif $field.5}} {{$field.5 nofilter}}{{/if}} aria-describedby="{{$field.0}}_tip">
+ <input class="form-control" name="{{$field.0}}" id="id_{{$field.0}}"{{if $field.6}} type="{{$field.6}}"{{else}} type="text"{{/if}} value="{{$field.2 nofilter}}"{{if $field.4 eq "required"}} required{{/if}}{{if $field.5 eq "autofocus"}} autofocus{{elseif $field.5}} {{$field.5 nofilter}}{{/if}} aria-describedby="{{$field.0}}_tip">
{{if $field.3}}
<span class="help-block" id="{{$field.0}}_tip" role="tooltip">{{$field.3 nofilter}}</span>
{{/if}}