$tz = 'UTC';
}
- $profile = DBA::selectFirst('profile', ['dob'], ['is-default' => true, 'uid' => $uid]);
+ $profile = DBA::selectFirst('profile', ['dob'], ['uid' => $uid]);
if (DBA::isResult($profile)) {
$tmp_dob = substr($profile['dob'], 5);
if (intval($tmp_dob)) {
"bower-asset/dompurify": "^1.0",
"bower-asset/perfect-scrollbar": "^0.6",
"bower-asset/vue": "^2.6",
+ "npm-asset/es-jquery-sortable": "^0.9.13",
"npm-asset/jquery": "^2.0",
"npm-asset/jquery-colorbox": "^1.6",
"npm-asset/jquery-datetimepicker": "^2.5",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "34ad225ce21474eb84ce78047d9f2c01",
+ "content-hash": "6659cc3edcbdb9d706019810788d8dc3",
"packages": [
{
"name": "asika/simple-console",
],
"time": "2018-01-03T13:39:39+00:00"
},
+ {
+ "name": "npm-asset/es-jquery-sortable",
+ "version": "0.9.13-patch2",
+ "dist": {
+ "type": "tar",
+ "url": "https://registry.npmjs.org/es-jquery-sortable/-/es-jquery-sortable-0.9.13-patch2.tgz",
+ "shasum": "a4db16d133fbce1bcd1543c98279902a6b0812a3"
+ },
+ "require": {
+ "npm-asset/jquery": ">=2.1.2,<3.0.0"
+ },
+ "type": "npm-asset-library",
+ "extra": {
+ "npm-asset-bugs": {
+ "url": "https://github.com/johnny/jquery-sortable/issues"
+ },
+ "npm-asset-main": "./source/js/jquery-sortable.js",
+ "npm-asset-directories": [],
+ "npm-asset-repository": {
+ "type": "git",
+ "url": "git+https://github.com/johnny/jquery-sortable.git"
+ },
+ "npm-asset-scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ }
+ },
+ "license": [
+ "BSD-3"
+ ],
+ "authors": [
+ ""
+ ],
+ "description": "jquery plugin for sortable, nestable lists",
+ "homepage": "https://github.com/johnny/jquery-sortable",
+ "keywords": [
+ "drag",
+ "dragging",
+ "sort",
+ "sortable",
+ "sorting"
+ ],
+ "time": "2019-11-20T03:55:51+00:00"
+ },
{
"name": "npm-asset/ev-emitter",
"version": "1.1.1",
-- ------------------------------------------
-- Friendica 2020.03-dev (Dalmatian Bellflower)
--- DB_UPDATE_VERSION 1330
+-- DB_UPDATE_VERSION 1332
-- ------------------------------------------
`reason` text COMMENT '',
`closeness` tinyint unsigned NOT NULL DEFAULT 99 COMMENT '',
`info` mediumtext COMMENT '',
- `profile-id` int unsigned NOT NULL DEFAULT 0 COMMENT '',
+ `profile-id` int unsigned COMMENT 'Deprecated',
`bdyear` varchar(4) NOT NULL DEFAULT '' COMMENT '',
`bd` date NOT NULL DEFAULT '0001-01-01' COMMENT '',
`notify_new_posts` boolean NOT NULL DEFAULT '0' COMMENT '',
CREATE TABLE IF NOT EXISTS `profile` (
`id` int unsigned NOT NULL auto_increment COMMENT 'sequential ID',
`uid` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'Owner User id',
- `profile-name` varchar(255) NOT NULL DEFAULT '' COMMENT 'Name of the profile',
- `is-default` boolean NOT NULL DEFAULT '0' COMMENT 'Mark this profile as default profile',
+ `profile-name` varchar(255) COMMENT 'Deprecated',
+ `is-default` boolean COMMENT 'Deprecated',
`hide-friends` boolean NOT NULL DEFAULT '0' COMMENT 'Hide friend list from viewers of this profile',
`name` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`pdesc` varchar(255) NOT NULL DEFAULT '' COMMENT 'Title or description',
`region` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`postal-code` varchar(32) NOT NULL DEFAULT '' COMMENT '',
`country-name` varchar(255) NOT NULL DEFAULT '' COMMENT '',
- `hometown` varchar(255) NOT NULL DEFAULT '' COMMENT '',
- `gender` varchar(32) NOT NULL DEFAULT '' COMMENT '',
- `marital` varchar(255) NOT NULL DEFAULT '' COMMENT '',
- `with` text COMMENT '',
- `howlong` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '',
- `sexual` varchar(255) NOT NULL DEFAULT '' COMMENT '',
- `politic` varchar(255) NOT NULL DEFAULT '' COMMENT '',
- `religion` varchar(255) NOT NULL DEFAULT '' COMMENT '',
+ `hometown` varchar(255) COMMENT 'Deprecated',
+ `gender` varchar(32) COMMENT 'Deprecated',
+ `marital` varchar(255) COMMENT 'Deprecated',
+ `with` text COMMENT 'Deprecated',
+ `howlong` datetime COMMENT 'Deprecated',
+ `sexual` varchar(255) COMMENT 'Deprecated',
+ `politic` varchar(255) COMMENT 'Deprecated',
+ `religion` varchar(255) COMMENT 'Deprecated',
`pub_keywords` text COMMENT '',
`prv_keywords` text COMMENT '',
- `likes` text COMMENT '',
- `dislikes` text COMMENT '',
- `about` text COMMENT '',
- `summary` varchar(255) NOT NULL DEFAULT '' COMMENT '',
- `music` text COMMENT '',
- `book` text COMMENT '',
- `tv` text COMMENT '',
- `film` text COMMENT '',
- `interest` text COMMENT '',
- `romance` text COMMENT '',
- `work` text COMMENT '',
- `education` text COMMENT '',
- `contact` text COMMENT '',
+ `likes` text COMMENT 'Deprecated',
+ `dislikes` text COMMENT 'Deprecated',
+ `about` text COMMENT 'Deprecated',
+ `summary` varchar(255) COMMENT 'Deprecated',
+ `music` text COMMENT 'Deprecated',
+ `book` text COMMENT 'Deprecated',
+ `tv` text COMMENT 'Deprecated',
+ `film` text COMMENT 'Deprecated',
+ `interest` text COMMENT 'Deprecated',
+ `romance` text COMMENT 'Deprecated',
+ `work` text COMMENT 'Deprecated',
+ `education` text COMMENT 'Deprecated',
+ `contact` text COMMENT 'Deprecated',
`homepage` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`xmpp` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`photo` varchar(255) NOT NULL DEFAULT '' COMMENT '',
PRIMARY KEY(`id`)
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='DFRN remote auth use';
+--
+-- TABLE profile_field
+--
+CREATE TABLE IF NOT EXISTS `profile_field` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'sequential ID',
+ `uid` mediumint(8) unsigned NOT NULL DEFAULT 0 COMMENT 'Owner user id',
+ `psid` int(10) unsigned DEFAULT NULL COMMENT 'ID of the permission set of this profile field - 0 = public',
+ `name` varchar(255) NOT NULL DEFAULT '' COMMENT 'Name of the field',
+ `value` text COMMENT 'Value of the field',
+ `order` mediumint(8) unsigned NOT NULL DEFAULT 1 COMMENT 'Field ordering per user',
+ `label` varchar(255) NOT NULL DEFAULT '' COMMENT 'Label of the field',
+ `created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '',
+ `edited` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '',
+ PRIMARY KEY (`id`),
+ KEY `uid` (`uid`),
+ KEY `psid` (`psid`),
+ KEY `order` (`order`)
+) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Custom profile fields';
+
--
-- TABLE push_subscriber
--
On success: Array of:
-* `multi_profiles`: true if user has activated multi_profiles
* `global_dir`: URL of the global directory set in server settings
* `friendica_owner`: user data of the authenticated user
* `profiles`: array of the profile data
+++ /dev/null
-Profiles
-========
-
-* [Home](help)
-
-Friendica has unlimited profiles.
-You may use different profiles to present different aspects of yourself to different audiences.
-
-Default / public profile
----
-You always have a profile known as your "default" or "public" profile.
-This profile is always available to the general public and usually cannot be hidden.
-You may, and probably should restrict the personal information you make available on your public profile.
-
-That said, if you want other friends to be able to find you, it helps to have the following information in your public profile:
-
-* Your real name
-* A photo of **you**
-* Your location, preferably at least the country.
-
-In addition, if you'd like to meet people that share some general interests with you, add some "Public Keywords" to your profile.
-Such as "music, linux, photography" or whatever.
-You can add as many keywords as you like.
-
-Your default or public profile is also shown to contacts on other networks, since they do not have the ability to view your private profiles.
-Only members of the Friendica network can see alternate/ private profiles.
-
-Alternate/ private profiles
----
-To create an alternate profile, select "Profiles" from the menu of your Friendica site.
-You may edit an existing profile, change the profile photo, or create a new profile.
-You may also "clone" your existing profile if you only wish to change a few items but don't wish to enter all the information again.
-
-To assign a profile to specific persons, select the person from your "Contacts" page and click the pencil "Edit" icon.
-You will find a dropdown box listing the various profiles available.
-If this box is not selectable, the person is not in a supported network and cannot be assigned a specific profile.
-
-Once a profile has been selected, when the person views your profile from one of the "magic profile links" on their site, they will see the private profile you have assigned.
-If they are not logged into their site or view your profile from elsewhere, they will see your public profile.
-
-A magic profile link is indicated by a special cursor when hovering over a contact's name or photo.
-Currently this cursor is a hand next to a small padlock.
-These magic cursors indicate that by following the link, you are able to access special areas of the other person's pages which are only available to friends and may not be available to the general public.
-
-You may also discover that (assuming you have the proper permissions) you may be able to post directly on the other person's profile (often called a "wall-to-wall" post).
-You may also be able to comment directly on posts from while visiting the other person's profile page.
-
-There are two settings which allow you to publish your profile to a directory and ensure that it can be found by others.
-You can change these through settings on the "Settings" page.
-One setting allows you to publish your profile in the site directory of this Friendica server.
-Another option (this may have been disabled by the site admin) allows you to publish your profile in a [Global Directory](Making-Friends.md#the-directories).
-
-If you do not wish to be visible to any of these directories, do not published your profile.
-
-Although you may have multiple profiles, you only have one profile photo.
-This is intentional; it avoids confusion by potentially seeing different profile pictures of a contact depending on what website you visit or conversation you participate in.
-You can always can use the free text information boxes within a profile such as "Tell us about yourself" and link other photos for yourself.
-
-Keywords and Directory Search
----
-On the site Directory page, you may search for people with published profiles who are on this site.
-The search is typically for your nickname or part of your full name.
-However this search will also match against other profile fields - such as gender, location, "about", work, and education.
-You may also include "Keywords" in your default profile - which may be used to search for common interests with other members.
-You have two sets of keywords available - public and private.
-Private keywords are *not* visible on your profile, but will bring up your profile when matched in a search of the site directory.
-Public keywords are used in the friend suggestion tool and although they aren't readily visible, they may be seen by viewing the HTML of your profile page.
-
-Directory searches are also able to use "boolean" logic so that you can search for "+lesbian +Florida" and find those who's sexual preference (or keywords) contain the world "lesbian" and that live in Florida.
-See the section on "Topical Tags" on the [Tags-and-Mentions](help/Tags-and-Mentions) page for more information on performing boolean searches.
-
-On your Contacts page is a link to "Find People with Shared Interests" (unless your site administrator has disabled the global directory).
-This will combine both your public and private keywords, and find people in the global directory who have matching and/or similar keywords.
-Private keywords are not identified or stored on the global directory.
-The more keywords you provide, the more relevant the search results that are returned.
-These are sorted by relevance.
-You may discover that you are the first person on the list - because you are very likely the most relevant match for your keywords in the directory.
## Schau Dir ebenfalls folgende Seiten an
-* [Profile](help/Profiles)
-
* [Gruppen und Privatssphäre](help/Groups-and-Privacy)
* [Account löschen](help/Remove-Account)
* [Beiträge erstellen](help/Text_editor)
* [Referenz der BBCode Elemente](help/BBCode)
* [Beiträge kommentieren, einordnen und löschen](help/Text_comment)
- * [Profile](help/Profiles)
* [Referenz der Accesskeys](help/Accesskeys)
* [Veranstaltungen](help/events)
* Du und andere Nutzer
+++ /dev/null
-Profile
-========
-
-* [Zur Startseite der Hilfe](help)
-
-Mit Friendica kann eine unbegrenzte Anzahl an Profilen angelegt werden.
-Du kannst verschiedene Profile nutzen, um verschiedenen Gruppen verschiedene Seiten von dir zu zeigen.
-
-Du hast immer ein Profil, das als dein "Standard"- (default) oder "öffentliches" (public) Profil angelegt ist.
-Dieses Profil ist immer für die Öffentlichkeit zugänglich und kann nicht versteckt werden (hier mag es einige wenige Ausnahmen auf privaten oder getrennten Seiten geben).
-Du kannst und solltest die Informationen, die du in deinem öffentlichen Profil veröffentlichst, begrenzen.
-
-Das bedeutet, dass du folgende Informationen in dein öffentlichen Profil eintragen solltest, wenn du willst, dass Freunde dich finden können ...
-
-* Dein richtiger Name
-* Ein Foto von **dir**
-* Dein geographischer Standort; zumindest das Land, in dem du lebst.
-
-Ohne diese Basisinformationen kannst du hier sehr einsam sein.
-Die meisten Leute, auch deine besten Freunde, werden nicht versuchen, einen Account mit Spitznamen und ohne Foto zu verbinden.
-
-Wenn du außerdem Leute mit gleichen Interessen treffen willst, dann nimm dir etwas Zeit und trage einige Stichworte ein.
-Zum Beispiel etwas wie "Musik, Linux, Photographie" oder andere Dinge.
-Du kannst so viele Stichworte eintragen, wie du willst.
-
-Dein "Standard-" oder "öffentliches" Profil wird außerdem Kontakten in anderen Netzwerken gezeigt, auch wenn sie nicht die Möglichkeit haben, die privaten Profile einzusehen.
-Nur Mitglieder des Friendica-Netzwerks können alternative oder private Profile sehen.
-
-Um ein alternatives Profil zu erstellen, gehe auf "Profil verwalten/editieren".
-Du kannst entweder ein bestehendes Profil bearbeiten, das Foto ändern, oder ein neues Profil erstellen.
-Du kannst ebenfalls einen Klon eines bestehenden Profils erstellen, falls du nur einige wenige Einstellungen ändern, aber nicht alle Daten noch mal eingeben willst.
-
-Um bestimmten Personen ein Profil zuzuweisen, wähle die Person über "Kontakte" und klicke auf das Bearbeiten-Symbol (Stift).
-Du wirst ein Auswahlmenü mit verschiedenen vorhandenen Profilen angezeigt bekommen.
-Wenn diese Auswahl nicht angezeigt wird, dann ist die Person in einem nicht unterstützten Netzwerk und kann dadurch auch kein Profil zugewiesen bekommen.
-
-Wenn eine befreundete Person auf den "magischen Profillink" klickt, sieht sie das private Profil, das du dieser Person zugewiesen hast.
-Wenn sie nicht eingeloggt ist oder das Profil von woanders angeschaut wird, wird nur das öffentliche Profil angezeigt.
-
-Ein "magischer Profillink" erscheint, wenn man mit der Maus über den Kontaktnamen oder das Foto geht.
-Der Cursor wird zur Hand und auf dem Bild erscheint ein Pfeil, der nach unten zeigt.
-Dieser "magische Cursor" zeigt an, dass du ein spezielles Profil angezeigt bekommst, das nur für Freunde, aber nicht für die Öffentlichkeit sichtbar ist.
-
-Du wirst außerdem möglicherweise entdecken (vorausgesetzt, du hast die nötigen Zugriffsrechte), dass du direkt auf die Seite einer anderen Person schreiben kannst (oft wird diese Beitragsart "wall-to-wall" genannt).
-Ebenso kannst du die Möglichkeit haben, direkt Beiträge zu kommentieren, während du die Seite der anderen Person besuchst.
-
-Es gibt zwei Einstellungen, welche erlauben, dein Profil ins Verzeichnis einzutragen, so dass du von anderen Personen gefunden werden kannst.
-Du kannst diese Einstellungen auf deiner "Einstellungen"-Seite ändern.
-Die eine Einstellung erlaubt dir, dein Profil im Verzeichnis dieses Servers zu veröffentlichen.
-Die zweite Option erlaubt es dir, dich in das globale Friendica-Verzeichnis einzutragen.
-Dies ist ein riesiges Verzeichnis, dass alle Personen von vielen Friendica-Installationen weltweit umfasst.
-
-Wenn du für andere nicht sichtbar sein willst, dann kannst du dein Profil einfach unveröffentlicht lassen.
-
-Außerdem hast du möglicherweise mehrere Profile, aber nur ein Profilfoto. Dies ist beabsichtigt.
-In frühen Tests haben wir mit verschiedenen Fotos für jedes Profil experimentiert und herausgefunden, dass es sehr verwirrend für die Nutzer ist.
-Sie sehen möglicherweise je nach Profil, Seite oder Unterhaltung verschiedene Fotos und merken, dass es unterschiedliche Profile gibt, die sie nicht einsehen können.
-
-(Du kannst aber die Rich-Text-Infoboxen in deinem Profil nutzen und dort weitere Bilder in das Feld "Erzähle uns ein bisschen von dir …" einfügen.)
-
-
-**Schlüsselwörter und Verzeichnissuche**
-
-Auf der Verzeichnisseite willst du vielleicht nach Personen deines Servers suchen, die ihre Profile veröffentlicht haben.
-Die Suche richtet sich normalerweise nach deinem Spitznamen oder Teilen deines richtigen Namens.
-Darüber hinaus wird dieses Feld auch andere Felder deines Profils wie Geschlecht, Ort, "über mich", Arbeit und Bildung finden.
-Du kannst zudem auch "Schlüsselwörter" in dein Standardprofil eintragen, so dass dich andere Personen über deine Interessen finden können.
-Du hast zwei Schlüsselwortarten zur Auswahl - öffentlich und privat. Private Schlüsselwörter werden *nicht* jedem angezeigt.
-Du kannst diese Schlüsselwörter nutzen, um andere Personen zu finden, die ebenfalls in einer bestimmten Gruppe sind oder z.B. das Fischen mögen, ohne dass es jeder in einem öffentlichen Profil sieht.
-Öffentliche Schlüsselwörter werden auf der "Kontaktvorschläge"-Seite genutzt.
-Auch wenn die Schlüsselwörter hier nicht direkt angezeigt werden, kann es trotzdem sein, dass diese im HTML-Code der Seite gesehen werden könnten.
-
-In der Verzeichnis-Suche kannst du ebenfalls die "booleasche"-Logik zu nutzen. Mit "+lesbisch +Florida" kannst du Leute finden, deren sexuelle Einstellung (oder andere Schlüsselwörter) das Wort "lesbisch" enthält und die in Florida leben.
-Schau dir den Bereich über "Thematische Tags" auf der "[Tags und Erwähnungen-Seite](help/Tags-and-Mentions) für weitere Informationen, um booleansche Suchen durchzuführen.
-
-Auf deiner Kontaktseite ist der Link "Ähnliche Interessen", um damit andere Leute zu finden (falls dein Seitenadministrator das globale Verzeichnis nicht ausgeschaltet hat).
-Hierfür werden die Schlüsselwörter aus deinen öffentlichen und privaten Profilen genutzt, um Personen im globalen Verzeichnis zu finden, die gleiche oder ähnliche Schlüsselwörter haben (deine privaten Schlüsselwörter werden nicht in das globale Verzeichnis übertragen oder gespeichert).
-Je mehr Schlüsselwörter du einträgst, umso genauer ist die Suche. Das Suchergebnis ist nach Relevanz sortiert.
-Gegebenenfalls stehst du ganz oben auf der Liste - schließlich bist du die Person, die am besten zu deinen Schlüsselwörtern passt.
use Friendica\Model\Group;
use Friendica\Model\Item;
use Friendica\Model\Mail;
+use Friendica\Model\Notify;
use Friendica\Model\Photo;
use Friendica\Model\Profile;
use Friendica\Model\User;
if ($a->argc!==3) {
throw new BadRequestException("Invalid argument count");
}
- $notes = DI::notify()->getAll([], ['seen' => 'ASC', 'date' => 'DESC'], 50);
+
+ $notifications = DI::notify()->select(['uid' => api_user()], ['order' => ['seen' => 'ASC', 'date' => 'DESC'], 'limit' => 50]);
if ($type == "xml") {
- $xmlnotes = [];
- if (!empty($notes)) {
- foreach ($notes as $note) {
- $xmlnotes[] = ["@attributes" => $note];
+ $xmlnotes = false;
+ if (!empty($notifications)) {
+ foreach ($notifications as $notification) {
+ $xmlnotes[] = ["@attributes" => $notification->toArray()];
}
}
- $notes = $xmlnotes;
+ $result = $xmlnotes;
+ } elseif (count($notifications) > 0) {
+ $result = $notifications->getArrayCopy();
+ } else {
+ $result = false;
}
- return api_format_data("notes", $type, ['note' => $notes]);
+
+ return api_format_data("notes", $type, ['note' => $result]);
}
/**
*/
function api_friendica_notification_seen($type)
{
- $a = DI::app();
+ $a = DI::app();
$user_info = api_get_user($a);
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
- if ($a->argc!==4) {
+ if ($a->argc !== 4) {
throw new BadRequestException("Invalid argument count");
}
$id = (!empty($_REQUEST['id']) ? intval($_REQUEST['id']) : 0);
- $nm = DI::notify();
- $note = $nm->getByID($id);
- if (is_null($note)) {
- throw new BadRequestException("Invalid argument");
- }
-
- $nm->setSeen($note);
- if ($note['otype']=='item') {
- // would be really better with an ItemsManager and $im->getByID() :-P
- $item = Item::selectFirstForUser(api_user(), [], ['id' => $note['iid'], 'uid' => api_user()]);
- if (DBA::isResult($item)) {
- // we found the item, return it to the user
- $ret = api_format_items([$item], $user_info, false, $type);
- $data = ['status' => $ret];
- return api_format_data("status", $type, $data);
+ try {
+ $notification = DI::notify()->getByID($id);
+ $notification->setSeen();
+
+ if ($notification->otype === Notify::OTYPE_ITEM) {
+ $item = Item::selectFirstForUser(api_user(), [], ['id' => $notification->iid, 'uid' => api_user()]);
+ if (DBA::isResult($item)) {
+ // we found the item, return it to the user
+ $ret = api_format_items([$item], $user_info, false, $type);
+ $data = ['status' => $ret];
+ return api_format_data("status", $type, $data);
+ }
+ // the item can't be found, but we set the notification as seen, so we count this as a success
}
- // the item can't be found, but we set the note as seen, so we count this as a success
+ return api_format_data('result', $type, ['result' => "success"]);
+ } catch (NotFoundException $e) {
+ throw new BadRequestException('Invalid argument');
}
- return api_format_data('result', $type, ['result' => "success"]);
}
/// @TODO move to top of file or somewhere better
/**
* Fetch all comments from a query. Additionally set the newest resharer as thread owner.
*
- * @param array $thread_items Database statement with thread posts
+ * @param mixed $thread_items Database statement with thread posts
* @param boolean $pinned Is the item pinned?
*
* @return array items with parents and comments
use Friendica\DI;
use Friendica\Model\Item;
use Friendica\Model\ItemContent;
+use Friendica\Model\Notify;
use Friendica\Model\User;
use Friendica\Model\UserItem;
+use Friendica\Object\Email;
use Friendica\Protocol\Activity;
-use Friendica\Util\DateTimeFormat;
-use Friendica\Util\Emailer;
/**
* Creates a notification entry and possibly sends a mail
// if it's a post figure out who's post it is.
$item = null;
- if ($params['otype'] === 'item' && $parent_id) {
+ if ($params['otype'] === Notify::OTYPE_ITEM && $parent_id) {
$item = Item::selectFirstForUser($params['uid'], Item::ITEM_FIELDLIST, ['id' => $parent_id, 'deleted' => false]);
}
$notify_id = 0;
if ($show_in_notification_page) {
- Logger::log("adding notification entry", Logger::DEBUG);
-
- /// @TODO One statement is enough
- $datarray = [];
- $datarray['name'] = $params['source_name'];
- $datarray['name_cache'] = strip_tags(BBCode::convert($params['source_name']));
- $datarray['url'] = $params['source_link'];
- $datarray['photo'] = $params['source_photo'];
- $datarray['date'] = DateTimeFormat::utcNow();
- $datarray['uid'] = $params['uid'];
- $datarray['link'] = $itemlink;
- $datarray['iid'] = $item_id;
- $datarray['parent'] = $parent_id;
- $datarray['type'] = $params['type'];
- $datarray['verb'] = $params['verb'];
- $datarray['otype'] = $params['otype'];
- $datarray['abort'] = false;
-
- Hook::callAll('enotify_store', $datarray);
-
- if ($datarray['abort']) {
- return false;
- }
-
- // create notification entry in DB
- $fields = ['name' => $datarray['name'], 'url' => $datarray['url'],
- 'photo' => $datarray['photo'], 'date' => $datarray['date'], 'uid' => $datarray['uid'],
- 'link' => $datarray['link'], 'iid' => $datarray['iid'], 'parent' => $datarray['parent'],
- 'type' => $datarray['type'], 'verb' => $datarray['verb'], 'otype' => $datarray['otype'],
- 'name_cache' => $datarray["name_cache"]];
- DBA::insert('notify', $fields);
+ $notification = DI::notify()->insert([
+ 'name' => $params['source_name'],
+ 'url' => $params['source_link'],
+ 'photo' => $params['source_photo'],
+ 'uid' => $params['uid'],
+ 'iid' => $item_id,
+ 'parent' => $parent_id,
+ 'type' => $params['type'],
+ 'verb' => $params['verb'],
+ 'otype' => $params['otype'],
+ ]);
- $notify_id = DBA::lastInsertId();
+ $notification->link = DI::baseUrl() . '/notification/view/' . $notification->id;
+ $notification->msg = Renderer::replaceMacros($epreamble, ['$itemlink' => $notification->link]);
- $itemlink = DI::baseUrl().'/notify/view/'.$notify_id;
- $msg = Renderer::replaceMacros($epreamble, ['$itemlink' => $itemlink]);
- $msg_cache = format_notification_message($datarray['name_cache'], strip_tags(BBCode::convert($msg)));
+ DI::notify()->update($notification);
- $fields = ['msg' => $msg, 'msg_cache' => $msg_cache];
- $condition = ['id' => $notify_id, 'uid' => $params['uid']];
- DBA::update('notify', $fields, $condition);
+ $itemlink = $notification->link;
+ $notify_id = $notification->id;
}
// send email notification if notification preferences permit
Logger::log('sending notification email');
if (isset($params['parent']) && (intval($params['parent']) != 0)) {
- $id_for_parent = $params['parent']."@".$hostname;
+ $id_for_parent = $params['parent'] . "@" . $hostname;
// Is this the first email notification for this parent item and user?
if (!DBA::exists('notify-threads', ['master-parent-item' => $params['parent'], 'receiver-uid' => $params['uid']])) {
- Logger::log("notify_id:".intval($notify_id).", parent: ".intval($params['parent'])."uid: ".intval($params['uid']), Logger::DEBUG);
+ Logger::log("notify_id:" . intval($notify_id) . ", parent: " . intval($params['parent']) . "uid: " . intval($params['uid']), Logger::DEBUG);
- $fields = ['notify-id' => $notify_id, 'master-parent-item' => $params['parent'],
- 'receiver-uid' => $params['uid'], 'parent-item' => 0];
+ $fields = ['notify-id' => $notify_id, 'master-parent-item' => $params['parent'],
+ 'receiver-uid' => $params['uid'], 'parent-item' => 0];
DBA::insert('notify-threads', $fields);
$additional_mail_header .= "Message-ID: <${id_for_parent}>\n";
- $log_msg = "include/enotify: No previous notification found for this parent:\n".
- " parent: ${params['parent']}\n"." uid : ${params['uid']}\n";
+ $log_msg = "include/enotify: No previous notification found for this parent:\n" .
+ " parent: ${params['parent']}\n" . " uid : ${params['uid']}\n";
Logger::log($log_msg, Logger::DEBUG);
} else {
// If not, just "follow" the thread.
$textversion = BBCode::toPlaintext($body);
$htmlversion = BBCode::convert($body);
- $datarray = [];
- $datarray['banner'] = $banner;
- $datarray['product'] = $product;
- $datarray['preamble'] = $preamble;
- $datarray['sitename'] = $sitename;
- $datarray['siteurl'] = $siteurl;
- $datarray['type'] = $params['type'];
- $datarray['parent'] = $parent_id;
- $datarray['source_name'] = $params['source_name'] ?? '';
- $datarray['source_link'] = $params['source_link'] ?? '';
+ $datarray = [];
+ $datarray['banner'] = $banner;
+ $datarray['product'] = $product;
+ $datarray['preamble'] = $preamble;
+ $datarray['sitename'] = $sitename;
+ $datarray['siteurl'] = $siteurl;
+ $datarray['type'] = $params['type'];
+ $datarray['parent'] = $parent_id;
+ $datarray['source_name'] = $params['source_name'] ?? '';
+ $datarray['source_link'] = $params['source_link'] ?? '';
$datarray['source_photo'] = $params['source_photo'] ?? '';
- $datarray['uid'] = $params['uid'];
- $datarray['username'] = $params['to_name'] ?? '';
- $datarray['hsitelink'] = $hsitelink;
- $datarray['tsitelink'] = $tsitelink;
- $datarray['hitemlink'] = '<a href="'.$itemlink.'">'.$itemlink.'</a>';
- $datarray['titemlink'] = $itemlink;
- $datarray['thanks'] = $thanks;
- $datarray['site_admin'] = $site_admin;
- $datarray['title'] = stripslashes($title);
- $datarray['htmlversion'] = $htmlversion;
- $datarray['textversion'] = $textversion;
- $datarray['subject'] = $subject;
- $datarray['headers'] = $additional_mail_header;
+ $datarray['uid'] = $params['uid'];
+ $datarray['username'] = $params['to_name'] ?? '';
+ $datarray['hsitelink'] = $hsitelink;
+ $datarray['tsitelink'] = $tsitelink;
+ $datarray['hitemlink'] = '<a href="' . $itemlink . '">' . $itemlink . '</a>';
+ $datarray['titemlink'] = $itemlink;
+ $datarray['thanks'] = $thanks;
+ $datarray['site_admin'] = $site_admin;
+ $datarray['title'] = stripslashes($title);
+ $datarray['htmlversion'] = $htmlversion;
+ $datarray['textversion'] = $textversion;
+ $datarray['subject'] = $subject;
+ $datarray['headers'] = $additional_mail_header;
Hook::callAll('enotify_mail', $datarray);
$content_allowed = ((!DI::config()->get('system', 'enotify_no_content')) || ($params['type'] == SYSTEM_EMAIL));
// load the template for private message notifications
- $tpl = Renderer::getMarkupTemplate('email_notify_html.tpl');
+ $tpl = Renderer::getMarkupTemplate('email_notify_html.tpl');
$email_html_body = Renderer::replaceMacros($tpl, [
- '$banner' => $datarray['banner'],
- '$product' => $datarray['product'],
- '$preamble' => str_replace("\n", "<br>\n", $datarray['preamble']),
- '$sitename' => $datarray['sitename'],
- '$siteurl' => $datarray['siteurl'],
- '$source_name' => $datarray['source_name'],
- '$source_link' => $datarray['source_link'],
- '$source_photo' => $datarray['source_photo'],
- '$username' => $datarray['username'],
- '$hsitelink' => $datarray['hsitelink'],
- '$hitemlink' => $datarray['hitemlink'],
- '$thanks' => $datarray['thanks'],
- '$site_admin' => $datarray['site_admin'],
- '$title' => $datarray['title'],
- '$htmlversion' => $datarray['htmlversion'],
- '$content_allowed' => $content_allowed,
+ '$banner' => $datarray['banner'],
+ '$product' => $datarray['product'],
+ '$preamble' => str_replace("\n", "<br>\n", $datarray['preamble']),
+ '$sitename' => $datarray['sitename'],
+ '$siteurl' => $datarray['siteurl'],
+ '$source_name' => $datarray['source_name'],
+ '$source_link' => $datarray['source_link'],
+ '$source_photo' => $datarray['source_photo'],
+ '$username' => $datarray['username'],
+ '$hsitelink' => $datarray['hsitelink'],
+ '$hitemlink' => $datarray['hitemlink'],
+ '$thanks' => $datarray['thanks'],
+ '$site_admin' => $datarray['site_admin'],
+ '$title' => $datarray['title'],
+ '$htmlversion' => $datarray['htmlversion'],
+ '$content_allowed' => $content_allowed,
]);
// load the template for private message notifications
- $tpl = Renderer::getMarkupTemplate('email_notify_text.tpl');
+ $tpl = Renderer::getMarkupTemplate('email_notify_text.tpl');
$email_text_body = Renderer::replaceMacros($tpl, [
- '$banner' => $datarray['banner'],
- '$product' => $datarray['product'],
- '$preamble' => $datarray['preamble'],
- '$sitename' => $datarray['sitename'],
- '$siteurl' => $datarray['siteurl'],
- '$source_name' => $datarray['source_name'],
- '$source_link' => $datarray['source_link'],
- '$source_photo' => $datarray['source_photo'],
- '$username' => $datarray['username'],
- '$tsitelink' => $datarray['tsitelink'],
- '$titemlink' => $datarray['titemlink'],
- '$thanks' => $datarray['thanks'],
- '$site_admin' => $datarray['site_admin'],
- '$title' => $datarray['title'],
- '$textversion' => $datarray['textversion'],
- '$content_allowed' => $content_allowed,
+ '$banner' => $datarray['banner'],
+ '$product' => $datarray['product'],
+ '$preamble' => $datarray['preamble'],
+ '$sitename' => $datarray['sitename'],
+ '$siteurl' => $datarray['siteurl'],
+ '$source_name' => $datarray['source_name'],
+ '$source_link' => $datarray['source_link'],
+ '$source_photo' => $datarray['source_photo'],
+ '$username' => $datarray['username'],
+ '$tsitelink' => $datarray['tsitelink'],
+ '$titemlink' => $datarray['titemlink'],
+ '$thanks' => $datarray['thanks'],
+ '$site_admin' => $datarray['site_admin'],
+ '$title' => $datarray['title'],
+ '$textversion' => $datarray['textversion'],
+ '$content_allowed' => $content_allowed,
]);
+ $email = new Email($sender_name, $sender_email, $sender_email, $params['to_email'],
+ $datarray['subject'], $email_html_body, $email_text_body,
+ $datarray['headers'], $params['uid']);
+
// use the Emailer class to send the message
- return Emailer::send([
- 'uid' => $params['uid'],
- 'fromName' => $sender_name,
- 'fromEmail' => $sender_email,
- 'replyTo' => $sender_email,
- 'toEmail' => $params['to_email'],
- 'messageSubject' => $datarray['subject'],
- 'htmlVersion' => $email_html_body,
- 'textVersion' => $email_text_body,
- 'additionalMailHeader' => $datarray['headers']
- ]);
+ return DI::emailer()->send($email);
}
return false;
notification($params);
}
-
-/**
- * Formats a notification message with the notification author
- *
- * Replace the name with {0} but ensure to make that only once. The {0} is used
- * later and prints the name in bold.
- *
- * @param string $name
- * @param string $message
- * @return string Formatted message
- */
-function format_notification_message($name, $message) {
- if ($name != '') {
- $pos = strpos($message, $name);
- } else {
- $pos = false;
- }
-
- if ($pos !== false) {
- $message = substr_replace($message, '{0}', $pos, strlen($name));
- }
-
- return $message;
-}
use Friendica\Model\Event;
use Friendica\Model\Item;
use Friendica\Model\Profile;
+use Friendica\Module\BaseProfile;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Temporal;
$sql_extra = " AND `event`.`cid` = 0 " . $sql_perms;
// get the tab navigation bar
- $tabs = Profile::getTabs($a, 'cal', false, $a->data['user']['nickname']);
+ $tabs = BaseProfile::getTabsHTML($a, 'cal', false, $a->data['user']['nickname']);
// The view mode part is similiar to /mod/events.php
if ($mode == 'view') {
if (!empty($a->user['nickname']) && $nickname != $a->user['nickname']) {
$profile = DBA::fetchFirst("SELECT `profile`.* , `contact`.`avatar-date` AS picdate, `user`.* FROM `profile`
INNER JOIN `contact` on `contact`.`uid` = `profile`.`uid` INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
- WHERE `user`.`nickname` = ? AND `profile`.`is-default` AND `contact`.`self` LIMIT 1",
+ WHERE `user`.`nickname` = ? AND `contact`.`self` LIMIT 1",
$nickname
);
if (DBA::isResult($profile)) {
use Friendica\DI;
use Friendica\Model\Event;
use Friendica\Model\Item;
-use Friendica\Model\Profile;
use Friendica\Model\User;
+use Friendica\Module\BaseProfile;
use Friendica\Module\Security\Login;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Strings;
$tabs = '';
// tabs
if ($a->theme_events_in_profile) {
- $tabs = Profile::getTabs($a, 'events', true);
+ $tabs = BaseProfile::getTabsHTML($a, 'events', true);
}
$mode = 'view';
use Friendica\App;
use Friendica\Content\Pager;
use Friendica\Content\Text\BBCode;
-use Friendica\Content\Text\HTML;
use Friendica\Core\Hook;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Model\Item;
use Friendica\Model\Photo;
use Friendica\Model\Term;
+use Friendica\Object\EMail\ItemCCEMail;
use Friendica\Protocol\Activity;
use Friendica\Protocol\Diaspora;
-use Friendica\Protocol\Email;
use Friendica\Util\DateTimeFormat;
-use Friendica\Util\Emailer;
use Friendica\Util\Security;
use Friendica\Util\Strings;
use Friendica\Worker\Delivery;
Hook::callAll('post_local_end', $datarray);
if (strlen($emailcc) && $profile_uid == local_user()) {
- $erecips = explode(',', $emailcc);
- if (count($erecips)) {
- foreach ($erecips as $recip) {
- $addr = trim($recip);
- if (!strlen($addr)) {
+ $recipients = explode(',', $emailcc);
+ if (count($recipients)) {
+ foreach ($recipients as $recipient) {
+ $address = trim($recipient);
+ if (!strlen($address)) {
continue;
}
- $disclaimer = '<hr />' . DI::l10n()->t('This message was sent to you by %s, a member of the Friendica social network.', $a->user['username'])
- . '<br />';
- $disclaimer .= DI::l10n()->t('You may visit them online at %s', DI::baseUrl() . '/profile/' . $a->user['nickname']) . EOL;
- $disclaimer .= DI::l10n()->t('Please contact the sender by replying to this post if you do not wish to receive these messages.') . EOL;
- if (!$datarray['title']=='') {
- $subject = Email::encodeHeader($datarray['title'], 'UTF-8');
- } else {
- $subject = Email::encodeHeader('[Friendica]' . ' ' . DI::l10n()->t('%s posted an update.', $a->user['username']), 'UTF-8');
- }
- $link = '<a href="' . DI::baseUrl() . '/profile/' . $a->user['nickname'] . '"><img src="' . $author['thumb'] . '" alt="' . $a->user['username'] . '" /></a><br /><br />';
- $html = Item::prepareBody($datarray);
- $message = '<html><body>' . $link . $html . $disclaimer . '</body></html>';
- $params = [
- 'fromName' => $a->user['username'],
- 'fromEmail' => $a->user['email'],
- 'toEmail' => $addr,
- 'replyTo' => $a->user['email'],
- 'messageSubject' => $subject,
- 'htmlVersion' => $message,
- 'textVersion' => HTML::toPlaintext($html.$disclaimer)
- ];
- Emailer::send($params);
+ DI::emailer()->send(new ItemCCEMail(DI::app(), DI::l10n(), DI::baseUrl(),
+ $datarray, $address, $author['thumb'] ?? ''));
}
}
}
"SELECT COUNT(*) AS `total`
FROM `profile`
JOIN `user` ON `user`.`uid` = `profile`.`uid`
- WHERE `is-default` = 1
- AND `user`.`hidewall` = 0
+ WHERE `user`.`hidewall` = 0
AND MATCH(`pub_keywords`) AGAINST (?)",
$search
);
"SELECT `pub_keywords`, `username`, `nickname`, `user`.`uid`
FROM `user`
JOIN `profile` ON `user`.`uid` = `profile`.`uid`
- WHERE `is-default` = 1
- AND `user`.`hidewall` = 0
+ WHERE `user`.`hidewall` = 0
AND MATCH(`pub_keywords`) AGAINST (?)
LIMIT ?, ?",
$search,
{
// item filter tabs
/// @TODO fix this logic, reduce duplication
- /// $a->page['content'] .= '<div class="tabs-wrapper">';
+ /// DI::page()['content'] .= '<div class="tabs-wrapper">';
list($no_active, $all_active, $post_active, $conv_active, $new_active, $starred_active, $bookmarked_active) = network_query_get_sel_tab($a);
// if no tabs are selected, defaults to activitys
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\Item;
-use Friendica\Model\Profile;
+use Friendica\Module\BaseProfile;
function notes_init(App $a)
{
return;
}
- $o = Profile::getTabs($a, 'notes', true);
+ $o = BaseProfile::getTabsHTML($a, 'notes', true);
if (!$update) {
$o .= '<h3>' . DI::l10n()->t('Personal Notes') . '</h3>';
+++ /dev/null
-<?php
-/**
- * @file mod/notifications.php
- * The notifications module
- */
-
-use Friendica\App;
-use Friendica\Content\ContactSelector;
-use Friendica\Content\Nav;
-use Friendica\Content\Pager;
-use Friendica\Core\Protocol;
-use Friendica\Core\Renderer;
-use Friendica\Core\System;
-use Friendica\Database\DBA;
-use Friendica\DI;
-use Friendica\Model\Notify;
-use Friendica\Module\Security\Login;
-
-/** @var array Array of URL parameters */
-const URL_TYPES = [
- Notify::NETWORK => 'network',
- Notify::SYSTEM => 'system',
- Notify::HOME => 'home',
- Notify::PERSONAL => 'personal',
- Notify::INTRO => 'intros',
-];
-
-/** @var array Array of the allowed notifies and their printable name */
-const PRINT_TYPES = [
- Notify::NETWORK => 'Network',
- Notify::SYSTEM => 'System',
- Notify::HOME => 'Home',
- Notify::PERSONAL => 'Personal',
- Notify::INTRO => 'Introductions',
-];
-
-/** @var array The array of access keys for notify pages */
-const ACCESS_KEYS = [
- Notify::NETWORK => 'w',
- Notify::SYSTEM => 'y',
- Notify::HOME => 'h',
- Notify::PERSONAL => 'r',
- Notify::INTRO => 'i',
-];
-
-function notifications_post(App $a)
-{
- if (!local_user()) {
- DI::baseUrl()->redirect();
- }
-
- $request_id = (($a->argc > 1) ? $a->argv[1] : 0);
-
- if ($request_id === 'all') {
- return;
- }
-
- if ($request_id) {
- $intro = DI::intro()->selectFirst(['id' => $request_id, 'uid' => local_user()]);
-
- switch ($_POST['submit']) {
- case DI::l10n()->t('Discard'):
- $intro->discard();
- break;
- case DI::l10n()->t('Ignore'):
- $intro->ignore();
- break;
- }
-
- DI::baseUrl()->redirect('notifications/intros');
- }
-}
-
-function notifications_content(App $a)
-{
- if (!local_user()) {
- notice(DI::l10n()->t('Permission denied.') . EOL);
- return Login::form();
- }
-
- $page = ($_REQUEST['page'] ?? 0) ?: 1;
- $show = ($_REQUEST['show'] ?? '') === 'all';
-
- Nav::setSelected('notifications');
-
- $json = (($a->argc > 1 && $a->argv[$a->argc - 1] === 'json') ? true : false);
-
- $nm = DI::notify();
-
- $o = '';
- // Get the nav tabs for the notification pages
- $tabs = getTabs(DI::args()->get(1, ''));
- $notif_content = [];
- $notif_nocontent = '';
-
- // Notification results per page
- $perpage = 20;
- $startrec = ($page * $perpage) - $perpage;
-
- $notif_header = DI::l10n()->t('Notifications');
-
- $all = false;
-
- // Get introductions
- if ((($a->argc > 1) && ($a->argv[1] == 'intros')) || (($a->argc == 1))) {
- Nav::setSelected('introductions');
-
- $id = 0;
- if (!empty($a->argv[2]) && intval($a->argv[2]) != 0) {
- $id = (int)$a->argv[2];
- }
-
- $all = (($a->argc > 2) && ($a->argv[2] == 'all'));
-
- $notifs = $nm->getIntroList($all, $startrec, $perpage, $id);
-
- // Get the network notifications
- } elseif (($a->argc > 1) && ($a->argv[1] == 'network')) {
- $notif_header = DI::l10n()->t('Network Notifications');
- $notifs = $nm->getNetworkList($show, $startrec, $perpage);
-
- // Get the system notifications
- } elseif (($a->argc > 1) && ($a->argv[1] == 'system')) {
- $notif_header = DI::l10n()->t('System Notifications');
- $notifs = $nm->getSystemList($show, $startrec, $perpage);
-
- // Get the personal notifications
- } elseif (($a->argc > 1) && ($a->argv[1] == 'personal')) {
- $notif_header = DI::l10n()->t('Personal Notifications');
- $notifs = $nm->getPersonalList($show, $startrec, $perpage);
-
- // Get the home notifications
- } elseif (($a->argc > 1) && ($a->argv[1] == 'home')) {
- $notif_header = DI::l10n()->t('Home Notifications');
- $notifs = $nm->getHomeList($show, $startrec, $perpage);
- // fallback - redirect to main page
- } else {
- DI::baseUrl()->redirect('notifications');
- }
-
- // Set the pager
- $pager = new Pager(DI::args()->getQueryString(), $perpage);
-
- // Add additional informations (needed for json output)
- $notifs['items_page'] = $pager->getItemsPerPage();
- $notifs['page'] = $pager->getPage();
-
- // Json output
- if (intval($json) === 1) {
- System::jsonExit($notifs);
- }
-
- $notif_tpl = Renderer::getMarkupTemplate('notifications.tpl');
-
- $notif_show_lnk = [
- 'href' => ($show ? 'notifications/' . $notifs['ident'] : 'notifications/' . $notifs['ident'] . '?show=all' ),
- 'text' => ($show ? DI::l10n()->t('Show unread') : DI::l10n()->t('Show all')),
- ];
-
- // Process the data for template creation
- if (($notifs['ident'] ?? '') == 'introductions') {
- $sugg = Renderer::getMarkupTemplate('suggestions.tpl');
- $tpl = Renderer::getMarkupTemplate('intros.tpl');
-
- // The link to switch between ignored and normal connection requests
- $notif_show_lnk = [
- 'href' => (!$all ? 'notifications/intros/all' : 'notifications/intros' ),
- 'text' => (!$all ? DI::l10n()->t('Show Ignored Requests') : DI::l10n()->t('Hide Ignored Requests'))
- ];
-
- // Loop through all introduction notifications.This creates an array with the output html for each
- // introduction
- foreach ($notifs['notifications'] as $notif) {
-
- // There are two kind of introduction. Contacts suggested by other contacts and normal connection requests.
- // We have to distinguish between these two because they use different data.
- switch ($notif['label']) {
- case 'friend_suggestion':
- $notif_content[] = Renderer::replaceMacros($sugg, [
- '$type' => $notif['label'],
- '$str_notifytype' => DI::l10n()->t('Notification type:'),
- '$notify_type'=> $notif['notify_type'],
- '$intro_id' => $notif['intro_id'],
- '$lbl_madeby' => DI::l10n()->t('Suggested by:'),
- '$madeby' => $notif['madeby'],
- '$madeby_url' => $notif['madeby_url'],
- '$madeby_zrl' => $notif['madeby_zrl'],
- '$madeby_addr'=> $notif['madeby_addr'],
- '$contact_id' => $notif['contact_id'],
- '$photo' => $notif['photo'],
- '$fullname' => $notif['name'],
- '$url' => $notif['url'],
- '$zrl' => $notif['zrl'],
- '$lbl_url' => DI::l10n()->t('Profile URL'),
- '$addr' => $notif['addr'],
- '$hidden' => ['hidden', DI::l10n()->t('Hide this contact from others'), ($notif['hidden'] == 1), ''],
- '$knowyou' => $notif['knowyou'],
- '$approve' => DI::l10n()->t('Approve'),
- '$note' => $notif['note'],
- '$request' => $notif['request'],
- '$ignore' => DI::l10n()->t('Ignore'),
- '$discard' => DI::l10n()->t('Discard'),
- ]);
- break;
-
- // Normal connection requests
- default:
- $friend_selected = (($notif['network'] !== Protocol::OSTATUS) ? ' checked="checked" ' : ' disabled ');
- $fan_selected = (($notif['network'] === Protocol::OSTATUS) ? ' checked="checked" disabled ' : '');
-
- $lbl_knowyou = '';
- $knowyou = '';
- $helptext = '';
- $helptext2 = '';
- $helptext3 = '';
-
- if ($notif['network'] === Protocol::DFRN) {
- $lbl_knowyou = DI::l10n()->t('Claims to be known to you: ');
- $knowyou = (($notif['knowyou']) ? DI::l10n()->t('yes') : DI::l10n()->t('no'));
- $helptext = DI::l10n()->t('Shall your connection be bidirectional or not?');
- $helptext2 = DI::l10n()->t('Accepting %s as a friend allows %s to subscribe to your posts, and you will also receive updates from them in your news feed.', $notif['name'], $notif['name']);
- $helptext3 = DI::l10n()->t('Accepting %s as a subscriber allows them to subscribe to your posts, but you will not receive updates from them in your news feed.', $notif['name']);
- } elseif ($notif['network'] === Protocol::DIASPORA) {
- $helptext = DI::l10n()->t('Shall your connection be bidirectional or not?');
- $helptext2 = DI::l10n()->t('Accepting %s as a friend allows %s to subscribe to your posts, and you will also receive updates from them in your news feed.', $notif['name'], $notif['name']);
- $helptext3 = DI::l10n()->t('Accepting %s as a sharer allows them to subscribe to your posts, but you will not receive updates from them in your news feed.', $notif['name']);
- }
-
- $dfrn_tpl = Renderer::getMarkupTemplate('netfriend.tpl');
- $dfrn_text = Renderer::replaceMacros($dfrn_tpl, [
- '$intro_id' => $notif['intro_id'],
- '$friend_selected' => $friend_selected,
- '$fan_selected'=> $fan_selected,
- '$approve_as1' => $helptext,
- '$approve_as2' => $helptext2,
- '$approve_as3' => $helptext3,
- '$as_friend' => DI::l10n()->t('Friend'),
- '$as_fan' => (($notif['network'] == Protocol::DIASPORA) ? DI::l10n()->t('Sharer') : DI::l10n()->t('Subscriber'))
- ]);
-
- $contact = DBA::selectFirst('contact', ['network', 'protocol'], ['id' => $notif['contact_id']]);
-
- if (($contact['network'] != Protocol::DFRN) || ($contact['protocol'] == Protocol::ACTIVITYPUB)) {
- $action = 'follow_confirm';
- } else {
- $action = 'dfrn_confirm';
- }
-
- $header = $notif['name'];
-
- if ($notif['addr'] != '') {
- $header .= ' <' . $notif['addr'] . '>';
- }
-
- $header .= ' (' . ContactSelector::networkToName($notif['network'], $notif['url']) . ')';
-
- if ($notif['network'] != Protocol::DIASPORA) {
- $discard = DI::l10n()->t('Discard');
- } else {
- $discard = '';
- }
-
- $notif_content[] = Renderer::replaceMacros($tpl, [
- '$type' => $notif['label'],
- '$header' => $header,
- '$str_notifytype' => DI::l10n()->t('Notification type:'),
- '$notify_type' => $notif['notify_type'],
- '$dfrn_text' => $dfrn_text,
- '$dfrn_id' => $notif['dfrn_id'],
- '$uid' => $notif['uid'],
- '$intro_id' => $notif['intro_id'],
- '$contact_id' => $notif['contact_id'],
- '$photo' => $notif['photo'],
- '$fullname' => $notif['name'],
- '$location' => $notif['location'],
- '$lbl_location'=> DI::l10n()->t('Location:'),
- '$about' => $notif['about'],
- '$lbl_about' => DI::l10n()->t('About:'),
- '$keywords' => $notif['keywords'],
- '$lbl_keywords'=> DI::l10n()->t('Tags:'),
- '$gender' => $notif['gender'],
- '$lbl_gender' => DI::l10n()->t('Gender:'),
- '$hidden' => ['hidden', DI::l10n()->t('Hide this contact from others'), ($notif['hidden'] == 1), ''],
- '$url' => $notif['url'],
- '$zrl' => $notif['zrl'],
- '$lbl_url' => DI::l10n()->t('Profile URL'),
- '$addr' => $notif['addr'],
- '$lbl_knowyou' => $lbl_knowyou,
- '$lbl_network' => DI::l10n()->t('Network:'),
- '$network' => ContactSelector::networkToName($notif['network'], $notif['url']),
- '$knowyou' => $knowyou,
- '$approve' => DI::l10n()->t('Approve'),
- '$note' => $notif['note'],
- '$ignore' => DI::l10n()->t('Ignore'),
- '$discard' => $discard,
- '$action' => $action,
- ]);
- break;
- }
- }
-
- if (count($notifs['notifications']) == 0) {
- info(DI::l10n()->t('No introductions.') . EOL);
- }
-
- // Normal notifications (no introductions)
- } elseif (!empty($notifs['notifications'])) {
- // Loop trough ever notification This creates an array with the output html for each
- // notification and apply the correct template according to the notificationtype (label).
- foreach ($notifs['notifications'] as $notif) {
- $notification_templates = [
- 'like' => 'notifications_likes_item.tpl',
- 'dislike' => 'notifications_dislikes_item.tpl',
- 'attend' => 'notifications_attend_item.tpl',
- 'attendno' => 'notifications_attend_item.tpl',
- 'attendmaybe' => 'notifications_attend_item.tpl',
- 'friend' => 'notifications_friends_item.tpl',
- 'comment' => 'notifications_comments_item.tpl',
- 'post' => 'notifications_posts_item.tpl',
- 'notify' => 'notify.tpl',
- ];
-
- $tpl_notif = Renderer::getMarkupTemplate($notification_templates[$notif['label']]);
-
- $notif_content[] = Renderer::replaceMacros($tpl_notif, [
- '$item_label' => $notif['label'],
- '$item_link' => $notif['link'],
- '$item_image' => $notif['image'],
- '$item_url' => $notif['url'],
- '$item_text' => $notif['text'],
- '$item_when' => $notif['when'],
- '$item_ago' => $notif['ago'],
- '$item_seen' => $notif['seen'],
- ]);
- }
- } else {
- $notif_nocontent = DI::l10n()->t('No more %s notifications.', $notifs['ident']);
- }
-
- $o .= Renderer::replaceMacros($notif_tpl, [
- '$notif_header' => $notif_header,
- '$tabs' => $tabs,
- '$notif_content' => $notif_content,
- '$notif_nocontent' => $notif_nocontent,
- '$notif_show_lnk' => $notif_show_lnk,
- '$notif_paginate' => $pager->renderMinimal(count($notif_content))
- ]);
-
- return $o;
-}
-
-/**
- * List of pages for the Notifications TabBar
- *
- * @param string $selected The selected notification tab
- *
- * @return array with with notifications TabBar data
- * @throws Exception
- */
-function getTabs(string $selected = '')
-{
- $tabs = [];
-
- foreach (URL_TYPES as $type => $url) {
- $tabs[] = [
- 'label' => DI::l10n()->t(PRINT_TYPES[$type]),
- 'url' => 'notifications/' . $url,
- 'sel' => (($selected == $url) ? 'active' : ''),
- 'id' => $type . '-tab',
- 'accesskey' => ACCESS_KEYS[$type],
- ];
- }
-
- return $tabs;
-}
use Friendica\Model\Photo;
use Friendica\Model\Profile;
use Friendica\Model\User;
+use Friendica\Module\BaseProfile;
use Friendica\Network\Probe;
use Friendica\Object\Image;
use Friendica\Protocol\Activity;
// tabs
$is_owner = (local_user() && (local_user() == $owner_uid));
- $o .= Profile::getTabs($a, 'photos', $is_owner, $a->data['user']['nickname']);
+ $o .= BaseProfile::getTabsHTML($a, 'photos', $is_owner, $a->data['user']['nickname']);
// Display upload form
if ($datatype === 'upload') {
* "birthdays-today": 0,
* "groups": [ ],
* "forums": [ ],
- * "notify": 0,
+ * "notification": 0,
* "notifications": [ ],
* "sysmsgs": {
* "notice": [ ],
if ($format == 'json') {
$data['groups'] = $groups_unseen;
$data['forums'] = $forums_unseen;
- $data['notify'] = $sysnotify_count + $intro_count + $register_count;
+ $data['notification'] = $sysnotify_count + $intro_count + $register_count;
$data['notifications'] = $notifications;
$data['sysmsgs'] = [
'notice' => $sysmsgs,
$notification["message"] = $notification["msg_cache"];
} else {
$notification["name"] = strip_tags(BBCode::convert($notification["name"]));
- $notification["message"] = format_notification_message($notification["name"], strip_tags(BBCode::convert($notification["msg"])));
+ $notification["message"] = Friendica\Model\Notify::formatMessage($notification["name"], strip_tags(BBCode::convert($notification["msg"])));
q(
"UPDATE `notify` SET `name_cache` = '%s', `msg_cache` = '%s' WHERE `id` = %d",
);
}
- $notification["href"] = DI::baseUrl() . "/notify/view/" . $notification["id"];
+ $notification["href"] = DI::baseUrl() . "/notification/view/" . $notification["id"];
if ($notification["visible"]
&& !$notification["deleted"]
if (! $system_mode && ! $global) {
$users = q("SELECT `user`.*,`profile`.`hide-friends` from user left join profile on `user`.`uid` = `profile`.`uid`
- where `user`.`nickname` = '%s' and `profile`.`is-default` = 1 limit 1",
+ where `user`.`nickname` = '%s' limit 1",
DBA::escape($nickname)
);
if (! DBA::isResult($users) || $users[0]['hidewall'] || $users[0]['hide-friends']) {
`profile`.`postal-code` AS `ppostalcode`, `profile`.`country-name` AS `pcountry`, `user`.`account-type`
FROM `contact` INNER JOIN `profile` ON `profile`.`uid` = `contact`.`uid`
INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
- WHERE `self` = 1 AND `profile`.`is-default`
+ WHERE `self` = 1
AND `contact`.`uid` IN (SELECT `uid` FROM `pconfig` WHERE `cat` = 'system' AND `k` = 'suggestme' AND `v` = 1) LIMIT %d, %d",
intval($startIndex),
intval($itemsPerPage)
+++ /dev/null
-<?php
-/**
- * @file mod/profiles.php
- */
-
-use Friendica\App;
-use Friendica\BaseModule;
-use Friendica\Content\ContactSelector;
-use Friendica\Content\Feature;
-use Friendica\Content\Nav;
-use Friendica\Core\Hook;
-use Friendica\Core\Renderer;
-use Friendica\Core\Worker;
-use Friendica\Database\DBA;
-use Friendica\DI;
-use Friendica\Model\Contact;
-use Friendica\Model\GContact;
-use Friendica\Model\Profile;
-use Friendica\Model\User;
-use Friendica\Module\Security\Login;
-use Friendica\Network\Probe;
-use Friendica\Util\DateTimeFormat;
-use Friendica\Util\Strings;
-use Friendica\Util\Temporal;
-
-function profiles_init(App $a) {
-
- Nav::setSelected('profiles');
-
- if (! local_user()) {
- return;
- }
-
- if (($a->argc > 2) && ($a->argv[1] === "drop") && intval($a->argv[2])) {
- $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d AND `is-default` = 0 LIMIT 1",
- intval($a->argv[2]),
- intval(local_user())
- );
- if (! DBA::isResult($r)) {
- notice(DI::l10n()->t('Profile not found.') . EOL);
- DI::baseUrl()->redirect('profiles');
- return; // NOTREACHED
- }
-
- BaseModule::checkFormSecurityTokenRedirectOnError('/profiles', 'profile_drop', 't');
-
- // move every contact using this profile as their default to the user default
-
- q("UPDATE `contact` SET `profile-id` = (SELECT `profile`.`id` AS `profile-id` FROM `profile` WHERE `profile`.`is-default` = 1 AND `profile`.`uid` = %d LIMIT 1) WHERE `profile-id` = %d AND `uid` = %d ",
- intval(local_user()),
- intval($a->argv[2]),
- intval(local_user())
- );
- q("DELETE FROM `profile` WHERE `id` = %d AND `uid` = %d",
- intval($a->argv[2]),
- intval(local_user())
- );
- if (DBA::isResult($r)) {
- info(DI::l10n()->t('Profile deleted.').EOL);
- }
-
- DI::baseUrl()->redirect('profiles');
- return; // NOTREACHED
- }
-
- if (($a->argc > 1) && ($a->argv[1] === 'new')) {
-
- BaseModule::checkFormSecurityTokenRedirectOnError('/profiles', 'profile_new', 't');
-
- $r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d",
- intval(local_user()));
-
- $num_profiles = (DBA::isResult($r0) ? count($r0) : 0);
-
- $name = DI::l10n()->t('Profile-') . ($num_profiles + 1);
-
- $r1 = q("SELECT `name`, `photo`, `thumb` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1",
- intval(local_user()));
-
- q("INSERT INTO `profile` (`uid` , `profile-name` , `name`, `photo`, `thumb`)
- VALUES ( %d, '%s', '%s', '%s', '%s' )",
- intval(local_user()),
- DBA::escape($name),
- DBA::escape($r1[0]['name']),
- DBA::escape($r1[0]['photo']),
- DBA::escape($r1[0]['thumb'])
- );
-
- $r3 = q("SELECT `id` FROM `profile` WHERE `uid` = %d AND `profile-name` = '%s' LIMIT 1",
- intval(local_user()),
- DBA::escape($name)
- );
-
- info(DI::l10n()->t('New profile created.') . EOL);
- if (DBA::isResult($r3) && count($r3) == 1) {
- DI::baseUrl()->redirect('profiles/' . $r3[0]['id']);
- }
-
- DI::baseUrl()->redirect('profiles');
- }
-
- if (($a->argc > 2) && ($a->argv[1] === 'clone')) {
-
- BaseModule::checkFormSecurityTokenRedirectOnError('/profiles', 'profile_clone', 't');
-
- $r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d",
- intval(local_user()));
-
- $num_profiles = (DBA::isResult($r0) ? count($r0) : 0);
-
- $name = DI::l10n()->t('Profile-') . ($num_profiles + 1);
- $r1 = q("SELECT * FROM `profile` WHERE `uid` = %d AND `id` = %d LIMIT 1",
- intval(local_user()),
- intval($a->argv[2])
- );
- if(! DBA::isResult($r1)) {
- notice(DI::l10n()->t('Profile unavailable to clone.') . EOL);
- exit();
- }
- unset($r1[0]['id']);
- $r1[0]['is-default'] = 0;
- $r1[0]['publish'] = 0;
- $r1[0]['net-publish'] = 0;
- $r1[0]['profile-name'] = DBA::escape($name);
-
- DBA::insert('profile', $r1[0]);
-
- $r3 = q("SELECT `id` FROM `profile` WHERE `uid` = %d AND `profile-name` = '%s' LIMIT 1",
- intval(local_user()),
- DBA::escape($name)
- );
- info(DI::l10n()->t('New profile created.') . EOL);
- if ((DBA::isResult($r3)) && (count($r3) == 1)) {
- DI::baseUrl()->redirect('profiles/'.$r3[0]['id']);
- }
-
- DI::baseUrl()->redirect('profiles');
-
- return; // NOTREACHED
- }
-
-
- if (($a->argc > 1) && (intval($a->argv[1]))) {
- $r = q("SELECT id FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1",
- intval($a->argv[1]),
- intval(local_user())
- );
- if (! DBA::isResult($r)) {
- notice(DI::l10n()->t('Profile not found.') . EOL);
- exit();
- }
-
- Profile::load($a, $a->user['nickname'], $r[0]['id']);
- }
-}
-
-function profile_clean_keywords($keywords)
-{
- $keywords = str_replace(",", " ", $keywords);
- $keywords = explode(" ", $keywords);
-
- $cleaned = [];
- foreach ($keywords as $keyword) {
- $keyword = trim(strtolower($keyword));
- $keyword = trim($keyword, "#");
- if ($keyword != "") {
- $cleaned[] = $keyword;
- }
- }
-
- $keywords = implode(", ", $cleaned);
-
- return $keywords;
-}
-
-function profiles_post(App $a) {
-
- if (! local_user()) {
- notice(DI::l10n()->t('Permission denied.') . EOL);
- return;
- }
-
- $namechanged = false;
-
- Hook::callAll('profile_post', $_POST);
-
- if (($a->argc > 1) && ($a->argv[1] !== "new") && intval($a->argv[1])) {
- $orig = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1",
- intval($a->argv[1]),
- intval(local_user())
- );
- if (! DBA::isResult($orig)) {
- notice(DI::l10n()->t('Profile not found.') . EOL);
- return;
- }
-
- BaseModule::checkFormSecurityTokenRedirectOnError('/profiles', 'profile_edit');
-
- $is_default = (($orig[0]['is-default']) ? 1 : 0);
-
- $profile_name = Strings::escapeTags(trim($_POST['profile_name']));
- if (! strlen($profile_name)) {
- notice(DI::l10n()->t('Profile Name is required.') . EOL);
- return;
- }
-
- $dob = !empty($_POST['dob']) ? Strings::escapeHtml(trim($_POST['dob'])) : '0000-00-00';
-
- $y = substr($dob, 0, 4);
- if ((! ctype_digit($y)) || ($y < 1900)) {
- $ignore_year = true;
- } else {
- $ignore_year = false;
- }
- if (!in_array($dob, ['0000-00-00', DBA::NULL_DATE])) {
- if (strpos($dob, '0000-') === 0 || strpos($dob, '0001-') === 0) {
- $ignore_year = true;
- $dob = substr($dob, 5);
- }
-
- if ($ignore_year) {
- $dob = '0000-' . DateTimeFormat::utc('1900-' . $dob, 'm-d');
- } else {
- $dob = DateTimeFormat::utc($dob, 'Y-m-d');
- }
- }
-
- $name = Strings::escapeTags(trim($_POST['name']));
-
- if (! strlen($name)) {
- $name = '[No Name]';
- }
-
- if ($orig[0]['name'] != $name) {
- $namechanged = true;
- }
-
- $pdesc = Strings::escapeTags(trim($_POST['pdesc'] ?? ''));
- $gender = Strings::escapeTags(trim($_POST['gender'] ?? ''));
- $address = Strings::escapeTags(trim($_POST['address'] ?? ''));
- $locality = Strings::escapeTags(trim($_POST['locality'] ?? ''));
- $region = Strings::escapeTags(trim($_POST['region'] ?? ''));
- $postal_code = Strings::escapeTags(trim($_POST['postal_code'] ?? ''));
- $country_name = Strings::escapeTags(trim($_POST['country_name'] ?? ''));
- $pub_keywords = profile_clean_keywords(Strings::escapeTags(trim($_POST['pub_keywords'] ?? '')));
- $prv_keywords = profile_clean_keywords(Strings::escapeTags(trim($_POST['prv_keywords'] ?? '')));
- $marital = Strings::escapeTags(trim($_POST['marital'] ?? ''));
- $howlong = Strings::escapeTags(trim($_POST['howlong'] ?? ''));
-
- $with = (!empty($_POST['with']) ? Strings::escapeTags(trim($_POST['with'])) : '');
-
- if (! strlen($howlong)) {
- $howlong = DBA::NULL_DATETIME;
- } else {
- $howlong = DateTimeFormat::convert($howlong, 'UTC', date_default_timezone_get());
- }
- // linkify the relationship target if applicable
-
- $withchanged = false;
-
- if (strlen($with)) {
- if ($with != strip_tags($orig[0]['with'])) {
- $withchanged = true;
- $prf = '';
- $lookup = $with;
- if (strpos($lookup, '@') === 0) {
- $lookup = substr($lookup, 1);
- }
- $lookup = str_replace('_',' ', $lookup);
- if (strpos($lookup, '@') || (strpos($lookup, 'http://'))) {
- $newname = $lookup;
- $links = @Probe::lrdd($lookup);
- if (count($links)) {
- foreach ($links as $link) {
- if ($link['@attributes']['rel'] === 'http://webfinger.net/rel/profile-page') {
- $prf = $link['@attributes']['href'];
- }
- }
- }
- } else {
- $newname = $lookup;
-
- $r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `uid` = %d LIMIT 1",
- DBA::escape($newname),
- intval(local_user())
- );
- if (! DBA::isResult($r)) {
- $r = q("SELECT * FROM `contact` WHERE `nick` = '%s' AND `uid` = %d LIMIT 1",
- DBA::escape($lookup),
- intval(local_user())
- );
- }
- if (DBA::isResult($r)) {
- $prf = $r[0]['url'];
- $newname = $r[0]['name'];
- }
- }
-
- if ($prf) {
- $with = str_replace($lookup, '<a href="' . $prf . '">' . $newname . '</a>', $with);
- if (strpos($with, '@') === 0) {
- $with = substr($with, 1);
- }
- }
- } else {
- $with = $orig[0]['with'];
- }
- }
-
- /// @TODO Not flexible enough for later expansion, let's have more OOP here
- $sexual = Strings::escapeTags(trim($_POST['sexual']));
- $xmpp = Strings::escapeTags(trim($_POST['xmpp']));
- $homepage = Strings::escapeTags(trim($_POST['homepage']));
- if ((strpos($homepage, 'http') !== 0) && (strlen($homepage))) {
- // neither http nor https in URL, add them
- $homepage = 'http://'.$homepage;
- }
- $hometown = Strings::escapeTags(trim($_POST['hometown']));
- $politic = Strings::escapeTags(trim($_POST['politic']));
- $religion = Strings::escapeTags(trim($_POST['religion']));
-
- $likes = Strings::escapeHtml(trim($_POST['likes']));
- $dislikes = Strings::escapeHtml(trim($_POST['dislikes']));
-
- $about = Strings::escapeHtml(trim($_POST['about']));
- $interest = Strings::escapeHtml(trim($_POST['interest']));
- $contact = Strings::escapeHtml(trim($_POST['contact']));
- $music = Strings::escapeHtml(trim($_POST['music']));
- $book = Strings::escapeHtml(trim($_POST['book']));
- $tv = Strings::escapeHtml(trim($_POST['tv']));
- $film = Strings::escapeHtml(trim($_POST['film']));
- $romance = Strings::escapeHtml(trim($_POST['romance']));
- $work = Strings::escapeHtml(trim($_POST['work']));
- $education = Strings::escapeHtml(trim($_POST['education']));
-
- $hide_friends = (($_POST['hide-friends'] == 1) ? 1: 0);
-
- DI::pConfig()->set(local_user(), 'system', 'detailled_profile', !empty($_POST['detailed_profile']) ? 1: 0);
-
- $changes = [];
- if ($is_default) {
- if ($marital != $orig[0]['marital']) {
- $changes[] = '[color=#ff0000]♥[/color] ' . DI::l10n()->t('Marital Status');
- }
- if ($withchanged) {
- $changes[] = '[color=#ff0000]♥[/color] ' . DI::l10n()->t('Romantic Partner');
- }
- if ($likes != $orig[0]['likes']) {
- $changes[] = DI::l10n()->t('Likes');
- }
- if ($dislikes != $orig[0]['dislikes']) {
- $changes[] = DI::l10n()->t('Dislikes');
- }
- if ($work != $orig[0]['work']) {
- $changes[] = DI::l10n()->t('Work/Employment');
- }
- if ($religion != $orig[0]['religion']) {
- $changes[] = DI::l10n()->t('Religion');
- }
- if ($politic != $orig[0]['politic']) {
- $changes[] = DI::l10n()->t('Political Views');
- }
- if ($gender != $orig[0]['gender']) {
- $changes[] = DI::l10n()->t('Gender');
- }
- if ($sexual != $orig[0]['sexual']) {
- $changes[] = DI::l10n()->t('Sexual Preference');
- }
- if ($xmpp != $orig[0]['xmpp']) {
- $changes[] = DI::l10n()->t('XMPP');
- }
- if ($homepage != $orig[0]['homepage']) {
- $changes[] = DI::l10n()->t('Homepage');
- }
- if ($interest != $orig[0]['interest']) {
- $changes[] = DI::l10n()->t('Interests');
- }
- if ($address != $orig[0]['address']) {
- $changes[] = DI::l10n()->t('Address');
- // New address not sent in notifications, potential privacy issues
- // in case this leaks to unintended recipients. Yes, it's in the public
- // profile but that doesn't mean we have to broadcast it to everybody.
- }
- if ($locality != $orig[0]['locality'] || $region != $orig[0]['region']
- || $country_name != $orig[0]['country-name']) {
- $changes[] = DI::l10n()->t('Location');
- }
- }
-
- $r = q("UPDATE `profile`
- SET `profile-name` = '%s',
- `name` = '%s',
- `pdesc` = '%s',
- `gender` = '%s',
- `dob` = '%s',
- `address` = '%s',
- `locality` = '%s',
- `region` = '%s',
- `postal-code` = '%s',
- `country-name` = '%s',
- `marital` = '%s',
- `with` = '%s',
- `howlong` = '%s',
- `sexual` = '%s',
- `xmpp` = '%s',
- `homepage` = '%s',
- `hometown` = '%s',
- `politic` = '%s',
- `religion` = '%s',
- `pub_keywords` = '%s',
- `prv_keywords` = '%s',
- `likes` = '%s',
- `dislikes` = '%s',
- `about` = '%s',
- `interest` = '%s',
- `contact` = '%s',
- `music` = '%s',
- `book` = '%s',
- `tv` = '%s',
- `film` = '%s',
- `romance` = '%s',
- `work` = '%s',
- `education` = '%s',
- `hide-friends` = %d
- WHERE `id` = %d AND `uid` = %d",
- DBA::escape($profile_name),
- DBA::escape($name),
- DBA::escape($pdesc),
- DBA::escape($gender),
- DBA::escape($dob),
- DBA::escape($address),
- DBA::escape($locality),
- DBA::escape($region),
- DBA::escape($postal_code),
- DBA::escape($country_name),
- DBA::escape($marital),
- DBA::escape($with),
- DBA::escape($howlong),
- DBA::escape($sexual),
- DBA::escape($xmpp),
- DBA::escape($homepage),
- DBA::escape($hometown),
- DBA::escape($politic),
- DBA::escape($religion),
- DBA::escape($pub_keywords),
- DBA::escape($prv_keywords),
- DBA::escape($likes),
- DBA::escape($dislikes),
- DBA::escape($about),
- DBA::escape($interest),
- DBA::escape($contact),
- DBA::escape($music),
- DBA::escape($book),
- DBA::escape($tv),
- DBA::escape($film),
- DBA::escape($romance),
- DBA::escape($work),
- DBA::escape($education),
- intval($hide_friends),
- intval($a->argv[1]),
- intval(local_user())
- );
-
- /// @TODO decide to use DBA::isResult() here and check $r
- if ($r) {
- info(DI::l10n()->t('Profile updated.') . EOL);
- }
-
- if ($is_default) {
- if ($namechanged) {
- q("UPDATE `user` set `username` = '%s' where `uid` = %d",
- DBA::escape($name),
- intval(local_user())
- );
- }
-
- Contact::updateSelfFromUserID(local_user());
-
- // Update global directory in background
- $url = $_SESSION['my_url'];
- if ($url && strlen(DI::config()->get('system', 'directory'))) {
- Worker::add(PRIORITY_LOW, "Directory", $url);
- }
-
- Worker::add(PRIORITY_LOW, 'ProfileUpdate', local_user());
-
- // Update the global contact for the user
- GContact::updateForUser(local_user());
- }
- }
-}
-
-function profiles_content(App $a) {
-
- if (! local_user()) {
- notice(DI::l10n()->t('Permission denied.') . EOL);
- return Login::form();
- }
-
- $o = '';
-
- if (($a->argc > 1) && (intval($a->argv[1]))) {
- $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1",
- intval($a->argv[1]),
- intval(local_user())
- );
- if (! DBA::isResult($r)) {
- notice(DI::l10n()->t('Profile not found.') . EOL);
- return;
- }
-
- DI::page()['htmlhead'] .= Renderer::replaceMacros(Renderer::getMarkupTemplate('profed_head.tpl'), [
- '$baseurl' => DI::baseUrl()->get(true),
- ]);
-
- $opt_tpl = Renderer::getMarkupTemplate("profile-hide-friends.tpl");
- $hide_friends = Renderer::replaceMacros($opt_tpl,[
- '$yesno' => [
- 'hide-friends', //Name
- DI::l10n()->t('Hide contacts and friends:'), //Label
- !!$r[0]['hide-friends'], //Value
- '', //Help string
- [DI::l10n()->t('No'), DI::l10n()->t('Yes')] //Off - On strings
- ],
- '$desc' => DI::l10n()->t('Hide your contact/friend list from viewers of this profile?'),
- '$yes_str' => DI::l10n()->t('Yes'),
- '$no_str' => DI::l10n()->t('No'),
- '$yes_selected' => (($r[0]['hide-friends']) ? " checked=\"checked\" " : ""),
- '$no_selected' => (($r[0]['hide-friends'] == 0) ? " checked=\"checked\" " : "")
- ]);
-
- $personal_account = !(in_array($a->user["page-flags"],
- [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP]));
-
- $detailed_profile = (DI::pConfig()->get(local_user(), 'system', 'detailled_profile') AND $personal_account);
-
- $is_default = (($r[0]['is-default']) ? 1 : 0);
- $tpl = Renderer::getMarkupTemplate("profile_edit.tpl");
- $o .= Renderer::replaceMacros($tpl, [
- '$personal_account' => $personal_account,
- '$detailled_profile' => $detailed_profile,
-
- '$details' => [
- 'detailed_profile', //Name
- DI::l10n()->t('Show more profile fields:'), //Label
- $detailed_profile, //Value
- '', //Help string
- [DI::l10n()->t('No'), DI::l10n()->t('Yes')] //Off - On strings
- ],
-
- '$multi_profiles' => Feature::isEnabled(local_user(), 'multi_profiles'),
- '$form_security_token' => BaseModule::getFormSecurityToken("profile_edit"),
- '$form_security_token_photo' => BaseModule::getFormSecurityToken("profile_photo"),
- '$profile_clone_link' => ((Feature::isEnabled(local_user(), 'multi_profiles')) ? 'profiles/clone/' . $r[0]['id'] . '?t=' . BaseModule::getFormSecurityToken("profile_clone") : ""),
- '$profile_drop_link' => 'profiles/drop/' . $r[0]['id'] . '?t=' . BaseModule::getFormSecurityToken("profile_drop"),
-
- '$profile_action' => DI::l10n()->t('Profile Actions'),
- '$banner' => DI::l10n()->t('Edit Profile Details'),
- '$submit' => DI::l10n()->t('Submit'),
- '$profpic' => DI::l10n()->t('Change Profile Photo'),
- '$profpiclink' => '/photos/' . $a->user['nickname'],
- '$viewprof' => DI::l10n()->t('View this profile'),
- '$viewallprof' => DI::l10n()->t('View all profiles'),
- '$editvis' => DI::l10n()->t('Edit visibility'),
- '$cr_prof' => DI::l10n()->t('Create a new profile using these settings'),
- '$cl_prof' => DI::l10n()->t('Clone this profile'),
- '$del_prof' => DI::l10n()->t('Delete this profile'),
-
- '$lbl_basic_section' => DI::l10n()->t('Basic information'),
- '$lbl_picture_section' => DI::l10n()->t('Profile picture'),
- '$lbl_location_section' => DI::l10n()->t('Location'),
- '$lbl_preferences_section' => DI::l10n()->t('Preferences'),
- '$lbl_status_section' => DI::l10n()->t('Status information'),
- '$lbl_about_section' => DI::l10n()->t('Additional information'),
- '$lbl_interests_section' => DI::l10n()->t('Interests'),
- '$lbl_personal_section' => DI::l10n()->t('Personal'),
- '$lbl_relation_section' => DI::l10n()->t('Relation'),
- '$lbl_miscellaneous_section' => DI::l10n()->t('Miscellaneous'),
-
- '$lbl_profile_photo' => DI::l10n()->t('Upload Profile Photo'),
- '$lbl_gender' => DI::l10n()->t('Your Gender:'),
- '$lbl_marital' => DI::l10n()->t('<span class="heart">♥</span> Marital Status:'),
- '$lbl_sexual' => DI::l10n()->t('Sexual Preference:'),
- '$lbl_ex2' => DI::l10n()->t('Example: fishing photography software'),
-
- '$disabled' => (($is_default) ? 'onclick="return false;" style="color: #BBBBFF;"' : ''),
- '$baseurl' => DI::baseUrl()->get(true),
- '$profile_id' => $r[0]['id'],
- '$profile_name' => ['profile_name', DI::l10n()->t('Profile Name:'), $r[0]['profile-name'], DI::l10n()->t('Required'), '*'],
- '$is_default' => $is_default,
- '$default' => (($is_default) ? '<p id="profile-edit-default-desc">' . DI::l10n()->t('This is your <strong>public</strong> profile.<br />It <strong>may</strong> be visible to anybody using the internet.') . '</p>' : ""),
- '$name' => ['name', DI::l10n()->t('Your Full Name:'), $r[0]['name']],
- '$pdesc' => ['pdesc', DI::l10n()->t('Title/Description:'), $r[0]['pdesc']],
- '$dob' => Temporal::getDateofBirthField($r[0]['dob'], $a->user['timezone']),
- '$hide_friends' => $hide_friends,
- '$address' => ['address', DI::l10n()->t('Street Address:'), $r[0]['address']],
- '$locality' => ['locality', DI::l10n()->t('Locality/City:'), $r[0]['locality']],
- '$region' => ['region', DI::l10n()->t('Region/State:'), $r[0]['region']],
- '$postal_code' => ['postal_code', DI::l10n()->t('Postal/Zip Code:'), $r[0]['postal-code']],
- '$country_name' => ['country_name', DI::l10n()->t('Country:'), $r[0]['country-name']],
- '$age' => ((intval($r[0]['dob'])) ? '(' . DI::l10n()->t('Age: ') . DI::l10n()->tt('%d year old', '%d years old', Temporal::getAgeByTimezone($r[0]['dob'], $a->user['timezone'])) . ')' : ''),
- '$gender' => DI::l10n()->t(ContactSelector::gender($r[0]['gender'])),
- '$marital' => ['selector' => ContactSelector::maritalStatus($r[0]['marital']), 'value' => DI::l10n()->t($r[0]['marital'])],
- '$with' => ['with', DI::l10n()->t("Who: \x28if applicable\x29"), strip_tags($r[0]['with']), DI::l10n()->t('Examples: cathy123, Cathy Williams, cathy@example.com')],
- '$howlong' => ['howlong', DI::l10n()->t('Since [date]:'), ($r[0]['howlong'] <= DBA::NULL_DATETIME ? '' : DateTimeFormat::local($r[0]['howlong']))],
- '$sexual' => ['selector' => ContactSelector::sexualPreference($r[0]['sexual']), 'value' => DI::l10n()->t($r[0]['sexual'])],
- '$about' => ['about', DI::l10n()->t('Tell us about yourself...'), $r[0]['about']],
- '$xmpp' => ['xmpp', DI::l10n()->t("XMPP \x28Jabber\x29 address:"), $r[0]['xmpp'], DI::l10n()->t("The XMPP address will be propagated to your contacts so that they can follow you.")],
- '$homepage' => ['homepage', DI::l10n()->t('Homepage URL:'), $r[0]['homepage']],
- '$hometown' => ['hometown', DI::l10n()->t('Hometown:'), $r[0]['hometown']],
- '$politic' => ['politic', DI::l10n()->t('Political Views:'), $r[0]['politic']],
- '$religion' => ['religion', DI::l10n()->t('Religious Views:'), $r[0]['religion']],
- '$pub_keywords' => ['pub_keywords', DI::l10n()->t('Public Keywords:'), $r[0]['pub_keywords'], DI::l10n()->t("\x28Used for suggesting potential friends, can be seen by others\x29")],
- '$prv_keywords' => ['prv_keywords', DI::l10n()->t('Private Keywords:'), $r[0]['prv_keywords'], DI::l10n()->t("\x28Used for searching profiles, never shown to others\x29")],
- '$likes' => ['likes', DI::l10n()->t('Likes:'), $r[0]['likes']],
- '$dislikes' => ['dislikes', DI::l10n()->t('Dislikes:'), $r[0]['dislikes']],
- '$music' => ['music', DI::l10n()->t('Musical interests'), $r[0]['music']],
- '$book' => ['book', DI::l10n()->t('Books, literature'), $r[0]['book']],
- '$tv' => ['tv', DI::l10n()->t('Television'), $r[0]['tv']],
- '$film' => ['film', DI::l10n()->t('Film/dance/culture/entertainment'), $r[0]['film']],
- '$interest' => ['interest', DI::l10n()->t('Hobbies/Interests'), $r[0]['interest']],
- '$romance' => ['romance', DI::l10n()->t('Love/romance'), $r[0]['romance']],
- '$work' => ['work', DI::l10n()->t('Work/employment'), $r[0]['work']],
- '$education' => ['education', DI::l10n()->t('School/education'), $r[0]['education']],
- '$contact' => ['contact', DI::l10n()->t('Contact information and Social Networks'), $r[0]['contact']],
- ]);
-
- $arr = ['profile' => $r[0], 'entry' => $o];
- Hook::callAll('profile_edit', $arr);
-
- return $o;
- } else {
- // If we don't support multi profiles, don't display this list.
- if (!Feature::isEnabled(local_user(), 'multi_profiles')) {
- $r = q("SELECT * FROM `profile` WHERE `uid` = %d AND `is-default`=1",
- local_user()
- );
- if (DBA::isResult($r)) {
- //Go to the default profile.
- DI::baseUrl()->redirect('profiles/' . $r[0]['id']);
- }
- }
-
- $r = q("SELECT * FROM `profile` WHERE `uid` = %d",
- local_user());
-
- if (DBA::isResult($r)) {
-
- $tpl = Renderer::getMarkupTemplate('profile_entry.tpl');
-
- $profiles = '';
- foreach ($r as $rr) {
- $profiles .= Renderer::replaceMacros($tpl, [
- '$photo' => DI::baseUrl()->remove($rr['thumb']),
- '$id' => $rr['id'],
- '$alt' => DI::l10n()->t('Profile Image'),
- '$profile_name' => $rr['profile-name'],
- '$visible' => (($rr['is-default']) ? '<strong>' . DI::l10n()->t('visible to everybody') . '</strong>'
- : '<a href="'.'profperm/'.$rr['id'].'" />' . DI::l10n()->t('Edit visibility') . '</a>')
- ]);
- }
-
- $tpl_header = Renderer::getMarkupTemplate('profile_listing_header.tpl');
- $o .= Renderer::replaceMacros($tpl_header,[
- '$header' => DI::l10n()->t('Edit/Manage Profiles'),
- '$chg_photo' => DI::l10n()->t('Change profile photo'),
- '$cr_new' => DI::l10n()->t('Create New Profile'),
- '$cr_new_link' => 'profiles/new?t=' . BaseModule::getFormSecurityToken("profile_new"),
- '$profiles' => $profiles
- ]);
- }
- return $o;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * @file mod/profperm.php
- */
-use Friendica\App;
-use Friendica\Core\Protocol;
-use Friendica\Content\Text\HTML;
-use Friendica\Database\DBA;
-use Friendica\DI;
-use Friendica\Model\Profile;
-
-function profperm_init(App $a)
-{
- if (!local_user()) {
- return;
- }
-
- $which = $a->user['nickname'];
- $profile = $a->argv[1];
-
- Profile::load($a, $which, $profile);
-}
-
-
-function profperm_content(App $a) {
-
- if (!local_user()) {
- notice(DI::l10n()->t('Permission denied') . EOL);
- return;
- }
-
-
- if ($a->argc < 2) {
- notice(DI::l10n()->t('Invalid profile identifier.') . EOL );
- return;
- }
-
- $o = '';
-
- // Switch to text mod interface if we have more than 'n' contacts or group members
-
- $switchtotext = DI::pConfig()->get(local_user(),'system','groupedit_image_limit');
- if (is_null($switchtotext)) {
- $switchtotext = DI::config()->get('system','groupedit_image_limit', 400);
- }
-
- if (($a->argc > 2) && intval($a->argv[1]) && intval($a->argv[2])) {
- $r = q("SELECT `id` FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 AND `self` = 0
- AND `network` = '%s' AND `id` = %d AND `uid` = %d LIMIT 1",
- DBA::escape(Protocol::DFRN),
- intval($a->argv[2]),
- intval(local_user())
- );
-
- if (DBA::isResult($r)) {
- $change = intval($a->argv[2]);
- }
- }
-
-
- if (($a->argc > 1) && (intval($a->argv[1]))) {
- $r = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d AND `is-default` = 0 LIMIT 1",
- intval($a->argv[1]),
- intval(local_user())
- );
- if (!DBA::isResult($r)) {
- notice(DI::l10n()->t('Invalid profile identifier.') . EOL );
- return;
- }
- $profile = $r[0];
-
- $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `profile-id` = %d",
- intval(local_user()),
- intval($a->argv[1])
- );
-
- $ingroup = [];
- if (DBA::isResult($r))
- foreach($r as $member)
- $ingroup[] = $member['id'];
-
- $members = $r;
-
- if (!empty($change)) {
- if (in_array($change,$ingroup)) {
- q("UPDATE `contact` SET `profile-id` = 0 WHERE `id` = %d AND `uid` = %d",
- intval($change),
- intval(local_user())
- );
- }
- else {
- q("UPDATE `contact` SET `profile-id` = %d WHERE `id` = %d AND `uid` = %d",
- intval($a->argv[1]),
- intval($change),
- intval(local_user())
- );
-
- }
-
- $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `profile-id` = %d",
- intval(local_user()),
- intval($a->argv[1])
- );
-
- $members = $r;
-
- $ingroup = [];
- if (DBA::isResult($r))
- foreach($r as $member)
- $ingroup[] = $member['id'];
- }
-
- $o .= '<h2>' . DI::l10n()->t('Profile Visibility Editor') . '</h2>';
-
- $o .= '<h3>' . DI::l10n()->t('Profile') . ' \'' . $profile['profile-name'] . '\'</h3>';
-
- $o .= '<div id="prof-edit-desc">' . DI::l10n()->t('Click on a contact to add or remove.') . '</div>';
-
- }
-
- $o .= '<div id="prof-update-wrapper">';
- if (!empty($change))
- $o = '';
-
- $o .= '<div id="prof-members-title">';
- $o .= '<h3>' . DI::l10n()->t('Visible To') . '</h3>';
- $o .= '</div>';
- $o .= '<div id="prof-members">';
-
- $textmode = (($switchtotext && (count($members) > $switchtotext)) ? true : false);
-
- foreach($members as $member) {
- if ($member['url']) {
- $member['click'] = 'profChangeMember(' . $profile['id'] . ',' . $member['id'] . '); return true;';
- $o .= HTML::micropro($member,true,'mpprof', $textmode);
- }
- }
- $o .= '</div><div id="prof-members-end"></div>';
- $o .= '<hr id="prof-separator" />';
-
- $o .= '<div id="prof-all-contcts-title">';
- $o .= '<h3>' . DI::l10n()->t("All Contacts \x28with secure profile access\x29") . '</h3>';
- $o .= '</div>';
- $o .= '<div id="prof-all-contacts">';
-
- $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `blocked` = 0 and `pending` = 0 and `self` = 0
- AND `network` = '%s' ORDER BY `name` ASC",
- intval(local_user()),
- DBA::escape(Protocol::DFRN)
- );
-
- if (DBA::isResult($r)) {
- $textmode = (($switchtotext && (count($r) > $switchtotext)) ? true : false);
- foreach($r as $member) {
- if (!in_array($member['id'],$ingroup)) {
- $member['click'] = 'profChangeMember(' . $profile['id'] . ',' . $member['id'] . '); return true;';
- $o .= HTML::micropro($member,true,'mpprof',$textmode);
- }
- }
- }
-
- $o .= '</div><div id="prof-all-contacts-end"></div>';
-
- if (!empty($change)) {
- echo $o;
- exit();
- }
- $o .= '</div>';
- return $o;
-
-}
DBA::update('user', ['blocked' => false, 'verified' => true], ['uid' => $register['uid']]);
- $profile = DBA::selectFirst('profile', ['net-publish'], ['uid' => $register['uid'], 'is-default' => true]);
+ $profile = DBA::selectFirst('profile', ['net-publish'], ['uid' => $register['uid']]);
if (DBA::isResult($profile) && $profile['net-publish'] && DI::config()->get('system', 'directory')) {
$url = DI::baseUrl() . '/profile/' . $user['nickname'];
];
$tabs[] = [
- 'label' => DI::l10n()->t('Profiles'),
- 'url' => 'profiles',
- 'selected' => (($a->argc == 1) && ($a->argv[0] === 'profiles')?'active':''),
+ 'label' => DI::l10n()->t('Profile'),
+ 'url' => 'settings/profile',
+ 'selected' => (($a->argc > 1) && ($a->argv[1] === 'profile')?'active':''),
'accesskey' => 'p',
];
`name` = '%s',
`net-publish` = %d,
`hide-friends` = %d
- WHERE `is-default` = 1 AND `uid` = %d",
+ WHERE `uid` = %d",
intval($publish),
DBA::escape($username),
intval($net_publish),
* ACCOUNT SETTINGS
*/
- $profile = DBA::selectFirst('profile', [], ['is-default' => true, 'uid' => local_user()]);
+ $profile = DBA::selectFirst('profile', [], ['uid' => local_user()]);
if (!DBA::isResult($profile)) {
notice(DI::l10n()->t('Unable to find your profile. Please contact your admin.') . EOL);
return;
+++ /dev/null
-<?php
-
-/**
- * Module: update_profile
- * Purpose: AJAX synchronisation of profile page
- */
-
-use Friendica\App;
-use Friendica\DI;
-use Friendica\Module\Profile;
-
-function update_profile_content(App $a) {
-
- $profile_uid = intval($_GET["p"]);
-
- header("Content-type: text/html");
- echo "<!DOCTYPE html><html><body>\r\n";
-
- // We can remove this hack once Internet Explorer recognises HTML5 natively
- echo "<section>";
-
- /**
- * Grab the page inner contents by calling the content function from the profile module directly,
- * but move any image src attributes to another attribute name. This is because
- * some browsers will prefetch all the images for the page even if we don't need them.
- * The only ones we need to fetch are those for new page additions, which we'll discover
- * on the client side and then swap the image back.
- */
-
- $text = Profile::content([], $profile_uid);
-
- if (DI::pConfig()->get(local_user(), "system", "bandwidth_saver")) {
- $replace = "<br />" . DI::l10n()->t("[Embedded content - reload page to view]") . "<br />";
- $pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*video[^>]*>(.*?)<\s*\/\s*video>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*embed[^>]*>(.*?)<\s*\/\s*embed>/i";
- $text = preg_replace($pattern, $replace, $text);
- $pattern = "/<\s*iframe[^>]*>(.*?)<\s*\/\s*iframe>/i";
- $text = preg_replace($pattern, $replace, $text);
- }
-
- // reportedly some versions of MSIE don't handle tabs in XMLHttpRequest documents very well
- echo str_replace("\t", " ", $text);
- echo "</section>";
- echo "</body></html>\r\n";
- exit();
-}
\ No newline at end of file
use Friendica\Model\Item;
use Friendica\Model\Profile;
use Friendica\Model\User;
+use Friendica\Module\BaseProfile;
use Friendica\Util\Security;
function videos_init(App $a)
// tabs
$_is_owner = (local_user() && (local_user() == $owner_uid));
- $o .= Profile::getTabs($a, 'videos', $_is_owner, $a->data['user']['nickname']);
+ $o .= BaseProfile::getTabsHTML($a, 'videos', $_is_owner, $a->data['user']['nickname']);
//
// dispatch request
{
parent::__construct($models);
- $this->models = $models;
$this->totalCount = $totalCount ?? count($models);
}
return $this->originalData;
}
+ public function resetOriginalData()
+ {
+ $this->originalData = $this->data;
+ }
+
/**
* Performance-improved model creation in a loop
*
*/
public function update(BaseModel $model)
{
- return $this->dba->update(static::$table_name, $model->toArray(), ['id' => $model->id], $model->getOriginalData());
+ if ($this->dba->update(static::$table_name, $model->toArray(), ['id' => $model->id], $model->getOriginalData())) {
+ $model->resetOriginalData();
+ return true;
+ }
+
+ return false;
}
/**
--- /dev/null
+<?php
+
+namespace Friendica\Collection;
+
+use Friendica\BaseCollection;
+use Friendica\Model;
+
+class Notifies extends BaseCollection
+{
+ /**
+ * @return Model\Notify
+ */
+ public function current()
+ {
+ return parent::current();
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Collection;
+
+use Friendica\BaseCollection;
+
+class ProfileFields extends BaseCollection
+{
+ /**
+ * @param callable $callback
+ * @return ProfileFields
+ */
+ public function map(callable $callback)
+ {
+ return parent::map($callback);
+ }
+
+ /**
+ * @param callable|null $callback
+ * @param int $flag
+ * @return ProfileFields
+ */
+ public function filter(callable $callback = null, int $flag = 0)
+ {
+ return parent::filter($callback, $flag);
+ }
+}
*/
class ContactSelector
{
- /**
- * @param string $current current
- * @param string $foreign_net network
- * @return string
- * @throws \Exception
- */
- public static function profileAssign($current, $foreign_net)
- {
- $o = '';
-
- $disabled = (($foreign_net) ? ' disabled="true" ' : '');
-
- $o .= "<select id=\"contact-profile-selector\" class=\"form-control\" $disabled name=\"profile-assign\" >\r\n";
-
- $s = DBA::select('profile', ['id', 'profile-name', 'is-default'], ['uid' => $_SESSION['uid']]);
- $r = DBA::toArray($s);
-
- if (DBA::isResult($r)) {
- foreach ($r as $rr) {
- $selected = (($rr['id'] == $current || ($current == 0 && $rr['is-default'] == 1)) ? " selected=\"selected\" " : "");
- $o .= "<option value=\"{$rr['id']}\" $selected >{$rr['profile-name']}</option>\r\n";
- }
- }
- $o .= "</select>\r\n";
- return $o;
- }
-
/**
* @param string $current current
* @param boolean $disabled optional, default false
'general' => [
DI::l10n()->t('General Features'),
//array('expire', DI::l10n()->t('Content Expiration'), DI::l10n()->t('Remove old posts/comments after a period of time')),
- ['multi_profiles', DI::l10n()->t('Multiple Profiles'), DI::l10n()->t('Ability to create multiple profiles'), false, DI::config()->get('feature_lock', 'multi_profiles', false)],
['photo_location', DI::l10n()->t('Photo Location'), DI::l10n()->t("Photo metadata is normally stripped. This extracts the location \x28if present\x29 prior to stripping metadata and links it to a map."), false, DI::config()->get('feature_lock', 'photo_location', false)],
['export_calendar', DI::l10n()->t('Export Public Calendar'), DI::l10n()->t('Ability for visitors to download the public calendar'), false, DI::config()->get('feature_lock', 'export_calendar', false)],
['trending_tags', DI::l10n()->t('Trending Tags'), DI::l10n()->t('Show a community page widget with a list of the most popular tags in recent public posts.'), false, DI::config()->get('feature_lock', 'trending_tags', false)],
$nav['settings'] = ['settings', DI::l10n()->t('Settings'), '', DI::l10n()->t('Account settings')];
- if (Feature::isEnabled(local_user(), 'multi_profiles')) {
- $nav['profiles'] = ['profiles', DI::l10n()->t('Profiles'), '', DI::l10n()->t('Manage/Edit Profiles')];
- }
-
$nav['contacts'] = ['contact', DI::l10n()->t('Contacts'), '', DI::l10n()->t('Manage/edit friends and contacts')];
}
use Friendica\Model\Contact;
use Friendica\Model\FileTag;
use Friendica\Model\GContact;
+use Friendica\Model\Group;
use Friendica\Model\Item;
use Friendica\Model\Profile;
use Friendica\Util\DateTimeFormat;
public static function unavailableNetworks()
{
// Always hide content from these networks
- $networks = ['face', 'apdn'];
+ $networks = [Protocol::PHANTOM, Protocol::FACEBOOK, Protocol::APPNET];
if (!Addon::isEnabled("discourse")) {
$networks[] = Protocol::DISCOURSE;
}
/**
- * Return networks widget
+ * Return group membership widget
+ *
+ * @param string $baseurl
+ * @param string $selected
+ * @return string
+ * @throws \Exception
+ */
+ public static function groups($baseurl, $selected = '')
+ {
+ if (!local_user()) {
+ return '';
+ }
+
+ $options = array_map(function ($group) {
+ return [
+ 'ref' => $group['id'],
+ 'name' => $group['name']
+ ];
+ }, Group::getByUserId(local_user()));
+
+ return self::filter(
+ 'group',
+ DI::l10n()->t('Groups'),
+ '',
+ DI::l10n()->t('Everyone'),
+ $baseurl,
+ $options,
+ $selected
+ );
+ }
+
+ /**
+ * Return contact relationship widget
*
* @param string $baseurl baseurl
* @param string $selected optional, default empty
use Friendica\Database\DBA;
use Friendica\Database\DBStructure;
use Friendica\DI;
+use Friendica\Model\Contact;
use Friendica\Model\Photo;
use Friendica\Object\Image;
+use Friendica\Repository\PermissionSet;
use Friendica\Util\Strings;
use Friendica\Worker\Delivery;
DI::pConfig()->set($newuid, 'system', 'previous_addr', $old_handle);
- foreach ($account['profile'] as &$profile) {
- foreach ($profile as $k => &$v) {
- $v = str_replace([$oldbaseurl, $oldaddr], [$newbaseurl, $newaddr], $v);
- foreach (["profile", "avatar"] as $k) {
- $v = str_replace($oldbaseurl . "/photo/" . $k . "/" . $olduid . ".jpg", $newbaseurl . "/photo/" . $k . "/" . $newuid . ".jpg", $v);
- }
- }
- $profile['uid'] = $newuid;
- $r = self::dbImportAssoc('profile', $profile);
- if ($r === false) {
- Logger::log("uimport:insert profile " . $profile['profile-name'] . " : ERROR : " . DBA::errorMessage(), Logger::INFO);
- info(DI::l10n()->t("User profile creation error"));
- DBA::delete('user', ['uid' => $newuid]);
- return;
- }
- }
-
$errorcount = 0;
foreach ($account['contact'] as &$contact) {
if ($contact['uid'] == $olduid && $contact['self'] == '1') {
}
}
+ foreach ($account['profile'] as &$profile) {
+ unset($profile['id']);
+ $profile['uid'] = $newuid;
+
+ foreach ($profile as $k => &$v) {
+ $v = str_replace([$oldbaseurl, $oldaddr], [$newbaseurl, $newaddr], $v);
+ foreach (["profile", "avatar"] as $k) {
+ $v = str_replace($oldbaseurl . "/photo/" . $k . "/" . $olduid . ".jpg", $newbaseurl . "/photo/" . $k . "/" . $newuid . ".jpg", $v);
+ }
+ }
+
+ if (count($account['profile']) === 1 || $profile['is-default']) {
+ $r = self::dbImportAssoc('profile', $profile);
+
+ if ($r === false) {
+ Logger::log("uimport:insert profile: ERROR : " . DBA::errorMessage(), Logger::INFO);
+ info(DI::l10n()->t("User profile creation error"));
+ DBA::delete('user', ['uid' => $newuid]);
+ DBA::delete('profile_field', ['uid' => $newuid]);
+ return;
+ }
+
+ $profile['id'] = DBA::lastInsertId();
+ }
+
+ DI::profileField()->migrateFromLegacyProfile($profile);
+ }
+
+ ///@TODO Replace with permissionset import
+ $self_contact = Contact::selectFirst(['id'], ['uid' => $newuid, 'self' => true]);
+ $allow_cid = DI::aclFormatter()->toString($self_contact['id']);
+ $self_psid = DI::permissionSet()->getIdFromACL($newuid, $allow_cid);
+
+ foreach ($account['profile_fields'] ?? [] as $profile_field) {
+ $profile_field['uid'] = $newuid;
+
+ ///@TODO Replace with permissionset import
+ $profile_field['psid'] = $profile_field['psid'] ? $self_psid : PermissionSet::PUBLIC;
+
+ if (self::dbImportAssoc('profile_field', $profile_field) === false) {
+ Logger::info("uimport:insert profile field " . $profile_field['id'] . " : ERROR : " . DBA::errorMessage());
+ }
+ }
+
foreach ($account['photo'] as &$photo) {
$photo['uid'] = $newuid;
$photo['data'] = hex2bin($photo['data']);
return self::$dice->create(Factory\Mastodon\Relationship::class);
}
+ /**
+ * @return \Friendica\Factory\Notification\Notification
+ */
+ public static function notification()
+ {
+ return self::$dice->create(Factory\Notification\Notification::class);
+ }
+
+ /**
+ * @return \Friendica\Factory\Notification\Introduction
+ */
+ public static function notificationIntro()
+ {
+ return self::$dice->create(Factory\Notification\Introduction::class);
+ }
+
//
// "Model" namespace instances
//
}
/**
- * @return Model\Notify
+ * @return Repository\Notify
*/
public static function notify()
{
- return self::$dice->create(Model\Notify::class);
+ return self::$dice->create(Repository\Notify::class);
}
/**
return self::$dice->create(Repository\PermissionSet::class);
}
+ /**
+ * @return Repository\ProfileField
+ */
+ public static function profileField()
+ {
+ return self::$dice->create(Repository\ProfileField::class);
+ }
+
//
// "Protocol" namespace instances
//
{
return self::$dice->create(Util\Profiler::class);
}
+
+ /**
+ * @return Util\Emailer
+ */
+ public static function emailer()
+ {
+ return self::$dice->create(Util\Emailer::class);
+ }
}
--- /dev/null
+<?php
+
+namespace Friendica\Factory\Notification;
+
+use Exception;
+use Friendica\App;
+use Friendica\App\BaseURL;
+use Friendica\BaseFactory;
+use Friendica\Content\Text\BBCode;
+use Friendica\Core\L10n;
+use Friendica\Core\PConfig\IPConfig;
+use Friendica\Core\Protocol;
+use Friendica\Core\Session\ISession;
+use Friendica\Database\Database;
+use Friendica\Model\Contact;
+use Friendica\Module\BaseNotifications;
+use Friendica\Network\HTTPException\InternalServerErrorException;
+use Friendica\Object\Notification;
+use Friendica\Util\Proxy;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Factory for creating notification objects based on introductions
+ * Currently, there are two main types of introduction based notifications:
+ * - Friend suggestion
+ * - Friend/Follower request
+ */
+class Introduction extends BaseFactory
+{
+ /** @var Database */
+ private $dba;
+ /** @var BaseURL */
+ private $baseUrl;
+ /** @var L10n */
+ private $l10n;
+ /** @var IPConfig */
+ private $pConfig;
+ /** @var ISession */
+ private $session;
+ /** @var string */
+ private $nick;
+
+ public function __construct(LoggerInterface $logger, Database $dba, BaseURL $baseUrl, L10n $l10n, App $app, IPConfig $pConfig, ISession $session)
+ {
+ parent::__construct($logger);
+
+ $this->dba = $dba;
+ $this->baseUrl = $baseUrl;
+ $this->l10n = $l10n;
+ $this->pConfig = $pConfig;
+ $this->session = $session;
+ $this->nick = $app->user['nickname'] ?? '';
+ }
+
+ /**
+ * Get introductions
+ *
+ * @param bool $all If false only include introductions into the query
+ * which aren't marked as ignored
+ * @param int $start Start the query at this point
+ * @param int $limit Maximum number of query results
+ * @param int $id When set, only the introduction with this id is displayed
+ *
+ * @return Notification\Introduction[]
+ */
+ public function getList(bool $all = false, int $start = 0, int $limit = BaseNotifications::DEFAULT_PAGE_LIMIT, int $id = 0)
+ {
+ $sql_extra = "";
+
+ if (empty($id)) {
+ if (!$all) {
+ $sql_extra = " AND NOT `ignore` ";
+ }
+
+ $sql_extra .= " AND NOT `intro`.`blocked` ";
+ } else {
+ $sql_extra = sprintf(" AND `intro`.`id` = %d ", intval($id));
+ }
+
+ $formattedNotifications = [];
+
+ try {
+ /// @todo Fetch contact details by "Contact::getDetailsByUrl" instead of queries to contact, fcontact and gcontact
+ $stmtNotifications = $this->dba->p(
+ "SELECT `intro`.`id` AS `intro_id`, `intro`.*, `contact`.*,
+ `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`,
+ `gcontact`.`network` AS `gnetwork`, `gcontact`.`addr` AS `gaddr`
+ FROM `intro`
+ LEFT JOIN `contact` ON `contact`.`id` = `intro`.`contact-id`
+ LEFT JOIN `gcontact` ON `gcontact`.`nurl` = `contact`.`nurl`
+ LEFT JOIN `fcontact` ON `intro`.`fid` = `fcontact`.`id`
+ WHERE `intro`.`uid` = ? $sql_extra
+ LIMIT ?, ?",
+ $_SESSION['uid'],
+ $start,
+ $limit
+ );
+
+ while ($notification = $this->dba->fetch($stmtNotifications)) {
+ // There are two kind of introduction. Contacts suggested by other contacts and normal connection requests.
+ // We have to distinguish between these two because they use different data.
+ // Contact suggestions
+ if ($notification['fid'] ?? '') {
+ $return_addr = bin2hex($this->nick . '@' .
+ $this->baseUrl->getHostName() .
+ (($this->baseUrl->getURLPath()) ? '/' . $this->baseUrl->getURLPath() : ''));
+
+ $formattedNotifications[] = new Notification\Introduction([
+ 'label' => 'friend_suggestion',
+ 'str_type' => $this->l10n->t('Friend Suggestion'),
+ 'intro_id' => $notification['intro_id'],
+ 'madeby' => $notification['name'],
+ 'madeby_url' => $notification['url'],
+ 'madeby_zrl' => Contact::magicLink($notification['url']),
+ 'madeby_addr' => $notification['addr'],
+ 'contact_id' => $notification['contact-id'],
+ 'photo' => (!empty($notification['fphoto']) ? Proxy::proxifyUrl($notification['fphoto'], false, Proxy::SIZE_SMALL) : "images/person-300.jpg"),
+ 'name' => $notification['fname'],
+ 'url' => $notification['furl'],
+ 'zrl' => Contact::magicLink($notification['furl']),
+ 'hidden' => $notification['hidden'] == 1,
+ 'post_newfriend' => (intval($this->pConfig->get(local_user(), 'system', 'post_newfriend')) ? '1' : 0),
+ 'note' => $notification['note'],
+ 'request' => $notification['frequest'] . '?addr=' . $return_addr]);
+
+ // Normal connection requests
+ } else {
+ $notification = $this->getMissingData($notification);
+
+ if (empty($notification['url'])) {
+ continue;
+ }
+
+ // Don't show these data until you are connected. Diaspora is doing the same.
+ if ($notification['gnetwork'] === Protocol::DIASPORA) {
+ $notification['glocation'] = "";
+ $notification['gabout'] = "";
+ $notification['ggender'] = "";
+ }
+
+ $formattedNotifications[] = new Notification\Introduction([
+ 'label' => (($notification['network'] !== Protocol::OSTATUS) ? 'friend_request' : 'follower'),
+ 'str_type' => (($notification['network'] !== Protocol::OSTATUS) ? $this->l10n->t('Friend/Connect Request') : $this->l10n->t('New Follower')),
+ 'dfrn_id' => $notification['issued-id'],
+ 'uid' => $this->session->get('uid'),
+ 'intro_id' => $notification['intro_id'],
+ 'contact_id' => $notification['contact-id'],
+ 'photo' => (!empty($notification['photo']) ? Proxy::proxifyUrl($notification['photo'], false, Proxy::SIZE_SMALL) : "images/person-300.jpg"),
+ 'name' => $notification['name'],
+ 'location' => BBCode::convert($notification['glocation'], false),
+ 'about' => BBCode::convert($notification['gabout'], false),
+ 'keywords' => $notification['gkeywords'],
+ 'gender' => $notification['ggender'],
+ 'hidden' => $notification['hidden'] == 1,
+ 'post_newfriend' => (intval($this->pConfig->get(local_user(), 'system', 'post_newfriend')) ? '1' : 0),
+ 'url' => $notification['url'],
+ 'zrl' => Contact::magicLink($notification['url']),
+ 'addr' => $notification['gaddr'],
+ 'network' => $notification['gnetwork'],
+ 'knowyou' => $notification['knowyou'],
+ 'note' => $notification['note'],
+ ]);
+ }
+ }
+ } catch (Exception $e) {
+ $this->logger->warning('Select failed.', ['uid' => $_SESSION['uid'], 'exception' => $e]);
+ }
+
+ return $formattedNotifications;
+ }
+
+ /**
+ * Check for missing contact data and try to fetch the data from
+ * from other sources
+ *
+ * @param array $intro The input array with the intro data
+ *
+ * @return array The array with the intro data
+ *
+ * @throws InternalServerErrorException
+ */
+ private function getMissingData(array $intro)
+ {
+ // If the network and the addr isn't available from the gcontact
+ // table entry, take the one of the contact table entry
+ if (empty($intro['gnetwork']) && !empty($intro['network'])) {
+ $intro['gnetwork'] = $intro['network'];
+ }
+ if (empty($intro['gaddr']) && !empty($intro['addr'])) {
+ $intro['gaddr'] = $intro['addr'];
+ }
+
+ // If the network and addr is still not available
+ // get the missing data data from other sources
+ if (empty($intro['gnetwork']) || empty($intro['gaddr'])) {
+ $ret = Contact::getDetailsByURL($intro['url']);
+
+ if (empty($intro['gnetwork']) && !empty($ret['network'])) {
+ $intro['gnetwork'] = $ret['network'];
+ }
+ if (empty($intro['gaddr']) && !empty($ret['addr'])) {
+ $intro['gaddr'] = $ret['addr'];
+ }
+ }
+
+ return $intro;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Factory\Notification;
+
+use Exception;
+use Friendica\App;
+use Friendica\App\BaseURL;
+use Friendica\BaseFactory;
+use Friendica\Content\Text\BBCode;
+use Friendica\Core\L10n;
+use Friendica\Core\PConfig\IPConfig;
+use Friendica\Core\Protocol;
+use Friendica\Core\Session\ISession;
+use Friendica\Database\Database;
+use Friendica\Model\Item;
+use Friendica\Module\BaseNotifications;
+use Friendica\Network\HTTPException\InternalServerErrorException;
+use Friendica\Protocol\Activity;
+use Friendica\Repository;
+use Friendica\Util\DateTimeFormat;
+use Friendica\Util\Proxy;
+use Friendica\Util\Temporal;
+use Friendica\Util\XML;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Factory for creating notification objects based on items
+ * Currently, there are the following types of item based notifications:
+ * - network
+ * - system
+ * - home
+ * - personal
+ */
+class Notification extends BaseFactory
+{
+ /** @var Database */
+ private $dba;
+ /** @var Repository\Notify */
+ private $notification;
+ /** @var BaseURL */
+ private $baseUrl;
+ /** @var L10n */
+ private $l10n;
+ /** @var string */
+ private $nurl;
+
+ public function __construct(LoggerInterface $logger, Database $dba, Repository\Notify $notification, BaseURL $baseUrl, L10n $l10n, App $app, IPConfig $pConfig, ISession $session)
+ {
+ parent::__construct($logger);
+
+ $this->dba = $dba;
+ $this->notification = $notification;
+ $this->baseUrl = $baseUrl;
+ $this->l10n = $l10n;
+ $this->nurl = $app->contact['nurl'] ?? '';
+ }
+
+ /**
+ * Format the item query in an usable array
+ *
+ * @param array $item The item from the db query
+ *
+ * @return array The item, extended with the notification-specific information
+ *
+ * @throws InternalServerErrorException
+ * @throws Exception
+ */
+ private function formatItem(array $item)
+ {
+ $item['seen'] = ($item['unseen'] > 0 ? false : true);
+
+ // For feed items we use the user's contact, since the avatar is mostly self choosen.
+ if (!empty($item['network']) && $item['network'] == Protocol::FEED) {
+ $item['author-avatar'] = $item['contact-avatar'];
+ }
+
+ $item['label'] = (($item['id'] == $item['parent']) ? 'post' : 'comment');
+ $item['link'] = $this->baseUrl->get(true) . '/display/' . $item['parent-guid'];
+ $item['image'] = Proxy::proxifyUrl($item['author-avatar'], false, Proxy::SIZE_MICRO);
+ $item['url'] = $item['author-link'];
+ $item['text'] = (($item['id'] == $item['parent'])
+ ? $this->l10n->t("%s created a new post", $item['author-name'])
+ : $this->l10n->t("%s commented on %s's post", $item['author-name'], $item['parent-author-name']));
+ $item['when'] = DateTimeFormat::local($item['created'], 'r');
+ $item['ago'] = Temporal::getRelativeDate($item['created']);
+
+ return $item;
+ }
+
+ /**
+ * @param array $item
+ *
+ * @return \Friendica\Object\Notification\Notification
+ *
+ * @throws InternalServerErrorException
+ */
+ private function createFromItem(array $item)
+ {
+ $item = $this->formatItem($item);
+
+ // Transform the different types of notification in an usable array
+ switch ($item['verb'] ?? '') {
+ case Activity::LIKE:
+ return new \Friendica\Object\Notification\Notification([
+ 'label' => 'like',
+ 'link' => $this->baseUrl->get(true) . '/display/' . $item['parent-guid'],
+ 'image' => Proxy::proxifyUrl($item['author-avatar'], false, Proxy::SIZE_MICRO),
+ 'url' => $item['author-link'],
+ 'text' => $this->l10n->t("%s liked %s's post", $item['author-name'], $item['parent-author-name']),
+ 'when' => $item['when'],
+ 'ago' => $item['ago'],
+ 'seen' => $item['seen']]);
+
+ case Activity::DISLIKE:
+ return new \Friendica\Object\Notification\Notification([
+ 'label' => 'dislike',
+ 'link' => $this->baseUrl->get(true) . '/display/' . $item['parent-guid'],
+ 'image' => Proxy::proxifyUrl($item['author-avatar'], false, Proxy::SIZE_MICRO),
+ 'url' => $item['author-link'],
+ 'text' => $this->l10n->t("%s disliked %s's post", $item['author-name'], $item['parent-author-name']),
+ 'when' => $item['when'],
+ 'ago' => $item['ago'],
+ 'seen' => $item['seen']]);
+
+ case Activity::ATTEND:
+ return new \Friendica\Object\Notification\Notification([
+ 'label' => 'attend',
+ 'link' => $this->baseUrl->get(true) . '/display/' . $item['parent-guid'],
+ 'image' => Proxy::proxifyUrl($item['author-avatar'], false, Proxy::SIZE_MICRO),
+ 'url' => $item['author-link'],
+ 'text' => $this->l10n->t("%s is attending %s's event", $item['author-name'], $item['parent-author-name']),
+ 'when' => $item['when'],
+ 'ago' => $item['ago'],
+ 'seen' => $item['seen']]);
+
+ case Activity::ATTENDNO:
+ return new \Friendica\Object\Notification\Notification([
+ 'label' => 'attendno',
+ 'link' => $this->baseUrl->get(true) . '/display/' . $item['parent-guid'],
+ 'image' => Proxy::proxifyUrl($item['author-avatar'], false, Proxy::SIZE_MICRO),
+ 'url' => $item['author-link'],
+ 'text' => $this->l10n->t("%s is not attending %s's event", $item['author-name'], $item['parent-author-name']),
+ 'when' => $item['when'],
+ 'ago' => $item['ago'],
+ 'seen' => $item['seen']]);
+
+ case Activity::ATTENDMAYBE:
+ return new \Friendica\Object\Notification\Notification([
+ 'label' => 'attendmaybe',
+ 'link' => $this->baseUrl->get(true) . '/display/' . $item['parent-guid'],
+ 'image' => Proxy::proxifyUrl($item['author-avatar'], false, Proxy::SIZE_MICRO),
+ 'url' => $item['author-link'],
+ 'text' => $this->l10n->t("%s may attending %s's event", $item['author-name'], $item['parent-author-name']),
+ 'when' => $item['when'],
+ 'ago' => $item['ago'],
+ 'seen' => $item['seen']]);
+
+ case Activity::FRIEND:
+ if (!isset($item['object'])) {
+ return new \Friendica\Object\Notification\Notification([
+ 'label' => 'friend',
+ 'link' => $item['link'],
+ 'image' => $item['image'],
+ 'url' => $item['url'],
+ 'text' => $item['text'],
+ 'when' => $item['when'],
+ 'ago' => $item['ago'],
+ 'seen' => $item['seen']]);
+ }
+
+ $xmlHead = "<" . "?xml version='1.0' encoding='UTF-8' ?" . ">";
+ $obj = XML::parseString($xmlHead . $item['object']);
+ $item['fname'] = $obj->title;
+
+ return new \Friendica\Object\Notification\Notification([
+ 'label' => 'friend',
+ 'link' => $this->baseUrl->get(true) . '/display/' . $item['parent-guid'],
+ 'image' => Proxy::proxifyUrl($item['author-avatar'], false, Proxy::SIZE_MICRO),
+ 'url' => $item['author-link'],
+ 'text' => $this->l10n->t("%s is now friends with %s", $item['author-name'], $item['fname']),
+ 'when' => $item['when'],
+ 'ago' => $item['ago'],
+ 'seen' => $item['seen']]);
+
+ default:
+ return new \Friendica\Object\Notification\Notification($item);
+ break;
+ }
+ }
+
+ /**
+ * Get system notifications
+ *
+ * @param bool $seen False => only include notifications into the query
+ * which aren't marked as "seen"
+ * @param int $start Start the query at this point
+ * @param int $limit Maximum number of query results
+ *
+ * @return \Friendica\Module\Notifications\Notification[]
+ */
+ public function getSystemList(bool $seen = false, int $start = 0, int $limit = BaseNotifications::DEFAULT_PAGE_LIMIT)
+ {
+ $conditions = ['uid' => local_user()];
+
+ if (!$seen) {
+ $conditions['seen'] = false;
+ }
+
+ $params = [];
+ $params['order'] = ['date' => 'DESC'];
+ $params['limit'] = [$start, $limit];
+
+ $formattedNotifications = [];
+ try {
+ $notifications = $this->notification->select($conditions, $params);
+
+ foreach ($notifications as $notification) {
+ $formattedNotifications[] = new \Friendica\Object\Notification\Notification([
+ 'label' => 'notification',
+ 'link' => $this->baseUrl->get(true) . '/notification/view/' . $notification->id,
+ 'image' => Proxy::proxifyUrl($notification->photo, false, Proxy::SIZE_MICRO),
+ 'url' => $notification->url,
+ 'text' => strip_tags(BBCode::convert($notification->msg)),
+ 'when' => DateTimeFormat::local($notification->date, 'r'),
+ 'ago' => Temporal::getRelativeDate($notification->date),
+ 'seen' => $notification->seen]);
+ }
+ } catch (Exception $e) {
+ $this->logger->warning('Select failed.', ['conditions' => $conditions, 'exception' => $e]);
+ }
+
+ return $formattedNotifications;
+ }
+
+ /**
+ * Get network notifications
+ *
+ * @param bool $seen False => only include notifications into the query
+ * which aren't marked as "seen"
+ * @param int $start Start the query at this point
+ * @param int $limit Maximum number of query results
+ *
+ * @return \Friendica\Object\Notification\Notification[]
+ */
+ public function getNetworkList(bool $seen = false, int $start = 0, int $limit = BaseNotifications::DEFAULT_PAGE_LIMIT)
+ {
+ $conditions = ['wall' => false, 'uid' => local_user()];
+
+ if (!$seen) {
+ $conditions['unseen'] = true;
+ }
+
+ $fields = ['id', 'parent', 'verb', 'author-name', 'unseen', 'author-link', 'author-avatar', 'contact-avatar',
+ 'network', 'created', 'object', 'parent-author-name', 'parent-author-link', 'parent-guid'];
+ $params = ['order' => ['received' => true], 'limit' => [$start, $limit]];
+
+ $formattedNotifications = [];
+
+ try {
+ $items = Item::selectForUser(local_user(), $fields, $conditions, $params);
+
+ while ($item = $this->dba->fetch($items)) {
+ $formattedNotifications[] = $this->createFromItem($item);
+ }
+ } catch (Exception $e) {
+ $this->logger->warning('Select failed.', ['conditions' => $conditions, 'exception' => $e]);
+ }
+
+ return $formattedNotifications;
+ }
+
+ /**
+ * Get personal notifications
+ *
+ * @param bool $seen False => only include notifications into the query
+ * which aren't marked as "seen"
+ * @param int $start Start the query at this point
+ * @param int $limit Maximum number of query results
+ *
+ * @return \Friendica\Object\Notification\Notification[]
+ */
+ public function getPersonalList(bool $seen = false, int $start = 0, int $limit = BaseNotifications::DEFAULT_PAGE_LIMIT)
+ {
+ $myUrl = str_replace('http://', '', $this->nurl);
+ $diaspUrl = str_replace('/profile/', '/u/', $myUrl);
+
+ $condition = ["NOT `wall` AND `uid` = ? AND (`item`.`author-id` = ? OR `item`.`tag` REGEXP ? OR `item`.`tag` REGEXP ?)",
+ local_user(), public_contact(), $myUrl . '\\]', $diaspUrl . '\\]'];
+
+ if (!$seen) {
+ $condition[0] .= " AND `unseen`";
+ }
+
+ $fields = ['id', 'parent', 'verb', 'author-name', 'unseen', 'author-link', 'author-avatar', 'contact-avatar',
+ 'network', 'created', 'object', 'parent-author-name', 'parent-author-link', 'parent-guid'];
+ $params = ['order' => ['received' => true], 'limit' => [$start, $limit]];
+
+ $formattedNotifications = [];
+
+ try {
+ $items = Item::selectForUser(local_user(), $fields, $condition, $params);
+
+ while ($item = $this->dba->fetch($items)) {
+ $formattedNotifications[] = $this->createFromItem($item);
+ }
+ } catch (Exception $e) {
+ $this->logger->warning('Select failed.', ['conditions' => $condition, 'exception' => $e]);
+ }
+
+ return $formattedNotifications;
+ }
+
+ /**
+ * Get home notifications
+ *
+ * @param bool $seen False => only include notifications into the query
+ * which aren't marked as "seen"
+ * @param int $start Start the query at this point
+ * @param int $limit Maximum number of query results
+ *
+ * @return \Friendica\Object\Notification\Notification[]
+ */
+ public function getHomeList(bool $seen = false, int $start = 0, int $limit = BaseNotifications::DEFAULT_PAGE_LIMIT)
+ {
+ $condition = ['wall' => true, 'uid' => local_user()];
+
+ if (!$seen) {
+ $condition['unseen'] = true;
+ }
+
+ $fields = ['id', 'parent', 'verb', 'author-name', 'unseen', 'author-link', 'author-avatar', 'contact-avatar',
+ 'network', 'created', 'object', 'parent-author-name', 'parent-author-link', 'parent-guid'];
+ $params = ['order' => ['received' => true], 'limit' => [$start, $limit]];
+
+ $formattedNotifications = [];
+
+ try {
+ $items = Item::selectForUser(local_user(), $fields, $condition, $params);
+
+ while ($item = $this->dba->fetch($items)) {
+ $item = $this->formatItem($item);
+
+ // Overwrite specific fields, not default item format
+ $item['label'] = 'comment';
+ $item['text'] = $this->l10n->t("%s commented on %s's post", $item['author-name'], $item['parent-author-name']);
+
+ $formattedNotifications[] = $this->createFromItem($item);
+ }
+ } catch (Exception $e) {
+ $this->logger->warning('Select failed.', ['conditions' => $condition, 'exception' => $e]);
+ }
+
+ return $formattedNotifications;
+ }
+}
$fields = ['name', 'photo', 'thumb', 'about', 'address', 'locality', 'region',
'country-name', 'gender', 'pub_keywords', 'xmpp', 'net-publish'];
- $profile = DBA::selectFirst('profile', $fields, ['uid' => $uid, 'is-default' => true]);
+ $profile = DBA::selectFirst('profile', $fields, ['uid' => $uid]);
if (!DBA::isResult($profile)) {
return;
}
// Update the profile
$fields = ['photo' => DI::baseUrl() . '/photo/profile/' .$uid . '.' . $file_suffix,
'thumb' => DI::baseUrl() . '/photo/avatar/' . $uid .'.' . $file_suffix];
- DBA::update('profile', $fields, ['uid' => $uid, 'is-default' => true]);
+ DBA::update('profile', $fields, ['uid' => $uid]);
}
}
namespace Friendica\Model;
use Exception;
-use Friendica\App;
+use Friendica\BaseModel;
use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\HTML;
-use Friendica\Core\PConfig\IPConfig;
-use Friendica\Core\L10n;
-use Friendica\Core\Protocol;
-use Friendica\Core\System;
use Friendica\Database\Database;
-use Friendica\DI;
-use Friendica\Protocol\Activity;
+use Friendica\Network\HTTPException\InternalServerErrorException;
use Friendica\Util\DateTimeFormat;
-use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Util\Temporal;
-use Friendica\Util\XML;
-use ImagickException;
use Psr\Log\LoggerInterface;
-use Friendica\Network\HTTPException;
/**
- * Methods for read and write notifications from/to database
- * or for formatting notifications
+ * Model for an entry in the notify table
+ * - Including additional, calculated properties
+ *
+ * Is used either for frontend interactions or for API-based interaction
+ * @see https://github.com/friendica/friendica/blob/develop/doc/API-Entities.md#notification
+ *
+ * @property string hash
+ * @property integer type
+ * @property string name Full name of the contact subject
+ * @property string url Profile page URL of the contact subject
+ * @property string photo Profile photo URL of the contact subject
+ * @property string date YYYY-MM-DD hh:mm:ss local server time
+ * @property string msg
+ * @property integer uid Owner User Id
+ * @property string link Notification URL
+ * @property integer iid Item Id
+ * @property integer parent Parent Item Id
+ * @property boolean seen Whether the notification was read or not.
+ * @property string verb Verb URL (@see http://activitystrea.ms)
+ * @property string otype Subject type (`item`, `intro` or `mail`)
+ *
+ * @property-read string name_cache Full name of the contact subject
+ * @property-read string msg_cache Plaintext version of the notification text with a placeholder (`{0}`) for the subject contact's name.
+ *
+ * @property-read integer timestamp Unix timestamp
+ * @property-read string dateRel Time since the note was posted, eg "1 hour ago"
+ * @property-read string $msg_html
+ * @property-read string $msg_plain
*/
-final class Notify
+class Notify extends BaseModel
{
- /** @var int The default limit of notifies per page */
- const DEFAULT_PAGE_LIMIT = 80;
+ const OTYPE_ITEM = 'item';
+ const OTYPE_INTRO = 'intro';
+ const OTYPE_MAIL = 'mail';
+ const OTYPE_PERSON = 'person';
- const NETWORK = 'network';
- const SYSTEM = 'system';
- const PERSONAL = 'personal';
- const HOME = 'home';
- const INTRO = 'intro';
+ /** @var \Friendica\Repository\Notify */
+ private $repo;
- /** @var Database */
- private $dba;
- /** @var L10n */
- private $l10n;
- /** @var App\Arguments */
- private $args;
- /** @var App\BaseURL */
- private $baseUrl;
- /** @var IPConfig */
- private $pConfig;
- /** @var LoggerInterface */
- private $logger;
-
- public function __construct(Database $dba, L10n $l10n, App\Arguments $args, App\BaseURL $baseUrl,
- IPConfig $pConfig, LoggerInterface $logger)
+ public function __construct(Database $dba, LoggerInterface $logger, \Friendica\Repository\Notify $repo, array $data = [])
{
- $this->dba = $dba;
- $this->l10n = $l10n;
- $this->args = $args;
- $this->baseUrl = $baseUrl;
- $this->pConfig = $pConfig;
- $this->logger = $logger;
- }
+ parent::__construct($dba, $logger, $data);
- /**
- * Set some extra properties to note array from db:
- * - timestamp as int in default TZ
- * - date_rel : relative date string
- * - msg_html: message as html string
- * - msg_plain: message as plain text string
- *
- * @param array $notes array of note arrays from db
- *
- * @return array Copy of input array with added properties
- *
- * @throws Exception
- */
- private function setExtra(array $notes)
- {
- $retNotes = [];
- foreach ($notes as $note) {
- $local_time = DateTimeFormat::local($note['date']);
- $note['timestamp'] = strtotime($local_time);
- $note['date_rel'] = Temporal::getRelativeDate($note['date']);
- $note['msg_html'] = BBCode::convert($note['msg'], false);
- $note['msg_plain'] = explode("\n", trim(HTML::toPlaintext($note['msg_html'], 0)))[0];
+ $this->repo = $repo;
- $retNotes[] = $note;
- }
- return $retNotes;
+ $this->setNameCache();
+ $this->setTimestamp();
+ $this->setMsg();
}
/**
- * Get all notifications for local_user()
+ * Set the notification as seen
*
- * @param array $filter optional Array "column name"=>value: filter query by columns values
- * @param array $order optional Array to order by
- * @param string $limit optional Query limits
+ * @param bool $seen true, if seen
*
- * @return array|bool of results or false on errors
- * @throws Exception
+ * @return bool True, if the seen state could be saved
*/
- public function getAll(array $filter = [], array $order = ['date' => 'DESC'], string $limit = "")
+ public function setSeen(bool $seen = true)
{
- $params = [];
-
- $params['order'] = $order;
-
- if (!empty($limit)) {
- $params['limit'] = $limit;
- }
-
- $dbFilter = array_merge($filter, ['uid' => local_user()]);
-
- $stmtNotifies = $this->dba->select('notify', [], $dbFilter, $params);
-
- if ($this->dba->isResult($stmtNotifies)) {
- return $this->setExtra($this->dba->toArray($stmtNotifies));
+ $this->seen = $seen;
+ try {
+ return $this->repo->update($this);
+ } catch (Exception $e) {
+ $this->logger->warning('Update failed.', ['$this' => $this, 'exception' => $e]);
+ return false;
}
-
- return false;
}
/**
- * Get one note for local_user() by $id value
- *
- * @param int $id identity
- *
- * @return array note values or null if not found
- * @throws Exception
+ * Set some extra properties to the notification from db:
+ * - timestamp as int in default TZ
+ * - date_rel : relative date string
*/
- public function getByID(int $id)
+ private function setTimestamp()
{
- $stmtNotify = $this->dba->selectFirst('notify', [], ['id' => $id, 'uid' => local_user()]);
- if ($this->dba->isResult($stmtNotify)) {
- return $this->setExtra([$stmtNotify])[0];
+ try {
+ $this->timestamp = strtotime(DateTimeFormat::local($this->date));
+ } catch (Exception $e) {
}
- return null;
- }
-
- /**
- * set seen state of $note of local_user()
- *
- * @param array $note note array
- * @param bool $seen optional true or false, default true
- *
- * @return bool true on success, false on errors
- * @throws Exception
- */
- public function setSeen(array $note, bool $seen = true)
- {
- return $this->dba->update('notify', ['seen' => $seen], [
- '(`link` = ? OR (`parent` != 0 AND `parent` = ? AND `otype` = ?)) AND `uid` = ?',
- $note['link'],
- $note['parent'],
- $note['otype'],
- local_user()
- ]);
- }
-
- /**
- * Set seen state of all notifications of local_user()
- *
- * @param bool $seen optional true or false. default true
- *
- * @return bool true on success, false on error
- * @throws Exception
- */
- public function setAllSeen(bool $seen = true)
- {
- return $this->dba->update('notify', ['seen' => $seen], ['uid' => local_user()]);
+ $this->dateRel = Temporal::getRelativeDate($this->date);
}
/**
- * Format the notification query in an usable array
- *
- * @param array $notifies The array from the db query
- * @param string $ident The notifications identifier (e.g. network)
+ * Sets the pre-formatted name (caching)
*
- * @return array
- * string 'label' => The type of the notification
- * string 'link' => URL to the source
- * string 'image' => The avatar image
- * string 'url' => The profile url of the contact
- * string 'text' => The notification text
- * string 'when' => The date of the notification
- * string 'ago' => T relative date of the notification
- * bool 'seen' => Is the notification marked as "seen"
- * @throws Exception
+ * @throws InternalServerErrorException
*/
- private function formatList(array $notifies, string $ident = "")
+ private function setNameCache()
{
- $formattedNotifies = [];
-
- foreach ($notifies as $notify) {
- // Because we use different db tables for the notification query
- // we have sometimes $notify['unseen'] and sometimes $notify['seen].
- // So we will have to transform $notify['unseen']
- if (array_key_exists('unseen', $notify)) {
- $notify['seen'] = ($notify['unseen'] > 0 ? false : true);
- }
-
- // For feed items we use the user's contact, since the avatar is mostly self choosen.
- if (!empty($notify['network']) && $notify['network'] == Protocol::FEED) {
- $notify['author-avatar'] = $notify['contact-avatar'];
- }
-
- // Depending on the identifier of the notification we need to use different defaults
- switch ($ident) {
- case self::SYSTEM:
- $default_item_label = 'notify';
- $default_item_link = $this->baseUrl->get(true) . '/notify/view/' . $notify['id'];
- $default_item_image = ProxyUtils::proxifyUrl($notify['photo'], false, ProxyUtils::SIZE_MICRO);
- $default_item_url = $notify['url'];
- $default_item_text = strip_tags(BBCode::convert($notify['msg']));
- $default_item_when = DateTimeFormat::local($notify['date'], 'r');
- $default_item_ago = Temporal::getRelativeDate($notify['date']);
- break;
-
- case self::HOME:
- $default_item_label = 'comment';
- $default_item_link = $this->baseUrl->get(true) . '/display/' . $notify['parent-guid'];
- $default_item_image = ProxyUtils::proxifyUrl($notify['author-avatar'], false, ProxyUtils::SIZE_MICRO);
- $default_item_url = $notify['author-link'];
- $default_item_text = $this->l10n->t("%s commented on %s's post", $notify['author-name'], $notify['parent-author-name']);
- $default_item_when = DateTimeFormat::local($notify['created'], 'r');
- $default_item_ago = Temporal::getRelativeDate($notify['created']);
- break;
-
- default:
- $default_item_label = (($notify['id'] == $notify['parent']) ? 'post' : 'comment');
- $default_item_link = $this->baseUrl->get(true) . '/display/' . $notify['parent-guid'];
- $default_item_image = ProxyUtils::proxifyUrl($notify['author-avatar'], false, ProxyUtils::SIZE_MICRO);
- $default_item_url = $notify['author-link'];
- $default_item_text = (($notify['id'] == $notify['parent'])
- ? $this->l10n->t("%s created a new post", $notify['author-name'])
- : $this->l10n->t("%s commented on %s's post", $notify['author-name'], $notify['parent-author-name']));
- $default_item_when = DateTimeFormat::local($notify['created'], 'r');
- $default_item_ago = Temporal::getRelativeDate($notify['created']);
- }
-
- // Transform the different types of notification in an usable array
- switch ($notify['verb']) {
- case Activity::LIKE:
- $formattedNotify = [
- 'label' => 'like',
- 'link' => $this->baseUrl->get(true) . '/display/' . $notify['parent-guid'],
- 'image' => ProxyUtils::proxifyUrl($notify['author-avatar'], false, ProxyUtils::SIZE_MICRO),
- 'url' => $notify['author-link'],
- 'text' => $this->l10n->t("%s liked %s's post", $notify['author-name'], $notify['parent-author-name']),
- 'when' => $default_item_when,
- 'ago' => $default_item_ago,
- 'seen' => $notify['seen']
- ];
- break;
-
- case Activity::DISLIKE:
- $formattedNotify = [
- 'label' => 'dislike',
- 'link' => $this->baseUrl->get(true) . '/display/' . $notify['parent-guid'],
- 'image' => ProxyUtils::proxifyUrl($notify['author-avatar'], false, ProxyUtils::SIZE_MICRO),
- 'url' => $notify['author-link'],
- 'text' => $this->l10n->t("%s disliked %s's post", $notify['author-name'], $notify['parent-author-name']),
- 'when' => $default_item_when,
- 'ago' => $default_item_ago,
- 'seen' => $notify['seen']
- ];
- break;
-
- case Activity::ATTEND:
- $formattedNotify = [
- 'label' => 'attend',
- 'link' => $this->baseUrl->get(true) . '/display/' . $notify['parent-guid'],
- 'image' => ProxyUtils::proxifyUrl($notify['author-avatar'], false, ProxyUtils::SIZE_MICRO),
- 'url' => $notify['author-link'],
- 'text' => $this->l10n->t("%s is attending %s's event", $notify['author-name'], $notify['parent-author-name']),
- 'when' => $default_item_when,
- 'ago' => $default_item_ago,
- 'seen' => $notify['seen']
- ];
- break;
-
- case Activity::ATTENDNO:
- $formattedNotify = [
- 'label' => 'attendno',
- 'link' => $this->baseUrl->get(true) . '/display/' . $notify['parent-guid'],
- 'image' => ProxyUtils::proxifyUrl($notify['author-avatar'], false, ProxyUtils::SIZE_MICRO),
- 'url' => $notify['author-link'],
- 'text' => $this->l10n->t("%s is not attending %s's event", $notify['author-name'], $notify['parent-author-name']),
- 'when' => $default_item_when,
- 'ago' => $default_item_ago,
- 'seen' => $notify['seen']
- ];
- break;
-
- case Activity::ATTENDMAYBE:
- $formattedNotify = [
- 'label' => 'attendmaybe',
- 'link' => $this->baseUrl->get(true) . '/display/' . $notify['parent-guid'],
- 'image' => ProxyUtils::proxifyUrl($notify['author-avatar'], false, ProxyUtils::SIZE_MICRO),
- 'url' => $notify['author-link'],
- 'text' => $this->l10n->t("%s may attend %s's event", $notify['author-name'], $notify['parent-author-name']),
- 'when' => $default_item_when,
- 'ago' => $default_item_ago,
- 'seen' => $notify['seen']
- ];
- break;
-
- case Activity::FRIEND:
- if (!isset($notify['object'])) {
- $formattedNotify = [
- 'label' => 'friend',
- 'link' => $default_item_link,
- 'image' => $default_item_image,
- 'url' => $default_item_url,
- 'text' => $default_item_text,
- 'when' => $default_item_when,
- 'ago' => $default_item_ago,
- 'seen' => $notify['seen']
- ];
- break;
- }
- /// @todo Check if this part here is used at all
- $this->logger->info('Complete data.', ['notify' => $notify, 'callStack' => System::callstack(20)]);
-
- $xmlHead = "<" . "?xml version='1.0' encoding='UTF-8' ?" . ">";
- $obj = XML::parseString($xmlHead . $notify['object']);
- $notify['fname'] = $obj->title;
-
- $formattedNotify = [
- 'label' => 'friend',
- 'link' => $this->baseUrl->get(true) . '/display/' . $notify['parent-guid'],
- 'image' => ProxyUtils::proxifyUrl($notify['author-avatar'], false, ProxyUtils::SIZE_MICRO),
- 'url' => $notify['author-link'],
- 'text' => $this->l10n->t("%s is now friends with %s", $notify['author-name'], $notify['fname']),
- 'when' => $default_item_when,
- 'ago' => $default_item_ago,
- 'seen' => $notify['seen']
- ];
- break;
-
- default:
- $formattedNotify = [
- 'label' => $default_item_label,
- 'link' => $default_item_link,
- 'image' => $default_item_image,
- 'url' => $default_item_url,
- 'text' => $default_item_text,
- 'when' => $default_item_when,
- 'ago' => $default_item_ago,
- 'seen' => $notify['seen']
- ];
- }
-
- $formattedNotifies[] = $formattedNotify;
- }
-
- return $formattedNotifies;
+ $this->name_cache = strip_tags(BBCode::convert($this->source_name ?? ''));
}
/**
- * Get network notifications
- *
- * @param bool $seen False => only include notifications into the query
- * which aren't marked as "seen"
- * @param int $start Start the query at this point
- * @param int $limit Maximum number of query results
- *
- * @return array [string, array]
- * string 'ident' => Notification identifier
- * array 'notifications' => Network notifications
- *
- * @throws Exception
- */
- public function getNetworkList(bool $seen = false, int $start = 0, int $limit = self::DEFAULT_PAGE_LIMIT)
- {
- $ident = self::NETWORK;
- $notifies = [];
-
- $condition = ['wall' => false, 'uid' => local_user()];
-
- if (!$seen) {
- $condition['unseen'] = true;
- }
-
- $fields = ['id', 'parent', 'verb', 'author-name', 'unseen', 'author-link', 'author-avatar', 'contact-avatar',
- 'network', 'created', 'object', 'parent-author-name', 'parent-author-link', 'parent-guid'];
- $params = ['order' => ['received' => true], 'limit' => [$start, $limit]];
-
- $items = Item::selectForUser(local_user(), $fields, $condition, $params);
-
- if ($this->dba->isResult($items)) {
- $notifies = $this->formatList(Item::inArray($items), $ident);
- }
-
- $arr = [
- 'notifications' => $notifies,
- 'ident' => $ident,
- ];
-
- return $arr;
- }
-
- /**
- * Get system notifications
- *
- * @param bool $seen False => only include notifications into the query
- * which aren't marked as "seen"
- * @param int $start Start the query at this point
- * @param int $limit Maximum number of query results
- *
- * @return array [string, array]
- * string 'ident' => Notification identifier
- * array 'notifications' => System notifications
- *
- * @throws Exception
+ * Set some extra properties to the notification from db:
+ * - msg_html: message as html string
+ * - msg_plain: message as plain text string
+ * - msg_cache: The pre-formatted message (caching)
*/
- public function getSystemList(bool $seen = false, int $start = 0, int $limit = self::DEFAULT_PAGE_LIMIT)
+ private function setMsg()
{
- $ident = self::SYSTEM;
- $notifies = [];
-
- $filter = ['uid' => local_user()];
- if (!$seen) {
- $filter['seen'] = false;
- }
-
- $params = [];
- $params['order'] = ['date' => 'DESC'];
- $params['limit'] = [$start, $limit];
-
- $stmtNotifies = $this->dba->select('notify',
- ['id', 'url', 'photo', 'msg', 'date', 'seen', 'verb'],
- $filter,
- $params);
-
- if ($this->dba->isResult($stmtNotifies)) {
- $notifies = $this->formatList($this->dba->toArray($stmtNotifies), $ident);
+ try {
+ $this->msg_html = BBCode::convert($this->msg, false);
+ $this->msg_plain = explode("\n", trim(HTML::toPlaintext($this->msg_html, 0)))[0];
+ $this->msg_cache = self::formatMessage($this->name_cache, strip_tags(BBCode::convert($this->msg)));
+ } catch (InternalServerErrorException $e) {
}
-
- $arr = [
- 'notifications' => $notifies,
- 'ident' => $ident,
- ];
-
- return $arr;
}
- /**
- * Get personal notifications
- *
- * @param bool $seen False => only include notifications into the query
- * which aren't marked as "seen"
- * @param int $start Start the query at this point
- * @param int $limit Maximum number of query results
- *
- * @return array [string, array]
- * string 'ident' => Notification identifier
- * array 'notifications' => Personal notifications
- *
- * @throws Exception
- */
- public function getPersonalList(bool $seen = false, int $start = 0, int $limit = self::DEFAULT_PAGE_LIMIT)
+ public function __set($name, $value)
{
- $ident = self::PERSONAL;
- $notifies = [];
+ parent::__set($name, $value);
- $myurl = str_replace('http://', '', DI::app()->contact['nurl']);
- $diasp_url = str_replace('/profile/', '/u/', $myurl);
-
- $condition = ["NOT `wall` AND `uid` = ? AND (`item`.`author-id` = ? OR `item`.`tag` REGEXP ? OR `item`.`tag` REGEXP ?)",
- local_user(), public_contact(), $myurl . '\\]', $diasp_url . '\\]'];
-
- if (!$seen) {
- $condition[0] .= " AND `unseen`";
+ if ($name == 'date') {
+ $this->setTimestamp();
}
- $fields = ['id', 'parent', 'verb', 'author-name', 'unseen', 'author-link', 'author-avatar', 'contact-avatar',
- 'network', 'created', 'object', 'parent-author-name', 'parent-author-link', 'parent-guid'];
- $params = ['order' => ['received' => true], 'limit' => [$start, $limit]];
-
- $items = Item::selectForUser(local_user(), $fields, $condition, $params);
-
- if ($this->dba->isResult($items)) {
- $notifies = $this->formatList(Item::inArray($items), $ident);
+ if ($name == 'msg') {
+ $this->setMsg();
}
- $arr = [
- 'notifications' => $notifies,
- 'ident' => $ident,
- ];
-
- return $arr;
- }
-
- /**
- * Get home notifications
- *
- * @param bool $seen False => only include notifications into the query
- * which aren't marked as "seen"
- * @param int $start Start the query at this point
- * @param int $limit Maximum number of query results
- *
- * @return array [string, array]
- * string 'ident' => Notification identifier
- * array 'notifications' => Home notifications
- *
- * @throws Exception
- */
- public function getHomeList(bool $seen = false, int $start = 0, int $limit = self::DEFAULT_PAGE_LIMIT)
- {
- $ident = self::HOME;
- $notifies = [];
-
- $condition = ['wall' => true, 'uid' => local_user()];
-
- if (!$seen) {
- $condition['unseen'] = true;
+ if ($name == 'source_name') {
+ $this->setNameCache();
}
-
- $fields = ['id', 'parent', 'verb', 'author-name', 'unseen', 'author-link', 'author-avatar', 'contact-avatar',
- 'network', 'created', 'object', 'parent-author-name', 'parent-author-link', 'parent-guid'];
- $params = ['order' => ['received' => true], 'limit' => [$start, $limit]];
-
- $items = Item::selectForUser(local_user(), $fields, $condition, $params);
-
- if ($this->dba->isResult($items)) {
- $notifies = $this->formatList(Item::inArray($items), $ident);
- }
-
- $arr = [
- 'notifications' => $notifies,
- 'ident' => $ident,
- ];
-
- return $arr;
}
/**
- * Get introductions
+ * Formats a notification message with the notification author
*
- * @param bool $all If false only include introductions into the query
- * which aren't marked as ignored
- * @param int $start Start the query at this point
- * @param int $limit Maximum number of query results
- * @param int $id When set, only the introduction with this id is displayed
+ * Replace the name with {0} but ensure to make that only once. The {0} is used
+ * later and prints the name in bold.
*
- * @return array [string, array]
- * string 'ident' => Notification identifier
- * array 'notifications' => Introductions
+ * @param string $name
+ * @param string $message
*
- * @throws ImagickException
- * @throws Exception
+ * @return string Formatted message
*/
- public function getIntroList(bool $all = false, int $start = 0, int $limit = self::DEFAULT_PAGE_LIMIT, int $id = 0)
+ public static function formatMessage($name, $message)
{
- /// @todo sanitize wording according to SELF::INTRO
- $ident = 'introductions';
- $notifies = [];
- $sql_extra = "";
-
- if (empty($id)) {
- if (!$all) {
- $sql_extra = " AND NOT `ignore` ";
- }
-
- $sql_extra .= " AND NOT `intro`.`blocked` ";
+ if ($name != '') {
+ $pos = strpos($message, $name);
} else {
- $sql_extra = sprintf(" AND `intro`.`id` = %d ", intval($id));
+ $pos = false;
}
- /// @todo Fetch contact details by "Contact::getDetailsByUrl" instead of queries to contact, fcontact and gcontact
- $stmtNotifies = $this->dba->p(
- "SELECT `intro`.`id` AS `intro_id`, `intro`.*, `contact`.*,
- `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`,
- `gcontact`.`network` AS `gnetwork`, `gcontact`.`addr` AS `gaddr`
- FROM `intro`
- LEFT JOIN `contact` ON `contact`.`id` = `intro`.`contact-id`
- LEFT JOIN `gcontact` ON `gcontact`.`nurl` = `contact`.`nurl`
- LEFT JOIN `fcontact` ON `intro`.`fid` = `fcontact`.`id`
- WHERE `intro`.`uid` = ? $sql_extra
- LIMIT ?, ?",
- $_SESSION['uid'],
- $start,
- $limit
- );
- if ($this->dba->isResult($stmtNotifies)) {
- $notifies = $this->formatIntroList($this->dba->toArray($stmtNotifies));
- }
-
- $arr = [
- 'ident' => $ident,
- 'notifications' => $notifies,
- ];
-
- return $arr;
- }
-
- /**
- * Format the notification query in an usable array
- *
- * @param array $intros The array from the db query
- *
- * @return array with the introductions
- * @throws HTTPException\InternalServerErrorException
- * @throws ImagickException
- */
- private function formatIntroList(array $intros)
- {
- $knowyou = '';
-
- $formattedIntros = [];
-
- foreach ($intros as $intro) {
- // There are two kind of introduction. Contacts suggested by other contacts and normal connection requests.
- // We have to distinguish between these two because they use different data.
- // Contact suggestions
- if ($intro['fid']) {
- $return_addr = bin2hex(DI::app()->user['nickname'] . '@' .
- $this->baseUrl->getHostName() .
- (($this->baseUrl->getURLPath()) ? '/' . $this->baseUrl->getURLPath() : ''));
-
- $intro = [
- 'label' => 'friend_suggestion',
- 'notify_type' => $this->l10n->t('Friend Suggestion'),
- 'intro_id' => $intro['intro_id'],
- 'madeby' => $intro['name'],
- 'madeby_url' => $intro['url'],
- 'madeby_zrl' => Contact::magicLink($intro['url']),
- 'madeby_addr' => $intro['addr'],
- 'contact_id' => $intro['contact-id'],
- 'photo' => (!empty($intro['fphoto']) ? ProxyUtils::proxifyUrl($intro['fphoto'], false, ProxyUtils::SIZE_SMALL) : "images/person-300.jpg"),
- 'name' => $intro['fname'],
- 'url' => $intro['furl'],
- 'zrl' => Contact::magicLink($intro['furl']),
- 'hidden' => $intro['hidden'] == 1,
- 'post_newfriend' => (intval($this->pConfig->get(local_user(), 'system', 'post_newfriend')) ? '1' : 0),
- 'knowyou' => $knowyou,
- 'note' => $intro['note'],
- 'request' => $intro['frequest'] . '?addr=' . $return_addr,
- ];
-
- // Normal connection requests
- } else {
- $intro = $this->getMissingIntroData($intro);
-
- if (empty($intro['url'])) {
- continue;
- }
-
- // Don't show these data until you are connected. Diaspora is doing the same.
- if ($intro['gnetwork'] === Protocol::DIASPORA) {
- $intro['glocation'] = "";
- $intro['gabout'] = "";
- $intro['ggender'] = "";
- }
- $intro = [
- 'label' => (($intro['network'] !== Protocol::OSTATUS) ? 'friend_request' : 'follower'),
- 'notify_type' => (($intro['network'] !== Protocol::OSTATUS) ? $this->l10n->t('Friend/Connect Request') : $this->l10n->t('New Follower')),
- 'dfrn_id' => $intro['issued-id'],
- 'uid' => $_SESSION['uid'],
- 'intro_id' => $intro['intro_id'],
- 'contact_id' => $intro['contact-id'],
- 'photo' => (!empty($intro['photo']) ? ProxyUtils::proxifyUrl($intro['photo'], false, ProxyUtils::SIZE_SMALL) : "images/person-300.jpg"),
- 'name' => $intro['name'],
- 'location' => BBCode::convert($intro['glocation'], false),
- 'about' => BBCode::convert($intro['gabout'], false),
- 'keywords' => $intro['gkeywords'],
- 'gender' => $intro['ggender'],
- 'hidden' => $intro['hidden'] == 1,
- 'post_newfriend' => (intval($this->pConfig->get(local_user(), 'system', 'post_newfriend')) ? '1' : 0),
- 'url' => $intro['url'],
- 'zrl' => Contact::magicLink($intro['url']),
- 'addr' => $intro['gaddr'],
- 'network' => $intro['gnetwork'],
- 'knowyou' => $intro['knowyou'],
- 'note' => $intro['note'],
- ];
- }
-
- $formattedIntros[] = $intro;
- }
-
- return $formattedIntros;
- }
-
- /**
- * Check for missing contact data and try to fetch the data from
- * from other sources
- *
- * @param array $intro The input array with the intro data
- *
- * @return array The array with the intro data
- * @throws HTTPException\InternalServerErrorException
- */
- private function getMissingIntroData(array $intro)
- {
- // If the network and the addr isn't available from the gcontact
- // table entry, take the one of the contact table entry
- if (empty($intro['gnetwork']) && !empty($intro['network'])) {
- $intro['gnetwork'] = $intro['network'];
- }
- if (empty($intro['gaddr']) && !empty($intro['addr'])) {
- $intro['gaddr'] = $intro['addr'];
- }
-
- // If the network and addr is still not available
- // get the missing data data from other sources
- if (empty($intro['gnetwork']) || empty($intro['gaddr'])) {
- $ret = Contact::getDetailsByURL($intro['url']);
-
- if (empty($intro['gnetwork']) && !empty($ret['network'])) {
- $intro['gnetwork'] = $ret['network'];
- }
- if (empty($intro['gaddr']) && !empty($ret['addr'])) {
- $intro['gaddr'] = $ret['addr'];
- }
+ if ($pos !== false) {
+ $message = substr_replace($message, '{0}', $pos, strlen($name));
}
- return $intro;
+ return $message;
}
}
namespace Friendica\Model;
use Friendica\App;
-use Friendica\Content\Feature;
-use Friendica\Content\ForumManager;
use Friendica\Content\Text\BBCode;
-use Friendica\Content\Text\HTML;
use Friendica\Content\Widget\ContactBlock;
use Friendica\Core\Cache\Duration;
use Friendica\Core\Hook;
use Friendica\Util\Network;
use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Util\Strings;
-use Friendica\Util\Temporal;
class Profile
{
*/
public static function getByUID($uid)
{
- $profile = DBA::selectFirst('profile', [], ['uid' => $uid, 'is-default' => true]);
- return $profile;
+ return DBA::selectFirst('profile', [], ['uid' => $uid]);
}
/**
}
}
- $profile = self::getByNickname($nickname, $user['uid'], $profile_id);
+ $profile = self::getByNickname($nickname, $user['uid']);
if (empty($profile) && empty($profiledata)) {
Logger::log('profile error: ' . DI::args()->getQueryString(), Logger::DEBUG);
}
if (empty($profile)) {
- $profile = ['uid' => 0, 'is-default' => false,'name' => $nickname];
- }
-
- // fetch user tags if this isn't the default profile
-
- if (!$profile['is-default']) {
- $condition = ['uid' => $profile['uid'], 'is-default' => true];
- $profile_id = DBA::selectFirst('profile', ['pub_keywords'], $condition);
- if (DBA::isResult($profile_id)) {
- $profile['pub_keywords'] = $profile_id['pub_keywords'];
- }
+ $profile = ['uid' => 0, 'name' => $nickname];
}
$a->profile = $profile;
if (local_user() && local_user() == $a->profile['uid'] && $profiledata) {
DI::page()['aside'] .= Renderer::replaceMacros(
- Renderer::getMarkupTemplate('profile_edlink.tpl'),
+ Renderer::getMarkupTemplate('settings/profile/link.tpl'),
[
'$editprofile' => DI::l10n()->t('Edit profile'),
'$profid' => $a->profile['id']
* @return array
* @throws \Exception
*/
- public static function getByNickname($nickname, $uid = 0, $profile_id = 0)
+ public static function getByNickname($nickname, $uid = 0)
{
- if (!empty(Session::getRemoteContactID($uid))) {
- $contact = DBA::selectFirst('contact', ['profile-id'], ['id' => Session::getRemoteContactID($uid)]);
- if (DBA::isResult($contact)) {
- $profile_id = $contact['profile-id'];
- }
- }
-
- $profile = null;
-
- if ($profile_id) {
- $profile = DBA::fetchFirst(
- "SELECT `contact`.`id` AS `contact_id`, `contact`.`photo` AS `contact_photo`,
- `contact`.`thumb` AS `contact_thumb`, `contact`.`micro` AS `contact_micro`,
- `profile`.*,
- `contact`.`avatar-date` AS picdate, `contact`.`addr`, `contact`.`url`, `user`.*
- FROM `profile`
- INNER JOIN `contact` on `contact`.`uid` = `profile`.`uid` AND `contact`.`self`
- INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
- WHERE `user`.`nickname` = ? AND `profile`.`id` = ? LIMIT 1",
- $nickname,
- intval($profile_id)
- );
- }
- if (!DBA::isResult($profile)) {
- $profile = DBA::fetchFirst(
- "SELECT `contact`.`id` AS `contact_id`, `contact`.`photo` as `contact_photo`,
- `contact`.`thumb` AS `contact_thumb`, `contact`.`micro` AS `contact_micro`,
- `profile`.*,
- `contact`.`avatar-date` AS picdate, `contact`.`addr`, `contact`.`url`, `user`.*
- FROM `profile`
- INNER JOIN `contact` ON `contact`.`uid` = `profile`.`uid` AND `contact`.`self`
- INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
- WHERE `user`.`nickname` = ? AND `profile`.`is-default` LIMIT 1",
- $nickname
- );
- }
+ $profile = DBA::fetchFirst(
+ "SELECT `contact`.`id` AS `contact_id`, `contact`.`photo` AS `contact_photo`,
+ `contact`.`thumb` AS `contact_thumb`, `contact`.`micro` AS `contact_micro`,
+ `profile`.*,
+ `contact`.`avatar-date` AS picdate, `contact`.`addr`, `contact`.`url`, `user`.*
+ FROM `profile`
+ INNER JOIN `contact` on `contact`.`uid` = `profile`.`uid` AND `contact`.`self`
+ INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
+ WHERE `user`.`nickname` = ? AND `profile`.`uid` = ? LIMIT 1",
+ $nickname,
+ intval($uid)
+ );
return $profile;
}
// show edit profile to yourself
if (!$is_contact && $local_user_is_self) {
- if (Feature::isEnabled(local_user(), 'multi_profiles')) {
- $profile['edit'] = [DI::baseUrl() . '/profiles', DI::l10n()->t('Profiles'), '', DI::l10n()->t('Manage/edit profiles')];
- $r = q(
- "SELECT * FROM `profile` WHERE `uid` = %d",
- local_user()
- );
-
- $profile['menu'] = [
- 'chg_photo' => DI::l10n()->t('Change profile photo'),
- 'cr_new' => DI::l10n()->t('Create New Profile'),
- 'entries' => [],
- ];
-
- if (DBA::isResult($r)) {
- foreach ($r as $rr) {
- $profile['menu']['entries'][] = [
- 'photo' => $rr['thumb'],
- 'id' => $rr['id'],
- 'alt' => DI::l10n()->t('Profile Image'),
- 'profile_name' => $rr['profile-name'],
- 'isdefault' => $rr['is-default'],
- 'visibile_to_everybody' => DI::l10n()->t('visible to everybody'),
- 'edit_visibility' => DI::l10n()->t('Edit visibility'),
- ];
- }
- }
- } else {
- $profile['edit'] = [DI::baseUrl() . '/profiles/' . $profile['id'], DI::l10n()->t('Edit profile'), '', DI::l10n()->t('Edit profile')];
- $profile['menu'] = [
- 'chg_photo' => DI::l10n()->t('Change profile photo'),
- 'cr_new' => null,
- 'entries' => [],
- ];
- }
+ $profile['edit'] = [DI::baseUrl() . '/settings/profile', DI::l10n()->t('Edit profile'), '', DI::l10n()->t('Edit profile')];
+ $profile['menu'] = [
+ 'chg_photo' => DI::l10n()->t('Change profile photo'),
+ 'cr_new' => null,
+ 'entries' => [],
+ ];
}
// Fetch the account type
]);
}
- public static function getAdvanced(App $a)
- {
- $uid = intval($a->profile['uid']);
-
- if ($a->profile['name']) {
- $profile = [];
-
- $profile['fullname'] = [DI::l10n()->t('Full Name:'), $a->profile['name']];
-
- if (Feature::isEnabled($uid, 'profile_membersince')) {
- $profile['membersince'] = [DI::l10n()->t('Member since:'), DateTimeFormat::local($a->profile['register_date'])];
- }
-
- if ($a->profile['gender']) {
- $profile['gender'] = [DI::l10n()->t('Gender:'), DI::l10n()->t($a->profile['gender'])];
- }
-
- if (!empty($a->profile['dob']) && $a->profile['dob'] > DBA::NULL_DATE) {
- $year_bd_format = DI::l10n()->t('j F, Y');
- $short_bd_format = DI::l10n()->t('j F');
-
- $val = DI::l10n()->getDay(
- intval($a->profile['dob']) ?
- DateTimeFormat::utc($a->profile['dob'] . ' 00:00 +00:00', $year_bd_format)
- : DateTimeFormat::utc('2001-' . substr($a->profile['dob'], 5) . ' 00:00 +00:00', $short_bd_format)
- );
-
- $profile['birthday'] = [DI::l10n()->t('Birthday:'), $val];
- }
-
- if (!empty($a->profile['dob'])
- && $a->profile['dob'] > DBA::NULL_DATE
- && $age = Temporal::getAgeByTimezone($a->profile['dob'], $a->profile['timezone'])
- ) {
- $profile['age'] = [DI::l10n()->t('Age: ') , DI::l10n()->tt('%d year old', '%d years old', $age)];
- }
-
- if ($a->profile['marital']) {
- $profile['marital'] = [DI::l10n()->t('Status:'), DI::l10n()->t($a->profile['marital'])];
- }
-
- /// @TODO Maybe use x() here, plus below?
- if ($a->profile['with']) {
- $profile['marital']['with'] = $a->profile['with'];
- }
-
- if (strlen($a->profile['howlong']) && $a->profile['howlong'] > DBA::NULL_DATETIME) {
- $profile['howlong'] = Temporal::getRelativeDate($a->profile['howlong'], DI::l10n()->t('for %1$d %2$s'));
- }
-
- if ($a->profile['sexual']) {
- $profile['sexual'] = [DI::l10n()->t('Sexual Preference:'), DI::l10n()->t($a->profile['sexual'])];
- }
-
- if ($a->profile['homepage']) {
- $profile['homepage'] = [DI::l10n()->t('Homepage:'), HTML::toLink($a->profile['homepage'])];
- }
-
- if ($a->profile['hometown']) {
- $profile['hometown'] = [DI::l10n()->t('Hometown:'), HTML::toLink($a->profile['hometown'])];
- }
-
- if ($a->profile['pub_keywords']) {
- $profile['pub_keywords'] = [DI::l10n()->t('Tags:'), $a->profile['pub_keywords']];
- }
-
- if ($a->profile['politic']) {
- $profile['politic'] = [DI::l10n()->t('Political Views:'), $a->profile['politic']];
- }
-
- if ($a->profile['religion']) {
- $profile['religion'] = [DI::l10n()->t('Religion:'), $a->profile['religion']];
- }
-
- if ($txt = BBCode::convert($a->profile['about'])) {
- $profile['about'] = [DI::l10n()->t('About:'), $txt];
- }
-
- if ($txt = BBCode::convert($a->profile['interest'])) {
- $profile['interest'] = [DI::l10n()->t('Hobbies/Interests:'), $txt];
- }
-
- if ($txt = BBCode::convert($a->profile['likes'])) {
- $profile['likes'] = [DI::l10n()->t('Likes:'), $txt];
- }
-
- if ($txt = BBCode::convert($a->profile['dislikes'])) {
- $profile['dislikes'] = [DI::l10n()->t('Dislikes:'), $txt];
- }
-
- if ($txt = BBCode::convert($a->profile['contact'])) {
- $profile['contact'] = [DI::l10n()->t('Contact information and Social Networks:'), $txt];
- }
-
- if ($txt = BBCode::convert($a->profile['music'])) {
- $profile['music'] = [DI::l10n()->t('Musical interests:'), $txt];
- }
-
- if ($txt = BBCode::convert($a->profile['book'])) {
- $profile['book'] = [DI::l10n()->t('Books, literature:'), $txt];
- }
-
- if ($txt = BBCode::convert($a->profile['tv'])) {
- $profile['tv'] = [DI::l10n()->t('Television:'), $txt];
- }
-
- if ($txt = BBCode::convert($a->profile['film'])) {
- $profile['film'] = [DI::l10n()->t('Film/dance/culture/entertainment:'), $txt];
- }
-
- if ($txt = BBCode::convert($a->profile['romance'])) {
- $profile['romance'] = [DI::l10n()->t('Love/Romance:'), $txt];
- }
-
- if ($txt = BBCode::convert($a->profile['work'])) {
- $profile['work'] = [DI::l10n()->t('Work/employment:'), $txt];
- }
-
- if ($txt = BBCode::convert($a->profile['education'])) {
- $profile['education'] = [DI::l10n()->t('School/education:'), $txt];
- }
-
- //show subcribed forum if it is enabled in the usersettings
- if (Feature::isEnabled($uid, 'forumlist_profile')) {
- $profile['forumlist'] = [DI::l10n()->t('Forums:'), ForumManager::profileAdvanced($uid)];
- }
-
- if ($a->profile['uid'] == local_user()) {
- $profile['edit'] = [DI::baseUrl() . '/profiles/' . $a->profile['id'], DI::l10n()->t('Edit profile'), '', DI::l10n()->t('Edit profile')];
- }
-
- $tpl = Renderer::getMarkupTemplate('profile/advanced.tpl');
- return Renderer::replaceMacros($tpl, [
- '$title' => DI::l10n()->t('Profile'),
- '$basic' => DI::l10n()->t('Basic'),
- '$advanced' => DI::l10n()->t('Advanced'),
- '$profile' => $profile
- ]);
- }
-
- return '';
- }
-
- /**
- * @param App $a
- * @param string $current
- * @param bool $is_owner
- * @param string $nickname
- * @return string
- * @throws \Friendica\Network\HTTPException\InternalServerErrorException
- */
- public static function getTabs(App $a, string $current, bool $is_owner, string $nickname = null)
- {
- if (is_null($nickname)) {
- $nickname = $a->user['nickname'];
- }
-
- $baseProfileUrl = DI::baseUrl() . '/profile/' . $nickname;
-
- $tabs = [
- [
- 'label' => DI::l10n()->t('Status'),
- 'url' => $baseProfileUrl,
- 'sel' => !$current ? 'active' : '',
- 'title' => DI::l10n()->t('Status Messages and Posts'),
- 'id' => 'status-tab',
- 'accesskey' => 'm',
- ],
- [
- 'label' => DI::l10n()->t('Profile'),
- 'url' => $baseProfileUrl . '/?tab=profile',
- 'sel' => $current == 'profile' ? 'active' : '',
- 'title' => DI::l10n()->t('Profile Details'),
- 'id' => 'profile-tab',
- 'accesskey' => 'r',
- ],
- [
- 'label' => DI::l10n()->t('Photos'),
- 'url' => DI::baseUrl() . '/photos/' . $nickname,
- 'sel' => $current == 'photos' ? 'active' : '',
- 'title' => DI::l10n()->t('Photo Albums'),
- 'id' => 'photo-tab',
- 'accesskey' => 'h',
- ],
- [
- 'label' => DI::l10n()->t('Videos'),
- 'url' => DI::baseUrl() . '/videos/' . $nickname,
- 'sel' => $current == 'videos' ? 'active' : '',
- 'title' => DI::l10n()->t('Videos'),
- 'id' => 'video-tab',
- 'accesskey' => 'v',
- ],
- ];
-
- // the calendar link for the full featured events calendar
- if ($is_owner && $a->theme_events_in_profile) {
- $tabs[] = [
- 'label' => DI::l10n()->t('Events'),
- 'url' => DI::baseUrl() . '/events',
- 'sel' => $current == 'events' ? 'active' : '',
- 'title' => DI::l10n()->t('Events and Calendar'),
- 'id' => 'events-tab',
- 'accesskey' => 'e',
- ];
- // if the user is not the owner of the calendar we only show a calendar
- // with the public events of the calendar owner
- } elseif (!$is_owner) {
- $tabs[] = [
- 'label' => DI::l10n()->t('Events'),
- 'url' => DI::baseUrl() . '/cal/' . $nickname,
- 'sel' => $current == 'cal' ? 'active' : '',
- 'title' => DI::l10n()->t('Events and Calendar'),
- 'id' => 'events-tab',
- 'accesskey' => 'e',
- ];
- }
-
- if ($is_owner) {
- $tabs[] = [
- 'label' => DI::l10n()->t('Personal Notes'),
- 'url' => DI::baseUrl() . '/notes',
- 'sel' => $current == 'notes' ? 'active' : '',
- 'title' => DI::l10n()->t('Only You Can See This'),
- 'id' => 'notes-tab',
- 'accesskey' => 't',
- ];
- }
-
- if (!empty($_SESSION['new_member']) && $is_owner) {
- $tabs[] = [
- 'label' => DI::l10n()->t('Tips for New Members'),
- 'url' => DI::baseUrl() . '/newmember',
- 'sel' => false,
- 'title' => DI::l10n()->t('Tips for New Members'),
- 'id' => 'newmember-tab',
- ];
- }
-
- if ($is_owner || empty($a->profile['hide-friends'])) {
- $tabs[] = [
- 'label' => DI::l10n()->t('Contacts'),
- 'url' => $baseProfileUrl . '/contacts',
- 'sel' => $current == 'contacts' ? 'active' : '',
- 'title' => DI::l10n()->t('Contacts'),
- 'id' => 'viewcontacts-tab',
- 'accesskey' => 'k',
- ];
- }
-
- $arr = ['is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => $current, 'tabs' => $tabs];
- Hook::callAll('profile_tabs', $arr);
-
- $tpl = Renderer::getMarkupTemplate('common_tabs.tpl');
-
- return Renderer::replaceMacros($tpl, ['$tabs' => $arr['tabs']]);
- }
-
/**
* Retrieves the my_url session variable
*
*/
public static function searchProfiles($start = 0, $count = 100, $search = null)
{
- $publish = (DI::config()->get('system', 'publish_all') ? '' : " AND `publish` = 1 ");
+ $publish = (DI::config()->get('system', 'publish_all') ? '' : "`publish` = 1");
$total = 0;
if (!empty($search)) {
$cnt = DBA::fetchFirst("SELECT COUNT(*) AS `total`
FROM `profile`
LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid`
- WHERE `is-default` $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed`
+ WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed`
AND ((`profile`.`name` LIKE ?) OR
(`user`.`nickname` LIKE ?) OR
(`profile`.`pdesc` LIKE ?) OR
$cnt = DBA::fetchFirst("SELECT COUNT(*) AS `total`
FROM `profile`
LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid`
- WHERE `is-default` $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed`");
+ WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed`");
}
if (DBA::isResult($cnt)) {
FROM `profile`
LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid`
LEFT JOIN `contact` ON `contact`.`uid` = `user`.`uid`
- WHERE `is-default` $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `contact`.`self`
+ WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `contact`.`self`
AND ((`profile`.`name` LIKE ?) OR
(`user`.`nickname` LIKE ?) OR
(`profile`.`pdesc` LIKE ?) OR
FROM `profile`
LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid`
LEFT JOIN `contact` ON `contact`.`uid` = `user`.`uid`
- WHERE `is-default` $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `contact`.`self`
+ WHERE $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `contact`.`self`
$order LIMIT ?,?",
$start, $count
);
--- /dev/null
+<?php
+
+namespace Friendica\Model;
+
+use Friendica\BaseModel;
+use Friendica\Database\Database;
+use Friendica\Network\HTTPException;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Custom profile field model class.
+ *
+ * Custom profile fields are user-created arbitrary profile fields that can be assigned a permission set to restrict its
+ * display to specific Friendica contacts as it requires magic authentication to work.
+ *
+ * @property int uid
+ * @property int order
+ * @property int psid
+ * @property string label
+ * @property string value
+ * @property string created
+ * @property string edited
+ * @property PermissionSet permissionset
+ */
+class ProfileField extends BaseModel
+{
+ /** @var PermissionSet */
+ private $permissionset;
+
+ /** @var \Friendica\Repository\PermissionSet */
+ private $permissionSetRepository;
+
+ public function __construct(Database $dba, LoggerInterface $logger, \Friendica\Repository\PermissionSet $permissionSetRepository, array $data = [])
+ {
+ parent::__construct($dba, $logger, $data);
+
+ $this->permissionSetRepository = $permissionSetRepository;
+ }
+
+ public function __get($name)
+ {
+ $this->checkValid();
+
+ switch ($name) {
+ case 'permissionset':
+ $this->permissionset =
+ $this->permissionset ??
+ $this->permissionSetRepository->selectFirst(['id' => $this->psid, 'uid' => $this->uid]);
+
+ $return = $this->permissionset;
+ break;
+ default:
+ $return = parent::__get($name);
+ break;
+ }
+
+ return $return;
+ }
+}
'photo' => DI::baseUrl() . "/photo/profile/{$uid}.jpg",
'thumb' => DI::baseUrl() . "/photo/avatar/{$uid}.jpg",
'publish' => $publish,
- 'is-default' => 1,
'net-publish' => $netpublish,
- 'profile-name' => DI::l10n()->t('default')
]);
if (!$insert_result) {
DBA::delete('user', ['uid' => $uid]);
$userStmt = DBA::p("SELECT `user`.`uid`, `user`.`login_date`, `contact`.`last-item`
FROM `user`
- INNER JOIN `profile` ON `profile`.`uid` = `user`.`uid` AND `profile`.`is-default`
+ INNER JOIN `profile` ON `profile`.`uid` = `user`.`uid`
INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid` AND `contact`.`self`
WHERE (`profile`.`publish` OR `profile`.`net-publish`) AND `user`.`verified`
AND NOT `user`.`blocked` AND NOT `user`.`account_removed`
--- /dev/null
+<?php
+
+namespace Friendica\Module;
+
+use Exception;
+use Friendica\BaseModule;
+use Friendica\Content\Pager;
+use Friendica\Core\Renderer;
+use Friendica\Core\System;
+use Friendica\DI;
+use Friendica\Network\HTTPException\ForbiddenException;
+use Friendica\Object\Notification\Notification;
+
+/**
+ * Base Module for each tab of the notification display
+ *
+ * General possibility to print it as JSON as well
+ */
+abstract class BaseNotifications extends BaseModule
+{
+ /** @var array Array of URL parameters */
+ const URL_TYPES = [
+ Notification::NETWORK => 'network',
+ Notification::SYSTEM => 'system',
+ Notification::HOME => 'home',
+ Notification::PERSONAL => 'personal',
+ Notification::INTRO => 'intros',
+ ];
+
+ /** @var array Array of the allowed notifications and their printable name */
+ const PRINT_TYPES = [
+ Notification::NETWORK => 'Network',
+ Notification::SYSTEM => 'System',
+ Notification::HOME => 'Home',
+ Notification::PERSONAL => 'Personal',
+ Notification::INTRO => 'Introductions',
+ ];
+
+ /** @var array The array of access keys for notification pages */
+ const ACCESS_KEYS = [
+ Notification::NETWORK => 'w',
+ Notification::SYSTEM => 'y',
+ Notification::HOME => 'h',
+ Notification::PERSONAL => 'r',
+ Notification::INTRO => 'i',
+ ];
+
+ /** @var int The default count of items per page */
+ const ITEMS_PER_PAGE = 20;
+ /** @var int The default limit of notifications per page */
+ const DEFAULT_PAGE_LIMIT = 80;
+
+ /** @var boolean True, if ALL entries should get shown */
+ protected static $showAll;
+ /** @var int The determined start item of the current page */
+ protected static $firstItemNum;
+
+ /**
+ * Collects all notifications from the backend
+ *
+ * @return array The determined notification array
+ * ['header', 'notifications']
+ */
+ abstract public static function getNotifications();
+
+ public static function init(array $parameters = [])
+ {
+ if (!local_user()) {
+ throw new ForbiddenException(DI::l10n()->t('Permission denied.'));
+ }
+
+ $page = ($_REQUEST['page'] ?? 0) ?: 1;
+
+ self::$firstItemNum = ($page * self::ITEMS_PER_PAGE) - self::ITEMS_PER_PAGE;
+ self::$showAll = ($_REQUEST['show'] ?? '') === 'all';
+ }
+
+ public static function post(array $parameters = [])
+ {
+ $request_id = DI::args()->get(1);
+
+ if ($request_id === 'all') {
+ return;
+ }
+
+ if ($request_id) {
+ $intro = DI::intro()->selectFirst(['id' => $request_id, 'uid' => local_user()]);
+
+ switch ($_POST['submit']) {
+ case DI::l10n()->t('Discard'):
+ $intro->discard();
+ break;
+ case DI::l10n()->t('Ignore'):
+ $intro->ignore();
+ break;
+ }
+
+ DI::baseUrl()->redirect('notifications/intros');
+ }
+ }
+
+ public static function rawContent(array $parameters = [])
+ {
+ // If the last argument of the query is NOT json, return
+ if (DI::args()->get(DI::args()->getArgc() - 1) !== 'json') {
+ return;
+ }
+
+ // Set the pager
+ $pager = new Pager(DI::args()->getQueryString(), self::ITEMS_PER_PAGE);
+
+ // Add additional informations (needed for json output)
+ $notifications = [
+ 'notifications' => static::getNotifications(),
+ 'items_page' => $pager->getItemsPerPage(),
+ 'page' => $pager->getPage(),
+ ];
+
+ System::jsonExit($notifications);
+ }
+
+ /**
+ * Shows the printable result of notifications for a specific tab
+ *
+ * @param string $header The notification header
+ * @param array $notifications The array with the notifications
+ * @param string $noContent The string in case there are no notifications
+ * @param array $showLink The possible links at the top
+ *
+ * @return string The rendered output
+ *
+ * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+ */
+ protected static function printContent(string $header, array $notifications, string $noContent, array $showLink)
+ {
+ // Get the nav tabs for the notification pages
+ $tabs = self::getTabs();
+
+ // Set the pager
+ $pager = new Pager(DI::args()->getQueryString(), self::ITEMS_PER_PAGE);
+
+ $notif_tpl = Renderer::getMarkupTemplate('notifications/notifications.tpl');
+ return Renderer::replaceMacros($notif_tpl, [
+ '$header' => $header ?? DI::l10n()->t('Notifications'),
+ '$tabs' => $tabs,
+ '$notifications' => $notifications,
+ '$noContent' => $noContent,
+ '$showLink' => $showLink,
+ '$paginate' => $pager->renderMinimal(count($notifications))
+ ]);
+ }
+
+ /**
+ * List of pages for the Notifications TabBar
+ *
+ * @return array with with notifications TabBar data
+ * @throws Exception
+ */
+ private static function getTabs()
+ {
+ $selected = DI::args()->get(1, '');
+
+ $tabs = [];
+
+ foreach (self::URL_TYPES as $type => $url) {
+ $tabs[] = [
+ 'label' => DI::l10n()->t(self::PRINT_TYPES[$type]),
+ 'url' => 'notifications/' . $url,
+ 'sel' => (($selected == $url) ? 'active' : ''),
+ 'id' => $type . '-tab',
+ 'accesskey' => self::ACCESS_KEYS[$type],
+ ];
+ }
+
+ return $tabs;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Module;
+
+use Friendica\App;
+use Friendica\BaseModule;
+use Friendica\Core\Hook;
+use Friendica\Core\Renderer;
+use Friendica\DI;
+
+class BaseProfile extends BaseModule
+{
+ /**
+ * Returns the HTML for the profile pages tabs
+ *
+ * @param App $a
+ * @param string $current
+ * @param bool $is_owner
+ * @param string $nickname
+ * @return string
+ * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+ */
+ public static function getTabsHTML(App $a, string $current, bool $is_owner, string $nickname = null)
+ {
+ if (is_null($nickname)) {
+ $nickname = $a->user['nickname'];
+ }
+
+ $baseProfileUrl = DI::baseUrl() . '/profile/' . $nickname;
+
+ $tabs = [
+ [
+ 'label' => DI::l10n()->t('Profile'),
+ 'url' => $baseProfileUrl . '/profile',
+ 'sel' => $current == 'profile' ? 'active' : '',
+ 'title' => DI::l10n()->t('Profile Details'),
+ 'id' => 'profile-tab',
+ 'accesskey' => 'r',
+ ],
+ [
+ 'label' => DI::l10n()->t('Status'),
+ 'url' => $baseProfileUrl . '/status',
+ 'sel' => $current == 'status' ? 'active' : '',
+ 'title' => DI::l10n()->t('Status Messages and Posts'),
+ 'id' => 'status-tab',
+ 'accesskey' => 'm',
+ ],
+ [
+ 'label' => DI::l10n()->t('Photos'),
+ 'url' => DI::baseUrl() . '/photos/' . $nickname,
+ 'sel' => $current == 'photos' ? 'active' : '',
+ 'title' => DI::l10n()->t('Photo Albums'),
+ 'id' => 'photo-tab',
+ 'accesskey' => 'h',
+ ],
+ [
+ 'label' => DI::l10n()->t('Videos'),
+ 'url' => DI::baseUrl() . '/videos/' . $nickname,
+ 'sel' => $current == 'videos' ? 'active' : '',
+ 'title' => DI::l10n()->t('Videos'),
+ 'id' => 'video-tab',
+ 'accesskey' => 'v',
+ ],
+ ];
+
+ // the calendar link for the full featured events calendar
+ if ($is_owner && $a->theme_events_in_profile) {
+ $tabs[] = [
+ 'label' => DI::l10n()->t('Events'),
+ 'url' => DI::baseUrl() . '/events',
+ 'sel' => $current == 'events' ? 'active' : '',
+ 'title' => DI::l10n()->t('Events and Calendar'),
+ 'id' => 'events-tab',
+ 'accesskey' => 'e',
+ ];
+ // if the user is not the owner of the calendar we only show a calendar
+ // with the public events of the calendar owner
+ } elseif (!$is_owner) {
+ $tabs[] = [
+ 'label' => DI::l10n()->t('Events'),
+ 'url' => DI::baseUrl() . '/cal/' . $nickname,
+ 'sel' => $current == 'cal' ? 'active' : '',
+ 'title' => DI::l10n()->t('Events and Calendar'),
+ 'id' => 'events-tab',
+ 'accesskey' => 'e',
+ ];
+ }
+
+ if ($is_owner) {
+ $tabs[] = [
+ 'label' => DI::l10n()->t('Personal Notes'),
+ 'url' => DI::baseUrl() . '/notes',
+ 'sel' => $current == 'notes' ? 'active' : '',
+ 'title' => DI::l10n()->t('Only You Can See This'),
+ 'id' => 'notes-tab',
+ 'accesskey' => 't',
+ ];
+ }
+
+ if (empty($a->profile['hide-friends'])) {
+ $tabs[] = [
+ 'label' => DI::l10n()->t('Contacts'),
+ 'url' => $baseProfileUrl . '/contacts',
+ 'sel' => $current == 'contacts' ? 'active' : '',
+ 'title' => DI::l10n()->t('Contacts'),
+ 'id' => 'viewcontacts-tab',
+ 'accesskey' => 'k',
+ ];
+ }
+
+ if (DI::session()->get('new_member') && $is_owner) {
+ $tabs[] = [
+ 'label' => DI::l10n()->t('Tips for New Members'),
+ 'url' => DI::baseUrl() . '/newmember',
+ 'sel' => false,
+ 'title' => DI::l10n()->t('Tips for New Members'),
+ 'id' => 'newmember-tab',
+ ];
+ }
+
+ $arr = ['is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => $current, 'tabs' => $tabs];
+
+ Hook::callAll('profile_tabs', $arr);
+
+ $tpl = Renderer::getMarkupTemplate('common_tabs.tpl');
+
+ return Renderer::replaceMacros($tpl, ['$tabs' => $arr['tabs']]);
+ }
+}
];
$tabs[] = [
- 'label' => DI::l10n()->t('Profiles'),
- 'url' => 'profiles',
- 'selected' => (($a->argc == 1) && ($a->argv[0] === 'profiles') ? 'active' : ''),
+ 'label' => DI::l10n()->t('Profile'),
+ 'url' => 'settings/profile',
+ 'selected' => (($a->argc > 1) && ($a->argv[1] === 'profile') ? 'active' : ''),
'accesskey' => 'p',
];
Hook::callAll('contact_edit_post', $_POST);
- $profile_id = intval($_POST['profile-assign'] ?? 0);
- if ($profile_id) {
- if (!DBA::exists('profile', ['id' => $profile_id, 'uid' => local_user()])) {
- notice(DI::l10n()->t('Could not locate selected profile.') . EOL);
- return;
- }
- }
-
$hidden = !empty($_POST['hidden']);
$notify = !empty($_POST['notify']);
$info = Strings::escapeHtml(trim($_POST['info'] ?? ''));
$r = DBA::update('contact', [
- 'profile-id' => $profile_id,
'priority' => $priority,
'info' => $info,
'hidden' => $hidden,
$a = DI::app();
- $nets = $_GET['nets'] ?? '';
- $rel = $_GET['rel'] ?? '';
+ $search = Strings::escapeTags(trim($_GET['search'] ?? ''));
+ $nets = Strings::escapeTags(trim($_GET['nets'] ?? ''));
+ $rel = Strings::escapeTags(trim($_GET['rel'] ?? ''));
+ $group = Strings::escapeTags(trim($_GET['group'] ?? ''));
if (empty(DI::page()['aside'])) {
DI::page()['aside'] = '';
$follow_widget = '';
$networks_widget = '';
$rel_widget = '';
+
+ if ($contact['uid'] != 0) {
+ $groups_widget = Model\Group::sidebarWidget('contact', 'group', 'full', 'everyone', $contact_id);
+ } else {
+ $groups_widget = '';
+ }
} else {
$vcard_widget = '';
$findpeople_widget = Widget::findPeople();
$networks_widget = Widget::networks($_SERVER['REQUEST_URI'], $nets);
$rel_widget = Widget::contactRels($_SERVER['REQUEST_URI'], $rel);
- }
-
- if ($contact['uid'] != 0) {
- $groups_widget = Model\Group::sidebarWidget('contact', 'group', 'full', 'everyone', $contact_id);
- } else {
- $groups_widget = null;
+ $groups_widget = Widget::groups($_SERVER['REQUEST_URI'], $group);
}
DI::page()['aside'] .= $vcard_widget . $findpeople_widget . $follow_widget . $groups_widget . $networks_widget . $rel_widget;
'$baseurl' => DI::baseUrl()->get(true),
]);
- $sort_type = 0;
$o = '';
Nav::setSelected('contact');
$poll_interval = ContactSelector::pollInterval($contact['priority'], !$poll_enabled);
}
- $profile_select = null;
- if ($contact['network'] == Protocol::DFRN) {
- $profile_select = ContactSelector::profileAssign($contact['profile-id'], $contact['network'] !== Protocol::DFRN);
- }
-
// Load contactact related actions like hide, suggest, delete and others
$contact_actions = self::getContactActions($contact);
if ($contact['uid'] != 0) {
- $lbl_vis1 = DI::l10n()->t('Profile Visibility');
$lbl_info1 = DI::l10n()->t('Contact Information / Notes');
$contact_settings_label = DI::l10n()->t('Contact Settings');
} else {
- $lbl_vis1 = null;
$lbl_info1 = null;
$contact_settings_label = null;
}
'$header' => DI::l10n()->t('Contact'),
'$tab_str' => $tab_str,
'$submit' => DI::l10n()->t('Submit'),
- '$lbl_vis1' => $lbl_vis1,
- '$lbl_vis2' => DI::l10n()->t('Please choose the profile you would like to display to %s when viewing your profile securely.', $contact['name']),
'$lbl_info1' => $lbl_info1,
'$lbl_info2' => DI::l10n()->t('Their personal note'),
'$reason' => trim(Strings::escapeTags($contact['reason'])),
'$updpub' => DI::l10n()->t('Update public posts'),
'$last_update' => $last_update,
'$udnow' => DI::l10n()->t('Update now'),
- '$profile_select' => $profile_select,
'$contact_id' => $contact['id'],
'$block_text' => ($contact['blocked'] ? DI::l10n()->t('Unblock') : DI::l10n()->t('Block')),
'$ignore_text' => ($contact['readonly'] ? DI::l10n()->t('Unignore') : DI::l10n()->t('Ignore')),
return $arr['output'];
}
- $select_uid = local_user();
+ $sql_values = [local_user()];
// @TODO: Replace with parameter from router
$type = $a->argv[1] ?? '';
switch ($type) {
case 'blocked':
- $sql_extra = sprintf(" AND EXISTS(SELECT `id` from `user-contact` WHERE `contact`.`id` = `user-contact`.`cid` and `user-contact`.`uid` = %d and `user-contact`.`blocked`)", intval(local_user()));
- $select_uid = 0;
+ $sql_extra = " AND EXISTS(SELECT `id` from `user-contact` WHERE `contact`.`id` = `user-contact`.`cid` and `user-contact`.`uid` = ? and `user-contact`.`blocked`)";
+ // This makes the query look for contact.uid = 0
+ array_unshift($sql_values, 0);
break;
case 'hidden':
$sql_extra = " AND `hidden` AND NOT `blocked` AND NOT `pending`";
break;
case 'ignored':
- $sql_extra = sprintf(" AND EXISTS(SELECT `id` from `user-contact` WHERE `contact`.`id` = `user-contact`.`cid` and `user-contact`.`uid` = %d and `user-contact`.`ignored`)", intval(local_user()));
- $select_uid = 0;
+ $sql_extra = " AND EXISTS(SELECT `id` from `user-contact` WHERE `contact`.`id` = `user-contact`.`cid` and `user-contact`.`uid` = ? and `user-contact`.`ignored`)";
+ // This makes the query look for contact.uid = 0
+ array_unshift($sql_values, 0);
break;
case 'archived':
$sql_extra = " AND `archive` AND NOT `blocked` AND NOT `pending`";
break;
case 'pending':
- $sql_extra = sprintf(" AND `pending` AND NOT `archive` AND ((`rel` = %d)
- OR EXISTS (SELECT `id` FROM `intro` WHERE `contact-id` = `contact`.`id` AND NOT `ignore`))", Model\Contact::SHARING);
+ $sql_extra = " AND `pending` AND NOT `archive` AND ((`rel` = ?)
+ OR EXISTS (SELECT `id` FROM `intro` WHERE `contact-id` = `contact`.`id` AND NOT `ignore`))";
+ $sql_values[] = Model\Contact::SHARING;
break;
default:
$sql_extra = " AND NOT `archive` AND NOT `blocked` AND NOT `pending`";
+ break;
+ }
+
+ $searching = false;
+ $search_hdr = null;
+ if ($search) {
+ $searching = true;
+ $search_hdr = $search;
+ $search_txt = preg_quote($search);
+ $sql_extra .= " AND (name REGEXP ? OR url REGEXP ? OR nick REGEXP ?)";
+ $sql_values[] = $search_txt;
+ $sql_values[] = $search_txt;
+ $sql_values[] = $search_txt;
}
- $sql_extra .= sprintf(" AND `network` != '%s' ", Protocol::PHANTOM);
+ if ($nets) {
+ $sql_extra .= " AND network = ? ";
+ $sql_values[] = $nets;
+ }
- $search = Strings::escapeTags(trim($_GET['search'] ?? ''));
- $nets = Strings::escapeTags(trim($_GET['nets'] ?? ''));
- $rel = Strings::escapeTags(trim($_GET['rel'] ?? ''));
+ switch ($rel) {
+ case 'followers':
+ $sql_extra .= " AND `rel` IN (?, ?)";
+ $sql_values[] = Model\Contact::FOLLOWER;
+ $sql_values[] = Model\Contact::FRIEND;
+ break;
+ case 'following':
+ $sql_extra .= " AND `rel` IN (?, ?)";
+ $sql_values[] = Model\Contact::SHARING;
+ $sql_values[] = Model\Contact::FRIEND;
+ break;
+ case 'mutuals':
+ $sql_extra .= " AND `rel` = ?";
+ $sql_values[] = Model\Contact::FRIEND;
+ break;
+ }
+
+ if ($group) {
+ $sql_extra = " AND EXISTS(SELECT `id` FROM `group_member` WHERE `gid` = ? AND `contact`.`id` = `contact-id`)";
+ $sql_values[] = $group;
+ }
+
+ $sql_extra .= Widget::unavailableNetworks();
+
+ $total = 0;
+ $stmt = DBA::p("SELECT COUNT(*) AS `total`
+ FROM `contact`
+ WHERE `uid` = ?
+ AND `self` = 0
+ AND NOT `deleted`
+ $sql_extra",
+ $sql_values
+ );
+ if (DBA::isResult($stmt)) {
+ $total = DBA::fetch($stmt)['total'];
+ }
+ DBA::close($stmt);
+
+ $pager = new Pager(DI::args()->getQueryString());
+
+ $sql_values[] = $pager->getStart();
+ $sql_values[] = $pager->getItemsPerPage();
+
+ $contacts = [];
+
+ $stmt = DBA::p("SELECT *
+ FROM `contact`
+ WHERE `uid` = ?
+ AND `self` = 0
+ AND NOT `deleted`
+ $sql_extra
+ ORDER BY `name` ASC
+ LIMIT ?, ?",
+ $sql_values
+ );
+ while ($contact = DBA::fetch($stmt)) {
+ $contact['blocked'] = Model\Contact::isBlockedByUser($contact['id'], local_user());
+ $contact['readonly'] = Model\Contact::isIgnoredByUser($contact['id'], local_user());
+ $contacts[] = self::getContactTemplateVars($contact);
+ }
+ DBA::close($stmt);
$tabs = [
[
],
];
- $tab_tpl = Renderer::getMarkupTemplate('common_tabs.tpl');
- $t = Renderer::replaceMacros($tab_tpl, ['$tabs' => $tabs]);
-
- $total = 0;
- $searching = false;
- $search_hdr = null;
- if ($search) {
- $searching = true;
- $search_hdr = $search;
- $search_txt = DBA::escape(Strings::protectSprintf(preg_quote($search)));
- $sql_extra .= " AND (name REGEXP '$search_txt' OR url REGEXP '$search_txt' OR nick REGEXP '$search_txt') ";
- }
-
- if ($nets) {
- $sql_extra .= sprintf(" AND network = '%s' ", DBA::escape($nets));
- }
-
- switch ($rel) {
- case 'followers': $sql_extra .= " AND `rel` IN (1, 3)"; break;
- case 'following': $sql_extra .= " AND `rel` IN (2, 3)"; break;
- case 'mutuals': $sql_extra .= " AND `rel` = 3"; break;
- }
-
- $sql_extra .= " AND NOT `deleted` ";
-
- $sql_extra2 = ((($sort_type > 0) && ($sort_type <= Model\Contact::FRIEND)) ? sprintf(" AND `rel` = %d ", intval($sort_type)) : '');
-
- $sql_extra3 = Widget::unavailableNetworks();
-
- $r = q("SELECT COUNT(*) AS `total` FROM `contact`
- WHERE `uid` = %d AND `self` = 0 $sql_extra $sql_extra2 $sql_extra3",
- intval($select_uid)
- );
- if (DBA::isResult($r)) {
- $total = $r[0]['total'];
- }
- $pager = new Pager(DI::args()->getQueryString());
-
- $contacts = [];
-
- $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 $sql_extra $sql_extra2 $sql_extra3 ORDER BY `name` ASC LIMIT %d , %d ",
- intval($select_uid),
- $pager->getStart(),
- $pager->getItemsPerPage()
- );
- if (DBA::isResult($r)) {
- foreach ($r as $rr) {
- $rr['blocked'] = Model\Contact::isBlockedByUser($rr['id'], local_user());
- $rr['readonly'] = Model\Contact::isIgnoredByUser($rr['id'], local_user());
- $contacts[] = self::getContactTemplateVars($rr);
- }
- }
+ $tabs_tpl = Renderer::getMarkupTemplate('common_tabs.tpl');
+ $tabs_html = Renderer::replaceMacros($tabs_tpl, ['$tabs' => $tabs]);
switch ($rel) {
case 'followers': $header = DI::l10n()->t('Followers'); break;
$tpl = Renderer::getMarkupTemplate('contacts-template.tpl');
$o .= Renderer::replaceMacros($tpl, [
'$header' => $header,
- '$tabs' => $t,
+ '$tabs' => $tabs_html,
'$total' => $total,
'$search' => $search_hdr,
'$desc' => DI::l10n()->t('Search your contacts'),
--- /dev/null
+<?php
+
+namespace Friendica\Module\Notifications;
+
+use Friendica\Content\ContactSelector;
+use Friendica\Content\Nav;
+use Friendica\Core\Protocol;
+use Friendica\Core\Renderer;
+use Friendica\Database\DBA;
+use Friendica\DI;
+use Friendica\Module\BaseNotifications;
+use Friendica\Object\Notification\Introduction;
+
+/**
+ * Prints notifications about introduction
+ */
+class Introductions extends BaseNotifications
+{
+ /**
+ * @inheritDoc
+ */
+ public static function getNotifications()
+ {
+ $id = (int)DI::args()->get(2, 0);
+ $all = DI::args()->get(2) == 'all';
+
+ $notifications = [
+ 'ident' => 'introductions',
+ 'notifications' => DI::notificationIntro()->getList($all, self::$firstItemNum, self::ITEMS_PER_PAGE, $id),
+ ];
+
+ return [
+ 'header' => DI::l10n()->t('Notifications'),
+ 'notifications' => $notifications,
+ ];
+ }
+
+ public static function content(array $parameters = [])
+ {
+ Nav::setSelected('introductions');
+
+ $all = DI::args()->get(2) == 'all';
+
+ $notificationContent = [];
+ $notificationNoContent = '';
+
+ $notificationResult = self::getNotifications();
+ $notifications = $notificationResult['notifications'] ?? [];
+ $notificationHeader = $notificationResult['header'] ?? '';
+
+ $notificationSuggestions = Renderer::getMarkupTemplate('notifications/suggestions.tpl');
+ $notificationTemplate = Renderer::getMarkupTemplate('notifications/intros.tpl');
+
+ // The link to switch between ignored and normal connection requests
+ $notificationShowLink = [
+ 'href' => (!$all ? 'notifications/intros/all' : 'notifications/intros'),
+ 'text' => (!$all ? DI::l10n()->t('Show Ignored Requests') : DI::l10n()->t('Hide Ignored Requests')),
+ ];
+
+ // Loop through all introduction notifications.This creates an array with the output html for each
+ // introduction
+ /** @var Introduction $notification */
+ foreach ($notifications['notifications'] as $notification) {
+
+ // There are two kind of introduction. Contacts suggested by other contacts and normal connection requests.
+ // We have to distinguish between these two because they use different data.
+ switch ($notification->getLabel()) {
+ case 'friend_suggestion':
+ $notificationContent[] = Renderer::replaceMacros($notificationSuggestions, [
+ '$type' => $notification->getLabel(),
+ '$str_notification_type' => DI::l10n()->t('Notification type:'),
+ '$str_type' => $notification->getType(),
+ '$intro_id' => $notification->getIntroId(),
+ '$lbl_madeby' => DI::l10n()->t('Suggested by:'),
+ '$madeby' => $notification->getMadeBy(),
+ '$madeby_url' => $notification->getMadeByUrl(),
+ '$madeby_zrl' => $notification->getMadeByZrl(),
+ '$madeby_addr' => $notification->getMadeByAddr(),
+ '$contact_id' => $notification->getContactId(),
+ '$photo' => $notification->getPhoto(),
+ '$fullname' => $notification->getName(),
+ '$url' => $notification->getUrl(),
+ '$zrl' => $notification->getZrl(),
+ '$lbl_url' => DI::l10n()->t('Profile URL'),
+ '$addr' => $notification->getAddr(),
+ '$hidden' => ['hidden', DI::l10n()->t('Hide this contact from others'), $notification->isHidden(), ''],
+ '$knowyou' => $notification->getKnowYou(),
+ '$approve' => DI::l10n()->t('Approve'),
+ '$note' => $notification->getNote(),
+ '$request' => $notification->getRequest(),
+ '$ignore' => DI::l10n()->t('Ignore'),
+ '$discard' => DI::l10n()->t('Discard'),
+ ]);
+ break;
+
+ // Normal connection requests
+ default:
+ $friend_selected = (($notification->getNetwork() !== Protocol::OSTATUS) ? ' checked="checked" ' : ' disabled ');
+ $fan_selected = (($notification->getNetwork() === Protocol::OSTATUS) ? ' checked="checked" disabled ' : '');
+
+ $lbl_knowyou = '';
+ $knowyou = '';
+ $helptext = '';
+ $helptext2 = '';
+ $helptext3 = '';
+
+ if ($notification->getNetwork() === Protocol::DFRN) {
+ $lbl_knowyou = DI::l10n()->t('Claims to be known to you: ');
+ $knowyou = ($notification->getKnowYou() ? DI::l10n()->t('yes') : DI::l10n()->t('no'));
+ $helptext = DI::l10n()->t('Shall your connection be bidirectional or not?');
+ $helptext2 = DI::l10n()->t('Accepting %s as a friend allows %s to subscribe to your posts, and you will also receive updates from them in your news feed.', $notification->getName(), $notification->getName());
+ $helptext3 = DI::l10n()->t('Accepting %s as a subscriber allows them to subscribe to your posts, but you will not receive updates from them in your news feed.', $notification->getName());
+ } elseif ($notification->getNetwork() === Protocol::DIASPORA) {
+ $helptext = DI::l10n()->t('Shall your connection be bidirectional or not?');
+ $helptext2 = DI::l10n()->t('Accepting %s as a friend allows %s to subscribe to your posts, and you will also receive updates from them in your news feed.', $notification->getName(), $notification->getName());
+ $helptext3 = DI::l10n()->t('Accepting %s as a sharer allows them to subscribe to your posts, but you will not receive updates from them in your news feed.', $notification->getName());
+ }
+
+ $dfrn_tpl = Renderer::getMarkupTemplate('notifications/netfriend.tpl');
+ $dfrn_text = Renderer::replaceMacros($dfrn_tpl, [
+ '$intro_id' => $notification->getIntroId(),
+ '$friend_selected' => $friend_selected,
+ '$fan_selected' => $fan_selected,
+ '$approve_as1' => $helptext,
+ '$approve_as2' => $helptext2,
+ '$approve_as3' => $helptext3,
+ '$as_friend' => DI::l10n()->t('Friend'),
+ '$as_fan' => (($notification->getNetwork() == Protocol::DIASPORA) ? DI::l10n()->t('Sharer') : DI::l10n()->t('Subscriber')),
+ ]);
+
+ $contact = DBA::selectFirst('contact', ['network', 'protocol'], ['id' => $notification->getContactId()]);
+
+ if (($contact['network'] != Protocol::DFRN) || ($contact['protocol'] == Protocol::ACTIVITYPUB)) {
+ $action = 'follow_confirm';
+ } else {
+ $action = 'dfrn_confirm';
+ }
+
+ $header = $notification->getName();
+
+ if ($notification->getAddr() != '') {
+ $header .= ' <' . $notification->getAddr() . '>';
+ }
+
+ $header .= ' (' . ContactSelector::networkToName($notification->getNetwork(), $notification->getUrl()) . ')';
+
+ if ($notification->getNetwork() != Protocol::DIASPORA) {
+ $discard = DI::l10n()->t('Discard');
+ } else {
+ $discard = '';
+ }
+
+ $notificationContent[] = Renderer::replaceMacros($notificationTemplate, [
+ '$type' => $notification->getLabel(),
+ '$header' => $header,
+ '$str_notification_type' => DI::l10n()->t('Notification type:'),
+ '$str_type' => $notification->getType(),
+ '$dfrn_text' => $dfrn_text,
+ '$dfrn_id' => $notification->getDfrnId(),
+ '$uid' => $notification->getUid(),
+ '$intro_id' => $notification->getIntroId(),
+ '$contact_id' => $notification->getContactId(),
+ '$photo' => $notification->getPhoto(),
+ '$fullname' => $notification->getName(),
+ '$location' => $notification->getLocation(),
+ '$lbl_location' => DI::l10n()->t('Location:'),
+ '$about' => $notification->getAbout(),
+ '$lbl_about' => DI::l10n()->t('About:'),
+ '$keywords' => $notification->getKeywords(),
+ '$lbl_keywords' => DI::l10n()->t('Tags:'),
+ '$gender' => $notification->getGender(),
+ '$lbl_gender' => DI::l10n()->t('Gender:'),
+ '$hidden' => ['hidden', DI::l10n()->t('Hide this contact from others'), $notification->isHidden(), ''],
+ '$url' => $notification->getUrl(),
+ '$zrl' => $notification->getZrl(),
+ '$lbl_url' => DI::l10n()->t('Profile URL'),
+ '$addr' => $notification->getAddr(),
+ '$lbl_knowyou' => $lbl_knowyou,
+ '$lbl_network' => DI::l10n()->t('Network:'),
+ '$network' => ContactSelector::networkToName($notification->getNetwork(), $notification->getUrl()),
+ '$knowyou' => $knowyou,
+ '$approve' => DI::l10n()->t('Approve'),
+ '$note' => $notification->getNote(),
+ '$ignore' => DI::l10n()->t('Ignore'),
+ '$discard' => $discard,
+ '$action' => $action,
+ ]);
+ break;
+ }
+ }
+
+ if (count($notifications['notifications']) == 0) {
+ info(DI::l10n()->t('No introductions.') . EOL);
+ $notificationNoContent = DI::l10n()->t('No more %s notifications.', $notifications['ident']);
+ }
+
+ return self::printContent($notificationHeader, $notificationContent, $notificationNoContent, $notificationShowLink);
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Module\Notifications;
+
+use Friendica\BaseModule;
+use Friendica\Core\System;
+use Friendica\DI;
+use Friendica\Network\HTTPException;
+
+/**
+ * Interacting with the /notification command
+ */
+class Notification extends BaseModule
+{
+ public static function init(array $parameters = [])
+ {
+ if (!local_user()) {
+ throw new HTTPException\UnauthorizedException(DI::l10n()->t('Permission denied.'));
+ }
+ }
+
+ public static function rawContent(array $parameters = [])
+ {
+ // @TODO: Replace with parameter from router
+ if (DI::args()->get(1) === 'mark' && DI::args()->get(2) === 'all') {
+ try {
+ $success = DI::notify()->setAllSeen();
+ }catch (\Exception $e) {
+ $success = false;
+ }
+
+ header('Content-type: application/json; charset=utf-8');
+ echo json_encode([
+ 'result' => ($success) ? 'success' : 'fail',
+ ]);
+ exit();
+ }
+ }
+
+ /**
+ * Redirect to the notifications main page or to the url for the chosen notifications
+ *
+ * @return string|void
+ * @throws HTTPException\InternalServerErrorException
+ */
+ public static function content(array $parameters = [])
+ {
+ // @TODO: Replace with parameter from router
+ if (DI::args()->getArgc() > 2 && DI::args()->get(1) === 'view' && intval(DI::args()->get(2))) {
+ try {
+ $notification = DI::notify()->getByID(DI::args()->get(2));
+ $notification->setSeen();
+
+ if (!empty($notification->link)) {
+ System::externalRedirect($notification->link);
+ }
+
+ } catch (HTTPException\NotFoundException $e) {
+ info(DI::l10n()->t('Invalid notification.'));
+ }
+
+ DI::baseUrl()->redirect();
+ }
+
+ // @TODO: Replace with parameter from router
+ DI::baseUrl()->redirect('notifications/system');
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Module\Notifications;
+
+use Friendica\Content\Nav;
+use Friendica\Core\Renderer;
+use Friendica\DI;
+use Friendica\Module\BaseNotifications;
+use Friendica\Object\Notification\Notification;
+
+/**
+ * Prints all notification types except introduction:
+ * - Network
+ * - System
+ * - Personal
+ * - Home
+ */
+class Notifications extends BaseNotifications
+{
+ /**
+ * {@inheritDoc}
+ */
+ public static function getNotifications()
+ {
+ $notificationHeader = '';
+ /** @var Notification[] $notifications */
+ $notifications = [];
+
+ // Get the network notifications
+ if ((DI::args()->get(1) == 'network')) {
+ $notificationHeader = DI::l10n()->t('Network Notifications');
+ $notifications = [
+ 'ident' => Notification::NETWORK,
+ 'notifications' => DI::notification()->getNetworkList(self::$showAll, self::$firstItemNum, self::ITEMS_PER_PAGE),
+ ];
+
+ // Get the system notifications
+ } elseif ((DI::args()->get(1) == 'system')) {
+ $notificationHeader = DI::l10n()->t('System Notifications');
+ $notifications = [
+ 'ident' => Notification::SYSTEM,
+ 'notifications' => DI::notification()->getSystemList(self::$showAll, self::$firstItemNum, self::ITEMS_PER_PAGE),
+ ];
+
+ // Get the personal notifications
+ } elseif ((DI::args()->get(1) == 'personal')) {
+ $notificationHeader = DI::l10n()->t('Personal Notifications');
+ $notifications = [
+ 'ident' => Notification::PERSONAL,
+ 'notifications' => DI::notification()->getPersonalList(self::$showAll, self::$firstItemNum, self::ITEMS_PER_PAGE),
+ ];
+
+ // Get the home notifications
+ } elseif ((DI::args()->get(1) == 'home')) {
+ $notificationHeader = DI::l10n()->t('Home Notifications');
+ $notifications = [
+ 'ident' => Notification::HOME,
+ 'notifications' => DI::notification()->getHomeList(self::$showAll, self::$firstItemNum, self::ITEMS_PER_PAGE),
+ ];
+ // fallback - redirect to main page
+ } else {
+ DI::baseUrl()->redirect('notifications');
+ }
+
+ return [
+ 'header' => $notificationHeader,
+ 'notifications' => $notifications,
+ ];
+ }
+
+ public static function content(array $parameters = [])
+ {
+ Nav::setSelected('notifications');
+
+ $notificationContent = [];
+ $notificationNoContent = '';
+
+ $notificationResult = self::getNotifications();
+ $notifications = $notificationResult['notifications'] ?? [];
+ $notificationHeader = $notificationResult['header'] ?? '';
+
+
+ if (!empty($notifications['notifications'])) {
+ // Loop trough ever notification This creates an array with the output html for each
+ // notification and apply the correct template according to the notificationtype (label).
+ /** @var Notification $notification */
+ foreach ($notifications['notifications'] as $notification) {
+ $notification_templates = [
+ 'like' => 'notifications/likes_item.tpl',
+ 'dislike' => 'notifications/dislikes_item.tpl',
+ 'attend' => 'notifications/attend_item.tpl',
+ 'attendno' => 'notifications/attend_item.tpl',
+ 'attendmaybe' => 'notifications/attend_item.tpl',
+ 'friend' => 'notifications/friends_item.tpl',
+ 'comment' => 'notifications/comments_item.tpl',
+ 'post' => 'notifications/posts_item.tpl',
+ 'notification' => 'notifications/notification.tpl',
+ ];
+
+ $notificationTemplate = Renderer::getMarkupTemplate($notification_templates[$notification->getLabel()]);
+
+ $notificationContent[] = Renderer::replaceMacros($notificationTemplate, [
+ '$item_label' => $notification->getLabel(),
+ '$item_link' => $notification->getLink(),
+ '$item_image' => $notification->getImage(),
+ '$item_url' => $notification->getUrl(),
+ '$item_text' => $notification->getText(),
+ '$item_when' => $notification->getWhen(),
+ '$item_ago' => $notification->getAgo(),
+ '$item_seen' => $notification->isSeen(),
+ ]);
+ }
+ } else {
+ $notificationNoContent = DI::l10n()->t('No more %s notifications.', $notifications['ident']);
+ }
+
+ $notificationShowLink = [
+ 'href' => (self::$showAll ? 'notifications/' . $notifications['ident'] : 'notifications/' . $notifications['ident'] . '?show=all'),
+ 'text' => (self::$showAll ? DI::l10n()->t('Show unread') : DI::l10n()->t('Show all')),
+ ];
+
+ return self::printContent($notificationHeader, $notificationContent, $notificationNoContent, $notificationShowLink);
+ }
+}
+++ /dev/null
-<?php
-
-namespace Friendica\Module\Notifications;
-
-use Friendica\BaseModule;
-use Friendica\Core\System;
-use Friendica\DI;
-use Friendica\Network\HTTPException;
-
-/**
- * Interacting with the /notify command
- */
-class Notify extends BaseModule
-{
- public static function init(array $parameters = [])
- {
- if (!local_user()) {
- throw new HTTPException\UnauthorizedException(DI::l10n()->t('Permission denied.'));
- }
- }
-
- public static function rawContent(array $parameters = [])
- {
- $a = DI::app();
-
- // @TODO: Replace with parameter from router
- if ($a->argc > 2 && $a->argv[1] === 'mark' && $a->argv[2] === 'all') {
- $success = DI::notify()->setAllSeen();
-
- header('Content-type: application/json; charset=utf-8');
- echo json_encode([
- 'result' => ($success) ? 'success' : 'fail',
- ]);
- exit();
- }
- }
-
- /**
- * Redirect to the notifications main page or to the url for the chosen notify
- *
- * @return string|void
- * @throws HTTPException\InternalServerErrorException
- */
- public static function content(array $parameters = [])
- {
- $a = DI::app();
-
- // @TODO: Replace with parameter from router
- if ($a->argc > 2 && $a->argv[1] === 'view' && intval($a->argv[2])) {
- $notificationsManager = DI::notify();
- // @TODO: Replace with parameter from router
- $note = $notificationsManager->getByID($a->argv[2]);
- if (!empty($note)) {
- $notificationsManager->setSeen($note);
- if (!empty($note['link'])) {
- System::externalRedirect($note['link']);
- }
- }
-
- DI::baseUrl()->redirect();
- }
-
- // @TODO: Replace with parameter from router
- DI::baseUrl()->redirect('notifications/system');
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Module;
-
-use Friendica\BaseModule;
-use Friendica\Content\Nav;
-use Friendica\Content\Pager;
-use Friendica\Content\Widget;
-use Friendica\Core\ACL;
-use Friendica\Core\Hook;
-use Friendica\Core\Session;
-use Friendica\Core\System;
-use Friendica\Database\DBA;
-use Friendica\DI;
-use Friendica\Model\Item;
-use Friendica\Model\Profile as ProfileModel;
-use Friendica\Model\User;
-use Friendica\Module\Security\Login;
-use Friendica\Protocol\ActivityPub;
-use Friendica\Util\DateTimeFormat;
-use Friendica\Util\Security;
-use Friendica\Util\Strings;
-use Friendica\Util\XML;
-
-require_once 'boot.php';
-
-class Profile extends BaseModule
-{
- public static $which = '';
- public static $profile = 0;
-
- public static function init(array $parameters = [])
- {
- $a = DI::app();
-
- // @TODO: Replace with parameter from router
- if ($a->argc < 2) {
- throw new \Friendica\Network\HTTPException\BadRequestException();
- }
-
- self::$which = filter_var($a->argv[1], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_STRIP_BACKTICK);
-
- // @TODO: Replace with parameter from router
- if (local_user() && $a->argc > 2 && $a->argv[2] === 'view') {
- self::$which = $a->user['nickname'];
- self::$profile = filter_var($a->argv[1], FILTER_SANITIZE_NUMBER_INT);
- }
- }
-
- public static function rawContent(array $parameters = [])
- {
- if (ActivityPub::isRequest()) {
- $user = DBA::selectFirst('user', ['uid'], ['nickname' => self::$which]);
- if (DBA::isResult($user)) {
- // The function returns an empty array when the account is removed, expired or blocked
- $data = ActivityPub\Transmitter::getProfile($user['uid']);
- if (!empty($data)) {
- System::jsonExit($data, 'application/activity+json');
- }
- }
-
- if (DBA::exists('userd', ['username' => self::$which])) {
- // Known deleted user
- $data = ActivityPub\Transmitter::getDeletedUser(self::$which);
-
- System::jsonError(410, $data);
- } else {
- // Any other case (unknown, blocked, unverified, expired, no profile, no self contact)
- System::jsonError(404, []);
- }
- }
- }
-
- public static function content(array $parameters = [], $update = 0)
- {
- $a = DI::app();
-
- if (!$update) {
- ProfileModel::load($a, self::$which, self::$profile);
-
- $page = DI::page();
-
- $page['htmlhead'] .= "\n";
-
- $blocked = !local_user() && !Session::getRemoteContactID($a->profile['uid']) && DI::config()->get('system', 'block_public');
- $userblock = !local_user() && !Session::getRemoteContactID($a->profile['uid']) && $a->profile['hidewall'];
-
- if (!empty($a->profile['page-flags']) && $a->profile['page-flags'] == User::PAGE_FLAGS_COMMUNITY) {
- $page['htmlhead'] .= '<meta name="friendica.community" content="true" />' . "\n";
- }
-
- if (!empty($a->profile['openidserver'])) {
- $page['htmlhead'] .= '<link rel="openid.server" href="' . $a->profile['openidserver'] . '" />' . "\n";
- }
-
- if (!empty($a->profile['openid'])) {
- $delegate = strstr($a->profile['openid'], '://') ? $a->profile['openid'] : 'https://' . $a->profile['openid'];
- $page['htmlhead'] .= '<link rel="openid.delegate" href="' . $delegate . '" />' . "\n";
- }
-
- // site block
- if (!$blocked && !$userblock) {
- $keywords = str_replace(['#', ',', ' ', ',,'], ['', ' ', ',', ','], $a->profile['pub_keywords'] ?? '');
- if (strlen($keywords)) {
- $page['htmlhead'] .= '<meta name="keywords" content="' . $keywords . '" />' . "\n";
- }
- }
-
- $page['htmlhead'] .= '<meta name="dfrn-global-visibility" content="' . ($a->profile['net-publish'] ? 'true' : 'false') . '" />' . "\n";
-
- if (!$a->profile['net-publish'] || $a->profile['hidewall']) {
- $page['htmlhead'] .= '<meta content="noindex, noarchive" name="robots" />' . "\n";
- }
-
- $page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . DI::baseUrl() . '/dfrn_poll/' . self::$which . '" title="DFRN: ' . DI::l10n()->t('%s\'s timeline', $a->profile['username']) . '"/>' . "\n";
- $page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . DI::baseUrl() . '/feed/' . self::$which . '/" title="' . DI::l10n()->t('%s\'s posts', $a->profile['username']) . '"/>' . "\n";
- $page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . DI::baseUrl() . '/feed/' . self::$which . '/comments" title="' . DI::l10n()->t('%s\'s comments', $a->profile['username']) . '"/>' . "\n";
- $page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . DI::baseUrl() . '/feed/' . self::$which . '/activity" title="' . DI::l10n()->t('%s\'s timeline', $a->profile['username']) . '"/>' . "\n";
- $uri = urlencode('acct:' . $a->profile['nickname'] . '@' . DI::baseUrl()->getHostname() . (DI::baseUrl()->getUrlPath() ? '/' . DI::baseUrl()->getUrlPath() : ''));
- $page['htmlhead'] .= '<link rel="lrdd" type="application/xrd+xml" href="' . DI::baseUrl() . '/xrd/?uri=' . $uri . '" />' . "\n";
- header('Link: <' . DI::baseUrl() . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false);
-
- $dfrn_pages = ['request', 'confirm', 'notify', 'poll'];
- foreach ($dfrn_pages as $dfrn) {
- $page['htmlhead'] .= '<link rel="dfrn-' . $dfrn . '" href="' . DI::baseUrl() . '/dfrn_' . $dfrn . '/' . self::$which . '" />' . "\n";
- }
- $page['htmlhead'] .= '<link rel="dfrn-poco" href="' . DI::baseUrl() . '/poco/' . self::$which . '" />' . "\n";
- }
-
- $category = $datequery = $datequery2 = '';
-
- if ($a->argc > 2) {
- for ($x = 2; $x < $a->argc; $x ++) {
- if (DI::dtFormat()->isYearMonth($a->argv[$x])) {
- if ($datequery) {
- $datequery2 = Strings::escapeHtml($a->argv[$x]);
- } else {
- $datequery = Strings::escapeHtml($a->argv[$x]);
- }
- } else {
- $category = $a->argv[$x];
- }
- }
- }
-
- if (empty($category)) {
- $category = $_GET['category'] ?? '';
- }
-
- $hashtags = $_GET['tag'] ?? '';
-
- if (DI::config()->get('system', 'block_public') && !local_user() && !Session::getRemoteContactID($a->profile['uid'])) {
- return Login::form();
- }
-
- $o = '';
-
- if ($update) {
- // Ensure we've got a profile owner if updating.
- $a->profile['uid'] = $update;
- } elseif ($a->profile['uid'] == local_user()) {
- Nav::setSelected('home');
- }
-
- $remote_contact = Session::getRemoteContactID($a->profile['uid']);
- $is_owner = local_user() == $a->profile['uid'];
- $last_updated_key = "profile:" . $a->profile['uid'] . ":" . local_user() . ":" . $remote_contact;
-
- if (!empty($a->profile['hidewall']) && !$is_owner && !$remote_contact) {
- notice(DI::l10n()->t('Access to this profile has been restricted.') . EOL);
- return '';
- }
-
- if (!$update) {
- $tab = Strings::escapeTags(trim($_GET['tab'] ?? ''));
-
- $o .= ProfileModel::getTabs($a, $tab, $is_owner, $a->profile['nickname']);
-
- if ($tab === 'profile') {
- $o .= ProfileModel::getAdvanced($a);
- Hook::callAll('profile_advanced', $o);
- return $o;
- }
-
- $o .= Widget::commonFriendsVisitor($a->profile['uid']);
-
- $commpage = $a->profile['page-flags'] == User::PAGE_FLAGS_COMMUNITY;
- $commvisitor = $commpage && $remote_contact;
-
- DI::page()['aside'] .= Widget::postedByYear(DI::baseUrl()->get(true) . '/profile/' . $a->profile['nickname'], $a->profile['uid'] ?? 0, true);
- DI::page()['aside'] .= Widget::categories(DI::baseUrl()->get(true) . '/profile/' . $a->profile['nickname'], XML::escape($category));
- DI::page()['aside'] .= Widget::tagCloud();
-
- if (Security::canWriteToUserWall($a->profile['uid'])) {
- $x = [
- 'is_owner' => $is_owner,
- 'allow_location' => ($is_owner || $commvisitor) && $a->profile['allow_location'],
- 'default_location' => $is_owner ? $a->user['default-location'] : '',
- 'nickname' => $a->profile['nickname'],
- 'lockstate' => is_array($a->user)
- && (strlen($a->user['allow_cid'])
- || strlen($a->user['allow_gid'])
- || strlen($a->user['deny_cid'])
- || strlen($a->user['deny_gid'])
- ) ? 'lock' : 'unlock',
- 'acl' => $is_owner ? ACL::getFullSelectorHTML(DI::page(), $a->user, true) : '',
- 'bang' => '',
- 'visitor' => $is_owner || $commvisitor ? 'block' : 'none',
- 'profile_uid' => $a->profile['uid'],
- ];
-
- $o .= status_editor($a, $x);
- }
- }
-
- // Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups
- $sql_extra = Item::getPermissionsSQLByUserId($a->profile['uid']);
- $sql_extra2 = '';
-
- $last_updated_array = Session::get('last_updated', []);
-
- if ($update) {
- $last_updated = $last_updated_array[$last_updated_key] ?? 0;
-
- // If the page user is the owner of the page we should query for unseen
- // items. Otherwise use a timestamp of the last succesful update request.
- if ($is_owner || !$last_updated) {
- $sql_extra4 = " AND `item`.`unseen`";
- } else {
- $gmupdate = gmdate(DateTimeFormat::MYSQL, $last_updated);
- $sql_extra4 = " AND `item`.`received` > '" . $gmupdate . "'";
- }
-
- $items_stmt = DBA::p(
- "SELECT DISTINCT(`parent-uri`) AS `uri`, `item`.`created`
- FROM `item`
- INNER JOIN `contact`
- ON `contact`.`id` = `item`.`contact-id`
- AND NOT `contact`.`blocked`
- AND NOT `contact`.`pending`
- WHERE `item`.`uid` = ?
- AND `item`.`visible`
- AND (NOT `item`.`deleted` OR `item`.`gravity` = ?)
- AND NOT `item`.`moderated`
- AND `item`.`wall`
- $sql_extra4
- $sql_extra
- ORDER BY `item`.`received` DESC",
- $a->profile['uid'],
- GRAVITY_ACTIVITY
- );
-
- if (!DBA::isResult($items_stmt)) {
- return '';
- }
-
- $pager = new Pager(DI::args()->getQueryString());
- } else {
- $sql_post_table = "";
-
- if (!empty($category)) {
- $sql_post_table = sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ",
- DBA::escape(Strings::protectSprintf($category)), intval(TERM_OBJ_POST), intval(TERM_CATEGORY), intval($a->profile['uid']));
- }
-
- if (!empty($hashtags)) {
- $sql_post_table .= sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ",
- DBA::escape(Strings::protectSprintf($hashtags)), intval(TERM_OBJ_POST), intval(TERM_HASHTAG), intval($a->profile['uid']));
- }
-
- if (!empty($datequery)) {
- $sql_extra2 .= Strings::protectSprintf(sprintf(" AND `thread`.`received` <= '%s' ", DBA::escape(DateTimeFormat::convert($datequery, 'UTC', date_default_timezone_get()))));
- }
- if (!empty($datequery2)) {
- $sql_extra2 .= Strings::protectSprintf(sprintf(" AND `thread`.`received` >= '%s' ", DBA::escape(DateTimeFormat::convert($datequery2, 'UTC', date_default_timezone_get()))));
- }
-
- // Does the profile page belong to a forum?
- // If not then we can improve the performance with an additional condition
- $condition = ['uid' => $a->profile['uid'], 'page-flags' => [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP]];
- if (!DBA::exists('user', $condition)) {
- $sql_extra3 = sprintf(" AND `thread`.`contact-id` = %d ", intval(intval($a->profile['contact_id'])));
- } else {
- $sql_extra3 = "";
- }
-
- // check if we serve a mobile device and get the user settings
- // accordingly
- if (DI::mode()->isMobile()) {
- $itemspage_network = DI::pConfig()->get(local_user(), 'system', 'itemspage_mobile_network', 10);
- } else {
- $itemspage_network = DI::pConfig()->get(local_user(), 'system', 'itemspage_network', 20);
- }
-
- // now that we have the user settings, see if the theme forces
- // a maximum item number which is lower then the user choice
- if (($a->force_max_items > 0) && ($a->force_max_items < $itemspage_network)) {
- $itemspage_network = $a->force_max_items;
- }
-
- $pager = new Pager(DI::args()->getQueryString(), $itemspage_network);
-
- $pager_sql = sprintf(" LIMIT %d, %d ", $pager->getStart(), $pager->getItemsPerPage());
-
- $items_stmt = DBA::p(
- "SELECT `item`.`uri`
- FROM `thread`
- STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid`
- $sql_post_table
- STRAIGHT_JOIN `contact`
- ON `contact`.`id` = `thread`.`contact-id`
- AND NOT `contact`.`blocked`
- AND NOT `contact`.`pending`
- WHERE `thread`.`uid` = ?
- AND `thread`.`visible`
- AND NOT `thread`.`deleted`
- AND NOT `thread`.`moderated`
- AND `thread`.`wall`
- $sql_extra3
- $sql_extra
- $sql_extra2
- ORDER BY `thread`.`received` DESC
- $pager_sql",
- $a->profile['uid']
- );
- }
-
- // Set a time stamp for this page. We will make use of it when we
- // search for new items (update routine)
- $last_updated_array[$last_updated_key] = time();
- Session::set('last_updated', $last_updated_array);
-
- if ($is_owner && !$update && !DI::config()->get('theme', 'hide_eventlist')) {
- $o .= ProfileModel::getBirthdays();
- $o .= ProfileModel::getEventsReminderHTML();
- }
-
- if ($is_owner) {
- $unseen = Item::exists(['wall' => true, 'unseen' => true, 'uid' => local_user()]);
- if ($unseen) {
- Item::update(['unseen' => false], ['wall' => true, 'unseen' => true, 'uid' => local_user()]);
- }
- }
-
- $items = DBA::toArray($items_stmt);
-
- if ($pager->getStart() == 0 && !empty($a->profile['uid'])) {
- $pinned_items = Item::selectPinned($a->profile['uid'], ['uri', 'pinned'], ['true' . $sql_extra]);
- $pinned = Item::inArray($pinned_items);
- $items = array_merge($items, $pinned);
- }
-
- $o .= conversation($a, $items, $pager, 'profile', $update, false, 'pinned_received', $a->profile['uid']);
-
- if (!$update) {
- $o .= $pager->renderMinimal(count($items));
- }
-
- return $o;
- }
-}
namespace Friendica\Module\Profile;
-use Friendica\BaseModule;
use Friendica\Content\ContactSelector;
use Friendica\Content\Nav;
use Friendica\Content\Pager;
use Friendica\DI;
use Friendica\Model\Contact;
use Friendica\Model\Profile;
+use Friendica\Module\BaseProfile;
use Friendica\Util\Proxy as ProxyUtils;
-class Contacts extends BaseModule
+class Contacts extends BaseProfile
{
public static function content(array $parameters = [])
{
$is_owner = $a->profile['uid'] == local_user();
- // tabs
- $o = Profile::getTabs($a, 'contacts', $is_owner, $nickname);
+ $o = self::getTabsHTML($a, 'contacts', $is_owner, $nickname);
if (!count($a->profile) || $a->profile['hide-friends']) {
notice(DI::l10n()->t('Permission denied.') . EOL);
--- /dev/null
+<?php
+
+namespace Friendica\Module\Profile;
+
+use Friendica\BaseModule;
+
+/**
+ * Profile index router
+ *
+ * The default profile path (https://domain.tld/profile/nickname) has to serve the profile data when queried as an
+ * ActivityPub endpoint, but it should show statuses to web users.
+ *
+ * Both these view have dedicated sub-paths,
+ * respectively https://domain.tld/profile/nickname/profile and https://domain.tld/profile/nickname/status
+ */
+class Index extends BaseModule
+{
+ public static function rawContent(array $parameters = [])
+ {
+ Profile::rawContent($parameters);
+ }
+
+ public static function content(array $parameters = [])
+ {
+ return Status::content($parameters);
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Module\Profile;
+
+use Friendica\Content\Feature;
+use Friendica\Content\ForumManager;
+use Friendica\Content\Nav;
+use Friendica\Content\Text\BBCode;
+use Friendica\Content\Text\HTML;
+use Friendica\Core\Hook;
+use Friendica\Core\Protocol;
+use Friendica\Core\Renderer;
+use Friendica\Core\Session;
+use Friendica\Core\System;
+use Friendica\Database\DBA;
+use Friendica\DI;
+use Friendica\Model\Contact;
+use Friendica\Model\Profile as ProfileModel;
+use Friendica\Model\Term;
+use Friendica\Model\User;
+use Friendica\Module\BaseProfile;
+use Friendica\Module\Security\Login;
+use Friendica\Network\HTTPException;
+use Friendica\Protocol\ActivityPub;
+use Friendica\Util\DateTimeFormat;
+use Friendica\Util\Temporal;
+
+class Profile extends BaseProfile
+{
+ public static function rawContent(array $parameters = [])
+ {
+ if (ActivityPub::isRequest()) {
+ $user = DBA::selectFirst('user', ['uid'], ['nickname' => $parameters['nickname']]);
+ if (DBA::isResult($user)) {
+ // The function returns an empty array when the account is removed, expired or blocked
+ $data = ActivityPub\Transmitter::getProfile($user['uid']);
+ if (!empty($data)) {
+ System::jsonExit($data, 'application/activity+json');
+ }
+ }
+
+ if (DBA::exists('userd', ['username' => $parameters['nickname']])) {
+ // Known deleted user
+ $data = ActivityPub\Transmitter::getDeletedUser($parameters['nickname']);
+
+ System::jsonError(410, $data);
+ } else {
+ // Any other case (unknown, blocked, nverified, expired, no profile, no self contact)
+ System::jsonError(404, []);
+ }
+ }
+ }
+
+ public static function content(array $parameters = [])
+ {
+ $a = DI::app();
+
+ ProfileModel::load($a, $parameters['nickname']);
+
+ if (!$a->profile) {
+ throw new HTTPException\NotFoundException(DI::l10n()->t('Profile not found.'));
+ }
+
+ $remote_contact_id = Session::getRemoteContactID($a->profile_uid);
+
+ if (DI::config()->get('system', 'block_public') && !local_user() && !$remote_contact_id) {
+ return Login::form();
+ }
+
+ $is_owner = local_user() == $a->profile_uid;
+
+ if (!empty($a->profile['hidewall']) && !$is_owner && !$remote_contact_id) {
+ throw new HTTPException\ForbiddenException(DI::l10n()->t('Access to this profile has been restricted.'));
+ }
+
+ if (!empty($a->profile['page-flags']) && $a->profile['page-flags'] == User::PAGE_FLAGS_COMMUNITY) {
+ DI::page()['htmlhead'] .= '<meta name="friendica.community" content="true" />' . "\n";
+ }
+
+ DI::page()['htmlhead'] .= self::buildHtmlHead($a->profile, $parameters['nickname'], $remote_contact_id);
+
+ Nav::setSelected('home');
+
+ $is_owner = local_user() == $a->profile['uid'];
+ $o = self::getTabsHTML($a, 'profile', $is_owner, $a->profile['nickname']);
+
+ if (!empty($a->profile['hidewall']) && !$is_owner && !$remote_contact_id) {
+ notice(DI::l10n()->t('Access to this profile has been restricted.'));
+ return '';
+ }
+
+ $view_as_contacts = [];
+ $view_as_contact_id = 0;
+ if ($is_owner) {
+ $view_as_contact_id = intval($_GET['viewas'] ?? 0);
+
+ $view_as_contacts = Contact::selectToArray(['id', 'name'], [
+ 'uid' => local_user(),
+ 'rel' => [Contact::FOLLOWER, Contact::SHARING, Contact::FRIEND],
+ 'network' => Protocol::DFRN,
+ 'blocked' => false,
+ ]);
+
+ // User manually provided a contact ID they aren't privy to, silently defaulting to their own view
+ if (!in_array($view_as_contact_id, array_column($view_as_contacts, 'id'))) {
+ $view_as_contact_id = 0;
+ }
+ }
+
+ $basic_fields = [];
+
+ $basic_fields += self::buildField('fullname', DI::l10n()->t('Full Name:'), $a->profile['name']);
+
+ if (Feature::isEnabled($a->profile_uid, 'profile_membersince')) {
+ $basic_fields += self::buildField(
+ 'membersince',
+ DI::l10n()->t('Member since:'),
+ DateTimeFormat::local($a->profile['register_date'])
+ );
+ }
+
+ if (!empty($a->profile['dob']) && $a->profile['dob'] > DBA::NULL_DATE) {
+ $year_bd_format = DI::l10n()->t('j F, Y');
+ $short_bd_format = DI::l10n()->t('j F');
+
+ $dob = DI::l10n()->getDay(
+ intval($a->profile['dob']) ?
+ DateTimeFormat::utc($a->profile['dob'] . ' 00:00 +00:00', $year_bd_format)
+ : DateTimeFormat::utc('2001-' . substr($a->profile['dob'], 5) . ' 00:00 +00:00', $short_bd_format)
+ );
+
+ $basic_fields += self::buildField('dob', DI::l10n()->t('Birthday:'), $dob);
+
+ if ($age = Temporal::getAgeByTimezone($a->profile['dob'], $a->profile['timezone'])) {
+ $basic_fields += self::buildField('age', DI::l10n()->t('Age: '), DI::l10n()->tt('%d year old', '%d years old', $age));
+ }
+ }
+
+ if ($a->profile['pdesc']) {
+ $basic_fields += self::buildField('pdesc', DI::l10n()->t('Description:'), HTML::toLink($a->profile['pdesc']));
+ }
+
+ if ($a->profile['xmpp']) {
+ $basic_fields += self::buildField('xmpp', DI::l10n()->t('XMPP:'), $a->profile['xmpp']);
+ }
+
+ if ($a->profile['homepage']) {
+ $basic_fields += self::buildField('homepage', DI::l10n()->t('Homepage:'), HTML::toLink($a->profile['homepage']));
+ }
+
+ if (
+ $a->profile['address']
+ || $a->profile['locality']
+ || $a->profile['postal-code']
+ || $a->profile['region']
+ || $a->profile['country-name']
+ ) {
+ $basic_fields += self::buildField('location', DI::l10n()->t('Location:'), ProfileModel::formatLocation($a->profile));
+ }
+
+ if ($a->profile['pub_keywords']) {
+ $tags = [];
+ foreach (explode(',', $a->profile['pub_keywords']) as $tag_label) {
+ $tags[] = [
+ 'url' => '/search?tag=' . $tag_label,
+ 'label' => Term::TAG_CHARACTER[Term::HASHTAG] . $tag_label,
+ ];
+ }
+
+ $basic_fields += self::buildField('pub_keywords', DI::l10n()->t('Tags:'), $tags);
+ }
+
+ $custom_fields = [];
+
+ // Defaults to the current logged in user self contact id to show self-only fields
+ $contact_id = $view_as_contact_id ?: $remote_contact_id ?: 0;
+
+ if ($is_owner && $contact_id === 0) {
+ $profile_fields = DI::profileField()->selectByUserId($a->profile_uid);
+ } else {
+ $profile_fields = DI::profileField()->selectByContactId($contact_id, $a->profile_uid);
+ }
+
+ foreach ($profile_fields as $profile_field) {
+ $custom_fields += self::buildField(
+ 'custom_' . $profile_field->order,
+ $profile_field->label,
+ BBCode::convert($profile_field->value),
+ 'aprofile custom'
+ );
+ };
+
+ //show subcribed forum if it is enabled in the usersettings
+ if (Feature::isEnabled($a->profile_uid, 'forumlist_profile')) {
+ $custom_fields += self::buildField(
+ 'forumlist',
+ DI::l10n()->t('Forums:'),
+ ForumManager::profileAdvanced($a->profile_uid)
+ );
+ }
+
+ $tpl = Renderer::getMarkupTemplate('profile/index.tpl');
+ $o .= Renderer::replaceMacros($tpl, [
+ '$title' => DI::l10n()->t('Profile'),
+ '$view_as_contacts' => $view_as_contacts,
+ '$view_as_contact_id' => $view_as_contact_id,
+ '$view_as' => DI::l10n()->t('View profile as:'),
+ '$basic' => DI::l10n()->t('Basic'),
+ '$advanced' => DI::l10n()->t('Advanced'),
+ '$is_owner' => $a->profile_uid == local_user(),
+ '$query_string' => DI::args()->getQueryString(),
+ '$basic_fields' => $basic_fields,
+ '$custom_fields' => $custom_fields,
+ '$profile' => $a->profile,
+ '$edit_link' => [
+ 'url' => DI::baseUrl() . '/settings/profile', DI::l10n()->t('Edit profile'),
+ 'title' => '',
+ 'label' => DI::l10n()->t('Edit profile')
+ ],
+ ]);
+
+ Hook::callAll('profile_advanced', $o);
+
+ return $o;
+ }
+
+ /**
+ * Creates a profile field structure to be used in the profile template
+ *
+ * @param string $name Arbitrary name of the field
+ * @param string $label Display label of the field
+ * @param mixed $value Display value of the field
+ * @param string $class Optional CSS class to apply to the field
+ * @return array
+ */
+ private static function buildField(string $name, string $label, $value, string $class = 'aprofile')
+ {
+ return [$name => [
+ 'id' => 'aprofile-' . $name,
+ 'class' => $class,
+ 'label' => $label,
+ 'value' => $value,
+ ]];
+ }
+
+ private static function buildHtmlHead(array $profile, string $nickname, int $remote_contact_id)
+ {
+ $baseUrl = DI::baseUrl();
+
+ $htmlhead = "\n";
+
+ if (!empty($profile['page-flags']) && $profile['page-flags'] == User::PAGE_FLAGS_COMMUNITY) {
+ $htmlhead .= '<meta name="friendica.community" content="true" />' . "\n";
+ }
+
+ if (!empty($profile['openidserver'])) {
+ $htmlhead .= '<link rel="openid.server" href="' . $profile['openidserver'] . '" />' . "\n";
+ }
+
+ if (!empty($profile['openid'])) {
+ $delegate = strstr($profile['openid'], '://') ? $profile['openid'] : 'https://' . $profile['openid'];
+ $htmlhead .= '<link rel="openid.delegate" href="' . $delegate . '" />' . "\n";
+ }
+
+ // site block
+ $blocked = !local_user() && !$remote_contact_id && DI::config()->get('system', 'block_public');
+ $userblock = !local_user() && !$remote_contact_id && $profile['hidewall'];
+ if (!$blocked && !$userblock) {
+ $keywords = str_replace(['#', ',', ' ', ',,'], ['', ' ', ',', ','], $profile['pub_keywords'] ?? '');
+ if (strlen($keywords)) {
+ $htmlhead .= '<meta name="keywords" content="' . $keywords . '" />' . "\n";
+ }
+ }
+
+ $htmlhead .= '<meta name="dfrn-global-visibility" content="' . ($profile['net-publish'] ? 'true' : 'false') . '" />' . "\n";
+
+ if (!$profile['net-publish'] || $profile['hidewall']) {
+ $htmlhead .= '<meta content="noindex, noarchive" name="robots" />' . "\n";
+ }
+
+ $htmlhead .= '<link rel="alternate" type="application/atom+xml" href="' . $baseUrl . '/dfrn_poll/' . $nickname . '" title="DFRN: ' . DI::l10n()->t('%s\'s timeline', $profile['username']) . '"/>' . "\n";
+ $htmlhead .= '<link rel="alternate" type="application/atom+xml" href="' . $baseUrl . '/feed/' . $nickname . '/" title="' . DI::l10n()->t('%s\'s posts', $profile['username']) . '"/>' . "\n";
+ $htmlhead .= '<link rel="alternate" type="application/atom+xml" href="' . $baseUrl . '/feed/' . $nickname . '/comments" title="' . DI::l10n()->t('%s\'s comments', $profile['username']) . '"/>' . "\n";
+ $htmlhead .= '<link rel="alternate" type="application/atom+xml" href="' . $baseUrl . '/feed/' . $nickname . '/activity" title="' . DI::l10n()->t('%s\'s timeline', $profile['username']) . '"/>' . "\n";
+ $uri = urlencode('acct:' . $profile['nickname'] . '@' . $baseUrl->getHostname() . ($baseUrl->getUrlPath() ? '/' . $baseUrl->getUrlPath() : ''));
+ $htmlhead .= '<link rel="lrdd" type="application/xrd+xml" href="' . $baseUrl . '/xrd/?uri=' . $uri . '" />' . "\n";
+ header('Link: <' . $baseUrl . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false);
+
+ $dfrn_pages = ['request', 'confirm', 'notify', 'poll'];
+ foreach ($dfrn_pages as $dfrn) {
+ $htmlhead .= '<link rel="dfrn-' . $dfrn . '" href="' . $baseUrl . '/dfrn_' . $dfrn . '/' . $nickname . '" />' . "\n";
+ }
+ $htmlhead .= '<link rel="dfrn-poco" href="' . $baseUrl . '/poco/' . $nickname . '" />' . "\n";
+
+ return $htmlhead;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Module\Profile;
+
+use Friendica\Content\Nav;
+use Friendica\Content\Pager;
+use Friendica\Content\Widget;
+use Friendica\Core\ACL;
+use Friendica\Core\Session;
+use Friendica\Database\DBA;
+use Friendica\DI;
+use Friendica\Model\Item;
+use Friendica\Model\Profile as ProfileModel;
+use Friendica\Model\User;
+use Friendica\Module\BaseProfile;
+use Friendica\Module\Security\Login;
+use Friendica\Util\DateTimeFormat;
+use Friendica\Util\Security;
+use Friendica\Util\Strings;
+use Friendica\Util\XML;
+
+class Status extends BaseProfile
+{
+ public static function content(array $parameters = [])
+ {
+ $args = DI::args();
+
+ $a = DI::app();
+
+ ProfileModel::load($a, $parameters['nickname']);
+
+ if (!$a->profile['net-publish'] || $a->profile['hidewall']) {
+ DI::page()['htmlhead'] .= '<meta content="noindex, noarchive" name="robots" />' . "\n";
+ }
+
+ DI::page()['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . DI::baseUrl() . '/dfrn_poll/' . $parameters['nickname'] . '" title="DFRN: ' . DI::l10n()->t('%s\'s timeline', $a->profile['username']) . '"/>' . "\n";
+ DI::page()['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . DI::baseUrl() . '/feed/' . $parameters['nickname'] . '/" title="' . DI::l10n()->t('%s\'s posts', $a->profile['username']) . '"/>' . "\n";
+ DI::page()['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . DI::baseUrl() . '/feed/' . $parameters['nickname'] . '/comments" title="' . DI::l10n()->t('%s\'s comments', $a->profile['username']) . '"/>' . "\n";
+ DI::page()['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . DI::baseUrl() . '/feed/' . $parameters['nickname'] . '/activity" title="' . DI::l10n()->t('%s\'s timeline', $a->profile['username']) . '"/>' . "\n";
+
+ $category = $datequery = $datequery2 = '';
+
+ $dtFormat = DI::dtFormat();
+
+ if ($args->getArgc() > 3) {
+ for ($x = 3; $x < $args->getArgc(); $x++) {
+ if ($dtFormat->isYearMonth($args->get($x))) {
+ if ($datequery) {
+ $datequery2 = Strings::escapeHtml($args->get($x));
+ } else {
+ $datequery = Strings::escapeHtml($args->get($x));
+ }
+ } else {
+ $category = $args->get($x);
+ }
+ }
+ }
+
+ if (empty($category)) {
+ $category = $_GET['category'] ?? '';
+ }
+
+ $hashtags = $_GET['tag'] ?? '';
+
+ if (DI::config()->get('system', 'block_public') && !local_user() && !Session::getRemoteContactID($a->profile['uid'])) {
+ return Login::form();
+ }
+
+ $o = '';
+
+ if ($a->profile['uid'] == local_user()) {
+ Nav::setSelected('home');
+ }
+
+ $remote_contact = Session::getRemoteContactID($a->profile['uid']);
+ $is_owner = local_user() == $a->profile['uid'];
+ $last_updated_key = "profile:" . $a->profile['uid'] . ":" . local_user() . ":" . $remote_contact;
+
+ if (!empty($a->profile['hidewall']) && !$is_owner && !$remote_contact) {
+ notice(DI::l10n()->t('Access to this profile has been restricted.') . EOL);
+ return '';
+ }
+
+ $o .= self::getTabsHTML($a, 'status', $is_owner, $a->profile['nickname']);
+
+ $o .= Widget::commonFriendsVisitor($a->profile['uid']);
+
+ $commpage = $a->profile['page-flags'] == User::PAGE_FLAGS_COMMUNITY;
+ $commvisitor = $commpage && $remote_contact;
+
+ DI::page()['aside'] .= Widget::postedByYear(DI::baseUrl() . '/profile/' . $a->profile['nickname'] . '/status', $a->profile['profile_uid'] ?? 0, true);
+ DI::page()['aside'] .= Widget::categories(DI::baseUrl() . '/profile/' . $a->profile['nickname'] . '/status', XML::escape($category));
+ DI::page()['aside'] .= Widget::tagCloud();
+
+ if (Security::canWriteToUserWall($a->profile['uid'])) {
+ $x = [
+ 'is_owner' => $is_owner,
+ 'allow_location' => ($is_owner || $commvisitor) && $a->profile['allow_location'],
+ 'default_location' => $is_owner ? $a->user['default-location'] : '',
+ 'nickname' => $a->profile['nickname'],
+ 'lockstate' => is_array($a->user)
+ && (strlen($a->user['allow_cid'])
+ || strlen($a->user['allow_gid'])
+ || strlen($a->user['deny_cid'])
+ || strlen($a->user['deny_gid'])
+ ) ? 'lock' : 'unlock',
+ 'acl' => $is_owner ? ACL::getFullSelectorHTML(DI::page(), $a->user, true) : '',
+ 'bang' => '',
+ 'visitor' => $is_owner || $commvisitor ? 'block' : 'none',
+ 'profile_uid' => $a->profile['uid'],
+ ];
+
+ $o .= status_editor($a, $x);
+ }
+
+ // Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups
+ $sql_extra = Item::getPermissionsSQLByUserId($a->profile['uid']);
+ $sql_extra2 = '';
+
+ $last_updated_array = Session::get('last_updated', []);
+
+ $sql_post_table = "";
+
+ if (!empty($category)) {
+ $sql_post_table = sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ",
+ DBA::escape(Strings::protectSprintf($category)), intval(TERM_OBJ_POST), intval(TERM_CATEGORY), intval($a->profile['uid']));
+ }
+
+ if (!empty($hashtags)) {
+ $sql_post_table .= sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ",
+ DBA::escape(Strings::protectSprintf($hashtags)), intval(TERM_OBJ_POST), intval(TERM_HASHTAG), intval($a->profile['uid']));
+ }
+
+ if (!empty($datequery)) {
+ $sql_extra2 .= Strings::protectSprintf(sprintf(" AND `thread`.`received` <= '%s' ", DBA::escape(DateTimeFormat::convert($datequery, 'UTC', date_default_timezone_get()))));
+ }
+ if (!empty($datequery2)) {
+ $sql_extra2 .= Strings::protectSprintf(sprintf(" AND `thread`.`received` >= '%s' ", DBA::escape(DateTimeFormat::convert($datequery2, 'UTC', date_default_timezone_get()))));
+ }
+
+ // Does the profile page belong to a forum?
+ // If not then we can improve the performance with an additional condition
+ $condition = ['uid' => $a->profile['uid'], 'page-flags' => [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP]];
+ if (!DBA::exists('user', $condition)) {
+ $sql_extra3 = sprintf(" AND `thread`.`contact-id` = %d ", intval(intval($a->profile['contact_id'])));
+ } else {
+ $sql_extra3 = "";
+ }
+
+ // check if we serve a mobile device and get the user settings
+ // accordingly
+ if (DI::mode()->isMobile()) {
+ $itemspage_network = DI::pConfig()->get(local_user(), 'system', 'itemspage_mobile_network', 10);
+ } else {
+ $itemspage_network = DI::pConfig()->get(local_user(), 'system', 'itemspage_network', 20);
+ }
+
+ // now that we have the user settings, see if the theme forces
+ // a maximum item number which is lower then the user choice
+ if (($a->force_max_items > 0) && ($a->force_max_items < $itemspage_network)) {
+ $itemspage_network = $a->force_max_items;
+ }
+
+ $pager = new Pager($args->getQueryString(), $itemspage_network);
+
+ $pager_sql = sprintf(" LIMIT %d, %d ", $pager->getStart(), $pager->getItemsPerPage());
+
+ $items_stmt = DBA::p(
+ "SELECT `item`.`uri`
+ FROM `thread`
+ STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid`
+ $sql_post_table
+ STRAIGHT_JOIN `contact`
+ ON `contact`.`id` = `thread`.`contact-id`
+ AND NOT `contact`.`blocked`
+ AND NOT `contact`.`pending`
+ WHERE `thread`.`uid` = ?
+ AND `thread`.`visible`
+ AND NOT `thread`.`deleted`
+ AND NOT `thread`.`moderated`
+ AND `thread`.`wall`
+ $sql_extra3
+ $sql_extra
+ $sql_extra2
+ ORDER BY `thread`.`received` DESC
+ $pager_sql",
+ $a->profile['uid']
+ );
+
+ // Set a time stamp for this page. We will make use of it when we
+ // search for new items (update routine)
+ $last_updated_array[$last_updated_key] = time();
+ Session::set('last_updated', $last_updated_array);
+
+ if ($is_owner && !DI::config()->get('theme', 'hide_eventlist')) {
+ $o .= ProfileModel::getBirthdays();
+ $o .= ProfileModel::getEventsReminderHTML();
+ }
+
+ if ($is_owner) {
+ $unseen = Item::exists(['wall' => true, 'unseen' => true, 'uid' => local_user()]);
+ if ($unseen) {
+ Item::update(['unseen' => false], ['wall' => true, 'unseen' => true, 'uid' => local_user()]);
+ }
+ }
+
+ $items = DBA::toArray($items_stmt);
+
+ if ($pager->getStart() == 0 && !empty($a->profile['uid'])) {
+ $pinned_items = Item::selectPinned($a->profile['uid'], ['uri', 'pinned']);
+ $pinned = Item::inArray($pinned_items);
+ $items = array_merge($items, $pinned);
+ }
+
+ $o .= conversation($a, $items, $pager, 'profile', false, false, 'pinned_received', $a->profile['uid']);
+
+ $o .= $pager->renderMinimal(count($items));
+
+ return $o;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Module\Settings\Profile;
+
+use Friendica\Core\ACL;
+use Friendica\Core\Hook;
+use Friendica\Core\Protocol;
+use Friendica\Core\Renderer;
+use Friendica\Core\Session;
+use Friendica\Core\Theme;
+use Friendica\Core\Worker;
+use Friendica\Database\DBA;
+use Friendica\DI;
+use Friendica\Model\Contact;
+use Friendica\Model\GContact;
+use Friendica\Model\Profile;
+use Friendica\Model\ProfileField;
+use Friendica\Model\User;
+use Friendica\Module\BaseSettingsModule;
+use Friendica\Module\Security\Login;
+use Friendica\Network\HTTPException;
+use Friendica\Util\DateTimeFormat;
+use Friendica\Util\Strings;
+use Friendica\Util\Temporal;
+
+class Index extends BaseSettingsModule
+{
+ public static function post(array $parameters = [])
+ {
+ if (!local_user()) {
+ return;
+ }
+
+ $profile = Profile::getByUID(local_user());
+ if (!DBA::isResult($profile)) {
+ return;
+ }
+
+ self::checkFormSecurityTokenRedirectOnError('/settings/profile', 'settings_profile');
+
+ Hook::callAll('profile_post', $_POST);
+
+ $dob = Strings::escapeHtml(trim($_POST['dob'] ?? '0000-00-00'));
+
+ $y = substr($dob, 0, 4);
+ if ((!ctype_digit($y)) || ($y < 1900)) {
+ $ignore_year = true;
+ } else {
+ $ignore_year = false;
+ }
+
+ if (!in_array($dob, ['0000-00-00', DBA::NULL_DATE])) {
+ if (strpos($dob, '0000-') === 0 || strpos($dob, '0001-') === 0) {
+ $ignore_year = true;
+ $dob = substr($dob, 5);
+ }
+
+ if ($ignore_year) {
+ $dob = '0000-' . DateTimeFormat::utc('1900-' . $dob, 'm-d');
+ } else {
+ $dob = DateTimeFormat::utc($dob, 'Y-m-d');
+ }
+ }
+
+ $name = Strings::escapeTags(trim($_POST['name'] ?? ''));
+ if (!strlen($name)) {
+ notice(DI::l10n()->t('Profile Name is required.'));
+ return;
+ }
+
+ $namechanged = $profile['name'] != $name;
+
+ $pdesc = Strings::escapeTags(trim($_POST['pdesc']));
+ $address = Strings::escapeTags(trim($_POST['address']));
+ $locality = Strings::escapeTags(trim($_POST['locality']));
+ $region = Strings::escapeTags(trim($_POST['region']));
+ $postal_code = Strings::escapeTags(trim($_POST['postal_code']));
+ $country_name = Strings::escapeTags(trim($_POST['country_name']));
+ $pub_keywords = self::cleanKeywords(Strings::escapeTags(trim($_POST['pub_keywords'])));
+ $prv_keywords = self::cleanKeywords(Strings::escapeTags(trim($_POST['prv_keywords'])));
+ $xmpp = Strings::escapeTags(trim($_POST['xmpp']));
+ $homepage = Strings::escapeTags(trim($_POST['homepage']));
+ if ((strpos($homepage, 'http') !== 0) && (strlen($homepage))) {
+ // neither http nor https in URL, add them
+ $homepage = 'http://' . $homepage;
+ }
+
+ $hide_friends = intval(!empty($_POST['hide-friends']));
+
+ $profileFields = DI::profileField()->selectByUserId(local_user());
+
+ $profileFields = DI::profileField()->updateCollectionFromForm(
+ local_user(),
+ $profileFields,
+ $_REQUEST['profile_field'],
+ $_REQUEST['profile_field_order']
+ );
+
+ DI::profileField()->saveCollection($profileFields);
+
+ $result = DBA::update(
+ 'profile',
+ [
+ 'name' => $name,
+ 'pdesc' => $pdesc,
+ 'dob' => $dob,
+ 'address' => $address,
+ 'locality' => $locality,
+ 'region' => $region,
+ 'postal-code' => $postal_code,
+ 'country-name' => $country_name,
+ 'xmpp' => $xmpp,
+ 'homepage' => $homepage,
+ 'pub_keywords' => $pub_keywords,
+ 'prv_keywords' => $prv_keywords,
+ 'hide-friends' => $hide_friends,
+ ],
+ ['uid' => local_user()]
+ );
+
+ if ($result) {
+ info(DI::l10n()->t('Profile updated.'));
+ } else {
+ notice(DI::l10n()->t('Profile couldn\'t be updated.'));
+ return;
+ }
+
+ if ($namechanged) {
+ DBA::update('user', ['username' => $name], ['uid' => local_user()]);
+ }
+
+ Contact::updateSelfFromUserID(local_user());
+
+ // Update global directory in background
+ if (Session::get('my_url') && strlen(DI::config()->get('system', 'directory'))) {
+ Worker::add(PRIORITY_LOW, 'Directory', Session::get('my_url'));
+ }
+
+ Worker::add(PRIORITY_LOW, 'ProfileUpdate', local_user());
+
+ // Update the global contact for the user
+ GContact::updateForUser(local_user());
+ }
+
+ public static function content(array $parameters = [])
+ {
+ if (!local_user()) {
+ notice(DI::l10n()->t('You must be logged in to use this module'));
+ return Login::form();
+ }
+
+ parent::content();
+
+ $o = '';
+
+ $profile = Profile::getByUID(local_user());
+ if (!DBA::isResult($profile)) {
+ throw new HTTPException\NotFoundException();
+ }
+
+ $a = DI::app();
+
+ DI::page()->registerFooterScript('view/asset/es-jquery-sortable/source/js/jquery-sortable-min.js');
+ DI::page()->registerFooterScript(Theme::getPathForFile('js/module/settings/profile/index.js'));
+
+ $custom_fields = [];
+
+ $profileFields = DI::profileField()->selectByUserId(local_user());
+ foreach ($profileFields as $profileField) {
+ /** @var ProfileField $profileField */
+ $defaultPermissions = ACL::getDefaultUserPermissions($profileField->permissionset->toArray());
+
+ $custom_fields[] = [
+ 'id' => $profileField->id,
+ 'legend' => $profileField->label,
+ 'fields' => [
+ 'label' => ['profile_field[' . $profileField->id . '][label]', DI::l10n()->t('Label:'), $profileField->label],
+ 'value' => ['profile_field[' . $profileField->id . '][value]', DI::l10n()->t('Value:'), $profileField->value],
+ 'acl' => ACL::getFullSelectorHTML(
+ DI::page(),
+ $a->user,
+ false,
+ $defaultPermissions,
+ ['network' => Protocol::DFRN],
+ 'profile_field[' . $profileField->id . ']'
+ ),
+ ],
+ 'permissions' => DI::l10n()->t('Field Permissions'),
+ 'permdesc' => DI::l10n()->t("(click to open/close)"),
+ ];
+ };
+
+ $custom_fields[] = [
+ 'id' => 'new',
+ 'legend' => DI::l10n()->t('Add a new profile field'),
+ 'fields' => [
+ 'label' => ['profile_field[new][label]', DI::l10n()->t('Label:')],
+ 'value' => ['profile_field[new][value]', DI::l10n()->t('Value:')],
+ 'acl' => ACL::getFullSelectorHTML(
+ DI::page(),
+ $a->user,
+ false,
+ ['allow_cid' => []],
+ ['network' => Protocol::DFRN],
+ 'profile_field[new]'
+ ),
+ ],
+ 'permissions' => DI::l10n()->t('Field Permissions'),
+ 'permdesc' => DI::l10n()->t("(click to open/close)"),
+ ];
+
+ DI::page()['htmlhead'] .= Renderer::replaceMacros(Renderer::getMarkupTemplate('settings/profile/index_head.tpl'), [
+ '$baseurl' => DI::baseUrl()->get(true),
+ ]);
+
+ $opt_tpl = Renderer::getMarkupTemplate('settings/profile/hide-friends.tpl');
+ $hide_friends = Renderer::replaceMacros($opt_tpl, [
+ '$yesno' => [
+ 'hide-friends', //Name
+ DI::l10n()->t('Hide contacts and friends:'), //Label
+ !!$profile['hide-friends'], //Value
+ '', //Help string
+ [DI::l10n()->t('No'), DI::l10n()->t('Yes')] //Off - On strings
+ ],
+ '$desc' => DI::l10n()->t('Hide your contact/friend list from viewers of this profile?'),
+ '$yes_str' => DI::l10n()->t('Yes'),
+ '$no_str' => DI::l10n()->t('No'),
+ '$yes_selected' => (($profile['hide-friends']) ? ' checked="checked"' : ''),
+ '$no_selected' => (($profile['hide-friends'] == 0) ? ' checked="checked"' : '')
+ ]);
+
+ $personal_account = !in_array($a->user['page-flags'], [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP]);
+
+ $tpl = Renderer::getMarkupTemplate('settings/profile/index.tpl');
+ $o .= Renderer::replaceMacros($tpl, [
+ '$personal_account' => $personal_account,
+
+ '$form_security_token' => self::getFormSecurityToken('settings_profile'),
+ '$form_security_token_photo' => self::getFormSecurityToken('settings_profile_photo'),
+
+ '$profile_action' => DI::l10n()->t('Profile Actions'),
+ '$banner' => DI::l10n()->t('Edit Profile Details'),
+ '$submit' => DI::l10n()->t('Submit'),
+ '$profpic' => DI::l10n()->t('Change Profile Photo'),
+ '$profpiclink' => '/photos/' . $a->user['nickname'],
+ '$viewprof' => DI::l10n()->t('View this profile'),
+
+ '$lbl_personal_section' => DI::l10n()->t('Personal'),
+ '$lbl_picture_section' => DI::l10n()->t('Profile picture'),
+ '$lbl_location_section' => DI::l10n()->t('Location'),
+ '$lbl_miscellaneous_section' => DI::l10n()->t('Miscellaneous'),
+ '$lbl_custom_fields_section' => DI::l10n()->t('Custom Profile Fields'),
+
+ '$lbl_profile_photo' => DI::l10n()->t('Upload Profile Photo'),
+
+ '$baseurl' => DI::baseUrl()->get(true),
+ '$nickname' => $a->user['nickname'],
+ '$name' => ['name', DI::l10n()->t('Display name:'), $profile['name']],
+ '$pdesc' => ['pdesc', DI::l10n()->t('Title/Description:'), $profile['pdesc']],
+ '$dob' => Temporal::getDateofBirthField($profile['dob'], $a->user['timezone']),
+ '$hide_friends' => $hide_friends,
+ '$address' => ['address', DI::l10n()->t('Street Address:'), $profile['address']],
+ '$locality' => ['locality', DI::l10n()->t('Locality/City:'), $profile['locality']],
+ '$region' => ['region', DI::l10n()->t('Region/State:'), $profile['region']],
+ '$postal_code' => ['postal_code', DI::l10n()->t('Postal/Zip Code:'), $profile['postal-code']],
+ '$country_name' => ['country_name', DI::l10n()->t('Country:'), $profile['country-name']],
+ '$age' => ((intval($profile['dob'])) ? '(' . DI::l10n()->t('Age: ') . DI::l10n()->tt('%d year old', '%d years old', Temporal::getAgeByTimezone($profile['dob'], $a->user['timezone'])) . ')' : ''),
+ '$xmpp' => ['xmpp', DI::l10n()->t('XMPP (Jabber) address:'), $profile['xmpp'], DI::l10n()->t('The XMPP address will be propagated to your contacts so that they can follow you.')],
+ '$homepage' => ['homepage', DI::l10n()->t('Homepage URL:'), $profile['homepage']],
+ '$pub_keywords' => ['pub_keywords', DI::l10n()->t('Public Keywords:'), $profile['pub_keywords'], DI::l10n()->t('(Used for suggesting potential friends, can be seen by others)')],
+ '$prv_keywords' => ['prv_keywords', DI::l10n()->t('Private Keywords:'), $profile['prv_keywords'], DI::l10n()->t('(Used for searching profiles, never shown to others)')],
+ '$custom_fields_description' => DI::l10n()->t("<p>Custom fields appear on <a href=\"%s\">your profile page</a>.</p>
+ <p>You can use BBCodes in the field values.</p>
+ <p>Reorder by dragging the field title.</p>
+ <p>Empty the label field to remove a custom field.</p>
+ <p>Non-public fields can only be seen by the selected Friendica contacts or the Friendica contacts in the selected groups.</p>",
+ 'profile/' . $a->user['nickname']
+ ),
+ '$custom_fields' => $custom_fields,
+ ]);
+
+ $arr = ['profile' => $profile, 'entry' => $o];
+ Hook::callAll('profile_edit', $arr);
+
+ return $o;
+ }
+
+ private static function cleanKeywords($keywords)
+ {
+ $keywords = str_replace(',', ' ', $keywords);
+ $keywords = explode(' ', $keywords);
+
+ $cleaned = [];
+ foreach ($keywords as $keyword) {
+ $keyword = trim(strtolower($keyword));
+ $keyword = trim($keyword, '#');
+ if ($keyword != '') {
+ $cleaned[] = $keyword;
+ }
+ }
+
+ $keywords = implode(', ', $cleaned);
+
+ return $keywords;
+ }
+}
$profile = self::exportMultiRow(
- sprintf("SELECT * FROM `profile` WHERE `uid` = %d ", intval(local_user()))
+ sprintf("SELECT *, 'default' AS `profile_name`, 1 AS `is-default` FROM `profile` WHERE `uid` = %d ", intval(local_user()))
+ );
+
+ $profile_fields = self::exportMultiRow(
+ sprintf("SELECT * FROM `profile_field` WHERE `uid` = %d ", intval(local_user()))
);
$photo = self::exportMultiRow(
'user' => $user,
'contact' => $contact,
'profile' => $profile,
+ 'profile_fields' => $profile_fields,
'photo' => $photo,
'pconfig' => $pconfig,
'group' => $group,
--- /dev/null
+<?php
+
+namespace Friendica\Module\Update;
+
+use Friendica\BaseModule;
+use Friendica\Content\Pager;
+use Friendica\Core\Session;
+use Friendica\Database\DBA;
+use Friendica\DI;
+use Friendica\Model\Item;
+use Friendica\Model\Profile as ProfileModel;
+use Friendica\Network\HTTPException\ForbiddenException;
+use Friendica\Util\DateTimeFormat;
+
+class Profile extends BaseModule
+{
+ public static function rawContent(array $parameters = [])
+ {
+ $a = DI::app();
+
+ if (DI::config()->get('system', 'block_public') && !local_user() && !Session::getRemoteContactID($a->profile['uid'])) {
+ throw new ForbiddenException();
+ }
+
+ $o = '';
+
+ $profile_uid = intval($_GET['p'] ?? 0);
+
+ // Ensure we've got a profile owner if updating.
+ $a->profile['uid'] = $profile_uid;
+
+ $remote_contact = Session::getRemoteContactID($a->profile['uid']);
+ $is_owner = local_user() == $a->profile['uid'];
+ $last_updated_key = "profile:" . $a->profile['uid'] . ":" . local_user() . ":" . $remote_contact;
+
+ if (!empty($a->profile['hidewall']) && !$is_owner && !$remote_contact) {
+ throw new ForbiddenException(DI::l10n()->t('Access to this profile has been restricted.'));
+ }
+
+ // Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups
+ $sql_extra = Item::getPermissionsSQLByUserId($a->profile['uid']);
+
+ $last_updated_array = Session::get('last_updated', []);
+
+ $last_updated = $last_updated_array[$last_updated_key] ?? 0;
+
+ // If the page user is the owner of the page we should query for unseen
+ // items. Otherwise use a timestamp of the last succesful update request.
+ if ($is_owner || !$last_updated) {
+ $sql_extra4 = " AND `item`.`unseen`";
+ } else {
+ $gmupdate = gmdate(DateTimeFormat::MYSQL, $last_updated);
+ $sql_extra4 = " AND `item`.`received` > '" . $gmupdate . "'";
+ }
+
+ $items_stmt = DBA::p(
+ "SELECT DISTINCT(`parent-uri`) AS `uri`, `item`.`created`
+ FROM `item`
+ INNER JOIN `contact`
+ ON `contact`.`id` = `item`.`contact-id`
+ AND NOT `contact`.`blocked`
+ AND NOT `contact`.`pending`
+ WHERE `item`.`uid` = ?
+ AND `item`.`visible`
+ AND (NOT `item`.`deleted` OR `item`.`gravity` = ?)
+ AND NOT `item`.`moderated`
+ AND `item`.`wall`
+ $sql_extra4
+ $sql_extra
+ ORDER BY `item`.`received` DESC",
+ $a->profile['uid'],
+ GRAVITY_ACTIVITY
+ );
+
+ if (!DBA::isResult($items_stmt)) {
+ return '';
+ }
+
+ $pager = new Pager(DI::args()->getQueryString());
+
+ // Set a time stamp for this page. We will make use of it when we
+ // search for new items (update routine)
+ $last_updated_array[$last_updated_key] = time();
+ Session::set('last_updated', $last_updated_array);
+
+ if ($is_owner && !$profile_uid && !DI::config()->get('theme', 'hide_eventlist')) {
+ $o .= ProfileModel::getBirthdays();
+ $o .= ProfileModel::getEventsReminderHTML();
+ }
+
+ if ($is_owner) {
+ $unseen = Item::exists(['wall' => true, 'unseen' => true, 'uid' => local_user()]);
+ if ($unseen) {
+ Item::update(['unseen' => false], ['wall' => true, 'unseen' => true, 'uid' => local_user()]);
+ }
+ }
+
+ $items = DBA::toArray($items_stmt);
+
+ $o .= conversation($a, $items, $pager, 'profile', $profile_uid, false, 'received', $a->profile['uid']);
+
+ header("Content-type: text/html");
+ echo "<!DOCTYPE html><html><body>\r\n";
+ // We can remove this hack once Internet Explorer recognises HTML5 natively
+ echo "<section>";
+ echo $o;
+ if (DI::pConfig()->get(local_user(), "system", "bandwidth_saver")) {
+ $replace = "<br />".DI::l10n()->t("[Embedded content - reload page to view]")."<br />";
+ $pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
+ $o = preg_replace($pattern, $replace, $o);
+ $pattern = "/<\s*video[^>]*>(.*?)<\s*\/\s*video>/i";
+ $o = preg_replace($pattern, $replace, $o);
+ $pattern = "/<\s*embed[^>]*>(.*?)<\s*\/\s*embed>/i";
+ $o = preg_replace($pattern, $replace, $o);
+ $pattern = "/<\s*iframe[^>]*>(.*?)<\s*\/\s*iframe>/i";
+ $o = preg_replace($pattern, $replace, $o);
+ }
+
+ // reportedly some versions of MSIE don't handle tabs in XMLHttpRequest documents very well
+ echo str_replace("\t", " ", $o);
+ echo "</section>";
+ echo "</body></html>\r\n";
+ exit();
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Object\EMail;
+
+use Friendica\Util\Emailer;
+
+/**
+ * Interface for a single mail, which can be send through Emailer::send()
+ *
+ * @see Emailer::send()
+ */
+interface IEmail
+{
+ /**
+ * Gets the senders name for this email
+ *
+ * @return string
+ */
+ function getFromName();
+
+ /**
+ * Gets the senders email address for this email
+ *
+ * @return string
+ */
+ function getFromAddress();
+
+ /**
+ * Gets the UID of the sender of this email
+ *
+ * @return int|null
+ */
+ function getRecipientUid();
+
+ /**
+ * Gets the reply-to address for this email
+ *
+ * @return string
+ */
+ function getReplyTo();
+
+ /**
+ * Gets the senders email address
+ *
+ * @return string
+ */
+ function getToAddress();
+
+ /**
+ * Gets the subject of this email
+ *
+ * @return string
+ */
+ function getSubject();
+
+ /**
+ * Gets the message body of this email (either html or plaintext)
+ *
+ * @param boolean $plain True, if returned as plaintext
+ *
+ * @return string
+ */
+ function getMessage(bool $plain = false);
+
+ /**
+ * Gets any additional mail header
+ *
+ * @return string
+ */
+ function getAdditionalMailHeader();
+}
--- /dev/null
+<?php
+
+namespace Friendica\Object\EMail;
+
+use Friendica\App;
+use Friendica\App\BaseURL;
+use Friendica\Content\Text\HTML;
+use Friendica\Core\L10n;
+use Friendica\Model\Item;
+use Friendica\Object\Email;
+
+/**
+ * Class for creating CC emails based on a received item
+ */
+class ItemCCEMail extends Email
+{
+ public function __construct(App $a, L10n $l10n, BaseURL $baseUrl, array $item, string $toAddress, string $authorThumb)
+ {
+ $disclaimer = '<hr />' . $l10n->t('This message was sent to you by %s, a member of the Friendica social network.', $a->user['username'])
+ . '<br />';
+ $disclaimer .= $l10n->t('You may visit them online at %s', $baseUrl . '/profile/' . $a->user['nickname']) . EOL;
+ $disclaimer .= $l10n->t('Please contact the sender by replying to this post if you do not wish to receive these messages.') . EOL;
+ if (!$item['title'] == '') {
+ $subject = Email::encodeHeader($item['title'], 'UTF-8');
+ } else {
+ $subject = Email::encodeHeader('[Friendica]' . ' ' . $l10n->t('%s posted an update.', $a->user['username']), 'UTF-8');
+ }
+ $link = '<a href="' . $baseUrl . '/profile/' . $a->user['nickname'] . '"><img src="' . $authorThumb . '" alt="' . $a->user['username'] . '" /></a><br /><br />';
+ $html = Item::prepareBody($item);
+ $message = '<html><body>' . $link . $html . $disclaimer . '</body></html>';;
+
+ parent::__construct($a->user['username'], $a->user['email'], $a->user['email'], $toAddress,
+ $subject, $message, HTML::toPlaintext($html . $disclaimer));
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Object;
+
+use Friendica\Object\EMail\IEmail;
+
+/**
+ * The default implementation of the IEmail interface
+ *
+ * Provides the possibility to reuse the email instance with new recipients (@see Email::withRecipient())
+ */
+class Email implements IEmail
+{
+ /** @var string */
+ private $fromName;
+ /** @var string */
+ private $fromAddress;
+ /** @var string */
+ private $replyTo;
+
+ /** @var string */
+ private $toAddress;
+
+ /** @var string */
+ private $subject;
+ /** @var string */
+ private $msgHtml;
+ /** @var string */
+ private $msgText;
+
+ /** @var string */
+ private $additionalMailHeader = '';
+ /** @var int|null */
+ private $toUid = null;
+
+ public function __construct(string $fromName, string $fromAddress, string $replyTo, string $toAddress,
+ string $subject, string $msgHtml, string $msgText,
+ string $additionalMailHeader = '', int $toUid = null)
+ {
+ $this->fromName = $fromName;
+ $this->fromAddress = $fromAddress;
+ $this->replyTo = $replyTo;
+ $this->toAddress = $toAddress;
+ $this->subject = $subject;
+ $this->msgHtml = $msgHtml;
+ $this->msgText = $msgText;
+ $this->additionalMailHeader = $additionalMailHeader;
+ $this->toUid = $toUid;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getFromName()
+ {
+ return $this->fromName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getFromAddress()
+ {
+ return $this->fromAddress;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getReplyTo()
+ {
+ return $this->replyTo;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getToAddress()
+ {
+ return $this->toAddress;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getSubject()
+ {
+ return $this->subject;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getMessage(bool $plain = false)
+ {
+ if ($plain) {
+ return $this->msgText;
+ } else {
+ return $this->msgHtml;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getAdditionalMailHeader()
+ {
+ return $this->additionalMailHeader;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function getRecipientUid()
+ {
+ return $this->toUid;
+ }
+
+ /**
+ * Returns the current email with a new recipient
+ *
+ * @param string $email The email of the recipient
+ * @param int $uid The (optional) UID of the recipient for further infos
+ *
+ * @return static
+ */
+ public function withRecipient(string $email, int $uid = null)
+ {
+ $newEmail = clone $this;
+ $newEmail->toAddress = $email;
+ $newEmail->toUid = $uid;
+
+ return $newEmail;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Object\Notification;
+
+/**
+ * A view-only object for printing introduction notifications to the frontend
+ */
+class Introduction implements \JsonSerializable
+{
+ /** @var string */
+ private $label = '';
+ /** @var string */
+ private $type = '';
+ /** @var integer */
+ private $intro_id = -1;
+ /** @var string */
+ private $madeBy = '';
+ /** @var string */
+ private $madeByUrl = '';
+ /** @var string */
+ private $madeByZrl = '';
+ /** @var string */
+ private $madeByAddr = '';
+ /** @var integer */
+ private $contactId = -1;
+ /** @var string */
+ private $photo = '';
+ /** @var string */
+ private $name = '';
+ /** @var string */
+ private $url = '';
+ /** @var string */
+ private $zrl = '';
+ /** @var boolean */
+ private $hidden = false;
+ /** @var integer */
+ private $postNewFriend = -1;
+ /** @var boolean */
+ private $knowYou = false;
+ /** @var string */
+ private $note = '';
+ /** @var string */
+ private $request = '';
+ /** @var int */
+ private $dfrnId = -1;
+ /** @var string */
+ private $addr = '';
+ /** @var string */
+ private $network = '';
+ /** @var int */
+ private $uid = -1;
+ /** @var string */
+ private $keywords = '';
+ /** @var string */
+ private $gender = '';
+ /** @var string */
+ private $location = '';
+ /** @var string */
+ private $about = '';
+
+ /**
+ * @return string
+ */
+ public function getLabel()
+ {
+ return $this->label;
+ }
+
+ /**
+ * @return string
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * @return int
+ */
+ public function getIntroId()
+ {
+ return $this->intro_id;
+ }
+
+ /**
+ * @return string
+ */
+ public function getMadeBy()
+ {
+ return $this->madeBy;
+ }
+
+ /**
+ * @return string
+ */
+ public function getMadeByUrl()
+ {
+ return $this->madeByUrl;
+ }
+
+ /**
+ * @return string
+ */
+ public function getMadeByZrl()
+ {
+ return $this->madeByZrl;
+ }
+
+ /**
+ * @return string
+ */
+ public function getMadeByAddr()
+ {
+ return $this->madeByAddr;
+ }
+
+ /**
+ * @return int
+ */
+ public function getContactId()
+ {
+ return $this->contactId;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPhoto()
+ {
+ return $this->photo;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * @return string
+ */
+ public function getUrl()
+ {
+ return $this->url;
+ }
+
+ /**
+ * @return string
+ */
+ public function getZrl()
+ {
+ return $this->zrl;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isHidden()
+ {
+ return $this->hidden;
+ }
+
+ /**
+ * @return int
+ */
+ public function getPostNewFriend()
+ {
+ return $this->postNewFriend;
+ }
+
+ /**
+ * @return string
+ */
+ public function getKnowYou()
+ {
+ return $this->knowYou;
+ }
+
+ /**
+ * @return string
+ */
+ public function getNote()
+ {
+ return $this->note;
+ }
+
+ /**
+ * @return string
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ /**
+ * @return string
+ */
+ public function getDfrnId()
+ {
+ return $this->dfrnId;
+ }
+
+ /**
+ * @return string
+ */
+ public function getAddr()
+ {
+ return $this->addr;
+ }
+
+ /**
+ * @return string
+ */
+ public function getNetwork()
+ {
+ return $this->network;
+ }
+
+ /**
+ * @return int
+ */
+ public function getUid()
+ {
+ return $this->uid;
+ }
+
+ /**
+ * @return string
+ */
+ public function getKeywords()
+ {
+ return $this->keywords;
+ }
+
+ /**
+ * @return string
+ */
+ public function getGender()
+ {
+ return $this->gender;
+ }
+
+ /**
+ * @return string
+ */
+ public function getLocation()
+ {
+ return $this->location;
+ }
+
+ /**
+ * @return string
+ */
+ public function getAbout()
+ {
+ return $this->about;
+ }
+
+ public function __construct(array $data = [])
+ {
+ $this->label = $data['label'] ?? '';
+ $this->type = $data['str_type'] ?? '';
+ $this->intro_id = $data['$intro_id'] ?? -1;
+ $this->madeBy = $data['madeBy'] ?? '';
+ $this->madeByUrl = $data['madeByUrl'] ?? '';
+ $this->madeByZrl = $data['madeByZrl'] ?? '';
+ $this->madeByAddr = $data['madeByAddr'] ?? '';
+ $this->contactId = $data['contactId'] ?? '';
+ $this->photo = $data['photo'] ?? '';
+ $this->name = $data['name'] ?? '';
+ $this->url = $data['url'] ?? '';
+ $this->zrl = $data['zrl'] ?? '';
+ $this->hidden = $data['hidden'] ?? false;
+ $this->postNewFriend = $data['postNewFriend'] ?? '';
+ $this->knowYou = $data['knowYou'] ?? false;
+ $this->note = $data['note'] ?? '';
+ $this->request = $data['request'] ?? '';
+ $this->dfrnId = $data['dfrn_id'] ?? -1;
+ $this->addr = $data['addr'] ?? '';
+ $this->network = $data['network'] ?? '';
+ $this->uid = $data['uid'] ?? -1;
+ $this->keywords = $data['keywords'] ?? '';
+ $this->gender = $data['gender'] ?? '';
+ $this->location = $data['location'] ?? '';
+ $this->about = $data['about'] ?? '';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function jsonSerialize()
+ {
+ return $this->toArray();
+ }
+
+ /**
+ * @return array
+ */
+ public function toArray()
+ {
+ return get_object_vars($this);
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Object\Notification;
+
+/**
+ * A view-only object for printing item notifications to the frontend
+ */
+class Notification implements \JsonSerializable
+{
+ const SYSTEM = 'system';
+ const PERSONAL = 'personal';
+ const NETWORK = 'network';
+ const INTRO = 'intro';
+ const HOME = 'home';
+
+ /** @var string */
+ private $label = '';
+ /** @var string */
+ private $link = '';
+ /** @var string */
+ private $image = '';
+ /** @var string */
+ private $url = '';
+ /** @var string */
+ private $text = '';
+ /** @var string */
+ private $when = '';
+ /** @var string */
+ private $ago = '';
+ /** @var boolean */
+ private $seen = false;
+
+ /**
+ * @return string
+ */
+ public function getLabel()
+ {
+ return $this->label;
+ }
+
+ /**
+ * @return string
+ */
+ public function getLink()
+ {
+ return $this->link;
+ }
+
+ /**
+ * @return string
+ */
+ public function getImage()
+ {
+ return $this->image;
+ }
+
+ /**
+ * @return string
+ */
+ public function getUrl()
+ {
+ return $this->url;
+ }
+
+ /**
+ * @return string
+ */
+ public function getText()
+ {
+ return $this->text;
+ }
+
+ /**
+ * @return string
+ */
+ public function getWhen()
+ {
+ return $this->when;
+ }
+
+ /**
+ * @return string
+ */
+ public function getAgo()
+ {
+ return $this->ago;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isSeen()
+ {
+ return $this->seen;
+ }
+
+ public function __construct(array $data)
+ {
+ $this->label = $data['label'] ?? '';
+ $this->link = $data['link'] ?? '';
+ $this->image = $data['image'] ?? '';
+ $this->url = $data['url'] ?? '';
+ $this->text = $data['text'] ?? '';
+ $this->when = $data['when'] ?? '';
+ $this->ago = $data['ago'] ?? '';
+ $this->seen = $data['seen'] ?? false;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function jsonSerialize()
+ {
+ return get_object_vars($this);
+ }
+
+ /**
+ * @return array
+ */
+ public function toArray()
+ {
+ return get_object_vars($this);
+ }
+}
}
$fields = ['locality', 'region', 'country-name'];
- $profile = DBA::selectFirst('profile', $fields, ['uid' => $uid, 'is-default' => true]);
+ $profile = DBA::selectFirst('profile', $fields, ['uid' => $uid]);
if (!DBA::isResult($profile)) {
return [];
}
`profile`.`pub_keywords`, `profile`.`xmpp`, `profile`.`dob`
FROM `profile`
INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
- WHERE `profile`.`is-default` AND NOT `user`.`hidewall` AND `user`.`uid` = %d",
+ WHERE NOT `user`.`hidewall` AND `user`.`uid` = %d",
intval($owner['uid'])
);
if (DBA::isResult($r)) {
FROM `profile`
INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
INNER JOIN `contact` ON `profile`.`uid` = `contact`.`uid`
- WHERE `user`.`uid` = %d AND `profile`.`is-default` AND `contact`.`self` LIMIT 1",
+ WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1",
intval($uid)
);
*/
private static function addAuthor(DOMDocument $doc, array $owner, $show_profile = true)
{
- $profile = DBA::selectFirst('profile', ['homepage', 'publish'], ['uid' => $owner['uid'], 'is-default' => true]);
+ $profile = DBA::selectFirst('profile', ['homepage', 'publish'], ['uid' => $owner['uid']]);
$author = $doc->createElement("author");
XML::addElement($doc, $author, "id", $owner["url"]);
if ($owner['account-type'] == User::ACCOUNT_TYPE_COMMUNITY) {
--- /dev/null
+<?php
+
+namespace Friendica\Repository;
+
+use Exception;
+use Friendica\BaseRepository;
+use Friendica\Core\Hook;
+use Friendica\Model;
+use Friendica\Collection;
+use Friendica\Network\HTTPException\NotFoundException;
+use Friendica\Util\DateTimeFormat;
+
+class Notify extends BaseRepository
+{
+ protected static $table_name = 'notify';
+
+ protected static $model_class = Model\Notify::class;
+
+ protected static $collection_class = Collection\Notifies::class;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return Model\Notify
+ */
+ protected function create(array $data)
+ {
+ return new Model\Notify($this->dba, $this->logger, $this, $data);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return Collection\Notifies
+ */
+ public function select(array $condition = [], array $params = [])
+ {
+ $params['order'] = $params['order'] ?? ['date' => 'DESC'];
+
+ $condition = array_merge($condition, ['uid' => local_user()]);
+
+ return parent::select($condition, $params);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return Model\Notify
+ * @throws NotFoundException
+ */
+ public function getByID(int $id)
+ {
+ return $this->selectFirst(['id' => $id, 'uid' => local_user()]);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return bool true on success, false on error
+ * @throws Exception
+ */
+ public function setAllSeen(bool $seen = true)
+ {
+ return $this->dba->update('notify', ['seen' => $seen], ['uid' => local_user()]);
+ }
+
+ /**
+ * @param array $fields
+ *
+ * @return Model\Notify
+ *
+ * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+ * @throws Exception
+ */
+ public function insert(array $fields)
+ {
+ $fields['date'] = DateTimeFormat::utcNow();
+ $fields['abort'] = false;
+
+ Hook::callAll('enotify_store', $fields);
+
+ if ($fields['abort']) {
+ $this->logger->debug('Abort adding notification entry', ['fields' => $fields]);
+ return null;
+ }
+
+ $this->logger->debug('adding notification entry', ['fields' => $fields]);
+
+ return parent::insert($fields);
+ }
+}
class PermissionSet extends BaseRepository
{
+ /** @var int Virtual permission set id for public permission */
+ const PUBLIC = 0;
+
protected static $table_name = 'permissionset';
protected static $model_class = Model\PermissionSet::class;
{
if (isset($condition['id']) && !$condition['id']) {
return $this->create([
- 'id' => 0,
+ 'id' => self::PUBLIC,
'uid' => $condition['uid'] ?? 0,
'allow_cid' => '',
'allow_gid' => '',
// Public permission
if (!$allow_cid && !$allow_gid && !$deny_cid && !$deny_gid) {
- return 0;
+ return self::PUBLIC;
}
$condition = [
--- /dev/null
+<?php
+
+namespace Friendica\Repository;
+
+use Friendica\BaseModel;
+use Friendica\BaseRepository;
+use Friendica\Collection;
+use Friendica\Core\L10n;
+use Friendica\Database\Database;
+use Friendica\Database\DBA;
+use Friendica\Model;
+use Friendica\Util\ACLFormatter;
+use Friendica\Util\DateTimeFormat;
+use Psr\Log\LoggerInterface;
+
+class ProfileField extends BaseRepository
+{
+ protected static $table_name = 'profile_field';
+
+ protected static $model_class = Model\ProfileField::class;
+
+ protected static $collection_class = Collection\ProfileFields::class;
+
+ /** @var PermissionSet */
+ private $permissionSet;
+ /** @var ACLFormatter */
+ private $aclFormatter;
+ /** @var L10n */
+ private $l10n;
+
+ public function __construct(Database $dba, LoggerInterface $logger, PermissionSet $permissionSet, ACLFormatter $aclFormatter, L10n $l10n)
+ {
+ parent::__construct($dba, $logger);
+
+ $this->permissionSet = $permissionSet;
+ $this->aclFormatter = $aclFormatter;
+ $this->l10n = $l10n;
+ }
+
+ /**
+ * @param array $data
+ * @return Model\ProfileField
+ */
+ protected function create(array $data)
+ {
+ return new Model\ProfileField($this->dba, $this->logger, $this->permissionSet, $data);
+ }
+
+ /**
+ * @param array $condition
+ * @return Model\ProfileField
+ * @throws \Friendica\Network\HTTPException\NotFoundException
+ */
+ public function selectFirst(array $condition)
+ {
+ return parent::selectFirst($condition);
+ }
+
+ /**
+ * @param array $condition
+ * @param array $params
+ * @return Collection\ProfileFields
+ * @throws \Exception
+ */
+ public function select(array $condition = [], array $params = [])
+ {
+ return parent::select($condition, $params);
+ }
+
+ /**
+ * @param array $condition
+ * @param array $params
+ * @param int|null $max_id
+ * @param int|null $since_id
+ * @param int $limit
+ * @return Collection\ProfileFields
+ * @throws \Exception
+ */
+ public function selectByBoundaries(array $condition = [], array $params = [], int $max_id = null, int $since_id = null, int $limit = self::LIMIT)
+ {
+ return parent::selectByBoundaries($condition, $params, $max_id, $since_id, $limit);
+ }
+
+ /**
+ * @param int $uid Field owner user Id
+ * @return Collection\ProfileFields
+ * @throws \Exception
+ */
+ public function selectByUserId(int $uid)
+ {
+ return $this->select(
+ ['uid' => $uid],
+ ['order' => ['order']]
+ );
+ }
+
+ /**
+ * Retrieve all custom profile field a given contact is able to access to, including public profile fields.
+ *
+ * @param int $cid Private contact id, must be owned by $uid
+ * @param int $uid Field owner user id
+ * @return Collection\ProfileFields
+ * @throws \Exception
+ */
+ public function selectByContactId(int $cid, int $uid)
+ {
+ $permissionSets = $this->permissionSet->selectByContactId($cid, $uid);
+
+ $psids = $permissionSets->column('id');
+
+ // Includes public custom fields
+ $psids[] = 0;
+
+ return $this->select(
+ ['uid' => $uid, 'psid' => $psids],
+ ['order' => ['order']]
+ );
+ }
+
+ /**
+ * @param array $fields
+ * @return Model\ProfileField|bool
+ * @throws \Exception
+ */
+ public function insert(array $fields)
+ {
+ $fields['created'] = DateTimeFormat::utcNow();
+ $fields['edited'] = DateTimeFormat::utcNow();
+
+ return parent::insert($fields);
+ }
+
+ /**
+ * @param Model\ProfileField $model
+ * @return bool
+ * @throws \Exception
+ */
+ public function update(BaseModel $model)
+ {
+ $model->edited = DateTimeFormat::utcNow();
+
+ return parent::update($model);
+ }
+
+ /**
+ * @param int $uid User Id
+ * @param Collection\ProfileFields $profileFields Collection of existing profile fields
+ * @param array $profileFieldInputs Array of profile field form inputs indexed by profile field id
+ * @param array $profileFieldOrder List of profile field id in order
+ * @return Collection\ProfileFields
+ * @throws \Exception
+ */
+ public function updateCollectionFromForm(int $uid, Collection\ProfileFields $profileFields, array $profileFieldInputs, array $profileFieldOrder)
+ {
+ // Returns an associative array of id => order values
+ $profileFieldOrder = array_flip($profileFieldOrder);
+
+ // Creation of the new field
+ if (!empty($profileFieldInputs['new']['label'])) {
+ $psid = $this->permissionSet->getIdFromACL(
+ $uid,
+ $this->aclFormatter->toString($profileFieldInputs['new']['contact_allow'] ?? ''),
+ $this->aclFormatter->toString($profileFieldInputs['new']['group_allow'] ?? ''),
+ $this->aclFormatter->toString($profileFieldInputs['new']['contact_deny'] ?? ''),
+ $this->aclFormatter->toString($profileFieldInputs['new']['group_deny'] ?? '')
+ );
+
+ $newProfileField = $this->insert([
+ 'uid' => $uid,
+ 'label' => $profileFieldInputs['new']['label'],
+ 'value' => $profileFieldInputs['new']['value'],
+ 'psid' => $psid,
+ 'order' => $profileFieldOrder['new'],
+ ]);
+
+ $profileFieldInputs[$newProfileField->id] = $profileFieldInputs['new'];
+ $profileFieldOrder[$newProfileField->id] = $profileFieldOrder['new'];
+
+ $profileFields[] = $newProfileField;
+ }
+
+ unset($profileFieldInputs['new']);
+ unset($profileFieldOrder['new']);
+
+ // Prunes profile field whose label has been emptied
+ $profileFields = $profileFields->filter(function (Model\ProfileField $profileField) use (&$profileFieldInputs, &$profileFieldOrder) {
+ $keepModel = !isset($profileFieldInputs[$profileField->id]) || !empty($profileFieldInputs[$profileField->id]['label']);
+
+ if (!$keepModel) {
+ unset($profileFieldInputs[$profileField->id]);
+ unset($profileFieldOrder[$profileField->id]);
+ $this->delete($profileField);
+ }
+
+ return $keepModel;
+ });
+
+ // Regenerates the order values if items were deleted
+ $profileFieldOrder = array_flip(array_keys($profileFieldOrder));
+
+ // Update existing profile fields from form values
+ $profileFields = $profileFields->map(function (Model\ProfileField $profileField) use ($uid, &$profileFieldInputs, &$profileFieldOrder) {
+ if (isset($profileFieldInputs[$profileField->id]) && isset($profileFieldOrder[$profileField->id])) {
+ $psid = $this->permissionSet->getIdFromACL(
+ $uid,
+ $this->aclFormatter->toString($profileFieldInputs[$profileField->id]['contact_allow'] ?? ''),
+ $this->aclFormatter->toString($profileFieldInputs[$profileField->id]['group_allow'] ?? ''),
+ $this->aclFormatter->toString($profileFieldInputs[$profileField->id]['contact_deny'] ?? ''),
+ $this->aclFormatter->toString($profileFieldInputs[$profileField->id]['group_deny'] ?? '')
+ );
+
+ $profileField->psid = $psid;
+ $profileField->label = $profileFieldInputs[$profileField->id]['label'];
+ $profileField->value = $profileFieldInputs[$profileField->id]['value'];
+ $profileField->order = $profileFieldOrder[$profileField->id];
+
+ unset($profileFieldInputs[$profileField->id]);
+ unset($profileFieldOrder[$profileField->id]);
+ }
+
+ return $profileField;
+ });
+
+ return $profileFields;
+ }
+
+ /**
+ * Migrates a legacy profile to the new slimmer profile with extra custom fields.
+ * Multi profiles are converted to ACl-protected custom fields and deleted.
+ *
+ * @param array $profile Profile table row
+ * @throws \Exception
+ */
+ public function migrateFromLegacyProfile(array $profile)
+ {
+ // Already processed, aborting
+ if ($profile['is-default'] === null) {
+ return;
+ }
+
+ if (!$profile['is-default']) {
+ $contacts = Model\Contact::selectToArray(['id'], ['uid' => $profile['uid'], 'profile-id' => $profile['id']]);
+ if (!count($contacts)) {
+ // No contact visibility selected defaults to user-only permission
+ $contacts = Model\Contact::selectToArray(['id'], ['uid' => $profile['uid'], 'self' => true]);
+ }
+
+ $allow_cid = $this->aclFormatter->toString(array_column($contacts, 'id'));
+ }
+
+ $psid = $this->permissionSet->getIdFromACL($profile['uid'], $allow_cid ?? '');
+
+ $order = 1;
+
+ $custom_fields = [
+ 'hometown' => $this->l10n->t('Hometown:'),
+ 'gender' => $this->l10n->t('Gender:'),
+ 'marital' => $this->l10n->t('Marital Status:'),
+ 'with' => $this->l10n->t('With:'),
+ 'howlong' => $this->l10n->t('Since:'),
+ 'sexual' => $this->l10n->t('Sexual Preference:'),
+ 'politic' => $this->l10n->t('Political Views:'),
+ 'religion' => $this->l10n->t('Religious Views:'),
+ 'likes' => $this->l10n->t('Likes:'),
+ 'dislikes' => $this->l10n->t('Dislikes:'),
+ 'about' => $this->l10n->t('About:'),
+ 'summary' => $this->l10n->t('Summary'),
+ 'music' => $this->l10n->t('Musical interests'),
+ 'book' => $this->l10n->t('Books, literature'),
+ 'tv' => $this->l10n->t('Television'),
+ 'film' => $this->l10n->t('Film/dance/culture/entertainment'),
+ 'interest' => $this->l10n->t('Hobbies/Interests'),
+ 'romance' => $this->l10n->t('Love/romance'),
+ 'work' => $this->l10n->t('Work/employment'),
+ 'education' => $this->l10n->t('School/education'),
+ 'contact' => $this->l10n->t('Contact information and Social Networks'),
+ ];
+
+ foreach ($custom_fields as $field => $label) {
+ if (!empty($profile[$field]) && $profile[$field] > DBA::NULL_DATE && $profile[$field] > DBA::NULL_DATETIME) {
+ $this->insert([
+ 'uid' => $profile['uid'],
+ 'psid' => $psid,
+ 'order' => $order++,
+ 'label' => trim($label, ':'),
+ 'value' => $profile[$field],
+ ]);
+ }
+
+ $profile[$field] = null;
+ }
+
+ if ($profile['is-default']) {
+ $profile['profile-name'] = null;
+ $profile['is-default'] = null;
+ $this->dba->update('profile', $profile, ['id' => $profile['id']]);
+ } elseif (!empty($profile['id'])) {
+ $this->dba->delete('profile', ['id' => $profile['id']]);
+ }
+ }
+}
*/
namespace Friendica\Util;
+use Friendica\App;
+use Friendica\Core\Config\IConfig;
use Friendica\Core\Hook;
-use Friendica\Core\Logger;
-use Friendica\DI;
+use Friendica\Core\PConfig\IPConfig;
+use Friendica\Network\HTTPException\InternalServerErrorException;
+use Friendica\Object\EMail\IEmail;
use Friendica\Protocol\Email;
+use Psr\Log\LoggerInterface;
/**
* class to handle emailing
*/
class Emailer
{
+ /** @var IConfig */
+ private $config;
+ /** @var IPConfig */
+ private $pConfig;
+ /** @var LoggerInterface */
+ private $logger;
+ /** @var App\BaseURL */
+ private $baseUrl;
+
+ public function __construct(IConfig $config, IPConfig $pConfig, App\BaseURL $baseURL, LoggerInterface $logger)
+ {
+ $this->config = $config;
+ $this->pConfig = $pConfig;
+ $this->logger = $logger;
+ $this->baseUrl = $baseURL;
+ }
+
/**
* Send a multipart/alternative message with Text and HTML versions
*
- * @param array $params parameters
- * fromName name of the sender
- * fromEmail email of the sender
- * replyTo address to direct responses
- * toEmail destination email address
- * messageSubject subject of the message
- * htmlVersion html version of the message
- * textVersion text only version of the message
- * additionalMailHeader additions to the SMTP mail header
- * optional uid user id of the destination user
+ * @param IEmail $email The email to send
*
* @return bool
- * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+ * @throws InternalServerErrorException
*/
- public static function send(array $params)
+ public function send(IEmail $email)
{
$params['sent'] = false;
}
$email_textonly = false;
- if (!empty($params['uid'])) {
- $email_textonly = DI::pConfig()->get($params['uid'], "system", "email_textonly");
+ if (!empty($email->getRecipientUid())) {
+ $email_textonly = $this->pConfig->get($email->getRecipientUid(), 'system', 'email_textonly');
}
- $fromName = Email::encodeHeader(html_entity_decode($params['fromName'], ENT_QUOTES, 'UTF-8'), 'UTF-8');
- $messageSubject = Email::encodeHeader(html_entity_decode($params['messageSubject'], ENT_QUOTES, 'UTF-8'), 'UTF-8');
+ $fromName = Email::encodeHeader(html_entity_decode($email->getFromName(), ENT_QUOTES, 'UTF-8'), 'UTF-8');
+ $fromAddress = $email->getFromAddress();
+ $replyTo = $email->getReplyTo();
+ $messageSubject = Email::encodeHeader(html_entity_decode($email->getSubject(), ENT_QUOTES, 'UTF-8'), 'UTF-8');
// generate a mime boundary
- $mimeBoundary =rand(0, 9)."-"
- .rand(100000000, 999999999)."-"
- .rand(100000000, 999999999)."=:"
- .rand(10000, 99999);
+ $mimeBoundary = rand(0, 9) . '-'
+ . rand(100000000, 999999999) . '-'
+ . rand(100000000, 999999999) . '=:'
+ . rand(10000, 99999);
// generate a multipart/alternative message header
- $messageHeader = ($params['additionalMailHeader'] ?? '') .
- "From: $fromName <{$params['fromEmail']}>\n" .
- "Reply-To: $fromName <{$params['replyTo']}>\n" .
- "MIME-Version: 1.0\n" .
- "Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\"";
+ $messageHeader = $email->getAdditionalMailHeader() .
+ "From: $fromName <{$fromAddress}>\n" .
+ "Reply-To: $fromName <{$replyTo}>\n" .
+ "MIME-Version: 1.0\n" .
+ "Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\"";
// assemble the final multipart message body with the text and html types included
- $textBody = chunk_split(base64_encode($params['textVersion']));
- $htmlBody = chunk_split(base64_encode($params['htmlVersion']));
- $multipartMessageBody = "--" . $mimeBoundary . "\n" . // plain text section
- "Content-Type: text/plain; charset=UTF-8\n" .
- "Content-Transfer-Encoding: base64\n\n" .
- $textBody . "\n";
-
- if (!$email_textonly && !is_null($params['htmlVersion'])) {
+ $textBody = chunk_split(base64_encode($email->getMessage(true)));
+ $htmlBody = chunk_split(base64_encode($email->getMessage()));
+ $multipartMessageBody = "--" . $mimeBoundary . "\n" . // plain text section
+ "Content-Type: text/plain; charset=UTF-8\n" .
+ "Content-Transfer-Encoding: base64\n\n" .
+ $textBody . "\n";
+
+ if (!$email_textonly && !is_null($email->getMessage())) {
$multipartMessageBody .=
- "--" . $mimeBoundary . "\n" . // text/html section
+ "--" . $mimeBoundary . "\n" . // text/html section
"Content-Type: text/html; charset=UTF-8\n" .
"Content-Transfer-Encoding: base64\n\n" .
$htmlBody . "\n";
}
$multipartMessageBody .=
- "--" . $mimeBoundary . "--\n"; // message ending
+ "--" . $mimeBoundary . "--\n"; // message ending
- if (DI::config()->get("system", "sendmail_params", true)) {
- $sendmail_params = '-f ' . $params['fromEmail'];
+ if ($this->config->get('system', 'sendmail_params', true)) {
+ $sendmail_params = '-f ' . $fromAddress;
} else {
$sendmail_params = null;
}
// send the message
$hookdata = [
- 'to' => $params['toEmail'],
- 'subject' => $messageSubject,
- 'body' => $multipartMessageBody,
- 'headers' => $messageHeader,
+ 'to' => $email->getToAddress(),
+ 'subject' => $messageSubject,
+ 'body' => $multipartMessageBody,
+ 'headers' => $messageHeader,
'parameters' => $sendmail_params,
- 'sent' => false,
+ 'sent' => false,
];
- Hook::callAll("emailer_send", $hookdata);
+ Hook::callAll('emailer_send', $hookdata);
if ($hookdata['sent']) {
return true;
$hookdata['headers'],
$hookdata['parameters']
);
- Logger::log("header " . 'To: ' . $params['toEmail'] . "\n" . $messageHeader, Logger::DEBUG);
- Logger::log("return value " . (($res)?"true":"false"), Logger::DEBUG);
+ $this->logger->debug('header ' . 'To: ' . $email->getToAddress() . '\n' . $messageHeader);
+ $this->logger->debug('return value ' . (($res) ? 'true' : 'false'));
return $res;
}
}
$r = q("SELECT `url` FROM `contact`
INNER JOIN `profile` ON `profile`.`uid` = `contact`.`uid`
INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
- WHERE `contact`.`self` AND `profile`.`net-publish` AND `profile`.`is-default` AND
+ WHERE `contact`.`self` AND `profile`.`net-publish` AND
NOT `user`.`account_expired` AND `user`.`verified`");
if (DBA::isResult($r)) {
use Friendica\Database\DBA;
if (!defined('DB_UPDATE_VERSION')) {
- define('DB_UPDATE_VERSION', 1330);
+ define('DB_UPDATE_VERSION', 1332);
}
return [
"reason" => ["type" => "text", "comment" => ""],
"closeness" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "99", "comment" => ""],
"info" => ["type" => "mediumtext", "comment" => ""],
- "profile-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""],
+ "profile-id" => ["type" => "int unsigned", "comment" => "Deprecated"],
"bdyear" => ["type" => "varchar(4)", "not null" => "1", "default" => "", "comment" => ""],
"bd" => ["type" => "date", "not null" => "1", "default" => DBA::NULL_DATE, "comment" => ""],
"notify_new_posts" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "Owner User id"],
- "profile-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Name of the profile"],
- "is-default" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Mark this profile as default profile"],
+ "profile-name" => ["type" => "varchar(255)", "comment" => "Deprecated"],
+ "is-default" => ["type" => "boolean", "comment" => "Deprecated"],
"hide-friends" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Hide friend list from viewers of this profile"],
"name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"pdesc" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Title or description"],
"region" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"postal-code" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""],
"country-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
- "hometown" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
- "gender" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""],
- "marital" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
- "with" => ["type" => "text", "comment" => ""],
- "howlong" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""],
- "sexual" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
- "politic" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
- "religion" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
+ "hometown" => ["type" => "varchar(255)", "comment" => "Deprecated"],
+ "gender" => ["type" => "varchar(32)", "comment" => "Deprecated"],
+ "marital" => ["type" => "varchar(255)", "comment" => "Deprecated"],
+ "with" => ["type" => "text", "comment" => "Deprecated"],
+ "howlong" => ["type" => "datetime", "comment" => "Deprecated"],
+ "sexual" => ["type" => "varchar(255)", "comment" => "Deprecated"],
+ "politic" => ["type" => "varchar(255)", "comment" => "Deprecated"],
+ "religion" => ["type" => "varchar(255)", "comment" => "Deprecated"],
"pub_keywords" => ["type" => "text", "comment" => ""],
"prv_keywords" => ["type" => "text", "comment" => ""],
- "likes" => ["type" => "text", "comment" => ""],
- "dislikes" => ["type" => "text", "comment" => ""],
- "about" => ["type" => "text", "comment" => ""],
- "summary" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
- "music" => ["type" => "text", "comment" => ""],
- "book" => ["type" => "text", "comment" => ""],
- "tv" => ["type" => "text", "comment" => ""],
- "film" => ["type" => "text", "comment" => ""],
- "interest" => ["type" => "text", "comment" => ""],
- "romance" => ["type" => "text", "comment" => ""],
- "work" => ["type" => "text", "comment" => ""],
- "education" => ["type" => "text", "comment" => ""],
- "contact" => ["type" => "text", "comment" => ""],
+ "likes" => ["type" => "text", "comment" => "Deprecated"],
+ "dislikes" => ["type" => "text", "comment" => "Deprecated"],
+ "about" => ["type" => "text", "comment" => "Deprecated"],
+ "summary" => ["type" => "varchar(255)", "comment" => "Deprecated"],
+ "music" => ["type" => "text", "comment" => "Deprecated"],
+ "book" => ["type" => "text", "comment" => "Deprecated"],
+ "tv" => ["type" => "text", "comment" => "Deprecated"],
+ "film" => ["type" => "text", "comment" => "Deprecated"],
+ "interest" => ["type" => "text", "comment" => "Deprecated"],
+ "romance" => ["type" => "text", "comment" => "Deprecated"],
+ "work" => ["type" => "text", "comment" => "Deprecated"],
+ "education" => ["type" => "text", "comment" => "Deprecated"],
+ "contact" => ["type" => "text", "comment" => "Deprecated"],
"homepage" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"xmpp" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"photo" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"PRIMARY" => ["id"],
]
],
+ "profile_field" => [
+ "comment" => "Custom profile fields",
+ "fields" => [
+ "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
+ "uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "Owner user id"],
+ "order" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "1", "comment" => "Field ordering per user"],
+ "psid" => ["type" => "int unsigned", "relation" => ["permissionset" => "id"], "comment" => "ID of the permission set of this profile field - 0 = public"],
+ "label" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Label of the field"],
+ "value" => ["type" => "text", "comment" => "Value of the field"],
+ "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "creation time"],
+ "edited" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "last edit time"],
+ ],
+ "indexes" => [
+ "PRIMARY" => ["id"],
+ "uid" => ["uid"],
+ "order" => ["order"],
+ "psid" => ["psid"],
+ ]
+ ],
"push_subscriber" => [
"comment" => "Used for OStatus: Contains feed subscribers",
"fields" => [
'/nodeinfo/{version}' => [Module\NodeInfo::class, [R::GET]],
'/nogroup' => [Module\Group::class, [R::GET]],
- '/notify' => [
- '[/]' => [Module\Notifications\Notify::class, [R::GET]],
- '/view/{id:\d+}' => [Module\Notifications\Notify::class, [R::GET]],
- '/mark/all' => [Module\Notifications\Notify::class, [R::GET]],
+ '/notifications' => [
+ '/network[/json]' => [Module\Notifications\Notifications::class, [R::GET, R::POST]],
+ '/system[/json]' => [Module\Notifications\Notifications::class, [R::GET, R::POST]],
+ '/personal[/json]' => [Module\Notifications\Notifications::class, [R::GET, R::POST]],
+ '/home[/json]' => [Module\Notifications\Notifications::class, [R::GET, R::POST]],
+ '/intros[/json]' => [Module\Notifications\Introductions::class, [R::GET, R::POST]],
+ '/intros/all[/json]' => [Module\Notifications\Introductions::class, [R::GET, R::POST]],
+ '/intros/{contact:\d+}[/json]' => [Module\Notifications\Introductions::class, [R::GET, R::POST]],
+ ],
+
+ '/notification' => [
+ '[/]' => [Module\Notifications\Notification::class, [R::GET]],
+ '/view/{id:\d+}' => [Module\Notifications\Notification::class, [R::GET]],
+ '/mark/all' => [Module\Notifications\Notification::class, [R::GET]],
],
'/objects/{guid}' => [Module\Objects::class, [R::GET]],
'/probe' => [Module\Debug\Probe::class, [R::GET]],
'/profile' => [
- '/{nickname}' => [Module\Profile::class, [R::GET]],
- '/{nickname}/{to:\d{4}-\d{2}-\d{2}}/{from:\d{4}-\d{2}-\d{2}}' => [Module\Profile::class, [R::GET]],
- '/{nickname}/contacts[/{type}]' => [Module\Profile\Contacts::class, [R::GET]],
- '/{profile:\d+}/view' => [Module\Profile::class, [R::GET]],
+ '/{nickname}' => [Module\Profile\Index::class, [R::GET]],
+ '/{nickname}/profile' => [Module\Profile\Profile::class, [R::GET]],
+ '/{nickname}/contacts[/{type}]' => [Module\Profile\Contacts::class, [R::GET]],
+ '/{nickname}/status[/{category}[/{date1}[/{date2}]]]' => [Module\Profile\Status::class, [R::GET]],
],
'/proxy' => [
],
'/delegation[/{action}/{user_id}]' => [Module\Settings\Delegation::class, [R::GET, R::POST]],
'/profile' => [
+ '[/]' => [Module\Settings\Profile\Index::class, [R::GET, R::POST]],
'/photo[/new]' => [Module\Settings\Profile\Photo\Index::class, [R::GET, R::POST]],
'/photo/crop/{guid}' => [Module\Settings\Profile\Photo\Crop::class, [R::GET, R::POST]],
],
'/starred/{item:\d+}' => [Module\Starred::class, [R::GET]],
'/toggle_mobile' => [Module\ToggleMobile::class, [R::GET]],
'/tos' => [Module\Tos::class, [R::GET]],
+
+ '/update_profile' => [Module\Update\Profile::class, [R::GET]],
+
'/view/theme/{theme}/style.pcss' => [Module\Theme::class, [R::GET]],
'/viewsrc/{item:\d+}' => [Module\Debug\ItemBody::class, [R::GET]],
'/webfinger' => [Module\Debug\WebFinger::class, [R::GET]],
'/post' => [
'/it' => [Module\NodeInfo::class, [Router::POST]],
],
- '/double' => [Module\Profile::class, [Router::GET, Router::POST]]
+ '/double' => [Module\Profile\Index::class, [Router::GET, Router::POST]]
],
],
];
$this->assertEquals(Module\Home::class, $router->getModuleClass('/'));
$this->assertEquals(Module\Friendica::class, $router->getModuleClass('/group/route'));
$this->assertEquals(Module\Xrd::class, $router->getModuleClass('/group2/group3/route'));
- $this->assertEquals(Module\Profile::class, $router->getModuleClass('/double'));
+ $this->assertEquals(Module\Profile\Index::class, $router->getModuleClass('/double'));
}
/**
// Don't find GET
$this->assertEquals(Module\NodeInfo::class, $router->getModuleClass('/post/it'));
- $this->assertEquals(Module\Profile::class, $router->getModuleClass('/double'));
+ $this->assertEquals(Module\Profile\Index::class, $router->getModuleClass('/double'));
}
}
return Update::SUCCESS;
}
+
+function update_1332()
+{
+ $condition = ["`is-default` IS NOT NULL"];
+ $profiles = DBA::select('profile', [], $condition);
+
+ while ($profile = DBA::fetch($profiles)) {
+ DI::profileField()->migrateFromLegacyProfile($profile);
+ }
+ DBA::close($profiles);
+
+ DBA::update('contact', ['profile-id' => null], ['`profile-id` IS NOT NULL']);
+
+ return Update::SUCCESS;
+}
}
/* notifications unseen */
-.notify-unseen { background-color: #cceeFF; }
+.notification-unseen { background-color: #cceeFF; }
/* autocomplete popup */
ul.acpopup {
display: none;
}
}
+
+/* Profile Settings Custom Fields */
+body.dragging, body.dragging * {
+ cursor: ns-resize !important;
+}
+
+.dragged {
+ position: absolute;
+ opacity: 0.5;
+ z-index: 2000;
+}
+
+#profile-custom-fields > fieldset > legend {
+ cursor: ns-resize;
+}
+
+#profile-custom-fields div.placeholder {
+ position: relative;
+ margin: 0;
+ padding: 0;
+ border-top: 1px dotted black;
+}
+#profile-custom-fields div.placeholder:before {
+ position: absolute;
+ content: "";
+ width: 0;
+ height: 0;
+ margin-top: -7px;
+ left: -7px;
+ top: -1px;
+ border: 7px solid transparent;
+ border-left-color: black;
+ border-right: none;
+}
window.location.href=window.location.href
}
- ['net', 'home', 'intro', 'mail', 'events', 'birthdays', 'notify'].forEach(function(type) {
+ ['net', 'home', 'intro', 'mail', 'events', 'birthdays', 'notification'].forEach(function(type) {
var number = data[type];
if (number == 0) {
number = '';
var notification_id = 0;
// Insert notifs into the notifications-menu
- $(data.notifications).each(function(key, notif) {
- var text = notif.message.format('<span class="contactname">' + notif.name + '</span>');
- var contact = ('<a href="' + notif.url + '"><span class="contactname">' + notif.name + '</span></a>');
- var seenclass = (notif.seen == 1) ? "notify-seen" : "notify-unseen";
+ $(data.notifications).each(function(key, notification) {
+ var text = notification.message.format('<span class="contactname">' + notification.name + '</span>');
+ var contact = ('<a href="' + notification.url + '"><span class="contactname">' + notification.name + '</span></a>');
+ var seenclass = (notification.seen == 1) ? "notification-seen" : "notification-unseen";
var html = notifications_tpl.format(
- notif.href, // {0} // link to the source
- notif.photo, // {1} // photo of the contact
+ notification.href, // {0} // link to the source
+ notification.photo, // {1} // photo of the contact
text, // {2} // preformatted text (autor + text)
- notif.date, // {3} // date of notification (time ago)
+ notification.date, // {3} // date of notification (time ago)
seenclass, // {4} // visited status of the notification
- new Date(notif.timestamp*1000), // {5} // date of notification
- notif.url, // {6} // profile url of the contact
- notif.message.format(contact), // {7} // preformatted html (text including author profile url)
+ new Date(notification.timestamp*1000), // {5} // date of notification
+ notification.url, // {6} // profile url of the contact
+ notification.message.format(contact), // {7} // preformatted html (text including author profile url)
'' // {8} // Deprecated
);
nnm.append(html);
});
}
- var notif = data['notify'];
+ var notif = data['notification'];
if (notif > 0) {
$("#nav-notifications-linkmenu").addClass("on");
} else {
}
}
-function notifyMarkAll() {
- $.get('notify/mark/all', function(data) {
+function notificationMarkAll() {
+ $.get('notification/mark/all', function(data) {
if (timer) {
clearTimeout(timer);
}
--- /dev/null
+$(function () {
+ $("#profile-custom-fields").sortable({
+ containerSelector: 'div#profile-custom-fields',
+ handle: 'legend',
+ itemSelector: 'fieldset',
+ placeholder: '<div class="placeholder"></div>',
+ onDrag: function($item, position, _super, event) {
+ delete position['left'];
+ $item.css(position);
+ event.preventDefault();
+ }
+ });
+});
</div>
<div id="contact-info-end"></div>
{{/if}}
-
- {{if $profile_select}}
- <div id="contact-edit-profile-select-text">
- <h4>{{$lbl_vis1}}</h4>
- <p>{{$lbl_vis2}}</p>
- </div>
- {{$profile_select nofilter}}
- <div id="contact-edit-profile-select-end"></div>
- {{/if}}
</div>
<input class="contact-edit-submit" type="submit" name="submit" value="{{$submit}}" />
+++ /dev/null
-<h2>{{$header}}</h2>
-
-<div class="intro-wrapper" id="intro-{{$contact_id}}" >
-
-<p class="intro-desc">{{$str_notifytype}} {{$notify_type}}</p>
-<img id="photo-{{$contact_id}}" class="intro-photo" src="{{$photo}}" width="175" height=175" title="{{$fullname}}" alt="{{$fullname}}" />
-<dl><dt>{{$lbl_url}}</dt><dd><a target="blank" href="{{$zrl}}">{{$url}}</a></dd></dl>
-{{if $location}}<dl><dt>{{$lbl_location}}</dt><dd>{{$location}}</dd></dl>{{/if}}
-{{if $gender}}<dl><dt>{{$lbl_gender}}</dt><dd>{{$gender}}</dd></dl>{{/if}}
-{{if $keywords}}<dl><dt>{{$lbl_keywords}}</dt><dd>{{$keywords}}</dd></dl>{{/if}}
-{{if $about}}<dl><dt>{{$lbl_about}}</dt><dd>{{$about nofilter}}</dd></dl>{{/if}}
-<div class="intro-knowyou">{{$lbl_knowyou}} {{$knowyou}}</div>
-<div class="intro-note" id="intro-note-{{$contact_id}}">{{$note}}</div>
-<div class="intro-wrapper-end" id="intro-wrapper-end-{{$contact_id}}"></div>
-<form class="intro-form" action="notifications/{{$intro_id}}" method="post">
-<input class="intro-submit-ignore" type="submit" name="submit" value="{{$ignore}}" />
-{{if $discard}}<input class="intro-submit-discard" type="submit" name="submit" value="{{$discard}}" />{{/if}}
-</form>
-<div class="intro-form-end"></div>
-
-<form class="intro-approve-form" action="{{$action}}" method="post">
-{{include file="field_checkbox.tpl" field=$hidden}}
-<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}}" >
-
-{{$dfrn_text nofilter}}
-
-<input class="intro-submit-approve" type="submit" name="submit" value="{{$approve}}" />
-</form>
-</div>
-<div class="intro-end"></div>
<a accesskey="c" id="nav-community-link" class="nav-commlink {{$nav.community.2}} {{$sel.community}}" href="{{$nav.community.0}}" title="{{$nav.community.3}}" >{{$nav.community.1}}</a>
{{/if}}
{{if $nav.introductions}}
- <a id="nav-notify-link" class="nav-commlink {{$nav.introductions.2}} {{$sel.introductions}}" href="{{$nav.introductions.0}}" title="{{$nav.introductions.3}}" >{{$nav.introductions.1}}</a>
+ <a id="nav-notification-link" class="nav-commlink {{$nav.introductions.2}} {{$sel.introductions}}" href="{{$nav.introductions.0}}" title="{{$nav.introductions.3}}" >{{$nav.introductions.1}}</a>
<span id="intro-update" class="nav-ajax-left"></span>
{{/if}}
{{if $nav.messages}}
{{if $nav.notifications}}
<a accesskey="f" id="nav-notifications-linkmenu" class="nav-commlink" href="{{$nav.notifications.0}}" rel="#nav-notifications-menu" title="{{$nav.notifications.1}}">{{$nav.notifications.1}}</a>
- <span id="notify-update" class="nav-ajax-left"></span>
+ <span id="notification-update" class="nav-ajax-left"></span>
<ul id="nav-notifications-menu" class="menu-popup">
<li id="nav-notifications-see-all"><a href="{{$nav.notifications.all.0}}">{{$nav.notifications.all.1}}</a></li>
- <li id="nav-notifications-mark-all"><a href="#" onclick="notifyMarkAll(); return false;">{{$nav.notifications.mark.3}}</a></li>
+ <li id="nav-notifications-mark-all"><a href="#" onclick="notificationMarkAll(); return false;">{{$nav.notifications.mark.3}}</a></li>
<li class="empty">{{$emptynotifications}}</li>
</ul>
{{/if}}
+++ /dev/null
-
-<div class="intro-approve-as-friend-desc">
- <p>{{$approve_as1}}</p>
- <p>{{$approve_as2}}</p>
- <p>{{$approve_as3}}</p>
-</div>
-
-<div class="intro-approve-as-friend-wrapper">
- <label class="intro-approve-as-friend-label" for="intro-approve-as-friend-{{$intro_id}}">{{$as_friend}}</label>
- <input type="radio" name="duplex" id="intro-approve-as-friend-{{$intro_id}}" class="intro-approve-as-friend" {{$friend_selected}} value="1" />
- <div class="intro-approve-friend-break" ></div>
-</div>
-<div class="intro-approve-as-friend-end"></div>
-<div class="intro-approve-as-fan-wrapper">
- <label class="intro-approve-as-fan-label" for="intro-approve-as-fan-{{$intro_id}}">{{$as_fan}}</label>
- <input type="radio" name="duplex" id="intro-approve-as-fan-{{$intro_id}}" class="intro-approve-as-fan" {{$fan_selected}} value="0" />
- <div class="intro-approve-fan-break"></div>
-</div>
-<div class="intro-approve-as-end"></div>
+++ /dev/null
-
-
-<h1>{{$notif_header}}</h1>
-
-{{if $tabs }}{{include file="common_tabs.tpl"}}{{/if}}
-
-<div class="notif-network-wrapper">
- {{* The "show ignored" link *}}
- {{if $notif_show_lnk}}<a href="{{$notif_show_lnk.href}}" id="notifications-show-hide-link">{{$notif_show_lnk.text}}</a>{{/if}}
-
- {{* The notifications *}}
- {{if $notif_content}}
- {{foreach $notif_content as $notification}}
- {{$notification nofilter}}
- {{/foreach}}
- {{/if}}
-
- {{* If no notifications messages available *}}
- {{if $notif_nocontent}}
- <div class="notif_nocontent">{{$notif_nocontent}}</div>
- {{/if}}
-
- {{* The pager *}}
- {{$notif_paginate nofilter}}
-</div>
--- /dev/null
+
+<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
+ <a href="{{$item_link}}"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
+</div>
\ No newline at end of file
--- /dev/null
+
+<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
+ <a href="{{$item_link}}"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
+</div>
\ No newline at end of file
--- /dev/null
+
+<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
+ <a href="{{$item_link}}"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
+</div>
\ No newline at end of file
--- /dev/null
+
+<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
+ <a href="{{$item_link}}" target="friendica-notifications"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
+</div>
\ No newline at end of file
--- /dev/null
+<h2>{{$header}}</h2>
+
+<div class="intro-wrapper" id="intro-{{$contact_id}}" >
+
+<p class="intro-desc">{{$str_notification_type}} {{$str_type}}</p>
+<img id="photo-{{$contact_id}}" class="intro-photo" src="{{$photo}}" width="175" height=175" title="{{$fullname}}" alt="{{$fullname}}" />
+<dl><dt>{{$lbl_url}}</dt><dd><a target="blank" href="{{$zrl}}">{{$url}}</a></dd></dl>
+{{if $location}}<dl><dt>{{$lbl_location}}</dt><dd>{{$location}}</dd></dl>{{/if}}
+{{if $gender}}<dl><dt>{{$lbl_gender}}</dt><dd>{{$gender}}</dd></dl>{{/if}}
+{{if $keywords}}<dl><dt>{{$lbl_keywords}}</dt><dd>{{$keywords}}</dd></dl>{{/if}}
+{{if $about}}<dl><dt>{{$lbl_about}}</dt><dd>{{$about nofilter}}</dd></dl>{{/if}}
+<div class="intro-knowyou">{{$lbl_knowyou}} {{$knowyou}}</div>
+<div class="intro-note" id="intro-note-{{$contact_id}}">{{$note}}</div>
+<div class="intro-wrapper-end" id="intro-wrapper-end-{{$contact_id}}"></div>
+<form class="intro-form" action="notifications/{{$intro_id}}" method="post">
+<input class="intro-submit-ignore" type="submit" name="submit" value="{{$ignore}}" />
+{{if $discard}}<input class="intro-submit-discard" type="submit" name="submit" value="{{$discard}}" />{{/if}}
+</form>
+<div class="intro-form-end"></div>
+
+<form class="intro-approve-form" action="{{$action}}" method="post">
+{{include file="field_checkbox.tpl" field=$hidden}}
+<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}}" >
+
+{{$dfrn_text nofilter}}
+
+<input class="intro-submit-approve" type="submit" name="submit" value="{{$approve}}" />
+</form>
+</div>
+<div class="intro-end"></div>
--- /dev/null
+
+<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
+ <a href="{{$item_link}}"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
+</div>
\ No newline at end of file
--- /dev/null
+
+<div class="intro-approve-as-friend-desc">
+ <p>{{$approve_as1}}</p>
+ <p>{{$approve_as2}}</p>
+ <p>{{$approve_as3}}</p>
+</div>
+
+<div class="intro-approve-as-friend-wrapper">
+ <label class="intro-approve-as-friend-label" for="intro-approve-as-friend-{{$intro_id}}">{{$as_friend}}</label>
+ <input type="radio" name="duplex" id="intro-approve-as-friend-{{$intro_id}}" class="intro-approve-as-friend" {{$friend_selected}} value="1" />
+ <div class="intro-approve-friend-break" ></div>
+</div>
+<div class="intro-approve-as-friend-end"></div>
+<div class="intro-approve-as-fan-wrapper">
+ <label class="intro-approve-as-fan-label" for="intro-approve-as-fan-{{$intro_id}}">{{$as_fan}}</label>
+ <input type="radio" name="duplex" id="intro-approve-as-fan-{{$intro_id}}" class="intro-approve-as-fan" {{$fan_selected}} value="0" />
+ <div class="intro-approve-fan-break"></div>
+</div>
+<div class="intro-approve-as-end"></div>
--- /dev/null
+
+<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
+ <a href="{{$item_link}}"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
+</div>
--- /dev/null
+
+<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
+ <a href="{{$item_link}}"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
+</div>
\ No newline at end of file
--- /dev/null
+
+
+<h1>{{$header}}</h1>
+
+{{if $tabs }}{{include file="common_tabs.tpl"}}{{/if}}
+
+<div class="notif-network-wrapper">
+ {{* The "show ignored" link *}}
+ {{if $showLink}}<a href="{{$showLink.href}}" id="notifications-show-hide-link">{{$showLink.text}}</a>{{/if}}
+
+ {{* The notifications *}}
+ {{if $notifications}}
+ {{foreach $notifications as $notification}}
+ {{$notification nofilter}}
+ {{/foreach}}
+ {{/if}}
+
+ {{* If no notifications messages available *}}
+ {{if $noContent}}
+ <div class="notification_nocontent">{{$noContent}}</div>
+ {{/if}}
+
+ {{* The pager *}}
+ {{$paginate nofilter}}
+</div>
--- /dev/null
+
+<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
+ <a href="{{$item_link}}"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
+</div>
\ No newline at end of file
--- /dev/null
+
+
+<div class="intro-wrapper" >
+
+<p class="intro-desc">{{$str_notification_type}} {{$str_type}}</p>
+{{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}}" alt="{{$fullname}}" /></a>
+<div class="intro-note" >{{$note}}</div>
+<div class="intro-wrapper-end"></div>
+<form class="intro-form" action="notifications/{{$intro_id}}" method="post">
+<input class="intro-submit-ignore" type="submit" name="submit" value="{{$ignore}}" />
+<input class="intro-submit-discard" type="submit" name="submit" value="{{$discard}}" />
+</form>
+<div class="intro-form-end"></div>
+
+<form class="intro-approve-form" action="{{$request}}" method="get">
+{{include file="field_checkbox.tpl" field=$hidden}}
+<input class="intro-submit-approve" type="submit" name="submit" value="{{$approve}}" />
+</form>
+</div>
+<div class="intro-end"></div>
+++ /dev/null
-
-<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
- <a href="{{$item_link}}" target="friendica-notification"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
-</div>
\ No newline at end of file
+++ /dev/null
-
-<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
- <a href="{{$item_link}}" target="friendica-notifications"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
-</div>
\ No newline at end of file
+++ /dev/null
-
-<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
- <a href="{{$item_link}}" target="friendica-notifications"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
-</div>
\ No newline at end of file
+++ /dev/null
-
-<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
- <a href="{{$item_link}}" target="friendica-notifications"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
-</div>
\ No newline at end of file
+++ /dev/null
-
-<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
- <a href="{{$item_link}}" target="friendica-notification"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
-</div>
\ No newline at end of file
+++ /dev/null
-
-<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
- <a href="{{$item_link}}" target="friendica-notifications"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
-</div>
+++ /dev/null
-
-<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
- <a href="{{$item_link}}" target="friendica-notifications"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
-</div>
\ No newline at end of file
+++ /dev/null
-
-<div class="notif-item {{if !$item_seen}}unseen{{/if}}">
- <a href="{{$item_link}}" target="friendica-notifications"><img src="{{$item_image}}" class="notif-image">{{$item_text nofilter}} <span class="notif-when">{{$item_ago}}</span></a>
-</div>
\ No newline at end of file
+++ /dev/null
-<script type="text/javascript" src="view/js/country.js" ></script>
\ No newline at end of file
+++ /dev/null
-<div id="profile-edit-hide-friends-wrapper">
- {{include file="field_yesno.tpl" field=$yesno}}
-</div>
+++ /dev/null
-
-<p id="hide-wall-text">
-{{$desc nofilter}}
-</p>
-
- <div id="hide-wall-yes-wrapper">
- <label id="hide-wall-yes-label" for="hide-wall-yes">{{$yes_str}}</label>
- <input type="radio" name="hidewall" id="hide-wall-yes" {{$yes_selected}} value="1" />
-
- <div id="hide-wall-break" ></div>
- </div>
- <div id="hide-wall-no-wrapper">
- <label id="hide-wall-no-label" for="hide-wall-no">{{$no_str}}</label>
- <input type="radio" name="hidewall" id="hide-wall-no" {{$no_selected}} value="0" />
-
- <div id="hide-wall-end"></div>
- </div>
+++ /dev/null
-
-<p id="profile-in-directory">
-{{$desc nofilter}}
-</p>
-
- <div id="profile-in-dir-yes-wrapper">
- <label id="profile-in-dir-yes-label" for="profile-in-dir-yes">{{$yes_str}}</label>
- <input type="radio" name="profile_in_directory" id="profile-in-dir-yes" {{$yes_selected}} value="1" />
-
- <div id="profile-in-dir-break" ></div>
- </div>
- <div id="profile-in-dir-no-wrapper">
- <label id="profile-in-dir-no-label" for="profile-in-dir-no">{{$no_str}}</label>
- <input type="radio" name="profile_in_directory" id="profile-in-dir-no" {{$no_selected}} value="0" />
-
- <div id="profile-in-dir-end"></div>
- </div>
+++ /dev/null
-
-<p id="profile-in-directory">
-{{$desc nofilter}}
-</p>
-
- <div id="profile-in-netdir-yes-wrapper">
- <label id="profile-in-netdir-yes-label" for="profile-in-netdir-yes">{{$yes_str}}</label>
- <input type="radio" name="profile_in_netdirectory" id="profile-in-netdir-yes" {{$yes_selected}} value="1" />
-
- <div id="profile-in-netdir-break" ></div>
- </div>
- <div id="profile-in-netdir-no-wrapper">
- <label id="profile-in-netdir-no-label" for="profile-in-netdir-no">{{$no_str}}</label>
- <input type="radio" name="profile_in_netdirectory" id="profile-in-netdir-no" {{$no_selected}} value="0" />
-
- <div id="profile-in-netdir-end"></div>
- </div>
+++ /dev/null
-
-{{include file="section_title.tpl"}}
-
-<dl id="aprofile-fullname" class="aprofile">
- <dt>{{$profile.fullname.0}}</dt>
- <dd>{{$profile.fullname.1}}</dd>
-</dl>
-
-{{if $profile.membersince}}
-<dl id="aprofile-membersince" class="aprofile">
- <dt>{{$profile.membersince.0}}</dt>
- <dd>{{$profile.membersince.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.gender}}
-<dl id="aprofile-gender" class="aprofile">
- <dt>{{$profile.gender.0}}</dt>
- <dd>{{$profile.gender.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.birthday}}
-<dl id="aprofile-birthday" class="aprofile">
- <dt>{{$profile.birthday.0}}</dt>
- <dd>{{$profile.birthday.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.age}}
-<dl id="aprofile-age" class="aprofile">
- <dt>{{$profile.age.0}}</dt>
- <dd>{{$profile.age.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.marital}}
-<dl id="aprofile-marital" class="aprofile">
- <dt><span class="heart">♥</span> {{$profile.marital.0}}</dt>
- <dd>{{$profile.marital.1}}{{if $profile.marital.with}} ({{$profile.marital.with nofilter}}){{/if}}{{if $profile.howlong}} {{$profile.howlong}}{{/if}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.sexual}}
-<dl id="aprofile-sexual" class="aprofile">
- <dt>{{$profile.sexual.0}}</dt>
- <dd>{{$profile.sexual.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.pub_keywords}}
-<dl id="aprofile-tags" class="aprofile">
- <dt>{{$profile.pub_keywords.0}}</dt>
- <dd>{{$profile.pub_keywords.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.homepage}}
-<dl id="aprofile-homepage" class="aprofile">
- <dt>{{$profile.homepage.0}}</dt>
- <dd>{{$profile.homepage.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.hometown}}
-<dl id="aprofile-hometown" class="aprofile">
- <dt>{{$profile.hometown.0}}</dt>
- <dd>{{$profile.hometown.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.politic}}
-<dl id="aprofile-politic" class="aprofile">
- <dt>{{$profile.politic.0}}</dt>
- <dd>{{$profile.politic.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.religion}}
-<dl id="aprofile-religion" class="aprofile">
- <dt>{{$profile.religion.0}}</dt>
- <dd>{{$profile.religion.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.about}}
-<dl id="aprofile-about" class="aprofile">
- <dt>{{$profile.about.0}}</dt>
- <dd>{{$profile.about.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.interest}}
-<dl id="aprofile-interest" class="aprofile">
- <dt>{{$profile.interest.0}}</dt>
- <dd>{{$profile.interest.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.likes}}
-<dl id="aprofile-likes" class="aprofile">
- <dt>{{$profile.likes.0}}</dt>
- <dd>{{$profile.likes.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.dislikes}}
-<dl id="aprofile-dislikes" class="aprofile">
- <dt>{{$profile.dislikes.0}}</dt>
- <dd>{{$profile.dislikes.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.contact}}
-<dl id="aprofile-contact" class="aprofile">
- <dt>{{$profile.contact.0}}</dt>
- <dd>{{$profile.contact.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-
-{{if $profile.music}}
-<dl id="aprofile-music" class="aprofile">
- <dt>{{$profile.music.0}}</dt>
- <dd>{{$profile.music.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-
-{{if $profile.book}}
-<dl id="aprofile-book" class="aprofile">
- <dt>{{$profile.book.0}}</dt>
- <dd>{{$profile.book.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-
-{{if $profile.tv}}
-<dl id="aprofile-tv" class="aprofile">
- <dt>{{$profile.tv.0}}</dt>
- <dd>{{$profile.tv.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-
-{{if $profile.film}}
-<dl id="aprofile-film" class="aprofile">
- <dt>{{$profile.film.0}}</dt>
- <dd>{{$profile.film.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-
-{{if $profile.romance}}
-<dl id="aprofile-romance" class="aprofile">
- <dt>{{$profile.romance.0}}</dt>
- <dd>{{$profile.romance.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-
-{{if $profile.work}}
-<dl id="aprofile-work" class="aprofile">
- <dt>{{$profile.work.0}}</dt>
- <dd>{{$profile.work.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.education}}
-<dl id="aprofile-education" class="aprofile">
- <dt>{{$profile.education.0}}</dt>
- <dd>{{$profile.education.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-
-{{if $profile.forumlist}}
-<dl id="aprofile-forumlist" class="aprofile">
- <dt>{{$profile.forumlist.0}}</dt>
- <dd>{{$profile.forumlist.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-
--- /dev/null
+<div id="profile-page" class="generic-page-wrapper">
+ {{include file="section_title.tpl"}}
+
+ {{* The link to edit the profile*}}
+{{if $is_owner}}
+ <div id="profile-edit-links">
+ <ul class="nav nav-pills preferences">
+ <li class="pull-right">
+ <a class="btn btn-link btn-sm" type="button" id="profile-edit-link" href="{{$edit_link.url}}" title="{{$edit_link.title}}">
+ <i class="fa fa-pencil-square-o" aria-hidden="true"></i> {{$edit_link.label}}
+ </a>
+ </li>
+ {{if count($view_as_contacts)}}
+ <li class="pull-right">
+ <form action="{{$query_string}}" method="get">
+ <button type="submit" class="btn btn-sm">{{$view_as}}</button>
+ <select name="viewas" class="input-sm">
+ <option value="0">Yourself</option>
+ {{foreach $view_as_contacts as $contact}}
+ <option value="{{$contact.id}}"{{if $contact.id == $view_as_contact_id}} selected{{/if}}>{{$contact.name}}</option>
+ {{/foreach}}
+ </select>
+
+ </form>
+ </li>
+ {{/if}}
+ </ul>
+ <div class="clear"></div>
+ </div>
+{{/if}}
+ <dl id="{{$basic_fields.fullname.id}}" class="row {{$basic_fields.fullname.class|default:'aprofile'}}">
+ <dt class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$basic_fields.fullname.label}}</dt>
+ <dd class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$basic_fields.fullname.value}}</dd>
+ </dl>
+
+{{if $basic_fields.membersince}}
+ <dl id="aprofile-membersince" class="row {{$basic_fields.membersince.class|default:'aprofile'}}">
+ <hr class="profile-separator">
+ <dt class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$basic_fields.membersince.label}}</dt>
+ <dd class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$basic_fields.membersince.value}}</dd>
+ </dl>
+{{/if}}
+
+{{if $basic_fields.birthday}}
+ <dl id="aprofile-birthday" class="row {{$basic_fields.birthday.class|default:'aprofile'}}">
+ <hr class="profile-separator">
+ <dt class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$basic_fields.birthday.label}}</dt>
+ <dd class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$basic_fields.birthday.value}}</dd>
+ </dl>
+{{/if}}
+
+{{if $basic_fields.age}}
+ <dl id="aprofile-age" class="row {{$basic_fields.age.class|default:'aprofile'}}">
+ <hr class="profile-separator">
+ <dt class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$basic_fields.age.label}}</dt>
+ <dd class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$basic_fields.age.value}}</dd>
+ </dl>
+{{/if}}
+
+{{if $basic_fields.location}}
+ <dl id="aprofile-location" class="row {{$basic_fields.location.class|default:'aprofile'}}">
+ <hr class="profile-separator">
+ <dt class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$basic_fields.location.label}}</dt>
+ <dd class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$basic_fields.location.value}}</dd>
+ </dl>
+{{/if}}
+
+{{if $basic_fields.homepage}}
+ <dl id="aprofile-homepage" class="row {{$basic_fields.homepage.class|default:'aprofile'}}">
+ <hr class="profile-separator">
+ <dt class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$basic_fields.homepage.label}}</dt>
+ <dd class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$basic_fields.homepage.value nofilter}}</dd>
+ </dl>
+{{/if}}
+
+{{if $basic_fields.xmpp}}
+ <dl id="aprofile-xmpp" class="row {{$basic_fields.xmpp.class|default:'aprofile'}}">
+ <hr class="profile-separator">
+ <dt class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$basic_fields.xmpp.label}}</dt>
+ <dd class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$basic_fields.xmpp.value nofilter}}</dd>
+ </dl>
+{{/if}}
+
+{{if $basic_fields.pub_keywords}}
+ <dl id="aprofile-tags" class="row {{$basic_fields.pub_keywords.class|default:'aprofile'}}">
+ <hr class="profile-separator">
+ <dt class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$basic_fields.pub_keywords.label}}</dt>
+ <dd class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">
+ {{foreach $basic_fields.pub_keywords.value as $tag}}
+ <a href="{{$tag.url}}" class="tag label btn-info sm">{{$tag.label}} <i class="fa fa-bolt" aria-hidden="true"></i></a>
+ {{/foreach}}
+ </dd>
+ </dl>
+{{/if}}
+
+{{foreach $custom_fields as $custom_field}}
+ <dl id="{{$custom_field.id}}" class="row {{$custom_field.class|default:'aprofile'}}">
+ <hr class="profile-separator">
+ <dt class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$custom_field.label}}</dt>
+ <dd class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$custom_field.value nofilter}}</dd>
+ </dl>
+{{/foreach}}
+</div>
+++ /dev/null
-
-{{$default nofilter}}
-
-<h1>{{$banner}}</h1>
-
-<div id="profile-edit-links">
-<ul>
-<li><a href="profile_photo" id="profile-photo_upload-link" title="{{$profpic}}">{{$profpic}}</a></li>
-<li><a href="profile/{{$profile_id}}/view?tab=profile" id="profile-edit-view-link" title="{{$viewprof}}">{{$viewprof}}</a></li>
-<li><a href="{{$profile_clone_link}}" id="profile-edit-clone-link" title="{{$cr_prof}}">{{$cl_prof}}</a></li>
-<li></li>
-<li><a href="{{$profile_drop_link}}" id="profile-edit-drop-link" title="{{$del_prof}}" {{$disabled}} >{{$del_prof}}</a></li>
-
-</ul>
-</div>
-
-<div id="profile-edit-links-end"></div>
-
-
-<div id="profile-edit-wrapper" >
-<form id="profile-edit-form" name="form1" action="profiles/{{$profile_id}}" method="post" >
-<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
-
-{{if $detailled_profile}}
-{{include file="field_yesno.tpl" field=$details}}
-<div id="profile-edit-profile-name-wrapper" >
-<label id="profile-edit-profile-name-label" for="profile-edit-profile-name" >{{$profile_name.1}} </label>
-<input type="text" size="32" name="profile_name" id="profile-edit-profile-name" value="{{$profile_name.2}}" /><div class="required">*</div>
-</div>
-<div id="profile-edit-profile-name-end"></div>
-
-<div id="profile-edit-name-wrapper" >
-<label id="profile-edit-name-label" for="profile-edit-name" >{{$name.1}} </label>
-<input type="text" size="32" name="name" id="profile-edit-name" value="{{$name.2}}" />
-</div>
-<div id="profile-edit-name-end"></div>
-
-<div id="profile-edit-pdesc-wrapper" >
-<label id="profile-edit-pdesc-label" for="profile-edit-pdesc" >{{$pdesc.1}} </label>
-<input type="text" size="32" name="pdesc" id="profile-edit-pdesc" value="{{$pdesc.1}}" />
-</div>
-<div id="profile-edit-pdesc-end"></div>
-
-
-<div id="profile-edit-gender-wrapper" >
-<label id="profile-edit-gender-label" for="gender-select" >{{$lbl_gender}} </label>
-{{$gender nofilter}}
-</div>
-<div id="profile-edit-gender-end"></div>
-
-<div id="profile-edit-dob-wrapper" >
-{{$dob nofilter}}
-</div>
-<div id="profile-edit-dob-end"></div>
-
-{{$hide_friends nofilter}}
-
-<div class="profile-edit-submit-wrapper" >
-<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" />
-</div>
-<div class="profile-edit-submit-end"></div>
-
-
-<div id="profile-edit-address-wrapper" >
-<label id="profile-edit-address-label" for="profile-edit-address" >{{$address.1}} </label>
-<input type="text" size="32" name="address" id="profile-edit-address" value="{{$address.2}}" />
-</div>
-<div id="profile-edit-address-end"></div>
-
-<div id="profile-edit-locality-wrapper" >
-<label id="profile-edit-locality-label" for="profile-edit-locality" >{{$locality.1}} </label>
-<input type="text" size="32" name="locality" id="profile-edit-locality" value="{{$locality.2}}" />
-</div>
-<div id="profile-edit-locality-end"></div>
-
-
-<div id="profile-edit-postal-code-wrapper" >
-<label id="profile-edit-postal-code-label" for="profile-edit-postal-code" >{{$postal_code.1}} </label>
-<input type="text" size="32" name="postal_code" id="profile-edit-postal-code" value="{{$postal_code.2}}" />
-</div>
-<div id="profile-edit-postal-code-end"></div>
-
-<div id="profile-edit-country-name-wrapper" >
-<label id="profile-edit-country-name-label" for="profile-edit-country-name" >{{$country_name.1}} </label>
-<select name="country_name" id="profile-edit-country-name" onChange="Fill_States('{{$region.2}}');">
-<option selected="selected" >{{$country_name.2}}</option>
-<option>temp</option>
-</select>
-</div>
-<div id="profile-edit-country-name-end"></div>
-
-<div id="profile-edit-region-wrapper" >
-<label id="profile-edit-region-label" for="profile-edit-region" >{{$region.1}} </label>
-<select name="region" id="profile-edit-region" onChange="Update_Globals();" >
-<option selected="selected" >{{$region.2}}</option>
-<option>temp</option>
-</select>
-</div>
-<div id="profile-edit-region-end"></div>
-
-<div id="profile-edit-hometown-wrapper" >
-<label id="profile-edit-hometown-label" for="profile-edit-hometown" >{{$hometown.1}} </label>
-<input type="text" size="32" name="hometown" id="profile-edit-hometown" value="{{$hometown.2}}" />
-</div>
-<div id="profile-edit-hometown-end"></div>
-
-<div class="profile-edit-submit-wrapper" >
-<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" />
-</div>
-<div class="profile-edit-submit-end"></div>
-
-<div id="profile-edit-marital-wrapper" >
-<label id="profile-edit-marital-label" for="profile-edit-marital" >{{$lbl_marital nofilter}} </label>
-{{$marital nofilter}}
-</div>
-<label id="profile-edit-with-label" for="profile-edit-with" > {{$with.1}} </label>
-<input type="text" size="32" name="with" id="profile-edit-with" title="{{$with.3}}" value="{{$with.2}}" />
-<label id="profile-edit-howlong-label" for="profile-edit-howlong" > {{$howlong.1}} </label>
-<input type="text" size="32" name="howlong" id="profile-edit-howlong" title="{{$howlong.1}}" value="{{$howlong.1}}" />
-
-<div id="profile-edit-marital-end"></div>
-
-<div id="profile-edit-sexual-wrapper" >
-<label id="profile-edit-sexual-label" for="sexual-select" >{{$lbl_sexual}} </label>
-{{$sexual nofilter}}
-</div>
-<div id="profile-edit-sexual-end"></div>
-
-
-
-<div id="profile-edit-homepage-wrapper" >
-<label id="profile-edit-homepage-label" for="profile-edit-homepage" >{{$homepage.1}} </label>
-<input type="url" size="32" name="homepage" id="profile-edit-homepage" value="{{$homepage.2}}" />
-</div>
-<div id="profile-edit-homepage-end"></div>
-
-<div id="profile-edit-xmpp-wrapper" >
-<label id="profile-edit-xmpp-label" for="profile-edit-xmpp" >{{$xmpp.1}} </label>
-<input type="text" size="32" name="xmpp" id="profile-edit-xmpp" title="{{$lbl_ex2}}" value="{{$xmpp.2}}" />
-</div><div id="profile-edit-xmpp-desc">{{$xmpp.3}}</div>
-<div id="profile-edit-xmpp-end"></div>
-
-
-<div id="profile-edit-politic-wrapper" >
-<label id="profile-edit-politic-label" for="profile-edit-politic" >{{$politic.1}} </label>
-<input type="text" size="32" name="politic" id="profile-edit-politic" value="{{$politic.2}}" />
-</div>
-<div id="profile-edit-politic-end"></div>
-
-<div id="profile-edit-religion-wrapper" >
-<label id="profile-edit-religion-label" for="profile-edit-religion" >{{$religion.1}} </label>
-<input type="text" size="32" name="religion" id="profile-edit-religion" value="{{$religion.2}}" />
-</div>
-<div id="profile-edit-religion-end"></div>
-
-<div id="profile-edit-pubkeywords-wrapper" >
-<label id="profile-edit-pubkeywords-label" for="profile-edit-pubkeywords" >{{$pub_keywords.1}} </label>
-<input type="text" size="32" name="pub_keywords" id="profile-edit-pubkeywords" title="{{$lbl_ex2}}" value="{{$pub_keywords.2}}" />
-</div><div id="profile-edit-pubkeywords-desc">{{$pub_keywords.3}}</div>
-<div id="profile-edit-pubkeywords-end"></div>
-
-<div id="profile-edit-prvkeywords-wrapper" >
-<label id="profile-edit-prvkeywords-label" for="profile-edit-prvkeywords" >{{$prv_keywords.1}} </label>
-<input type="text" size="32" name="prv_keywords" id="profile-edit-prvkeywords" title="{{$lbl_ex2}}" value="{{$prv_keywords.2}}" />
-</div><div id="profile-edit-prvkeywords-desc">{{$prv_keywords.3}}</div>
-<div id="profile-edit-prvkeywords-end"></div>
-
-
-<div class="profile-edit-submit-wrapper" >
-<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" />
-</div>
-<div class="profile-edit-submit-end"></div>
-
-<div id="about-jot-wrapper" >
-<p id="about-jot-desc" >
-{{$about.1}}
-</p>
-
-<textarea rows="10" cols="72" id="profile-about-text" name="about" >{{$about.2}}</textarea>
-
-</div>
-<div id="about-jot-end"></div>
-
-
-<div id="interest-jot-wrapper" >
-<p id="interest-jot-desc" >
-{{$interest.1}}
-</p>
-
-<textarea rows="10" cols="72" id="interest-jot-text" name="interest" >{{$interest.2}}</textarea>
-
-</div>
-<div id="interest-jot-end"></div>
-
-
-<div id="likes-jot-wrapper" >
-<p id="likes-jot-desc" >
-{{$likes.1}}
-</p>
-
-<textarea rows="10" cols="72" id="likes-jot-text" name="likes" >{{$likes.2}}</textarea>
-
-</div>
-<div id="likes-jot-end"></div>
-
-
-<div id="dislikes-jot-wrapper" >
-<p id="dislikes-jot-desc" >
-{{$dislikes.1}}
-</p>
-
-<textarea rows="10" cols="72" id="dislikes-jot-text" name="dislikes" >{{$dislikes.2}}</textarea>
-
-</div>
-<div id="dislikes-jot-end"></div>
-
-
-<div id="contact-jot-wrapper" >
-<p id="contact-jot-desc" >
-{{$contact.1}}
-</p>
-
-<textarea rows="10" cols="72" id="contact-jot-text" name="contact" >{{$contact.2}}</textarea>
-
-</div>
-<div id="contact-jot-end"></div>
-
-
-<div class="profile-edit-submit-wrapper" >
-<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" />
-</div>
-<div class="profile-edit-submit-end"></div>
-
-
-<div id="music-jot-wrapper" >
-<p id="music-jot-desc" >
-{{$music.1}}
-</p>
-
-<textarea rows="10" cols="72" id="music-jot-text" name="music" >{{$music.2}}</textarea>
-
-</div>
-<div id="music-jot-end"></div>
-
-<div id="book-jot-wrapper" >
-<p id="book-jot-desc" >
-{{$book.1}}
-</p>
-
-<textarea rows="10" cols="72" id="book-jot-text" name="book" >{{$book.2}}</textarea>
-
-</div>
-<div id="book-jot-end"></div>
-
-
-
-<div id="tv-jot-wrapper" >
-<p id="tv-jot-desc" >
-{{$tv.1}}
-</p>
-
-<textarea rows="10" cols="72" id="tv-jot-text" name="tv" >{{$tv.2}}</textarea>
-
-</div>
-<div id="tv-jot-end"></div>
-
-
-
-<div id="film-jot-wrapper" >
-<p id="film-jot-desc" >
-{{$film.1}}
-</p>
-
-<textarea rows="10" cols="72" id="film-jot-text" name="film" >{{$film.2}}</textarea>
-
-</div>
-<div id="film-jot-end"></div>
-
-
-<div class="profile-edit-submit-wrapper" >
-<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" />
-</div>
-<div class="profile-edit-submit-end"></div>
-
-
-<div id="romance-jot-wrapper" >
-<p id="romance-jot-desc" >
-{{$romance.1}}
-</p>
-
-<textarea rows="10" cols="72" id="romance-jot-text" name="romance" >{{$romance.2}}</textarea>
-
-</div>
-<div id="romance-jot-end"></div>
-
-
-
-<div id="work-jot-wrapper" >
-<p id="work-jot-desc" >
-{{$work.1}}
-</p>
-
-<textarea rows="10" cols="72" id="work-jot-text" name="work" >{{$work.2}}</textarea>
-
-</div>
-<div id="work-jot-end"></div>
-
-
-
-<div id="education-jot-wrapper" >
-<p id="education-jot-desc" >
-{{$education.1}}
-</p>
-
-<textarea rows="10" cols="72" id="education-jot-text" name="education" >{{$education.2}}</textarea>
-
-</div>
-<div id="education-jot-end"></div>
-
-
-
-<div class="profile-edit-submit-wrapper" >
-<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" />
-</div>
-<div class="profile-edit-submit-end"></div>
-
-{{else}}
-{{if $personal_account}}
-{{include file="field_yesno.tpl" field=$details}}
-{{/if}}
-<div id="profile-edit-profile-name-wrapper" >
-<label id="profile-edit-profile-name-label" for="profile-edit-profile-name" >{{$profile_name.1}} </label>
-<input type="text" size="32" name="profile_name" id="profile-edit-profile-name" value="{{$profile_name.2}}" /><div class="required">*</div>
-</div>
-<div id="profile-edit-profile-name-end"></div>
-
-<div id="profile-edit-name-wrapper" >
-<label id="profile-edit-name-label" for="profile-edit-name" >{{$name.1}} </label>
-<input type="text" size="32" name="name" id="profile-edit-name" value="{{$name.2}}" />
-</div>
-<div id="profile-edit-name-end"></div>
-
-{{if $personal_account}}
-<div id="profile-edit-gender-wrapper" >
-<label id="profile-edit-gender-label" for="gender-select" >{{$lbl_gender}} </label>
-{{$gender nofilter}}
-</div>
-<div id="profile-edit-gender-end"></div>
-
-<div id="profile-edit-dob-wrapper" >
-{{$dob nofilter}}
-</div>
-<div id="profile-edit-dob-end"></div>
-{{/if}}
-
-<div id="profile-edit-homepage-wrapper" >
-<label id="profile-edit-homepage-label" for="profile-edit-homepage" >{{$homepage.1}} </label>
-<input type="url" size="32" name="homepage" id="profile-edit-homepage" value="{{$homepage.2}}" />
-</div>
-<div id="profile-edit-homepage-end"></div>
-
-<div id="profile-edit-xmpp-wrapper" >
-<label id="profile-edit-xmpp-label" for="profile-edit-xmpp" >{{$xmpp.1}} </label>
-<input type="text" size="32" name="xmpp" id="profile-edit-xmpp" title="{{$lbl_ex2}}" value="{{$xmpp.2}}" />
-</div><div id="profile-edit-xmpp-desc">{{$xmpp.3}}</div>
-<div id="profile-edit-xmpp-end"></div>
-
-
-{{$hide_friends nofilter}}
-
-<div id="profile-edit-address-wrapper" >
-<label id="profile-edit-address-label" for="profile-edit-address" >{{$address.1}} </label>
-<input type="text" size="32" name="address" id="profile-edit-address" value="{{$address.2}}" />
-</div>
-<div id="profile-edit-address-end"></div>
-
-<div id="profile-edit-locality-wrapper" >
-<label id="profile-edit-locality-label" for="profile-edit-locality" >{{$locality.1}} </label>
-<input type="text" size="32" name="locality" id="profile-edit-locality" value="{{$locality.2}}" />
-</div>
-<div id="profile-edit-locality-end"></div>
-
-
-<div id="profile-edit-postal-code-wrapper" >
-<label id="profile-edit-postal-code-label" for="profile-edit-postal-code" >{{$postal_code.1}} </label>
-<input type="text" size="32" name="postal_code" id="profile-edit-postal-code" value="{{$postal_code.2}}" />
-</div>
-<div id="profile-edit-postal-code-end"></div>
-
-<div id="profile-edit-country-name-wrapper" >
-<label id="profile-edit-country-name-label" for="profile-edit-country-name" >{{$country_name.1}} </label>
-<select name="country_name" id="profile-edit-country-name" onChange="Fill_States('{{$region.2}}');">
-<option selected="selected" >{{$country_name.1}}</option>
-<option>temp</option>
-</select>
-</div>
-<div id="profile-edit-country-name-end"></div>
-
-<div id="profile-edit-region-wrapper" >
-<label id="profile-edit-region-label" for="profile-edit-region" >{{$region.1}} </label>
-<select name="region" id="profile-edit-region" onChange="Update_Globals();" >
-<option selected="selected" >{{$region.2}}</option>
-<option>temp</option>
-</select>
-</div>
-<div id="profile-edit-region-end"></div>
-
-<div id="profile-edit-pubkeywords-wrapper" >
-<label id="profile-edit-pubkeywords-label" for="profile-edit-pubkeywords" >{{$pub_keywords.1}} </label>
-<input type="text" size="32" name="pub_keywords" id="profile-edit-pubkeywords" title="{{$lbl_ex2}}" value="{{$pub_keywords.2}}" />
-</div><div id="profile-edit-pubkeywords-desc">{{$pub_keywords.3}}</div>
-<div id="profile-edit-pubkeywords-end"></div>
-
-<div id="profile-edit-prvkeywords-wrapper" >
-<label id="profile-edit-prvkeywords-label" for="profile-edit-prvkeywords" >{{$prv_keywords.1}} </label>
-<input type="text" size="32" name="prv_keywords" id="profile-edit-prvkeywords" title="{{$lbl_ex2}}" value="{{$prv_keywords.2}}" />
-</div><div id="profile-edit-prvkeywords-desc">{{$prv_keywords.3}}</div>
-<div id="profile-edit-prvkeywords-end"></div>
-
-<div id="about-jot-wrapper" >
-<p id="about-jot-desc" >
-{{$about.1}}
-</p>
-
-<textarea rows="10" cols="72" id="profile-about-text" name="about" >{{$about.2}}</textarea>
-
-</div>
-<div id="about-jot-end"></div>
-
-<div class="profile-edit-submit-wrapper" >
-<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" />
-</div>
-<div class="profile-edit-submit-end"></div>
-
- <input type="hidden" name="pdesc" id="profile-edit-pdesc" value="{{$pdesc.2}}" />
- <input type="hidden" id="contact-jot-text" name="contact" value="{{$contact.2}}" />
- <input type="hidden" name="hometown" id="profile-edit-hometown" value="{{$hometown.2}}" />
- <input type="hidden" name="politic" id="profile-edit-politic" value="{{$politic.2}}" />
- <input type="hidden" name="religion" id="profile-edit-religion" value="{{$religion.2}}" />
- <input type="hidden" id="likes-jot-text" name="likes" value="{{$likes.2}}" />
- <input type="hidden" id="dislikes-jot-text" name="dislikes" value="{{$dislikes.2}}" />
- <input type="hidden" name="marital" id="profile-edit-marital" value="{{$marital.2}}" />
- <input type="hidden" name="with" id="profile-edit-with" value="{{$with.2}}" />
- <input type="hidden" name="howlong" id="profile-edit-howlong" value="{{$howlong.2}}" />
- <input type="hidden" name="sexual" id="profile-edit-sexual" value="{{$sexual.2}}" />
- <input type="hidden" id="romance-jot-text" name="romance" value="{{$romance.2}}" />
- <input type="hidden" id="work-jot-text" name="work" value="{{$work.2}}" />
- <input type="hidden" id="education-jot-text" name="education" value="{{$education.2}}" />
- <input type="hidden" id="interest-jot-text" name="interest" value="{{$interest.2}}" />
- <input type="hidden" id="music-jot-text" name="music" value="{{$music.2}}" />
- <input type="hidden" id="book-jot-text" name="book" value="{{$book.2}}" />
- <input type="hidden" id="tv-jot-text" name="tv" value="{{$tv.2}}" />
- <input type="hidden" id="film-jot-text" name="film" value="{{$film.2}}" />
-
-{{/if}}
-</form>
-</div>
-<script type="text/javascript">Fill_Country('{{$country_name.2}}');Fill_States('{{$region.2}}');</script>
+++ /dev/null
-
-<div class="profile-edit-side-div"><a class="profile-edit-side-link icon edit" title="{{$editprofile}}" href="profiles/{{$profid}}" ></a></div>
-<div class="clear"></div>
\ No newline at end of file
+++ /dev/null
-
-<div class="profile-listing" >
- <div class="profile-listing-photo-wrapper" >
- <a href="profiles/{{$id}}" class="profile-listing-edit-link"><img class="profile-listing-photo" id="profile-listing-photo-{{$id}}" src="{{$photo}}" alt="{{$alt}}" /></a>
- </div>
- <div class="profile-listing-photo-end"></div>
- <div class="profile-listing-name" id="profile-listing-name-{{$id}}">
- <a href="profiles/{{$id}}" class="profile-listing-edit-link" >{{$profile_name}}</a>
- </div>
- <div class="profile-listing-visible">{{$visible nofilter}}</div>
-</div>
-<div class="profile-listing-end"></div>
+++ /dev/null
-
-<h1>{{$header}}</h1>
-
-<p id="profile-listing-desc" class="button" >
- <a href="profile_photo" >{{$chg_photo}}</a>
-</p>
-
-<div id="profile-listing-new-link-wrapper" class="button" >
- <a href="{{$cr_new_link}}" id="profile-listing-new-link" title="{{$cr_new}}" >{{$cr_new}}</a>
-</div>
-
-<div id="profile-listing-profiles">
- {{$profiles nofilter}}
-</div>
--- /dev/null
+<fieldset data-id="{{$profile_field.id}}">
+ <legend>≡ {{$profile_field.legend}}</legend>
+
+ <input type="hidden" name="profile_field_order[]" value="{{$profile_field.id}}">
+
+ {{include file="field_input.tpl" field=$profile_field.fields.label}}
+
+ {{include file="field_textarea.tpl" field=$profile_field.fields.value}}
+ <details>
+ <summary>Permissions</summary>
+ {{$profile_field.fields.acl nofilter}}
+ </details>
+</fieldset>
\ No newline at end of file
--- /dev/null
+<div id="profile-edit-hide-friends-wrapper">
+ {{include file="field_yesno.tpl" field=$yesno}}
+</div>
--- /dev/null
+<h1>{{$banner}}</h1>
+
+{{$default nofilter}}
+
+<div id="profile-edit-links">
+ <ul>
+ <li><a href="settings/profile/photo" id="profile-photo_upload-link" title="{{$profpic}}">{{$profpic}}</a></li>
+ <li><a href="profile/{{$nickname}}" id="profile-edit-view-link" title="{{$viewprof}}">{{$viewprof}}</a></li>
+ </ul>
+</div>
+
+<div id="profile-edit-links-end"></div>
+
+<div id="profile-edit-wrapper">
+ <form id="profile-edit-form" name="form1" action="settings/profiles" method="post">
+ <input type="hidden" name="form_security_token" value="{{$form_security_token}}">
+
+ <div id="profile-edit-name-wrapper">
+ <label id="profile-edit-name-label" for="profile-edit-name">{{$name.1}} </label>
+ <input type="text" size="32" name="name" id="profile-edit-name" value="{{$name.2}}"/>
+ </div>
+ <div id="profile-edit-name-end"></div>
+ <div id="profile-edit-pdesc-wrapper">
+ <label id="profile-edit-pdesc-label" for="profile-edit-pdesc">{{$pdesc.1}} </label>
+ <input type="text" size="32" name="pdesc" id="profile-edit-pdesc" value="{{$pdesc.1}}"/>
+ </div>
+ <div id="profile-edit-pdesc-end"></div>
+ <div id="profile-edit-dob-wrapper">
+ {{$dob nofilter}}
+ </div>
+ <div id="profile-edit-dob-end"></div>
+ {{$hide_friends nofilter}}
+ <div class="profile-edit-submit-wrapper">
+ <input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
+ </div>
+ <div class="profile-edit-submit-end"></div>
+ <div id="profile-edit-address-wrapper">
+ <label id="profile-edit-address-label" for="profile-edit-address">{{$address.1}} </label>
+ <input type="text" size="32" name="address" id="profile-edit-address" value="{{$address.2}}"/>
+ </div>
+ <div id="profile-edit-address-end"></div>
+ <div id="profile-edit-locality-wrapper">
+ <label id="profile-edit-locality-label" for="profile-edit-locality">{{$locality.1}} </label>
+ <input type="text" size="32" name="locality" id="profile-edit-locality" value="{{$locality.2}}"/>
+ </div>
+ <div id="profile-edit-locality-end"></div>
+ <div id="profile-edit-postal-code-wrapper">
+ <label id="profile-edit-postal-code-label" for="profile-edit-postal-code">{{$postal_code.1}} </label>
+ <input type="text" size="32" name="postal_code" id="profile-edit-postal-code" value="{{$postal_code.2}}"/>
+ </div>
+ <div id="profile-edit-postal-code-end"></div>
+ <div id="profile-edit-country-name-wrapper">
+ <label id="profile-edit-country-name-label" for="profile-edit-country-name">{{$country_name.1}} </label>
+ <select name="country_name" id="profile-edit-country-name" onChange="Fill_States('{{$region.2}}');">
+ <option selected="selected">{{$country_name.2}}</option>
+ <option>temp</option>
+ </select>
+ </div>
+ <div id="profile-edit-country-name-end"></div>
+ <div id="profile-edit-region-wrapper">
+ <label id="profile-edit-region-label" for="profile-edit-region">{{$region.1}} </label>
+ <select name="region" id="profile-edit-region" onChange="Update_Globals();">
+ <option selected="selected">{{$region.2}}</option>
+ <option>temp</option>
+ </select>
+ </div>
+ <div id="profile-edit-hometown-end"></div>
+ <div class="profile-edit-submit-wrapper">
+ <input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
+ </div>
+ <div class="profile-edit-submit-end"></div>
+ <div id="profile-edit-homepage-wrapper">
+ <label id="profile-edit-homepage-label" for="profile-edit-homepage">{{$homepage.1}} </label>
+ <input type="url" size="32" name="homepage" id="profile-edit-homepage" value="{{$homepage.2}}"/>
+ </div>
+ <div id="profile-edit-homepage-end"></div>
+ <div id="profile-edit-xmpp-wrapper">
+ <label id="profile-edit-xmpp-label" for="profile-edit-xmpp">{{$xmpp.1}} </label>
+ <input type="text" size="32" name="xmpp" id="profile-edit-xmpp" title="{{$lbl_ex2}}" value="{{$xmpp.2}}"/>
+ </div>
+ <div id="profile-edit-xmpp-desc">{{$xmpp.3}}</div>
+ <div id="profile-edit-xmpp-end"></div>
+ <div id="profile-edit-pubkeywords-wrapper">
+ <label id="profile-edit-pubkeywords-label" for="profile-edit-pubkeywords">{{$pub_keywords.1}} </label>
+ <input type="text" size="32" name="pub_keywords" id="profile-edit-pubkeywords" title="{{$lbl_ex2}}" value="{{$pub_keywords.2}}"/>
+ </div>
+ <div id="profile-edit-pubkeywords-desc">{{$pub_keywords.3}}</div>
+ <div id="profile-edit-pubkeywords-end"></div>
+ <div id="profile-edit-prvkeywords-wrapper">
+ <label id="profile-edit-prvkeywords-label" for="profile-edit-prvkeywords">{{$prv_keywords.1}} </label>
+ <input type="text" size="32" name="prv_keywords" id="profile-edit-prvkeywords" title="{{$lbl_ex2}}" value="{{$prv_keywords.2}}"/>
+ </div>
+ <div id="profile-edit-prvkeywords-desc">{{$prv_keywords.3}}</div>
+ <div id="profile-edit-prvkeywords-end"></div>
+ <div class="profile-edit-submit-wrapper">
+ <input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
+ </div>
+ <div class="profile-edit-submit-end"></div>
+
+ <h3>{{$lbl_custom_fields_section}}</h3>
+ {{$custom_fields_description nofilter}}
+ <div id="profile-custom-fields">
+ {{foreach $custom_fields as $custom_field}}
+ {{include file="settings/profile/field/edit.tpl" profile_field=$custom_field}}
+ {{/foreach}}
+ </div>
+
+ <div class="profile-edit-submit-wrapper">
+ <input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
+ </div>
+ <div class="profile-edit-submit-end"></div>
+ </form>
+</div>
+<script type="text/javascript">
+ Fill_Country('{{$country_name.2}}');
+ Fill_States('{{$region.2}}');
+</script>
--- /dev/null
+<script type="text/javascript" src="view/js/country.js" ></script>
\ No newline at end of file
--- /dev/null
+<div class="profile-edit-side-div"><a class="profile-edit-side-link icon edit" title="{{$editprofile}}" href="settings/profile"></a></div>
+<div class="clear"></div>
<div class="settings-content-block">
<div id="settings-notifications">
-<div id="settings-notify-desc">{{$lbl_not}}</div>
+<div id="settings-notification-desc">{{$lbl_not}}</div>
<div class="group">
{{include file="field_intcheckbox.tpl" field=$notify1}}
+++ /dev/null
-
-
-<div class="intro-wrapper" >
-
-<p class="intro-desc">{{$str_notifytype}} {{$notify_type}}</p>
-{{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}}" alt="{{$fullname}}" /></a>
-<div class="intro-note" >{{$note}}</div>
-<div class="intro-wrapper-end"></div>
-<form class="intro-form" action="notifications/{{$intro_id}}" method="post">
-<input class="intro-submit-ignore" type="submit" name="submit" value="{{$ignore}}" />
-<input class="intro-submit-discard" type="submit" name="submit" value="{{$discard}}" />
-</form>
-<div class="intro-form-end"></div>
-
-<form class="intro-approve-form" action="{{$request}}" method="get">
-{{include file="field_checkbox.tpl" field=$hidden}}
-<input class="intro-submit-approve" type="submit" name="submit" value="{{$approve}}" />
-</form>
-</div>
-<div class="intro-end"></div>
{{$profile_photo_txt nofilter}}
</li>
<li>
- <a target="newmember" href="profiles">{{$profiles_link}}</a><br />
+ <a target="newmember" href="settings/profile">{{$profiles_link}}</a><br />
{{$profiles_txt nofilter}}
</li>
<li>
- <a target="newmember" href="profiles">{{$profiles_keywords_link}}</a><br />
+ <a target="newmember" href="settings/profile">{{$profiles_keywords_link}}</a><br />
{{$profiles_keywords_txt nofilter}}
</li>
</ul>
background:#444;
}
-.notify-seen {
+.notification-seen {
background:#111;
}
#profile-edit-links ul {
list-style-type: none;
}
-
#profile-edit-links li {
margin-top: 10px;
}
+
+#profile-menu {
+ display: none;
+}
+
.profile-edit-side-div {
float: right;
}
#settings-notifications label {
margin-left: 20px;
}
-#settings-notify-desc, #settings-activity-desc {
+#settings-notification-desc, #settings-activity-desc {
font-weight: bold;
margin-bottom: 15px;
}
#crepair-url-label,
#crepair-request-label,
#crepair-confirm-label,
-#crepair-notify-label,
+#crepair-notification-label,
#crepair-photo-label,
#crepair-poll-label {
float: left;
margin-right: -20px;
}
-.nav-notify {
+.nav-notification {
display: none;
position: absolute;
font-size: 10px;
min-width: 15px;
text-align: right;
}
-.nav-notify.show {
+.nav-notification.show {
display: block;
}
#nav-notifications-menu {
padding: 7px 7px 0px 0px;
}
-.notify-seen {
+.notification-seen {
background: #DDDDDD;
}
<a accesskey="c" id="nav-community-link" class="nav-commlink {{$nav.community.2}} {{$sel.community}}" href="{{$nav.community.0}}" title="{{$nav.community.3}}" >{{$nav.community.1}}</a>
{{/if}}
{{if $nav.introductions}}
- <a id="nav-notify-link" class="nav-commlink {{$nav.introductions.2}} {{$sel.introductions}}" href="{{$nav.introductions.0}}" title="{{$nav.introductions.3}}" >{{$nav.introductions.1}}</a>
+ <a id="nav-notification-link" class="nav-commlink {{$nav.introductions.2}} {{$sel.introductions}}" href="{{$nav.introductions.0}}" title="{{$nav.introductions.3}}" >{{$nav.introductions.1}}</a>
<span id="intro-update" class="nav-ajax-left"></span>
{{/if}}
{{if $nav.messages}}
{{if $nav.notifications}}
<a accesskey="f" id="nav-notifications-linkmenu" class="nav-commlink" href="{{$nav.notifications.0}}" rel="#nav-notifications-menu" title="{{$nav.notifications.1}}">{{$nav.notifications.1}}</a>
- <span id="notify-update" class="nav-ajax-left"></span>
+ <span id="notification-update" class="nav-ajax-left"></span>
<ul id="nav-notifications-menu" class="menu-popup">
<li id="nav-notifications-see-all"><a href="{{$nav.notifications.all.0}}">{{$nav.notifications.all.1}}</a></li>
- <li id="nav-notifications-mark-all"><a href="#" onclick="notifyMarkAll(); return false;">{{$nav.notifications.mark.3}}</a></li>
+ <li id="nav-notifications-mark-all"><a href="#" onclick="notificationMarkAll(); return false;">{{$nav.notifications.mark.3}}</a></li>
<li class="empty">{{$emptynotifications}}</li>
</ul>
{{/if}}
text-decoration: none;
text-align: left
}
-#topbar-first .topbar-nav .nav-segment .nav-notify {
+#topbar-first .topbar-nav .nav-segment .nav-notification {
position: absolute;
top: 4px;
right: -2px;
font-size: 12px;
}
-#topbar-first #nav-notifications-menu li.notify-unseen {
+#topbar-first #nav-notifications-menu li.notification-unseen {
border-left: 3px solid #f3fcfd;
background-color: #f3fcfd;
}
#topbar-first .account .user-title span {
color: $nav_icon_color;
}
-#topbar-first .account #main-menu .nav-notify {
+#topbar-first .account #main-menu .nav-notification {
position: absolute;
top: 4px;
right: -2px;
font-family: ".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Helvetica,Arial,sans-serif;
}
-#topbar-first #nav-notifications-menu li.notify-unseen {
+#topbar-first #nav-notifications-menu li.notification-unseen {
border-left: 3px solid #f3fcfd;
background-color: antiquewhite;
}
</div>
</div>
{{/if}}
- {{if $lbl_vis1}}
- <div class="panel">
- <div class="section-subtitle-wrapper" role="tab" id="contact-edit-profile-select">
- <h4>
- <a class="accordion-toggle collapsed" data-toggle="collapse" data-parent="#contact-edit-tools" href="#contact-edit-profile-select-collapse" aria-expanded="false" aria-controls="contact-edit-profile-select-collapse">
- {{$lbl_vis1}}
- </a>
- </h4>
- </div>
- <div id="contact-edit-profile-select-collapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="contact-edit-profile-select">
- <div class="section-content-tools-wrapper">
- {{if $profile_select}}
- <div id="contact-edit-profile-select-text">
- <p>{{$lbl_vis2}}</p>
- </div>
- <div class="form-group">
- {{$profile_select nofilter}}
- </div>
- <div class="clear"></div>
- {{/if}}
-
- <div class="form-group pull-right settings-submit-wrapper" >
- <button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
- </div>
- <div class="clear"></div>
- </div>
- </div>
- </div>
- {{/if}}
</div>
</form>{{* End of the form *}}
+++ /dev/null
-
-{{* 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-{{$intro_id}}" class="intro-photo media-object" src="{{$photo}}" title="{{$fullname}}" alt="{{$fullname}}" />
- </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-{{$intro_id}}');" aria-label="{{$approve}}" title="{{$approve}}" 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}}" aria-label="{{$ignore}}" title="{{$ignore}}" data-toggle="tooltip"><i class="fa fa-ban" aria-hidden="true"></i></button>
- {{if $discard}}<button class="btn-link intro-submit-discard intro-action-link" type="submit" name="submit" value="{{$discard}}" aria-label="{{$discard}}" title="{{$discard}}" data-toggle="tooltip"><i class="fa fa-trash-o" aria-hidden="true"></i></button>{{/if}}
- </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>
- {{* 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">
- <div class="intro-url"><span class="intro-url-label">{{$lbl_url}}: </span><a href="{{$zrl}}">{{$url}}</a></div>
- {{if $network}}<div class="intro-network"><span class="intro-network-label">{{$lbl_network}}</span> {{$network}}</div>{{/if}}
- {{if $location}}<div class="intro-location"><span class="intro-location-label">{{$lbl_location}}</span> {{$location}}</div>{{/if}}
- {{if $gender}}<div class="intro-gender"><span class="intro-gender-label">{{$lbl_gender}}</span> {{$gender}}</div>{{/if}}
- {{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 nofilter}}</div>{{/if}}
- <div class="intro-knowyou"><span class="intro-knowyou-label">{{$lbl_knowyou}}</span>{{$knowyou}}</div>
- <div class="intro-note intro-note-{{$intro_id}}">{{$note}}</div>
- </div>
-
- {{* Additional information of the contact for mobile view *}}
- <div class="intro-contact-info xs hidden-lg hidden-md hidden-sm">
- <div class="intro-url"><span class="intro-url-label">{{$lbl_url}}:</span><a href="{{$zrl}}">{{$url}}</a></div>
- {{if $network}}<div class="intro-network"><span class="intro-network-label">{{$lbl_network}}</span>{{$network}}</div>{{/if}}
- {{if $location}}<div class="intro-location"><span class="intro-location-label">{{$lbl_location}}</span>{{$location}}</div>{{/if}}
- {{if $gender}}<div class="intro-gender"><span class="intro-gender-label">{{$lbl_gender}}</span>{{$gender}}</div>{{/if}}
- {{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 nofilter}}</div>{{/if}}
- <div class="intro-knowyou"><span class="intro-knowyou-label">{{$lbl_knowyou}}</span>{{$knowyou}}</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-{{$intro_id}}" style="display: none;">
-
- <h3 class="heading">{{$fullname}}{{if $addr}} ({{$addr}}){{/if}}</h3>
- <form class="intro-approve-form" {{if $request}}action="{{$request}}" method="get"{{else}}action="{{$action}}" 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 nofilter}}
-
- <div class="pull-right">
- <button class="btn btn-primary intro-submit-approve" type="submit" name="submit" value="{{$approve}}">{{$approve}}</button>
- </div>
- <div class="clear"></div>
- </form>
- </div>
- </div>
-
- {{* On mobile touch devices we use buttons for approve, ingnore && discard to have a better UX *}}
- {{if $APP->is_mobile}}
- <div class="intro-action-buttons">
- <form class="intro-form pull-left" action="notifications/{{$intro_id}}" method="post">
- <button class="btn btn-small btn-default intro-submit-ignore" type="submit" name="submit" value="{{$ignore}}">{{$ignore}}</button>
- {{if $discard}}<button class="btn btn-small btn-default intro-submit-discard" type="submit" name="submit" value="{{$discard}}">{{$discard}}</button> {{/if}}
- </form>
- <button class="btn btn-small btn-primary intro-submit-approve pull-right" onclick="addElmToModal('#intro-approve-wrapper-{{$intro_id}}')">{{$approve}}</button>
- </div>
- <div class="clear"></div>
- {{/if}}
-</div>
-<div class="intro-end"></div>
<ul class="nav navbar-nav navbar-left" role="menubar">
<li id="nav-communication" class="nav-segment" role="presentation">
{{if $nav.network}}
- <a accesskey="n" role="menuitem" class="nav-menu {{$sel.network}}" href="{{$nav.network.0}}" data-toggle="tooltip" aria-label="{{$nav.network.3}}" title="{{$nav.network.3}}"><i class="fa fa-lg fa-th" aria-hidden="true"></i><span id="net-update" class="nav-network-badge badge nav-notify"></span></a>
+ <a accesskey="n" role="menuitem" class="nav-menu {{$sel.network}}" href="{{$nav.network.0}}" data-toggle="tooltip" aria-label="{{$nav.network.3}}" title="{{$nav.network.3}}"><i class="fa fa-lg fa-th" aria-hidden="true"></i><span id="net-update" class="nav-network-badge badge nav-notification"></span></a>
{{/if}}
{{if $nav.home}}
- <a accesskey="p" role="menuitem" class="nav-menu {{$sel.home}}" href="{{$nav.home.0}}" data-toggle="tooltip" aria-label="{{$nav.home.3}}" title="{{$nav.home.3}}"><i class="fa fa-lg fa-home" aria-hidden="true"></i><span id="home-update" class="nav-home-badge badge nav-notify"></span></a>
+ <a accesskey="p" role="menuitem" class="nav-menu {{$sel.home}}" href="{{$nav.home.0}}" data-toggle="tooltip" aria-label="{{$nav.home.3}}" title="{{$nav.home.3}}"><i class="fa fa-lg fa-home" aria-hidden="true"></i><span id="home-update" class="nav-home-badge badge nav-notification"></span></a>
{{/if}}
{{if $nav.community}}
<li id="nav-personal" class="nav-segment hidden-xs" role="presentation">
{{if $nav.messages}}
- <a role="menuitem" id="nav-messages-link" href="{{$nav.messages.0}}" data-toggle="tooltip" aria-label="{{$nav.messages.1}}" title="{{$nav.messages.1}}" class="nav-menu {{$sel.messages}}"><i class="fa fa-envelope fa-lg" aria-hidden="true"></i><span id="mail-update" class="nav-mail-badge badge nav-notify"></span></a>
+ <a role="menuitem" id="nav-messages-link" href="{{$nav.messages.0}}" data-toggle="tooltip" aria-label="{{$nav.messages.1}}" title="{{$nav.messages.1}}" class="nav-menu {{$sel.messages}}"><i class="fa fa-envelope fa-lg" aria-hidden="true"></i><span id="mail-update" class="nav-mail-badge badge nav-notification"></span></a>
{{/if}}
{{if $nav.events}}
{{if $nav.contacts}}
<a role="menuitem" id="nav-contacts-link" class="nav-menu {{$sel.contacts}} {{$nav.contacts.2}}" href="{{$nav.contacts.0}}" data-toggle="tooltip" aria-label="{{$nav.contacts.1}}" title="{{$nav.contacts.1}}" ><i class="fa fa-users fa-lg" aria-hidden="true"></i></a>
- <span id="intro-update" class="nav-intro-badge badge nav-notify" onclick="window.location.href = '{{$nav.introductions.0}}' " data-toggle="tooltip" aria-label="{{$nav.introductions.3}}" title="{{$nav.introductions.3}}"></span>
+ <span id="intro-update" class="nav-intro-badge badge nav-notification" onclick="window.location.href = '{{$nav.introductions.0}}' " data-toggle="tooltip" aria-label="{{$nav.introductions.3}}" title="{{$nav.introductions.3}}"></span>
{{/if}}
</li>
<a href="{{$nav.notifications.0}}" rel="#nav-notifications-menu" data-toggle="tooltip" aria-label="{{$nav.notifications.1}}" title="{{$nav.notifications.1}}" role="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" aria-controls="nav-notifications-menu">
<i class="fa fa-bell fa-lg" aria-hidden="true"></i>
<span role="menuitem" class="sr-only">{{$nav.notifications.1}}</span>
- <span id="notify-update" class="nav-notify-badge badge nav-notify dropdown" data-toggle="dropdown"></span>
+ <span id="notification-update" class="nav-notification-badge badge nav-notification dropdown" data-toggle="dropdown"></span>
</a>
{{* The notifications dropdown menu. There are two parts of menu. The second is at the bottom of this file. It is loaded via js. Look at nav-notifications-template *}}
<div class="arrow"></div>
{{$nav.notifications.1}}
<div class="dropdown-header-link">
- <button role="menuitem" type="button" class="btn-link" onclick="notifyMarkAll();" data-toggle="tooltip" aria-label="{{$nav.notifications.mark.3}}" title="{{$nav.notifications.mark.3}}">{{$nav.notifications.mark.1}}</button>
+ <button role="menuitem" type="button" class="btn-link" onclick="notificationMarkAll();" data-toggle="tooltip" aria-label="{{$nav.notifications.mark.3}}" title="{{$nav.notifications.mark.3}}">{{$nav.notifications.mark.1}}</button>
</div>
</li>
<li role="presentation"><a role="menuitem" href="{{$nav.notifications.all.0}}" title="{{$nav.notifications.1}}"><i class="fa fa-bell fa-fw" aria-hidden="true"></i> {{$nav.notifications.1}}</a></li>
{{/if}}
{{if $nav.messages}}
- <li role="presentation"><a role="menuitem" class="nav-commlink {{$nav.messages.2}} {{$sel.messages}}" href="{{$nav.messages.0}}" title="{{$nav.messages.3}}" ><i class="fa fa-envelope fa-fw" aria-hidden="true"></i> {{$nav.messages.1}} <span id="mail-update-li" class="nav-mail-badge badge nav-notify"></span></a></li>
+ <li role="presentation"><a role="menuitem" class="nav-commlink {{$nav.messages.2}} {{$sel.messages}}" href="{{$nav.messages.0}}" title="{{$nav.messages.3}}" ><i class="fa fa-envelope fa-fw" aria-hidden="true"></i> {{$nav.messages.1}} <span id="mail-update-li" class="nav-mail-badge badge nav-notification"></span></a></li>
{{/if}}
<li role="presentation" class="divider"></li>
{{if $nav.contacts}}
- <li role="presentation"><a role="menuitem" id="nav-menu-contacts-link" class="nav-link {{$nav.contacts.2}}" href="{{$nav.contacts.0}}" title="{{$nav.contacts.3}}"><i class="fa fa-users fa-fw" aria-hidden="true"></i> {{$nav.contacts.1}}</a><span id="intro-update-li" class="nav-intro-badge badge nav-notify"></span></li>
+ <li role="presentation"><a role="menuitem" id="nav-menu-contacts-link" class="nav-link {{$nav.contacts.2}}" href="{{$nav.contacts.0}}" title="{{$nav.contacts.3}}"><i class="fa fa-users fa-fw" aria-hidden="true"></i> {{$nav.contacts.1}}</a><span id="intro-update-li" class="nav-intro-badge badge nav-notification"></span></li>
{{/if}}
{{if $nav.delegation}}
<li role="presentation"><a role="menuitem" id="nav-delegation-link" class="nav-commlink {{$nav.delegation.2}} {{$sel.delegation}}" href="{{$nav.delegation.0}}" title="{{$nav.delegation.3}}"><i class="fa fa-flag fa-fw" aria-hidden="true"></i> {{$nav.delegation.1}}</a></li>
+++ /dev/null
-<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}}
-
- {{if $tabs }}{{include file="common_tabs.tpl"}}{{/if}}
-
- <div class="notif-network-wrapper">
- {{* The "show ignored" link *}}
- {{if $notif_show_lnk}}<a href="{{$notif_show_lnk.href}}" id="notifications-show-hide-link">{{$notif_show_lnk.text}}</a>{{/if}}
-
- {{* The notifications *}}
- {{if $notif_content}}
- <ul class="notif-network-list media-list">
- {{foreach $notif_content as $notification}}
- <li>{{$notification nofilter}}</li>
- {{/foreach}}
- </ul>
- {{/if}}
-
- {{* If no notifications messages available *}}
- {{if $notif_nocontent}}
- <div class="notif_nocontent">{{$notif_nocontent}}</div>
- {{/if}}
- </div>
-
- {{* The pager *}}
- {{$notif_paginate nofilter}}
-</div>
--- /dev/null
+
+{{include file="notifications/notification.tpl"}}
--- /dev/null
+
+{{include file="notifications/notification.tpl"}}
--- /dev/null
+
+{{include file="notifications/notification.tpl"}}
--- /dev/null
+
+{{include file="notifications/notification.tpl"}}
--- /dev/null
+
+{{* 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-{{$intro_id}}" class="intro-photo media-object" src="{{$photo}}" title="{{$fullname}}" alt="{{$fullname}}" />
+ </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-{{$intro_id}}');" aria-label="{{$approve}}" title="{{$approve}}" 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}}" aria-label="{{$ignore}}" title="{{$ignore}}" data-toggle="tooltip"><i class="fa fa-ban" aria-hidden="true"></i></button>
+ {{if $discard}}<button class="btn-link intro-submit-discard intro-action-link" type="submit" name="submit" value="{{$discard}}" aria-label="{{$discard}}" title="{{$discard}}" data-toggle="tooltip"><i class="fa fa-trash-o" aria-hidden="true"></i></button>{{/if}}
+ </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_notification_type}}</span> {{$str_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">
+ <div class="intro-url"><span class="intro-url-label">{{$lbl_url}}: </span><a href="{{$zrl}}">{{$url}}</a></div>
+ {{if $network}}<div class="intro-network"><span class="intro-network-label">{{$lbl_network}}</span> {{$network}}</div>{{/if}}
+ {{if $location}}<div class="intro-location"><span class="intro-location-label">{{$lbl_location}}</span> {{$location}}</div>{{/if}}
+ {{if $gender}}<div class="intro-gender"><span class="intro-gender-label">{{$lbl_gender}}</span> {{$gender}}</div>{{/if}}
+ {{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 nofilter}}</div>{{/if}}
+ <div class="intro-knowyou"><span class="intro-knowyou-label">{{$lbl_knowyou}}</span>{{$knowyou}}</div>
+ <div class="intro-note intro-note-{{$intro_id}}">{{$note}}</div>
+ </div>
+
+ {{* Additional information of the contact for mobile view *}}
+ <div class="intro-contact-info xs hidden-lg hidden-md hidden-sm">
+ <div class="intro-url"><span class="intro-url-label">{{$lbl_url}}:</span><a href="{{$zrl}}">{{$url}}</a></div>
+ {{if $network}}<div class="intro-network"><span class="intro-network-label">{{$lbl_network}}</span>{{$network}}</div>{{/if}}
+ {{if $location}}<div class="intro-location"><span class="intro-location-label">{{$lbl_location}}</span>{{$location}}</div>{{/if}}
+ {{if $gender}}<div class="intro-gender"><span class="intro-gender-label">{{$lbl_gender}}</span>{{$gender}}</div>{{/if}}
+ {{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 nofilter}}</div>{{/if}}
+ <div class="intro-knowyou"><span class="intro-knowyou-label">{{$lbl_knowyou}}</span>{{$knowyou}}</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-{{$intro_id}}" style="display: none;">
+
+ <h3 class="heading">{{$fullname}}{{if $addr}} ({{$addr}}){{/if}}</h3>
+ <form class="intro-approve-form" {{if $request}}action="{{$request}}" method="get"{{else}}action="{{$action}}" 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 nofilter}}
+
+ <div class="pull-right">
+ <button class="btn btn-primary intro-submit-approve" type="submit" name="submit" value="{{$approve}}">{{$approve}}</button>
+ </div>
+ <div class="clear"></div>
+ </form>
+ </div>
+ </div>
+
+ {{* On mobile touch devices we use buttons for approve, ingnore && discard to have a better UX *}}
+ {{if $APP->is_mobile}}
+ <div class="intro-action-buttons">
+ <form class="intro-form pull-left" action="notifications/{{$intro_id}}" method="post">
+ <button class="btn btn-small btn-default intro-submit-ignore" type="submit" name="submit" value="{{$ignore}}">{{$ignore}}</button>
+ {{if $discard}}<button class="btn btn-small btn-default intro-submit-discard" type="submit" name="submit" value="{{$discard}}">{{$discard}}</button> {{/if}}
+ </form>
+ <button class="btn btn-small btn-primary intro-submit-approve pull-right" onclick="addElmToModal('#intro-approve-wrapper-{{$intro_id}}')">{{$approve}}</button>
+ </div>
+ <div class="clear"></div>
+ {{/if}}
+</div>
+<div class="intro-end"></div>
--- /dev/null
+
+{{include file="notifications/notification.tpl"}}
--- /dev/null
+
+{{include file="notifications/notification.tpl"}}
--- /dev/null
+<script type="text/javascript" src="../../frameworks/jquery-color/jquery.color.js"></script>
+<script type="text/javascript" src="../../js/mod_notifications.js"></script>
+
+<div class="generic-page-wrapper">
+ {{include file="section_title.tpl" title=$header}}
+
+ {{if $tabs }}{{include file="common_tabs.tpl"}}{{/if}}
+
+ <div class="notif-network-wrapper">
+ {{* The "show ignored" link *}}
+ {{if $showLink}}<a href="{{$showLink.href}}" id="notifications-show-hide-link">{{$showLink.text}}</a>{{/if}}
+
+ {{* The notifications *}}
+ {{if $notifications}}
+ <ul class="notif-network-list media-list">
+ {{foreach $notifications as $notification}}
+ <li>{{$notification nofilter}}</li>
+ {{/foreach}}
+ </ul>
+ {{/if}}
+
+ {{* If no notifications messages available *}}
+ {{if $noContent}}
+ <div class="notification_nocontent">{{$noContent}}</div>
+ {{/if}}
+ </div>
+
+ {{* The pager *}}
+ {{$paginate nofilter}}
+</div>
--- /dev/null
+
+<div class="notif-item {{if !$item_seen}}unseen{{/if}} {{$item_label}} media">
+ <div class="notif-photo-wrapper media-object pull-left">
+ <a class="userinfo click-card" href="{{$item_url}}"><img src="{{$item_image}}" class="notif-image"></a>
+ </div>
+ <div class="notif-desc-wrapper media-body">
+ <a href="{{$item_link}}">
+ {{$item_text nofilter}}
+ <div><time class="notif-when time" data-toggle="tooltip" title="{{$item_when}}">{{$item_ago}}</time></div>
+ </a>
+ </div>
+</div>
--- /dev/null
+
+{{include file="notifications/notification.tpl"}}
--- /dev/null
+
+{{include file="notifications/intros.tpl"}}
\ No newline at end of file
+++ /dev/null
-
-{{include file="notify.tpl"}}
+++ /dev/null
-
-{{include file="notify.tpl"}}
+++ /dev/null
-
-{{include file="notify.tpl"}}
+++ /dev/null
-
-{{include file="notify.tpl"}}
+++ /dev/null
-
-{{include file="notify.tpl"}}
+++ /dev/null
-
-{{include file="notify.tpl"}}
+++ /dev/null
-
-{{include file="notify.tpl"}}
+++ /dev/null
-
-<div class="notif-item {{if !$item_seen}}unseen{{/if}} {{$item_label}} media">
- <div class="notif-photo-wrapper media-object pull-left">
- <a class="userinfo click-card" href="{{$item_url}}"><img src="{{$item_image}}" class="notif-image"></a>
- </div>
- <div class="notif-desc-wrapper media-body">
- <a href="{{$item_link}}">
- {{$item_text nofilter}}
- <div><time class="notif-when time" data-toggle="tooltip" title="{{$item_when}}">{{$item_ago}}</time></div>
- </a>
- </div>
-</div>
+++ /dev/null
-<div id="profile-page" class="generic-page-wrapper">
- <h3 class="">{{$title}}</h3>
-
- {{* The link to edit the profile*}}
- {{if $profile.edit}}
- <ul class="nav nav-pills preferences">
- <li class="pull-right">
- <a class="btn btn-link btn-sm" type="button" id="profile-edit-link" href="{{$profile.edit.0}}" title="{{$profile.edit.3}}">
- <i class="fa fa-pencil-square-o" aria-hidden="true"></i> {{$profile.edit.1}}
- </a>
- </li>
- </ul>
- <div class="clear"></div>
- {{/if}}
-
- {{* Frio does split the profile information in "standard" and "advanced". This is the tab menu for swithching between this modes *}}
- <ul id="profile-menu" class="nav nav-tabs" role="tablist">
- <li role="presentation" class="active">
- <a href="#profile-content-standard" aria-controls="profile-content-standard" role="tab" data-toggle="tab">{{$basic}}</a>
- </li>
- <li role="presentation">
- <a href="#profile-content-advanced" aria-controls="profile-content-advanced" role="tab" data-toggle="tab">{{$advanced}}</a>
- </li>
- </ul>
-
- <div class="tab-content">
- <div role="tabpanel" class="tab-pane active" id="profile-content-standard">
- <div id="aprofile-fullname" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.fullname.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.fullname.1}}</div>
- </div>
-
- {{if $profile.membersince}}
- <div id="aprofile-membersince" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.membersince.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.membersince.1}}</div>
- </div>
- {{/if}}
-
- {{if $profile.gender}}
- <div id="aprofile-gender" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.gender.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.gender.1}}</div>
- </div>
- {{/if}}
-
- {{if $profile.birthday}}
- <div id="aprofile-birthday" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.birthday.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.birthday.1}}</div>
- </div>
- {{/if}}
-
- {{if $profile.age}}
- <div id="aprofile-age" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.age.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.age.1}}</div>
- </div>
- {{/if}}
-
- {{if $profile.hometown}}
- <div id="aprofile-hometown" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.hometown.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.hometown.1}}</div>
- </div>
- {{/if}}
-
- {{if $profile.marital}}
- <div id="aprofile-marital" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted"><span class="heart">♥</span> {{$profile.marital.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.marital.1}}{{if $profile.marital.with}} ({{$profile.marital.with nofilter}}){{/if}}{{if $profile.howlong}} {{$profile.howlong}}{{/if}}</div>
- </div>
- {{/if}}
-
- {{if $profile.homepage}}
- <div id="aprofile-homepage" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.homepage.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.homepage.1 nofilter}}</div>
- </div>
- {{/if}}
-
- {{if $profile.about}}
- <div id="aprofile-about" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.about.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.about.1 nofilter}}</div>
- </div>
- {{/if}}
-
- {{if $profile.pub_keywords}}
- <div id="aprofile-tags" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.pub_keywords.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.pub_keywords.1}}</div>
- </div>
- {{/if}}
- </div>
-
- <div role="tabpanel" class="tab-pane advanced" id="profile-content-advanced">
- {{if $profile.sexual}}
- <div id="aprofile-sexual" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.sexual.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.sexual.1}}</div>
- </div>
- {{/if}}
-
- {{if $profile.politic}}
- <div id="aprofile-politic" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.politic.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.politic.1}}</div>
- </div>
- {{/if}}
-
- {{if $profile.religion}}
- <div id="aprofile-religion" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.religion.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.religion.1}}</div>
- </div>
- {{/if}}
-
-
- {{if $profile.interest}}
- <div id="aprofile-interest" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.interest.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.interest.1 nofilter}}</div>
- </div>
- {{/if}}
-
- {{if $profile.likes}}
- <div id="aprofile-likes" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.likes.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.likes.1 nofilter}}</div>
- </div>
- {{/if}}
-
- {{if $profile.dislikes}}
- <div id="aprofile-dislikes" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.dislikes.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.dislikes.1 nofilter}}</div>
- </div>
- {{/if}}
-
- {{if $profile.contact}}
- <div id="aprofile-contact" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.contact.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.contact.1 nofilter}}</div>
- </div>
- {{/if}}
-
- {{if $profile.music}}
- <div id="aprofile-music" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.music.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.music.1 nofilter}}</div>
- </div>
- {{/if}}
-
-
- {{if $profile.book}}
- <div id="aprofile-book" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.book.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.book.1 nofilter}}</div>
- </div>
- {{/if}}
-
-
- {{if $profile.tv}}
- <div id="aprofile-tv" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.tv.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.tv.1 nofilter}}</div>
- </div>
- {{/if}}
-
-
- {{if $profile.film}}
- <div id="aprofile-film" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.film.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.film.1 nofilter}}</div>
- </div>
- {{/if}}
-
-
- {{if $profile.romance}}
- <div id="aprofile-romance" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.romance.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.romance.1 nofilter}}</div>
- </div>
- {{/if}}
-
-
- {{if $profile.work}}
- <div id="aprofile-work" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.work.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.work.1 nofilter}}</div>
- </div>
- {{/if}}
-
- {{if $profile.education}}
- <div id="aprofile-education" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.education.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.education.1 nofilter}}</div>
- </div>
- {{/if}}
-
- {{if $profile.forumlist}}
- <div id="aprofile-forumlist" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 aprofile">
- <hr class="profile-separator">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-12 profile-label-name text-muted">{{$profile.forumlist.0}}</div>
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-12 profile-entry">{{$profile.forumlist.1 nofilter}}</div>
- </div>
- {{/if}}
- </div>
- </div>
-</div>
+++ /dev/null
-
-<div class="generic-page-wrapper">
- {{include file="section_title.tpl" title=$banner}}
-
- {{* The actions dropdown which can performed to the current profile *}}
- <div id="profile-edit-links">
- <ul class="nav nav-pills preferences">
- <li class="dropdown pull-right">
- <button type="button" class="btn btn-link btn-sm dropdown-toggle" id="profile-edit-links-dropdown" data-toggle="dropdown" aria-expanded="false">
- <i class="fa fa-angle-down" aria-hidden="true"></i> {{$profile_action}}
- </button>
- <ul class="dropdown-menu pull-right" role="menu" aria-labelledby="profile-edit-links-dropdown">
- <li role="presentation"><a role="menuitem" href="{{$profpiclink}}" id="profile-photo_upload-link" title="{{$profpic}}"><i class="fa fa-user" aria-hidden="true"></i> {{$profpic}}</a></li>
- <li role="presentation"><button role="menuitem" type="button" class="btn-link" id="profile-photo_upload-link-new" title="{{$lbl_profile_photo}}" onclick="openClose('profile-photo-upload-section');"><i class="fa fa-user" aria-hidden="true"></i> {{$lbl_profile_photo}}</button></li>
- {{if ! $is_default}}
- <li role="presentation" class="nav-item"><a role="menuitem" href="profperm/{{$profile_id}}" id="profile-edit-visibility-link" title="{{$editvis}}"><i class="fa fa-pencil" aria-hidden="true"></i> {{$editvis}}</a>
- </li>
- {{/if}}
- <li role="presentation" class="divider"></li>
- <li role="presentation"><a role="menuitem" href="profile/{{$profile_id}}/view?tab=profile" id="profile-edit-view-link" title="{{$viewprof}}">{{$viewprof}}</a></li>
- <li role="presentation"><a role="menuitem" href="profiles" id="profile-edit-view-link" title="{{$viewallprof}}">{{$viewallprof}}</a></li>
- {{if $profile_clone_link}}
- <li role="presentation" class="divider"></li>
- <li role="presentation"><a role="menuitem" href="{{$profile_clone_link}}" id="profile-edit-clone-link" title="{{$cr_prof}}">{{$cl_prof}}</a></li>
- {{/if}}
- {{if !$is_default}}
- <li role="presentation" class="divider"></li>
- <li role="presentation"><a role="menuitem" href="{{$profile_drop_link}}" id="profile-edit-drop-link" title="{{$del_prof}}"><i class="fa fa-trash" aria-hidden="true"></i> {{$del_prof}}</a></li>
- {{/if}}
- </ul>
- </li>
-
- </ul>
- </div>
-
- <div id="profile-edit-links-end"></div>
-
- <form enctype="multipart/form-data" action="profile_photo" method="post">
- <input type='hidden' name='form_security_token' value='{{$form_security_token_photo}}'>
- <input type="hidden" name="profile" value="{{$profile_name.2}}" />
-
- <div id="profile-photo-upload-section" class="panel">
- <a id="profile-photo-upload-close" class="close pull-right" onclick="openClose('profile-photo-upload-section');"><i class="fa fa-times" aria-hidden="true"></i></a>
- <div id="profile-photo-upload-wrapper">
- <label id="profile-photo-upload-label" for="profile-photo-upload">{{$lbl_profile_photo}}:</label>
- <input name="userfile" type="file" id="profile-photo-upload" size="48" />
- </div>
-
- <div class="profile-edit-submit-wrapper pull-right" >
- <button type="submit" name="submit" class="profile-edit-submit-butto btn btn-primary" value="{{$submit}}">{{$submit}}</button>
- </div>
- <div class="clear"></div>
- </div>
- </form>
-
- {{* Most of the Variables used below are arrays in the following style
- 0 => Some kind of identifier (e.g. for the ID)
- 1 => The label description
- 2 => The input values
- 3 => The additional help text (if available)
- *}}
-
- <form id="profile-edit-form" name="form1" action="profiles/{{$profile_id}}" method="post" >
- <input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
-
- {{* Some hints to characteristics of the current profile (if available) *}}
- {{if $is_default}}
- <div class="section-content-info-wrapper">{{$default nofilter}}</div>
- {{/if}}
-
- {{* friendica differs in $detailled_profile (all fields available and a short Version if this is variable false *}}
- {{if $detailled_profile}}
- <div class="panel-group panel-group-settings" id="profile-edit-wrapper" role="tablist" aria-multiselectable="true">
- {{* The personal settings *}}
- <div class="panel">
- <div class="section-subtitle-wrapper" role="tab" id="personal">
- <h4>
- <a class="accordion-toggle collapsed" data-toggle="collapse" data-parent="#profile-edit-wrapper" href="#personal-collapse" aria-expanded="true" aria-controls="personal-collapse">
- {{$lbl_personal_section}}
- </a>
- </h4>
- </div>
- {{* for the $detailled_profile we use bootstraps collapsable panel-groups to have expandable groups *}}
- <div id="personal-collapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="personal">
- <div class="section-content-tools-wrapper">
- {{include file="field_yesno.tpl" field=$details}}
-
- {{include file="field_input.tpl" field=$profile_name}}
-
- {{include file="field_input.tpl" field=$name}}
-
- {{include file="field_input.tpl" field=$pdesc}}
-
- <div id="profile-edit-gender-wrapper" class="form-group field select">
- <label id="profile-edit-gender-label" for="gender-select" >{{$lbl_gender}} </label>
- {{$gender nofilter}}
- </div>
- <div class="clear"></div>
-
- {{$dob nofilter}}
-
- {{$hide_friends nofilter}}
-
- <div class="form-group pull-right" >
- <button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
- </div>
- <div class="clear"></div>
- </div>
- </div>
- </div>
-
- {{* The location settings *}}
- <div class="panel">
- <div class="section-subtitle-wrapper" role="tab" id="location">
- <h4>
- <a class="accordion-toggle collapsed" data-toggle="collapse" data-parent="#profile-edit-wrapper" href="#location-collapse" aria-expanded="false" aria-controls="location-collapse">
- {{$lbl_location_section}}
- </a>
- </h4>
- </div>
- <div id="location-collapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="location">
- <div class="section-content-tools-wrapper">
- {{include file="field_input.tpl" field=$address}}
-
- {{include file="field_input.tpl" field=$locality}}
-
-
- {{include file="field_input.tpl" field=$postal_code}}
-
- <div id="profile-edit-country-name-wrapper" class="form-group field select">
- <label id="profile-edit-country-name-label" for="profile-edit-country-name" >{{$country_name.1}} </label>
- <select name="country_name" id="profile-edit-country-name" class="form-control" onChange="Fill_States('{{$region.2}}');">
- <option selected="selected" >{{$country_name.2}}</option>
- <option>temp</option>
- </select>
- </div>
- <div class="clear"></div>
-
- <div id="profile-edit-region-wrapper" class="form-group field select">
- <label id="profile-edit-region-label" for="profile-edit-region" >{{$region.1}} </label>
- <select name="region" id="profile-edit-region" class="form-control" onChange="Update_Globals();" >
- <option selected="selected" >{{$region.2}}</option>
- <option>temp</option>
- </select>
- </div>
- <div class="clear"></div>
-
- {{include file="field_input.tpl" field=$hometown}}
-
- <div class="form-group pull-right" >
- <button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
- </div>
- <div class="clear"></div>
- </div>
- </div>
- </div>
-
- {{* The settings for relations *}}
- <div class="panel">
- <div class="section-subtitle-wrapper" role="tab" id="relation">
- <h4>
- <a class="accordion-toggle collapsed" data-toggle="collapse" data-parent="#profile-edit-wrapper" href="#relation-collapse" aria-expanded="false" aria-controls="relation-collapse">
- {{$lbl_relation_section}}
- </a>
- </h4>
- </div>
- <div id="relation-collapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="relation">
- <div class="section-content-tools-wrapper">
- <div id="profile-edit-marital-wrapper" class="form-group field select" >
- <label id="profile-edit-marital-label" for="profile-edit-marital" >{{$lbl_marital nofilter}}</label>
- {{$marital.selector nofilter}}
- </div>
- <div class="clear"></div>
-
- {{include file="field_input.tpl" field=$with}}
-
- {{include file="field_input.tpl" field=$howlong}}
-
- <div id="profile-edit-sexual-wrapper" class="form-group field select" >
- <label id="profile-edit-sexual-label" for="sexual-select" >{{$lbl_sexual}}</label>
- {{$sexual.selector nofilter}}
- </div>
- <div class="clear"></div>
-
- <div class="form-group pull-right" >
- <button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
- </div>
- <div class="clear"></div>
- </div>
- </div>
- </div>
-
- {{* The miscellanous other settings *}}
- <div class="panel">
- <div class="section-subtitle-wrapper" role="tab" id="miscellaneous">
- <h4>
- <a class="accordion-toggle collapsed" data-toggle="collapse" data-parent="#profile-edit-wrapper" href="#miscellaneous-collapse" aria-expanded="false" aria-controls="miscellaneous-collapse">
- {{$lbl_miscellaneous_section}}
- </a>
- </h4>
- </div>
- <div id="miscellaneous-collapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="miscellaneous">
- <div class="section-content-tools-wrapper">
- {{include file="field_input.tpl" field=$homepage}}
-
- {{include file="field_input.tpl" field=$xmpp}}
-
- {{include file="field_input.tpl" field=$pub_keywords}}
-
- {{include file="field_input.tpl" field=$prv_keywords}}
-
- {{include file="field_input.tpl" field=$politic}}
-
- {{include file="field_input.tpl" field=$religion}}
-
-
- {{include file="field_textarea.tpl" field=$about}}
-
- {{include file="field_textarea.tpl" field=$contact}}
-
- {{include file="field_textarea.tpl" field=$interest}}
-
- {{include file="field_textarea.tpl" field=$likes}}
-
- {{include file="field_textarea.tpl" field=$dislikes}}
-
- {{include file="field_textarea.tpl" field=$music}}
-
- {{include file="field_textarea.tpl" field=$book}}
-
- {{include file="field_textarea.tpl" field=$tv}}
-
- {{include file="field_textarea.tpl" field=$film}}
-
- {{include file="field_textarea.tpl" field=$romance}}
-
- {{include file="field_textarea.tpl" field=$work}}
-
- {{include file="field_textarea.tpl" field=$education}}
-
- <div class="form-group pull-right" >
- <button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
- </div>
- <div class="clear"></div>
- </div>
- </div>
- </div>
- </div>
-
- {{else}}
- {{* if $detailled_profile not available a short version of the setting page is displayed *}}
- {{if $personal_account}}
- {{include file="field_yesno.tpl" field=$details}}
- {{/if}}
-
- {{include file="field_input.tpl" field=$profile_name}}
-
- {{include file="field_input.tpl" field=$name}}
-
- {{if $personal_account}}
- <div id="profile-edit-gender-wrapper" class="form-group field select">
- <label id="profile-edit-gender-label" for="gender-select" >{{$lbl_gender}} </label>
- {{$gender nofilter}}
- </div>
- <div class="clear"></div>
-
- {{$dob nofilter}}
-
- {{/if}}
-
- {{include file="field_input.tpl" field=$homepage}}
-
- {{include file="field_input.tpl" field=$xmpp}}
-
- {{$hide_friends nofilter}}
-
- {{include file="field_input.tpl" field=$address}}
-
- {{include file="field_input.tpl" field=$locality}}
-
-
- {{include file="field_input.tpl" field=$postal_code}}
-
- <div id="profile-edit-country-name-wrapper" class="form-group field select">
- <label id="profile-edit-country-name-label" for="profile-edit-country-name" >{{$country_name.1}} </label>
- <select name="country_name" id="profile-edit-country-name" class="form-control" onChange="Fill_States('{{$region.2}}');">
- <option selected="selected" >{{$country_name.2}}</option>
- <option>temp</option>
- </select>
- </div>
- <div class="clear"></div>
-
- <div id="profile-edit-region-wrapper" class="form-group field select">
- <label id="profile-edit-region-label" for="profile-edit-region" >{{$region.1}} </label>
- <select name="region" id="profile-edit-region" class="form-control" onChange="Update_Globals();" >
- <option selected="selected" >{{$region.2}}</option>
- <option>temp</option>
- </select>
- </div>
- <div class="clear"></div>
-
- {{include file="field_input.tpl" field=$pub_keywords}}
-
- {{include file="field_input.tpl" field=$prv_keywords}}
-
- {{include file="field_textarea.tpl" field=$about}}
-
- <div class="form-group pull-right" >
- <button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
- </div>
- <div class="clear"></div>
-
- <input type="hidden" name="pdesc" id="profile-edit-pdesc" value="{{$pdesc.2}}" />
- <input type="hidden" id="contact-jot-text" name="contact" value="{{$contact.2}}" />
- <input type="hidden" name="hometown" id="profile-edit-hometown" value="{{$hometown.2}}" />
- <input type="hidden" name="politic" id="profile-edit-politic" value="{{$politic.2}}" />
- <input type="hidden" name="religion" id="profile-edit-religion" value="{{$religion.2}}" />
- <input type="hidden" id="likes-jot-text" name="likes" value="{{$likes.2}}" />
- <input type="hidden" id="dislikes-jot-text" name="dislikes" value="{{$dislikes.2}}" />
- <input type="hidden" name="marital" id="profile-edit-marital" value="{{$marital.value}}" />
- <input type="hidden" name="with" id="profile-edit-with" value="{{$with.2}}" />
- <input type="hidden" name="howlong" id="profile-edit-howlong" value="{{$howlong.2}}" />
- <input type="hidden" name="sexual" id="profile-edit-sexual" value="{{$sexual.value}}" />
- <input type="hidden" id="romance-jot-text" name="romance" value="{{$romance.2}}" />
- <input type="hidden" id="work-jot-text" name="work" value="{{$work.2}}" />
- <input type="hidden" id="education-jot-text" name="education" value="{{$education.2}}" />
- <input type="hidden" id="interest-jot-text" name="interest" value="{{$interest.2}}" />
- <input type="hidden" id="music-jot-text" name="music" value="{{$music.2}}" />
- <input type="hidden" id="book-jot-text" name="book" value="{{$book.2}}" />
- <input type="hidden" id="tv-jot-text" name="tv" value="{{$tv.2}}" />
- <input type="hidden" id="film-jot-text" name="film" value="{{$film.2}}" />
-
- {{/if}}
- </form>
-</div>
-
-<script type="text/javascript">
- Fill_Country('{{$country_name.2}}');
- Fill_States('{{$region.2}}');
-
- // initiale autosize for the textareas
- autosize($("textarea.text-autosize"));
-</script>
+++ /dev/null
-
-<div class="profile-listing-row" >
- <div class="profile-listing-cell" >
- <a href="profiles/{{$id}}" class="profile-listing-edit-link"><img class="profile-listing-photo" id="profile-listing-photo-{{$id}}" src="{{$photo}}" alt="{{$alt}}" /></a>
- </div>
- <div class="profile-listing-photo-end"></div>
- <div class="profile-listing-cell" id="profile-listing-name-{{$id}}">
- <a href="profiles/{{$id}}" class="profile-listing-edit-link" >{{$profile_name}}</a>
- </div>
- <div class="profile-listing-cell">
- {{$visible nofilter}}
- </div>
-</div>
-<div class="profile-listing-end"></div>
-
+++ /dev/null
-
-<div class="generic-page-wrapper">
- <div class="section-title-wrapper pull-left">
- <h2>{{$header}}</h2>
- </div>
- <div id="profile-listing-new-link-wrapper" class="pull-right" >
- <a href="{{$cr_new_link}}" id="profile-listing-new-link" class="page-action faded-icon" title="{{$cr_new}}" data-toggle="tooltip">
- <i class="fa fa-plus"></i></a>
- </div>
-
- <div class="section-content-wrapper">
- <div id="profile-listing-profiles" class="profile-listing-table">
- {{$profiles nofilter}}
- </div>
- </div>
-</div>
--- /dev/null
+<fieldset data-id="{{$profile_field.id}}">
+ <legend>≡ {{$profile_field.legend}}</legend>
+
+ <input type="hidden" name="profile_field_order[]" value="{{$profile_field.id}}">
+
+ {{include file="field_input.tpl" field=$profile_field.fields.label}}
+
+ {{include file="field_textarea.tpl" field=$profile_field.fields.value}}
+
+ {{* Block for setting default permissions *}}
+ <p>
+ <a id="settings-default-perms-menu" class="settings-default-perms" data-toggle="modal" data-target="#profile-field-acl-{{$profile_field.id}}">{{$profile_field.permissions}} {{$profile_field.permdesc}}</a>
+ </p>
+
+ {{* We include the aclModal directly into the template since we cant use frio's default modal *}}
+ <div class="modal" id="profile-field-acl-{{$profile_field.id}}">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
+ <h4 class="modal-title">{{$profile_field.permissions}}</h4>
+ </div>
+ <div class="modal-body">
+ {{$profile_field.fields.acl nofilter}}
+ </div>
+ </div>
+ </div>
+ </div>
+</fieldset>
\ No newline at end of file
--- /dev/null
+<div class="generic-page-wrapper">
+ {{include file="section_title.tpl" title=$banner}}
+
+ {{* The actions dropdown which can performed to the current profile *}}
+ <div id="profile-edit-links">
+ <ul class="nav nav-pills preferences">
+ <li class="dropdown pull-right">
+ <button type="button" class="btn btn-link btn-sm dropdown-toggle" id="profile-edit-links-dropdown" data-toggle="dropdown" aria-expanded="false">
+ <i class="fa fa-angle-down" aria-hidden="true"></i> {{$profile_action}}
+ </button>
+ <ul class="dropdown-menu pull-right" role="menu" aria-labelledby="profile-edit-links-dropdown">
+ <li role="presentation"><a role="menuitem" href="{{$profpiclink}}" id="profile-photo_upload-link" title="{{$profpic}}"><i class="fa fa-user" aria-hidden="true"></i> {{$profpic}}</a></li>
+ <li role="presentation"><button role="menuitem" type="button" class="btn-link" id="profile-photo_upload-link-new" title="{{$lbl_profile_photo}}" onclick="openClose('profile-photo-upload-section');"><i class="fa fa-user" aria-hidden="true"></i> {{$lbl_profile_photo}}</button></li>
+ <li role="presentation" class="divider"></li>
+ <li role="presentation"><a role="menuitem" href="profile/{{$nickname}}" id="profile-edit-view-link" title="{{$viewprof}}">{{$viewprof}}</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+
+ <div id="profile-edit-links-end"></div>
+
+ <form enctype="multipart/form-data" action="settings/profile/photo" method="post">
+ <input type="hidden" name="form_security_token" value="{{$form_security_token_photo}}">
+
+ <div id="profile-photo-upload-section" class="panel">
+ <a id="profile-photo-upload-close" class="close pull-right" onclick="openClose('profile-photo-upload-section');"><i class="fa fa-times" aria-hidden="true"></i></a>
+ <div id="profile-photo-upload-wrapper">
+ <label id="profile-photo-upload-label" for="profile-photo-upload">{{$lbl_profile_photo}}:</label>
+ <input name="userfile" type="file" id="profile-photo-upload" size="48" />
+ </div>
+
+ <div class="profile-edit-submit-wrapper pull-right">
+ <button type="submit" name="submit" class="profile-edit-submit-button btn btn-primary" value="{{$submit}}">{{$submit}}</button>
+ </div>
+ <div class="clear"></div>
+ </div>
+ </form>
+
+ {{* Most of the Variables used below are arrays in the following style
+ 0 => Some kind of identifier (e.g. for the ID)
+ 1 => The label description
+ 2 => The input values
+ 3 => The additional help text (if available)
+ *}}
+
+ <form id="profile-edit-form" name="form1" action="" method="post">
+ <input type="hidden" name="form_security_token" value="{{$form_security_token}}">
+
+ <div class="panel-group panel-group-settings" id="profile-edit-wrapper" role="tablist" aria-multiselectable="true">
+ {{* The personal settings *}}
+ <div class="panel">
+ <div class="section-subtitle-wrapper" role="tab" id="personal">
+ <h4>
+ <a class="accordion-toggle" data-toggle="collapse" data-parent="#profile-edit-wrapper" href="#personal-collapse" aria-expanded="true" aria-controls="personal-collapse">
+ {{$lbl_personal_section}}
+ </a>
+ </h4>
+ </div>
+ {{* for the $detailed_profile we use bootstraps collapsable panel-groups to have expandable groups *}}
+ <div id="personal-collapse" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="personal">
+ <div class="section-content-tools-wrapper">
+ {{include file="field_input.tpl" field=$name}}
+
+ {{include file="field_input.tpl" field=$pdesc}}
+
+ {{$dob nofilter}}
+
+ {{$hide_friends nofilter}}
+
+ <div class="form-group pull-right">
+ <button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
+ </div>
+ <div class="clear"></div>
+ </div>
+ </div>
+ </div>
+
+ {{* The location settings *}}
+ <div class="panel">
+ <div class="section-subtitle-wrapper" role="tab" id="location">
+ <h4>
+ <a class="accordion-toggle collapsed" data-toggle="collapse" data-parent="#profile-edit-wrapper" href="#location-collapse" aria-expanded="false" aria-controls="location-collapse">
+ {{$lbl_location_section}}
+ </a>
+ </h4>
+ </div>
+ <div id="location-collapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="location">
+ <div class="section-content-tools-wrapper">
+ {{include file="field_input.tpl" field=$address}}
+
+ {{include file="field_input.tpl" field=$locality}}
+
+ {{include file="field_input.tpl" field=$postal_code}}
+
+ <div id="profile-edit-country-name-wrapper" class="form-group field select">
+ <label id="profile-edit-country-name-label" for="profile-edit-country-name">{{$country_name.1}} </label>
+ <select name="country_name" id="profile-edit-country-name" class="form-control" onChange="Fill_States('{{$region.2}}');">
+ <option selected="selected">{{$country_name.2}}</option>
+ <option>temp</option>
+ </select>
+ </div>
+ <div class="clear"></div>
+
+ <div id="profile-edit-region-wrapper" class="form-group field select">
+ <label id="profile-edit-region-label" for="profile-edit-region">{{$region.1}} </label>
+ <select name="region" id="profile-edit-region" class="form-control" onChange="Update_Globals();">
+ <option selected="selected">{{$region.2}}</option>
+ <option>temp</option>
+ </select>
+ </div>
+ <div class="clear"></div>
+
+ <div class="form-group pull-right">
+ <button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
+ </div>
+ <div class="clear"></div>
+ </div>
+ </div>
+ </div>
+
+ {{* The miscellanous other settings *}}
+ <div class="panel">
+ <div class="section-subtitle-wrapper" role="tab" id="miscellaneous">
+ <h4>
+ <a class="accordion-toggle collapsed" data-toggle="collapse" data-parent="#profile-edit-wrapper" href="#miscellaneous-collapse" aria-expanded="false" aria-controls="miscellaneous-collapse">
+ {{$lbl_miscellaneous_section}}
+ </a>
+ </h4>
+ </div>
+ <div id="miscellaneous-collapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="miscellaneous">
+ <div class="section-content-tools-wrapper">
+ {{include file="field_input.tpl" field=$homepage}}
+
+ {{include file="field_input.tpl" field=$xmpp}}
+
+ {{include file="field_input.tpl" field=$pub_keywords}}
+
+ {{include file="field_input.tpl" field=$prv_keywords}}
+
+ <div class="form-group pull-right">
+ <button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
+ </div>
+ <div class="clear"></div>
+ </div>
+ </div>
+ </div>
+
+ {{* The miscellanous other settings *}}
+ <div class="panel">
+ <div class="section-subtitle-wrapper" role="tab" id="custom-fields">
+ <h4>
+ <a class="accordion-toggle collapsed" data-toggle="collapse" data-parent="#profile-edit-wrapper" href="#custom-fields-collapse" aria-expanded="false" aria-controls="custom-fields-collapse">
+ {{$lbl_custom_fields_section}}
+ </a>
+ </h4>
+ </div>
+ <div id="custom-fields-collapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="custom-fields">
+ <div class="section-content-tools-wrapper">
+ {{$custom_fields_description nofilter}}
+ <div id="profile-custom-fields">
+ {{foreach $custom_fields as $custom_field}}
+ {{include file="settings/profile/field/edit.tpl" profile_field=$custom_field}}
+ {{/foreach}}
+ </div>
+
+ <div class="form-group pull-right">
+ <button type="submit" name="submit" class="btn btn-primary" value="{{$submit}}">{{$submit}}</button>
+ </div>
+ <div class="clear"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
+
+<script type="text/javascript">
+ Fill_Country('{{$country_name.2}}');
+ Fill_States('{{$region.2}}');
+
+ // initiale autosize for the textareas
+ autosize($("textarea.text-autosize"));
+</script>
<div class="section-content-tools-wrapper">
<div id="settings-notifications">
- <div id="settings-notify-desc"><h4>{{$lbl_not}}</h4></div>
+ <div id="settings-notification-desc"><h4>{{$lbl_not}}</h4></div>
<div class="group">
{{include file="field_intcheckbox.tpl" field=$notify1}}
+++ /dev/null
-
-{{include file="intros.tpl"}}
\ No newline at end of file
{{if $item.owner_self}}
{{include file="sub/delivery_count.tpl" delivery=$item.delivery}}
{{/if}}
- <span class="pinned">{{$item.pinned}}</span>
+ {{if $item.pinned}}
+ • <i class="fa fa-thumb-tack" aria-hidden="true" title="{{$item.pinned}}"></i>
+ <span class="sr-only">{{$item.pinned}}</span>
+ {{/if}}
+
</small>
</div>
width: 22px;
height: 22px;
}
-nav .nav-menu-icon .nav-notify {
+nav .nav-menu-icon .nav-notification {
top: 3px;
}
nav .nav-menu {
nav .nav-menu.selected {
border-bottom: 3px solid #9eabb0;
}
-nav .nav-notify {
+nav .nav-notification {
display: none;
position: absolute;
background-color: #19aeff;
min-width: 15px;
text-align: right;
}
-nav .nav-notify.show {
+nav .nav-notification.show {
display: block;
}
nav #nav-help-link,
list-style: none;
margin-top: 10px;
}
+#profile-menu {
+ display: none;
+}
#profile-edit-default-desc {
color: #FF0000;
border: 1px solid #FF8888;
width: 22px;
height: 22px;
}
-nav .nav-menu-icon .nav-notify {
+nav .nav-menu-icon .nav-notification {
top: 3px;
}
nav .nav-menu {
nav .nav-menu.selected {
border-bottom: 3px solid #9eabb0;
}
-nav .nav-notify {
+nav .nav-notification {
display: none;
position: absolute;
background-color: #dc0000;
min-width: 15px;
text-align: right;
}
-nav .nav-notify.show {
+nav .nav-notification.show {
display: block;
}
nav #nav-help-link,
list-style: none;
margin-top: 10px;
}
+#profile-menu {
+ display: none;
+}
#profile-edit-default-desc {
color: #FF0000;
border: 1px solid #FF8888;
width: 22px;
height: 22px;
}
-nav .nav-menu-icon .nav-notify {
+nav .nav-menu-icon .nav-notification {
top: 3px;
}
nav .nav-menu {
nav .nav-menu.selected {
border-bottom: 3px solid #9eabb0;
}
-nav .nav-notify {
+nav .nav-notification {
display: none;
position: absolute;
background-color: #86608e;
min-width: 15px;
text-align: right;
}
-nav .nav-notify.show {
+nav .nav-notification.show {
display: block;
}
nav #nav-help-link,
list-style: none;
margin-top: 10px;
}
+#profile-menu {
+ display: none;
+}
#profile-edit-default-desc {
color: #FF0000;
border: 1px solid #FF8888;
}
img { width: 22px; height: 22px; }
- .nav-notify { top: 3px; }
+ .nav-notification { top: 3px; }
}
.nav-menu {
}
- .nav-notify {
+ .nav-notification {
display: none;
position: absolute;
background-color: @NavbarNotifBg;
margin-top: 10px;
}
+#profile-menu {
+ display: none;
+}
+
#profile-edit-default-desc {
color: #FF0000;
border: 1px solid #FF8888;
{{if $nav.network}}
<li id="nav-network-link" class="nav-menu {{$sel.network}}">
<a accesskey="n" class="{{$nav.network.2}}" href="{{$nav.network.0}}" title="{{$nav.network.3}}" >{{$nav.network.1}}</a>
- <span id="net-update" class="nav-notify"></span>
+ <span id="net-update" class="nav-notification"></span>
</li>
{{/if}}
{{if $nav.home}}
<li id="nav-home-link" class="nav-menu {{$sel.home}}">
<a accesskey="p" class="{{$nav.home.2}}" href="{{$nav.home.0}}" title="{{$nav.home.3}}" >{{$nav.home.1}}</a>
- <span id="home-update" class="nav-notify"></span>
+ <span id="home-update" class="nav-notification"></span>
</li>
{{/if}}
<a class="{{$nav.introductions.2}}" href="{{$nav.introductions.0}}" title="{{$nav.introductions.3}}" >
<span class="icon s22 intro">{{$nav.introductions.1}}</a>
</a>
- <span id="intro-update" class="nav-notify"></span>
+ <span id="intro-update" class="nav-notification"></span>
</li>
{{/if}}
<a class="{{$nav.messages.2}}" href="{{$nav.messages.0}}" title="{{$nav.messages.3}}" >
<span class="icon s22 mail">{{$nav.messages.1}}</a>
</a>
- <span id="mail-update" class="nav-notify"></span>
+ <span id="mail-update" class="nav-notification"></span>
</li>
{{/if}}
{{if $nav.notifications}}
<li id="nav-notifications-linkmenu" class="nav-menu-icon"><a accesskey="f" href="{{$nav.notifications.0}}" rel="#nav-notifications-menu" title="{{$nav.notifications.1}}"><span class="icon s22 notify">{{$nav.notifications.1}}</span></a>
- <span id="notify-update" class="nav-notify"></span>
+ <span id="notification-update" class="nav-notification"></span>
<ul id="nav-notifications-menu" class="menu-popup">
<!-- TODO: better icons! -->
- <li id="nav-notifications-mark-all" class="toolbar"><a href="#" onclick="notifyMarkAll(); return false;" title="{{$nav.notifications.mark.3}}"><span class="icon s10 edit"></span></a></a><a href="{{$nav.notifications.all.0}}" title="{{$nav.notifications.all.1}}"><span class="icon s10 plugin"></span></a></li>
+ <li id="nav-notifications-mark-all" class="toolbar"><a href="#" onclick="notificationMarkAll(); return false;" title="{{$nav.notifications.mark.3}}"><span class="icon s10 edit"></span></a></a><a href="{{$nav.notifications.all.0}}" title="{{$nav.notifications.all.1}}"><span class="icon s10 plugin"></span></a></li>
<li class="empty">{{$emptynotifications}}</li>
</ul>
</li>
top: 1px;
}
+.btn {
+ background-color: transparent;
+ box-shadow: none;
+ border: none;
+ padding: 0;
+ text-align: inherit;
+}
+
#search-text,
#search-submit,
#search-save {
padding-left: 11px;
}
-#notify-update {
+#notification-update {
background-position: 0px -168px;
}
position: absolute;
}
+#profile-menu {
+ display: none;
+}
+
#cropimage-wrapper {
float:left;
}
margin-right: -20px;
}
-.nav-notify {
+.nav-notification {
display: none;
position: absolute;
font-size: 10px;
min-width: 15px;
text-align: right;
}
-.nav-notify.show {
+.nav-notification.show {
display: block;
}
#nav-notifications-menu {
filter: alpha(opacity=100);
}
-.notify-seen {
+.notification-seen {
background: #000000;
}
-.notify-seen a {
+.notification-seen a {
color: #efefef !important;
}
}
#settings-activity-desc,
-#settings-notify-desc {
+#settings-notification-desc {
margin: 10px 10px 10px 0;
font-weight: bold;
}
<!-- {{if $nav.notifications}}<a id="intro-update" class="nav-ajax-update" href="{{$nav.notifications.0}}" title="{{$nav.notifications.1}}"></a>{{/if}} -->
{{if $nav.introductions}}<a id="intro-update" class="nav-ajax-update" href="{{$nav.introductions.0}}" title="{{$nav.introductions.1}}"></a>{{/if}}
{{if $nav.messages}}<a id="mail-update" class="nav-ajax-update" href="{{$nav.messages.0}}" title="{{$nav.messages.1}}"></a>{{/if}}
- {{if $nav.notifications}}<a rel="#nav-notifications-menu" id="notify-update" class="nav-ajax-update" href="{{$nav.notifications.0}}" title="{{$nav.notifications.1}}"></a>{{/if}}
+ {{if $nav.notifications}}<a rel="#nav-notifications-menu" id="notification-update" class="nav-ajax-update" href="{{$nav.notifications.0}}" title="{{$nav.notifications.1}}"></a>{{/if}}
<ul id="nav-notifications-menu" class="menu-popup">
- <li id="nav-notifications-mark-all"><a href="#" onclick="notifyMarkAll(); return false;">{{$nav.notifications.mark.3}}</a></li>
+ <li id="nav-notifications-mark-all"><a href="#" onclick="notificationMarkAll(); return false;">{{$nav.notifications.mark.3}}</a></li>
<li id="nav-notifications-see-all"><a href="{{$nav.notifications.all.0}}">{{$nav.notifications.all.1}}</a></li>
<li class="empty">{{$emptynotifications}}</li>
</ul>
<li><a id="nav-directory-link" class="nav-link {{$nav.directory.2}}" href="{{$nav.directory.0}}">{{$nav.directory.1}}</a></li>
{{if $nav.apps}}<li><a id="nav-apps-link" class="nav-link {{$nav.apps.2}}" href="{{$nav.apps.0}}">{{$nav.apps.1}}</a></li>{{/if}}
- {{if $nav.notifications}}<li><a id="nav-notify-link" class="nav-commlink nav-sep {{$nav.notifications.2}}" href="{{$nav.notifications.0}}">{{$nav.notifications.1}}</a></li>{{/if}}
+ {{if $nav.notifications}}<li><a id="nav-notification-link" class="nav-commlink nav-sep {{$nav.notifications.2}}" href="{{$nav.notifications.0}}">{{$nav.notifications.1}}</a></li>{{/if}}
{{if $nav.messages}}<li><a id="nav-messages-link" class="nav-commlink {{$nav.messages.2}}" href="{{$nav.messages.0}}">{{$nav.messages.1}}</a></li>{{/if}}
{{if $nav.contacts}}<li><a id="nav-contacts-link" class="nav-commlink {{$nav.contacts.2}}" href="{{$nav.contacts.0}}">{{$nav.contacts.1}}</a></li>{{/if}}
background-color: #1C2126 !important;
}
-nav .nav-notify {
+nav .nav-notification {
background-color: #2C77AE !important
}
}
/* Notifications */
-li.notify-unseen {
+li.notification-unseen {
background-color: #252C33;
}
-li.notify-seen {
+li.notification-seen {
background-color: #1C2126;
}
font: bold 11px/16px Arial;
}
-nav .nav-notify {
+nav .nav-notification {
/* background-color: #427FED; */
background-color: #CB4437;
top: -3px;
border-radius: 10px;
}
-nav .nav-menu-icon .nav-notify {
+nav .nav-menu-icon .nav-notification {
top: 0px;
}
font: bold 11px/16px Arial;
}
-nav .nav-notify {
+nav .nav-notification {
background-color: #CB4437;
top: -3px;
right: -4px;
border-radius: 10px;
}
-nav .nav-menu-icon .nav-notify {
+nav .nav-menu-icon .nav-notification {
top: 0px;
}
color: #fff;
}
-nav .nav-notify {
+nav .nav-notification {
background-color: #F80;
top: 0px;
right: -5px;
border-radius: 5px 5px 5px 5px;
}
-nav .nav-menu-icon .nav-notify {
+nav .nav-menu-icon .nav-notification {
top: 0px;
}
margin-right: 4px;
}
-nav .nav-menu > a > .nav-notify,
-nav .nav-menu-icon > a > .nav-notify {
+nav .nav-menu > a > .nav-notification,
+nav .nav-menu-icon > a > .nav-notification {
position: absolute;
top: 3px;
right: -5px;
margin-right: -20px;
}
-nav .nav-notify {
+nav .nav-notification {
display: none;
background-color: #F80;
-moz-border-radius: 5px 5px 5px 5px;
text-align: center;
color: white;
}
-nav .nav-notify.show {
+nav .nav-notification.show {
display: inline-block;
}
padding: 5px 10px; */
}
-.notify-unseen {background-color: #FFF; }
+.notification-unseen {background-color: #FFF; }
-.notify-seen {
+.notification-seen {
background: none repeat scroll 0 0 #EEE;
}
list-style: none;
}
+#profile-menu {
+ display: none;
+}
+
.profile-edit-side-div {
/* display: none; */
float: right;
}
#profile-edit-wrapper .toggle-section-content {
background:#ededed;
- max-width:599px;
padding:5px;
}
</div>
<div id="contact-info-end"></div>
{{/if}}
-
- {{if $profile_select}}
- <div id="contact-edit-profile-select-text">
- <h4>{{$lbl_vis1}}</h4>
- <p>{{$lbl_vis2}}</p>
- </div>
- {{$profile_select nofilter}}
- <div id="contact-edit-profile-select-end"></div>
- {{/if}}
</div>
<input class="contact-edit-submit" type="submit" name="submit" value="{{$submit}}" />
{{/if}}
<a accesskey="p" class="{{$nav.home.2}}" href="{{$nav.home.0}}" title="{{$nav.home.3}}" >
<span class="desktop-view">{{$nav.home.1}}</span>
<i class="icon s22 icon-home mobile-view"><span class="sr-only">{{$nav.home.1}}</span></i>
- <span id="home-update" class="nav-notify"></span>
+ <span id="home-update" class="nav-notification"></span>
</a>
</li>
{{/if}}
<a accesskey="n" class="{{$nav.network.2}}" href="{{$nav.network.0}}" title="{{$nav.network.3}}" >
<span class="desktop-view">{{$nav.network.1}}</span>
<i class="icon s22 icon-th mobile-view"><span class="sr-only">{{$nav.network.1}}</span></i>
- <span id="net-update" class="nav-notify"></span>
+ <span id="net-update" class="nav-notification"></span>
</a>
</li>
{{/if}}
<li role="menu" aria-haspopup="true" id="nav-messages-linkmenu" class="nav-menu-icon">
<a href="{{$nav.messages.0}}" title="{{$nav.messages.1}}">
<span class="icon s22 icon-envelope"><span class="sr-only">{{$nav.messages.1}}</span></span>
- <span id="mail-update" class="nav-notify"></span>
+ <span id="mail-update" class="nav-notification"></span>
</a>
</li>
{{/if}}
<li role="menu" aria-haspopup="true" id="nav-notifications-linkmenu" class="nav-menu-icon">
<a title="{{$nav.notifications.1}}">
<span class="icon s22 icon-bell tilted-icon"><span class="sr-only">{{$nav.notifications.1}}</span></span>
- <span id="notify-update" class="nav-notify"></span>
+ <span id="notification-update" class="nav-notification"></span>
</a>
<ul id="nav-notifications-menu" class="menu-popup">
- <li role="menuitem" id="nav-notifications-mark-all"><a onclick="notifyMarkAll(); return false;">{{$nav.notifications.mark.1}}</a></li>
+ <li role="menuitem" id="nav-notifications-mark-all"><a onclick="notificationMarkAll(); return false;">{{$nav.notifications.mark.1}}</a></li>
<li role="menuitem" id="nav-notifications-see-all"><a href="{{$nav.notifications.all.0}}">{{$nav.notifications.all.1}}</a></li>
<li role="menuitem" class="empty">{{$emptynotifications}}</li>
</ul>
{{if $userinfo}}
<li role="menu" aria-haspopup="true" id="nav-user-linkmenu" class="nav-menu">
- <a accesskey="u" title="{{$sitelocation}}"><img src="{{$userinfo.icon}}" alt="{{$userinfo.name}}"><span id="nav-user-linklabel">{{$userinfo.name}}</span><span id="intro-update" class="nav-notify"></span></a>
+ <a accesskey="u" title="{{$sitelocation}}"><img src="{{$userinfo.icon}}" alt="{{$userinfo.name}}"><span id="nav-user-linklabel">{{$userinfo.name}}</span><span id="intro-update" class="nav-notification"></span></a>
<ul id="nav-user-menu" class="menu-popup">
<li role="menuitem"> <a class="{{$nav.search.2}}" href="{{$nav.search.0}}" title="{{$nav.search.3}}" >{{$nav.search.1}}</a> </li>
- {{if $nav.introductions}}<li role="menuitem"><a class="{{$nav.introductions.2}}" href="{{$nav.introductions.0}}" title="{{$nav.introductions.3}}" >{{$nav.introductions.1}}</a><span id="intro-update-li" class="nav-notify"></span></li>{{/if}}
+ {{if $nav.introductions}}<li role="menuitem"><a class="{{$nav.introductions.2}}" href="{{$nav.introductions.0}}" title="{{$nav.introductions.3}}" >{{$nav.introductions.1}}</a><span id="intro-update-li" class="nav-notification"></span></li>{{/if}}
{{if $nav.contacts}}<li role="menuitem"><a class="{{$nav.contacts.2}}" href="{{$nav.contacts.0}}" title="{{$nav.contacts.3}}" >{{$nav.contacts.1}}</a></li>{{/if}}
- {{if $nav.messages}}<li role="menuitem"><a class="{{$nav.messages.2}}" href="{{$nav.messages.0}}" title="{{$nav.messages.3}}" >{{$nav.messages.1}} <span id="mail-update-li" class="nav-notify"></span></a></li>{{/if}}
+ {{if $nav.messages}}<li role="menuitem"><a class="{{$nav.messages.2}}" href="{{$nav.messages.0}}" title="{{$nav.messages.3}}" >{{$nav.messages.1}} <span id="mail-update-li" class="nav-notification"></span></a></li>{{/if}}
{{if $nav.delegation}}<li role="menuitem"><a class="{{$nav.delegation.2}}" href="{{$nav.delegation.0}}" title="{{$nav.delegation.3}}">{{$nav.delegation.1}}</a></li>{{/if}}
{{if $nav.usermenu.1}}<li role="menuitem"><a class="{{$nav.usermenu.1.2}}" href="{{$nav.usermenu.1.0}}" title="{{$nav.usermenu.1.3}}">{{$nav.usermenu.1.1}}</a></li>{{/if}}
{{if $nav.settings}}<li role="menuitem"><a class="{{$nav.settings.2}}" href="{{$nav.settings.0}}" title="{{$nav.settings.3}}">{{$nav.settings.1}}</a></li>{{/if}}
+++ /dev/null
-{{if $profile.edit}}
- <div class="profile-view-actions">
- <a class="btn" href="{{$profile.edit.0}}" id="profile-view-edit-link" title="{{$profile.edit.3}}">{{$profile.edit.1}}</a>
- </div>
-{{/if}}
-
-{{include file="section_title.tpl"}}
-
-<dl id="aprofile-fullname" class="aprofile">
- <dt>{{$profile.fullname.0}}</dt>
- <dd>{{$profile.fullname.1}}</dd>
-</dl>
-
-{{if $profile.membersince}}
-<dl id="aprofile-membersince" class="aprofile">
- <dt>{{$profile.membersince.0}}</dt>
- <dd>{{$profile.membersince.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.gender}}
-<dl id="aprofile-gender" class="aprofile">
- <dt>{{$profile.gender.0}}</dt>
- <dd>{{$profile.gender.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.birthday}}
-<dl id="aprofile-birthday" class="aprofile">
- <dt>{{$profile.birthday.0}}</dt>
- <dd>{{$profile.birthday.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.age}}
-<dl id="aprofile-age" class="aprofile">
- <dt>{{$profile.age.0}}</dt>
- <dd>{{$profile.age.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.marital}}
-<dl id="aprofile-marital" class="aprofile">
- <dt><span class="heart">♥</span> {{$profile.marital.0}}</dt>
- <dd>{{$profile.marital.1}}{{if $profile.marital.with}} ({{$profile.marital.with}}){{/if}}{{if $profile.howlong}} {{$profile.howlong}}{{/if}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.sexual}}
-<dl id="aprofile-sexual" class="aprofile">
- <dt>{{$profile.sexual.0}}</dt>
- <dd>{{$profile.sexual.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.pub_keywords}}
-<dl id="aprofile-tags" class="aprofile">
- <dt>{{$profile.pub_keywords.0}}</dt>
- <dd>{{$profile.pub_keywords.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.homepage}}
-<dl id="aprofile-homepage" class="aprofile">
- <dt>{{$profile.homepage.0}}</dt>
- <dd>{{$profile.homepage.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.hometown}}
-<dl id="aprofile-hometown" class="aprofile">
- <dt>{{$profile.hometown.0}}</dt>
- <dd>{{$profile.hometown.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.politic}}
-<dl id="aprofile-politic" class="aprofile">
- <dt>{{$profile.politic.0}}</dt>
- <dd>{{$profile.politic.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.religion}}
-<dl id="aprofile-religion" class="aprofile">
- <dt>{{$profile.religion.0}}</dt>
- <dd>{{$profile.religion.1}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.about}}
-<dl id="aprofile-about" class="aprofile">
- <dt>{{$profile.about.0}}</dt>
- <dd>{{$profile.about.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.interest}}
-<dl id="aprofile-interest" class="aprofile">
- <dt>{{$profile.interest.0}}</dt>
- <dd>{{$profile.interest.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.likes}}
-<dl id="aprofile-likes" class="aprofile">
- <dt>{{$profile.likes.0}}</dt>
- <dd>{{$profile.likes.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.dislikes}}
-<dl id="aprofile-dislikes" class="aprofile">
- <dt>{{$profile.dislikes.0}}</dt>
- <dd>{{$profile.dislikes.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.contact}}
-<dl id="aprofile-contact" class="aprofile">
- <dt>{{$profile.contact.0}}</dt>
- <dd>{{$profile.contact.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-
-{{if $profile.music}}
-<dl id="aprofile-music" class="aprofile">
- <dt>{{$profile.music.0}}</dt>
- <dd>{{$profile.music.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-
-{{if $profile.book}}
-<dl id="aprofile-book" class="aprofile">
- <dt>{{$profile.book.0}}</dt>
- <dd>{{$profile.book.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-
-{{if $profile.tv}}
-<dl id="aprofile-tv" class="aprofile">
- <dt>{{$profile.tv.0}}</dt>
- <dd>{{$profile.tv.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-
-{{if $profile.film}}
-<dl id="aprofile-film" class="aprofile">
- <dt>{{$profile.film.0}}</dt>
- <dd>{{$profile.film.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-
-{{if $profile.romance}}
-<dl id="aprofile-romance" class="aprofile">
- <dt>{{$profile.romance.0}}</dt>
- <dd>{{$profile.romance.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-
-{{if $profile.work}}
-<dl id="aprofile-work" class="aprofile">
- <dt>{{$profile.work.0}}</dt>
- <dd>{{$profile.work.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.education}}
-<dl id="aprofile-education" class="aprofile">
- <dt>{{$profile.education.0}}</dt>
- <dd>{{$profile.education.1 nofilter}}</dd>
-</dl>
-{{/if}}
-
-{{if $profile.forumlist}}
-<dl id="aprofile-forumlist" class="aprofile">
- <dt>{{$profile.forumlist.0}}</dt>
- <dd>{{$profile.forumlist.1 nofilter}}</dd>
-</dl>
-{{/if}}
+++ /dev/null
-<script>
- $(document).ready(function() {
-
- $('.toggle-section-content').hide();
- $('.js-section-toggler').click(function(){
- $('.toggle-section-content').hide();
- $(this).next('.toggle-section-content').toggle();
- });
-
- });
-</script>
-
-<h1>{{$banner}}</h1>
-
-<div id="profile-edit-links">
-<ul>
- <li><a class="btn" href="profile/{{$profile_id}}/view?tab=profile" id="profile-edit-view-link" title="{{$viewprof}}">{{$viewprof}}</a></li>
- {{if $multi_profiles}}
- <li><a class="btn" href="{{$profile_clone_link}}" id="profile-edit-clone-link" title="{{$cr_prof}}">{{$cl_prof}}</a></li>
- <li><a class="btn" href="{{$profile_drop_link}}" id="profile-edit-drop-link" title="{{$del_prof}}" {{$disabled}} >{{$del_prof}}</a></li>
- {{/if}}
-</ul>
-</div>
-<div id="profile-edit-links-end"></div>
-
-{{$default nofilter}}
-
-<div id="profile-edit-wrapper" >
-
-<form enctype="multipart/form-data" action="profile_photo" method="post">
- <input type='hidden' name='form_security_token' value='{{$form_security_token_photo}}'>
- <input type="hidden" name="profile" value="{{$profile_name.2}}" />
-
- <!-- Profile picture -->
-{{if $detailled_profile}}
- <div class="toggle-section js-toggle-section">
- <a class="section-caption js-section-toggler" href="javascript:;">{{$lbl_picture_section}} »</a>
- <div class="js-section toggle-section-content hidden">
-{{/if}}
-
- <div id="profile-photo-upload-wrapper">
- <label id="profile-photo-upload-label" for="profile-photo-upload">{{$lbl_profile_photo}}:</label>
- <input name="userfile" type="file" id="profile-photo-upload" size="48" />
- </div>
-
- <div class="profile-edit-submit-wrapper" >
- <input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" />
- </div>
- <div class="profile-edit-submit-end"></div>
-
-{{if $detailled_profile}}
- </div>
- </div>
-{{/if}}
-</form>
-
-<form id="profile-edit-form" name="form1" action="profiles/{{$profile_id}}" method="post" >
- <input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
-
-{{if $detailled_profile}}
- <!-- Basic information -->
- <div class="toggle-section js-toggle-section">
- <a class="section-caption js-section-toggler" href="javascript:;">{{$lbl_basic_section}} »</a>
- <div class="js-section toggle-section-content hidden">
-
- {{include file="field_yesno.tpl" field=$details}}
-
- {{if $multi_profiles}}
- <div id="profile-edit-profile-name-wrapper" >
- <label id="profile-edit-profile-name-label" for="profile-edit-profile-name" >{{$profile_name.1}} </label>
- <input type="text" size="32" name="profile_name" id="profile-edit-profile-name" value="{{$profile_name.2}}" /><div class="required">*</div>
- </div>
- <div id="profile-edit-profile-name-end"></div>
- {{else}}
- <input type="hidden" name="profile_name" id="profile-edit-profile-name" value="{{$profile_name.2}}" />
- {{/if}}
-
- <div id="profile-edit-name-wrapper" >
- <label id="profile-edit-name-label" for="profile-edit-name" >{{$name.1}} </label>
- <input type="text" size="32" name="name" id="profile-edit-name" value="{{$name.2}}" />
- </div>
- <div id="profile-edit-name-end"></div>
-
- <div id="profile-edit-gender-wrapper" >
- <label id="profile-edit-gender-label" for="gender-select" >{{$lbl_gender}} </label>
- {{$gender nofilter}}
- </div>
- <div id="profile-edit-gender-end"></div>
-
- <div id="profile-edit-pdesc-wrapper" >
- <label id="profile-edit-pdesc-label" for="profile-edit-pdesc" >{{$pdesc.1}} </label>
- <input type="text" size="32" name="pdesc" id="profile-edit-pdesc" value="{{$pdesc.2}}" />
- </div>
- <div id="profile-edit-pdesc-end"></div>
-
- <div id="profile-edit-xmpp-wrapper" >
- <label id="profile-edit-xmpp-label" for="profile-edit-xmpp" >{{$xmpp.1}} </label>
- <input type="text" size="32" name="xmpp" id="profile-edit-xmpp" value="{{$xmpp.2}}" />
- </div>
- <div id="profile-edit-xmpp-desc">{{$xmpp.3}}</div>
- <div id="profile-edit-xmpp-end"></div>
-
- <div id="profile-edit-homepage-wrapper" >
- <label id="profile-edit-homepage-label" for="profile-edit-homepage" >{{$homepage.1}} </label>
- <input type="text" size="32" name="homepage" id="profile-edit-homepage" value="{{$homepage.2}}" />
- </div>
- <div id="profile-edit-homepage-end"></div>
-
- <div id="profile-edit-dob-wrapper" >
- {{$dob nofilter}}
- </div>
- <div id="profile-edit-dob-end"></div>
-
- {{$hide_friends nofilter}}
-
- <div id="about-jot-wrapper">
- <div id="about-jot-desc">{{$about.1}}</div>
- <textarea rows="10" cols="72" id="profile-about-text" name="about" style="width:599px;">{{$about.2}}</textarea>
- </div>
- <div id="about-jot-end"></div>
-
- <div id="contact-jot-wrapper" >
- <div id="contact-jot-desc">{{$contact.1}}</div>
- <textarea rows="10" cols="72" id="contact-jot-text" name="contact" style="width:599px;">{{$contact.2}}</textarea>
- </div>
- <div id="contact-jot-end"></div>
-
- <div id="profile-edit-pubkeywords-wrapper" >
- <label id="profile-edit-pubkeywords-label" for="profile-edit-pubkeywords" >{{$pub_keywords.1}} </label>
- <input type="text" size="32" name="pub_keywords" id="profile-edit-pubkeywords" title="{{$lbl_ex2}}" value="{{$pub_keywords.2}}" />
- </div>
- <div id="profile-edit-pubkeywords-desc">{{$pub_keywords.3}}</div>
- <div id="profile-edit-pubkeywords-end"></div>
-
- <div id="profile-edit-prvkeywords-wrapper" >
- <label id="profile-edit-prvkeywords-label" for="profile-edit-prvkeywords" >{{$prv_keywords.1}} </label>
- <input type="text" size="32" name="prv_keywords" id="profile-edit-prvkeywords" title="{{$lbl_ex2}}" value="{{$prv_keywords.2}}" />
- </div>
- <div id="profile-edit-prvkeywords-desc">{{$prv_keywords.3}}</div>
- <div id="profile-edit-prvkeywords-end"></div>
-
- <div class="profile-edit-submit-wrapper" >
- <input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" />
- </div>
- <div class="profile-edit-submit-end"></div>
-
- </div>
- </div>
-
- <!-- About you -->
- <div class="toggle-section js-toggle-section">
- <a class="section-caption js-section-toggler" href="javascript:;">{{$lbl_about_section}} »</a>
- <div class="js-section toggle-section-content hidden">
-
- <div><b>{{$lbl_location_section}}</b></div>
-
- <div id="profile-edit-address-wrapper" >
- <label id="profile-edit-address-label" for="profile-edit-address" >{{$address.1}} </label>
- <input type="text" size="32" name="address" id="profile-edit-address" value="{{$address.2}}" />
- </div>
- <div id="profile-edit-address-end"></div>
-
- <div id="profile-edit-locality-wrapper" >
- <label id="profile-edit-locality-label" for="profile-edit-locality" >{{$locality.1}} </label>
- <input type="text" size="32" name="locality" id="profile-edit-locality" value="{{$locality.2}}" />
- </div>
- <div id="profile-edit-locality-end"></div>
-
- <div id="profile-edit-postal-code-wrapper" >
- <label id="profile-edit-postal-code-label" for="profile-edit-postal-code" >{{$postal_code.1}} </label>
- <input type="text" size="32" name="postal_code" id="profile-edit-postal-code" value="{{$postal_code.2}}" />
- </div>
- <div id="profile-edit-postal-code-end"></div>
-
- <div id="profile-edit-country-name-wrapper" >
- <label id="profile-edit-country-name-label" for="profile-edit-country-name" >{{$country_name.1}} </label>
- <select name="country_name" id="profile-edit-country-name" onChange="Fill_States('{{$region.2}}');">
- <option selected="selected" >{{$country_name.2}}</option>
- </select>
- </div>
- <div id="profile-edit-country-name-end"></div>
-
- <div id="profile-edit-region-wrapper" >
- <label id="profile-edit-region-label" for="profile-edit-region" >{{$region.2}} </label>
- <select name="region" id="profile-edit-region" onChange="Update_Globals();" >
- <option selected="selected" >{{$region.2}}</option>
- </select>
- </div>
- <div id="profile-edit-region-end"></div>
-
- <div id="profile-edit-hometown-wrapper" >
- <label id="profile-edit-hometown-label" for="profile-edit-hometown" >{{$hometown.1}} </label>
- <input type="text" size="32" name="hometown" id="profile-edit-hometown" value="{{$hometown.2}}" />
- </div>
- <div id="profile-edit-hometown-end"></div>
-
- <br>
-
- <div><b>{{$lbl_preferences_section}}</b></div>
-
- <div id="profile-edit-sexual-wrapper" >
- <label id="profile-edit-sexual-label" for="sexual-select" >{{$lbl_sexual}} </label>
- {{$sexual nofilter}}
- </div>
- <div id="profile-edit-sexual-end"></div>
-
- <div id="profile-edit-politic-wrapper" >
- <label id="profile-edit-politic-label" for="profile-edit-politic" >{{$politic.1}} </label>
- <input type="text" size="32" name="politic" id="profile-edit-politic" value="{{$politic.2}}" />
- </div>
- <div id="profile-edit-politic-end"></div>
-
- <div id="profile-edit-religion-wrapper" >
- <label id="profile-edit-religion-label" for="profile-edit-religion" >{{$religion.1}} </label>
- <input type="text" size="32" name="religion" id="profile-edit-religion" value="{{$religion.2}}" />
- </div>
- <div id="profile-edit-religion-end"></div>
-
- <div id="likes-jot-wrapper">
- <div id="likes-jot-desc">{{$likes.1}}</div>
- <textarea rows="10" cols="72" id="likes-jot-text" name="likes" style="width:599px;">{{$likes.2}}</textarea>
- </div>
- <div id="likes-jot-end"></div>
-
- <div id="dislikes-jot-wrapper">
- <div id="dislikes-jot-desc">{{$dislikes.1}}</div>
- <textarea rows="10" cols="72" id="dislikes-jot-text" name="dislikes" style="width:599px;">{{$dislikes.2}}</textarea>
- </div>
- <div id="dislikes-jot-end"></div>
-
- <div class="profile-edit-submit-wrapper" >
- <input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" />
- </div>
- <div class="profile-edit-submit-end"></div>
-
- </div>
- </div>
-
- <!-- Status -->
- <div class="toggle-section js-toggle-section">
- <a class="section-caption js-section-toggler" href="javascript:;">{{$lbl_status_section}} »</a>
- <div class="js-section toggle-section-content hidden">
-
- <div id="profile-edit-marital-wrapper" >
- <label id="profile-edit-marital-label" for="profile-edit-marital" >{{$lbl_marital nofilter}} </label>
- {{$marital nofilter}}
- </div>
- <label id="profile-edit-with-label" for="profile-edit-with" > {{$with.1}} </label>
- <input type="text" size="32" name="with" id="profile-edit-with" title="{{$with.3}}" value="{{$with.2}}" />
- <label id="profile-edit-howlong-label" for="profile-edit-howlong" > {{$howlong.1}} </label>
- <input type="text" size="32" name="howlong" id="profile-edit-howlong" title="{{$howlong.1}}" value="{{$howlong.2}}" />
- <div id="profile-edit-marital-end"></div>
-
- <div id="romance-jot-wrapper" >
- <div id="romance-jot-desc">{{$romance.1}}</div>
- <textarea rows="10" cols="72" id="romance-jot-text" name="romance" style="width:599px;">{{$romance.2}}</textarea>
- </div>
- <div id="romance-jot-end"></div>
-
- <div id="work-jot-wrapper">
- <div id="work-jot-desc">{{$work.1}}</div>
- <textarea rows="10" cols="72" id="work-jot-text" name="work" style="width:599px;">{{$work.2}}</textarea>
- </div>
- <div id="work-jot-end"></div>
-
- <div id="education-jot-wrapper" >
- <div id="education-jot-desc">{{$education.1}}</div>
- <textarea rows="10" cols="72" id="education-jot-text" name="education" style="width:599px;">{{$education.2}}</textarea>
- </div>
- <div id="education-jot-end"></div>
-
- <div class="profile-edit-submit-wrapper" >
- <input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" />
- </div>
- <div class="profile-edit-submit-end"></div>
-
- </div>
- </div>
-
- <!-- Interests -->
- <div class="toggle-section js-toggle-section">
- <a class="section-caption js-section-toggler" href="javascript:;">{{$lbl_interests_section}} »</a>
- <div class="js-section toggle-section-content hidden">
-
- <div id="interest-jot-wrapper">
- <div id="interest-jot-desc">{{$interest.1}}</div>
- <textarea rows="10" cols="72" id="interest-jot-text" name="interest" style="width:599px;">{{$interest.2}}</textarea>
- </div>
- <div id="interest-jot-end"></div>
-
- <div id="music-jot-wrapper">
- <div id="music-jot-desc">{{$music.1}}</div>
- <textarea rows="10" cols="72" id="music-jot-text" name="music" style="width:599px;">{{$music.2}}</textarea>
- </div>
- <div id="music-jot-end"></div>
-
- <div id="book-jot-wrapper">
- <div id="book-jot-desc">{{$book.1}}</div>
- <textarea rows="10" cols="72" id="book-jot-text" name="book" style="width:599px;">{{$book.2}}</textarea>
- </div>
- <div id="book-jot-end"></div>
-
- <div id="tv-jot-wrapper">
- <div id="tv-jot-desc">{{$tv.1}}</div>
- <textarea rows="10" cols="72" id="tv-jot-text" name="tv" style="width:599px;">{{$tv.2}}</textarea>
- </div>
- <div id="tv-jot-end"></div>
-
- <div id="film-jot-wrapper">
- <div id="film-jot-desc">{{$film.1}}</div>
- <textarea rows="10" cols="72" id="film-jot-text" name="film" style="width:599px;">{{$film.2}}</textarea>
- </div>
- <div id="film-jot-end"></div>
-
- <div class="profile-edit-submit-wrapper" >
- <input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" />
- </div>
- <div class="profile-edit-submit-end"></div>
-
- </div>
- </div>
-{{else}}
-
-{{if $personal_account}}
-{{include file="field_yesno.tpl" field=$details}}
-{{/if}}
-<div id="profile-edit-profile-name-wrapper" >
-<label id="profile-edit-profile-name-label" for="profile-edit-profile-name" >{{$profile_name.1}} </label>
-<input type="text" size="32" name="profile_name" id="profile-edit-profile-name" value="{{$profile_name.2}}" /><div class="required">*</div>
-</div>
-<div id="profile-edit-profile-name-end"></div>
-
-<div id="profile-edit-name-wrapper" >
-<label id="profile-edit-name-label" for="profile-edit-name" >{{$name.1}} </label>
-<input type="text" size="32" name="name" id="profile-edit-name" value="{{$name.2}}" />
-</div>
-<div id="profile-edit-name-end"></div>
-
-{{if $personal_account}}
-<div id="profile-edit-gender-wrapper" >
-<label id="profile-edit-gender-label" for="gender-select" >{{$lbl_gender}} </label>
-{{$gender nofilter}}
-</div>
-<div id="profile-edit-gender-end"></div>
-
-<div id="profile-edit-dob-wrapper" >
-{{$dob nofilter}}
-</div>
-<div id="profile-edit-dob-end"></div>
-{{/if}}
-
- <div id="profile-edit-xmpp-wrapper" >
- <label id="profile-edit-xmpp-label" for="profile-edit-xmpp" >{{$xmpp.1}} </label>
- <input type="text" size="32" name="xmpp" id="profile-edit-xmpp" value="{{$xmpp.2}}" />
- </div>
- <div id="profile-edit-xmpp-desc">{{$xmpp.3}}</div>
- <div id="profile-edit-xmpp-end"></div>
-
- <div id="profile-edit-homepage-wrapper" >
- <label id="profile-edit-homepage-label" for="profile-edit-homepage" >{{$homepage.1}} </label>
- <input type="text" size="32" name="homepage" id="profile-edit-homepage" value="{{$homepage.2}}" />
- </div>
- <div id="profile-edit-homepage-end"></div>
-
-{{$hide_friends nofilter}}
-
-<div id="profile-edit-address-wrapper" >
-<label id="profile-edit-address-label" for="profile-edit-address" >{{$address.1}} </label>
-<input type="text" size="32" name="address" id="profile-edit-address" value="{{$address.2}}" />
-</div>
-<div id="profile-edit-address-end"></div>
-
-<div id="profile-edit-locality-wrapper" >
-<label id="profile-edit-locality-label" for="profile-edit-locality" >{{$locality.1}} </label>
-<input type="text" size="32" name="locality" id="profile-edit-locality" value="{{$locality.2}}" />
-</div>
-<div id="profile-edit-locality-end"></div>
-
-
-<div id="profile-edit-postal-code-wrapper" >
-<label id="profile-edit-postal-code-label" for="profile-edit-postal-code" >{{$postal_code.1}} </label>
-<input type="text" size="32" name="postal_code" id="profile-edit-postal-code" value="{{$postal_code.2}}" />
-</div>
-<div id="profile-edit-postal-code-end"></div>
-
-<div id="profile-edit-country-name-wrapper" >
-<label id="profile-edit-country-name-label" for="profile-edit-country-name" >{{$country_name.1}} </label>
-<select name="country_name" id="profile-edit-country-name" onChange="Fill_States('{{$region.2}}');">
-<option selected="selected" >{{$country_name.2}}</option>
-<option>temp</option>
-</select>
-</div>
-<div id="profile-edit-country-name-end"></div>
-<div id="profile-edit-region-wrapper" >
-<label id="profile-edit-region-label" for="profile-edit-region" >{{$region.1}} </label>
-<select name="region" id="profile-edit-region" onChange="Update_Globals();" >
-<option selected="selected" >{{$region.2}}</option>
-<option>temp</option>
-</select>
-</div>
-<div id="profile-edit-region-end"></div>
-
-<div id="profile-edit-pubkeywords-wrapper" >
-<label id="profile-edit-pubkeywords-label" for="profile-edit-pubkeywords" >{{$pub_keywords.1}} </label>
-<input type="text" size="32" name="pub_keywords" id="profile-edit-pubkeywords" title="{{$lbl_ex2}}" value="{{$pub_keywords.2}}" />
-</div><div id="profile-edit-pubkeywords-desc">{{$pub_keywords.3}}</div>
-<div id="profile-edit-pubkeywords-end"></div>
-
-<div id="profile-edit-prvkeywords-wrapper" >
-<label id="profile-edit-prvkeywords-label" for="profile-edit-prvkeywords" >{{$prv_keywords.1}} </label>
-<input type="text" size="32" name="prv_keywords" id="profile-edit-prvkeywords" title="{{$lbl_ex2}}" value="{{$prv_keywords.2}}" />
-</div><div id="profile-edit-prvkeywords-desc">{{$prv_keywords.3}}</div>
-<div id="profile-edit-prvkeywords-end"></div>
-
-<div id="about-jot-wrapper" >
-<p id="about-jot-desc" >
-{{$about.1}}
-</p>
-
-<textarea rows="10" cols="72" id="profile-about-text" name="about" >{{$about.2}}</textarea>
-
-</div>
-<div id="about-jot-end"></div>
-
-<div class="profile-edit-submit-wrapper" >
-<input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}" />
-</div>
-<div class="profile-edit-submit-end"></div>
-
- <input type="hidden" name="pdesc" id="profile-edit-pdesc" value="{{$pdesc.2}}" />
- <input type="hidden" id="contact-jot-text" name="contact" value="{{$contact.2}}" />
- <input type="hidden" name="hometown" id="profile-edit-hometown" value="{{$hometown.2}}" />
- <input type="hidden" name="politic" id="profile-edit-politic" value="{{$politic.2}}" />
- <input type="hidden" name="religion" id="profile-edit-religion" value="{{$religion.2}}" />
- <input type="hidden" id="likes-jot-text" name="likes" value="{{$likes.2}}" />
- <input type="hidden" id="dislikes-jot-text" name="dislikes" value="{{$dislikes.2}}" />
- <input type="hidden" name="marital" id="profile-edit-marital" value="{{$marital.2}}" />
- <input type="hidden" name="with" id="profile-edit-with" value="{{$with.2}}" />
- <input type="hidden" name="howlong" id="profile-edit-howlong" value="{{$howlong.2}}" />
- <input type="hidden" name="sexual" id="profile-edit-sexual" value="{{$sexual.2}}" />
- <input type="hidden" id="romance-jot-text" name="romance" value="{{$romance.2}}" />
- <input type="hidden" id="work-jot-text" name="work" value="{{$work.2}}" />
- <input type="hidden" id="education-jot-text" name="education" value="{{$education.2}}" />
- <input type="hidden" id="interest-jot-text" name="interest" value="{{$interest.2}}" />
- <input type="hidden" id="music-jot-text" name="music" value="{{$music.2}}" />
- <input type="hidden" id="book-jot-text" name="book" value="{{$book.2}}" />
- <input type="hidden" id="tv-jot-text" name="tv" value="{{$tv.2}}" />
- <input type="hidden" id="film-jot-text" name="film" value="{{$film.2}}" />
-
-{{/if}}
-
-</form>
-</div>
-<script type="text/javascript">Fill_Country('{{$country_name.2}}');Fill_States('{{$region.2}}');</script>
+++ /dev/null
-
-<div class="clear"></div>
--- /dev/null
+<script>
+ $(document).ready(function () {
+ //$('.toggle-section-content + .toggle-section-content').hide();
+ $('.js-section-toggler').click(function () {
+ $('.toggle-section-content').hide();
+ $(this).next('.toggle-section-content').toggle();
+ });
+ });
+</script>
+
+<h1>{{$banner}}</h1>
+
+<div id="profile-edit-links">
+ <ul>
+ <li><a class="btn" href="profile/{{$nickname}}" id="profile-edit-view-link" title="{{$viewprof}}">{{$viewprof}}</a></li>
+ </ul>
+</div>
+<div id="profile-edit-links-end"></div>
+
+<div id="profile-edit-wrapper">
+ <form enctype="multipart/form-data" action="settings/profile/photo" method="post">
+ <input type="hidden" name="form_security_token" value="{{$form_security_token_photo}}">
+
+ <!-- Profile picture -->
+ <div class="toggle-section js-toggle-section">
+ <a class="section-caption js-section-toggler" href="javascript:;">{{$lbl_picture_section}} »</a>
+ <div class="js-section toggle-section-content hidden">
+
+ <div id="profile-photo-upload-wrapper">
+ <label id="profile-photo-upload-label" for="profile-photo-upload">{{$lbl_profile_photo}}:</label>
+ <input name="userfile" type="file" id="profile-photo-upload" size="48"/>
+ </div>
+
+ <div class="profile-edit-submit-wrapper">
+ <input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
+ </div>
+ <div class="profile-edit-submit-end"></div>
+
+ </div>
+ </div>
+ </form>
+
+ <form id="profile-edit-form" name="form1" action="" method="post">
+ <input type="hidden" name="form_security_token" value="{{$form_security_token}}">
+
+ <!-- Basic information -->
+ <div class="toggle-section js-toggle-section">
+ <a class="section-caption js-section-toggler" href="javascript:;">{{$lbl_personal_section}} »</a>
+ <div class="js-section toggle-section-content hidden">
+
+ <div id="profile-edit-name-wrapper">
+ <label id="profile-edit-name-label" for="profile-edit-name">{{$name.1}} </label>
+ <input type="text" size="32" name="name" id="profile-edit-name" value="{{$name.2}}"/>
+ </div>
+ <div id="profile-edit-name-end"></div>
+
+ <div id="profile-edit-pdesc-wrapper">
+ <label id="profile-edit-pdesc-label" for="profile-edit-pdesc">{{$pdesc.1}} </label>
+ <input type="text" size="32" name="pdesc" id="profile-edit-pdesc" value="{{$pdesc.2}}"/>
+ </div>
+ <div id="profile-edit-pdesc-end"></div>
+
+ <div id="profile-edit-xmpp-wrapper">
+ <label id="profile-edit-xmpp-label" for="profile-edit-xmpp">{{$xmpp.1}} </label>
+ <input type="text" size="32" name="xmpp" id="profile-edit-xmpp" value="{{$xmpp.2}}"/>
+ </div>
+ <div id="profile-edit-xmpp-desc">{{$xmpp.3}}</div>
+ <div id="profile-edit-xmpp-end"></div>
+
+ <div id="profile-edit-homepage-wrapper">
+ <label id="profile-edit-homepage-label" for="profile-edit-homepage">{{$homepage.1}} </label>
+ <input type="text" size="32" name="homepage" id="profile-edit-homepage" value="{{$homepage.2}}"/>
+ </div>
+ <div id="profile-edit-homepage-end"></div>
+
+ <div id="profile-edit-dob-wrapper">
+ {{$dob nofilter}}
+ </div>
+ <div id="profile-edit-dob-end"></div>
+
+ {{$hide_friends nofilter}}
+
+ <div id="profile-edit-pubkeywords-wrapper">
+ <label id="profile-edit-pubkeywords-label" for="profile-edit-pubkeywords">{{$pub_keywords.1}} </label>
+ <input type="text" size="32" name="pub_keywords" id="profile-edit-pubkeywords" title="{{$lbl_ex2}}" value="{{$pub_keywords.2}}"/>
+ </div>
+ <div id="profile-edit-pubkeywords-desc">{{$pub_keywords.3}}</div>
+ <div id="profile-edit-pubkeywords-end"></div>
+
+ <div id="profile-edit-prvkeywords-wrapper">
+ <label id="profile-edit-prvkeywords-label" for="profile-edit-prvkeywords">{{$prv_keywords.1}} </label>
+ <input type="text" size="32" name="prv_keywords" id="profile-edit-prvkeywords" title="{{$lbl_ex2}}" value="{{$prv_keywords.2}}"/>
+ </div>
+ <div id="profile-edit-prvkeywords-desc">{{$prv_keywords.3}}</div>
+ <div id="profile-edit-prvkeywords-end"></div>
+
+ <div class="profile-edit-submit-wrapper">
+ <input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
+ </div>
+ <div class="profile-edit-submit-end"></div>
+
+ </div>
+ </div>
+ <!-- About you -->
+ <div class="toggle-section js-toggle-section">
+ <a class="section-caption js-section-toggler" href="javascript:;">{{$lbl_location_section}} »</a>
+ <div class="js-section toggle-section-content hidden">
+
+ <div id="profile-edit-address-wrapper">
+ <label id="profile-edit-address-label" for="profile-edit-address">{{$address.1}} </label>
+ <input type="text" size="32" name="address" id="profile-edit-address" value="{{$address.2}}"/>
+ </div>
+ <div id="profile-edit-address-end"></div>
+
+ <div id="profile-edit-locality-wrapper">
+ <label id="profile-edit-locality-label" for="profile-edit-locality">{{$locality.1}} </label>
+ <input type="text" size="32" name="locality" id="profile-edit-locality" value="{{$locality.2}}"/>
+ </div>
+ <div id="profile-edit-locality-end"></div>
+
+ <div id="profile-edit-postal-code-wrapper">
+ <label id="profile-edit-postal-code-label" for="profile-edit-postal-code">{{$postal_code.1}} </label>
+ <input type="text" size="32" name="postal_code" id="profile-edit-postal-code" value="{{$postal_code.2}}"/>
+ </div>
+ <div id="profile-edit-postal-code-end"></div>
+
+ <div id="profile-edit-country-name-wrapper">
+ <label id="profile-edit-country-name-label" for="profile-edit-country-name">{{$country_name.1}} </label>
+ <select name="country_name" id="profile-edit-country-name" onChange="Fill_States('{{$region.2}}');">
+ <option selected="selected">{{$country_name.2}}</option>
+ </select>
+ </div>
+ <div id="profile-edit-country-name-end"></div>
+
+ <div id="profile-edit-region-wrapper">
+ <label id="profile-edit-region-label" for="profile-edit-region">{{$region.1}} </label>
+ <select name="region" id="profile-edit-region" onChange="Update_Globals();">
+ <option selected="selected">{{$region.2}}</option>
+ </select>
+ </div>
+ <div id="profile-edit-region-end"></div>
+
+ <div class="profile-edit-submit-wrapper">
+ <input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
+ </div>
+ <div class="profile-edit-submit-end"></div>
+ </div>
+ </div>
+ <!-- Interests -->
+ <div class="toggle-section js-toggle-section">
+ <a class="section-caption js-section-toggler" href="javascript:;">{{$lbl_custom_fields_section}} »</a>
+ <div class="js-section toggle-section-content hidden">
+ {{$custom_fields_description nofilter}}
+ <div id="profile-custom-fields">
+ {{foreach $custom_fields as $custom_field}}
+ {{include file="settings/profile/field/edit.tpl" profile_field=$custom_field}}
+ {{/foreach}}
+ </div>
+
+ <div class="profile-edit-submit-wrapper">
+ <input type="submit" name="submit" class="profile-edit-submit-button" value="{{$submit}}"/>
+ </div>
+ <div class="profile-edit-submit-end"></div>
+ </div>
+ </div>
+ </form>
+</div>
+<script type="text/javascript">
+ Fill_Country('{{$country_name.2}}');
+ Fill_States('{{$region.2}}');
+</script>
--- /dev/null
+
+<div class="clear"></div>
// last 9 users
if ($show_lastusers) {
- $publish = (DI::config()->get('system', 'publish_all') ? '' : " AND `publish` = 1 ");
+ $publish = (DI::config()->get('system', 'publish_all') ? '' : "`publish` = 1");
$order = " ORDER BY `register_date` DESC ";
$tpl = Renderer::getMarkupTemplate('ch_directory_item.tpl');
$r = q("SELECT `profile`.*, `user`.`nickname`
FROM `profile` LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid`
- WHERE `is-default` = 1 $publish AND `user`.`blocked` = 0 $order LIMIT %d , %d ",
+ WHERE $publish AND `user`.`blocked` = 0 $order LIMIT %d , %d ",
0,
9
);