diff --git a/boot.php b/boot.php index e92be51a9f..b1e98270c0 100644 --- a/boot.php +++ b/boot.php @@ -41,7 +41,7 @@ define('FRIENDICA_PLATFORM', 'Friendica'); define('FRIENDICA_CODENAME', 'The Tazmans Flax-lily'); define('FRIENDICA_VERSION', '2018.08-dev'); define('DFRN_PROTOCOL_VERSION', '2.23'); -define('DB_UPDATE_VERSION', 1282); +define('DB_UPDATE_VERSION', 1283); define('NEW_UPDATE_ROUTINE_VERSION', 1170); /** diff --git a/composer.json b/composer.json index 9ef0dcd101..04e4b655da 100644 --- a/composer.json +++ b/composer.json @@ -74,7 +74,8 @@ "require-dev": { "phpunit/dbunit": "^2.0", "phpdocumentor/reflection-docblock": "^3.0.2", - "phpunit/php-token-stream": "^1.4.2" + "phpunit/php-token-stream": "^1.4.2", + "mikey179/vfsStream": "^1.6" }, "scripts": { "test": "phpunit" diff --git a/composer.lock b/composer.lock index 409deb2e8f..76c20a1b93 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "9e24971ae9340c5d9d4d4ca477d4ec29", + "content-hash": "d62c3e3d6971ee63a862a22ff3cd3768", "packages": [ { "name": "asika/simple-console", @@ -2252,6 +2252,52 @@ ], "time": "2015-06-14T21:17:01+00:00" }, + { + "name": "mikey179/vfsStream", + "version": "v1.6.5", + "source": { + "type": "git", + "url": "https://github.com/mikey179/vfsStream.git", + "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", + "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-0": { + "org\\bovigo\\vfs\\": "src/main/php" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Frank Kleine", + "homepage": "http://frankkleine.de/", + "role": "Developer" + } + ], + "description": "Virtual file system to mock the real file system in unit tests.", + "homepage": "http://vfs.bovigo.org/", + "time": "2017-08-01T08:02:14+00:00" + }, { "name": "myclabs/deep-copy", "version": "1.7.0", diff --git a/config/dbstructure.json b/config/dbstructure.json index 2c1ecddc56..c467ba6bc7 100644 --- a/config/dbstructure.json +++ b/config/dbstructure.json @@ -1224,6 +1224,19 @@ "username": ["username(32)"] } }, + "user-contact": { + "comment": "User specific public contact data", + "fields": { + "cid": {"type": "int unsigned", "not null": "1", "default": "0", "primary": "1", "relation": {"contact": "id"}, "comment": "Contact id of the linked public contact"}, + "uid": {"type": "mediumint unsigned", "not null": "1", "default": "0", "primary": "1", "relation": {"user": "uid"}, "comment": "User id"}, + "blocked": {"type": "boolean", "comment": "Contact is completely blocked for this user"}, + "ignored": {"type": "boolean", "comment": "Posts from this contact are ignored"}, + "collapsed": {"type": "boolean", "comment": "Posts from this contact are collapsed"} + }, + "indexes": { + "PRIMARY": ["uid", "cid"] + } + }, "user-item": { "comment": "User specific item data", "fields": { diff --git a/database.sql b/database.sql index 0dbeb80dd0..60d4b1c88e 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2018.08-dev (The Tazmans Flax-lily) --- DB_UPDATE_VERSION 1282 +-- DB_UPDATE_VERSION 1283 -- ------------------------------------------ @@ -1173,6 +1173,18 @@ CREATE TABLE IF NOT EXISTS `userd` ( INDEX `username` (`username`(32)) ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Deleted usernames'; +-- +-- TABLE user-contact +-- +CREATE TABLE IF NOT EXISTS `user-contact` ( + `cid` int unsigned NOT NULL DEFAULT 0 COMMENT 'Contact id of the linked public contact', + `uid` mediumint unsigned NOT NULL DEFAULT 0 COMMENT 'User id', + `blocked` boolean COMMENT 'Contact is completely blocked for this user', + `ignored` boolean COMMENT 'Posts from this contact are ignored', + `collapsed` boolean COMMENT 'Posts from this contact are collapsed', + PRIMARY KEY(`uid`,`cid`) +) DEFAULT COLLATE utf8mb4_general_ci COMMENT='User specific public contact data'; + -- -- TABLE user-item -- diff --git a/doc/Install.md b/doc/Install.md index 79747c0837..3854c32bce 100644 --- a/doc/Install.md +++ b/doc/Install.md @@ -111,30 +111,86 @@ You might wish to move/rename `config/local.ini.php` to another name and empty ( ### Option B: Run the automatic install script -Open the file htconfig.php in the main Friendica directory with a text editor. -Remove the `die('...');` line and edit the lines to suit your installation (MySQL, language, theme etc.). -Then save the file (do not rename it). +You have the following options to automatically install Friendica: +- creating a prepared config file (f.e. `prepared.ini.php`) +- using environment variables (f.e. `MYSQL_HOST`) +- using options (f.e. `--dbhost `) -Navigate to the main Friendica directory and execute the following command: - - bin/console autoinstall - -Or if you wish to include all optional checks, execute this statement instead: - - bin/console autoinstall -a - -At this point visit your website again, and register your personal account. - -*If* the automatic installation fails for any reason, check the following: - -* Does "config/local.ini.php" already exist? If yes, the automatic installation won't start -* Are the settings inside "htconfig.php" correct? If not, edit the file again. -* Is the empty MySQL-database created? If not, create it. +You can combine environment variables and options, but be aware that options are prioritized over environment variables. For more information during the installation, you can use this command line option bin/console autoinstall -v +If you wish to include all optional checks, use `-a` like this statement: + + bin/console autoinstall -a + +*If* the automatic installation fails for any reason, check the following: + +* Does `config/local.ini.php` already exist? If yes, the automatic installation won't start +* Are the options in the `config/local.ini.php` correct? If not, edit them directly. +* Is the empty MySQL-database created? If not, create it. + +#### B.1: Config file + +You can use a prepared config file like [local-sample.ini.php](config/local-sample.ini.php). + +Navigate to the main Friendica directory and execute the following command: + + bin/console autoinstall -f + +#### B.2: Environment variables + +There are two types of environment variables. +- those you can use in normal mode too (Currently just **database credentials**) +- those you can only use during installation (because Friendica will normally ignore it) + +You can use the options during installation too and skip some of the environment variables. + +**Database credentials** + +if you don't use the option `--savedb` during installation, the DB credentials will **not** be saved in the `config/local.ini.php`. + +- `MYSQL_HOST` The host of the mysql/mariadb database +- `MYSQL_PORT` The port of the mysql/mariadb database +- `MYSQL_USERNAME` The username of the mysql database login (used for mysql) +- `MYSQL_USER` The username of the mysql database login (used for mariadb) +- `MYSQL_PASSWORD` The password of the mysql/mariadb database login +- `MYSQL_DATABASE` The name of the mysql/mariadb database + +**Friendica settings** + +This variables wont be used at normal Friendica runtime. +Instead, they get saved into `config/local.ini.php`. + +- `FRIENDICA_PHP_PATH` The path of the PHP binary +- `FRIENDICA_ADMIN_MAIL` The admin email address of Friendica (this email will be used for admin access) +- `FRIENDICA_TZ` The timezone of Friendica +- `FRIENDICA_LANG` The langauge of Friendica + +Navigate to the main Friendica directory and execute the following command: + + bin/console autoinstall [--savedb] + +#### B.3: Execution options + +All options will be saved in the `config/local.ini.php` and are overruling the associated environment variables. + +- `-H|--dbhost ` The host of the mysql/mariadb database (env `MYSQL_HOST`) +- `-p|--dbport ` The port of the mysql/mariadb database (env `MYSQL_PORT`) +- `-U|--dbuser ` The username of the mysql/mariadb database login (env `MYSQL_USER` or `MYSQL_USERNAME`) +- `-P|--dbpass ` The password of the mysql/mariadb database login (env `MYSQL_PASSWORD`) +- `-d|--dbdata ` The name of the mysql/mariadb database (env `MYSQL_DATABASE`) +- `-b|--phppath ` The path of the PHP binary (env `FRIENDICA_PHP_PATH`) +- `-A|--admin ` The admin email address of Friendica (env `FRIENDICA_ADMIN_MAIL`) +- `-T|--tz ` The timezone of Friendica (env `FRIENDICA_TZ`) +- `-L|--land ` The language of Friendica (env `FRIENDICA_LANG`) + +Navigate to the main Friendica directory and execute the following command: + + bin/console autoinstall [options] + ### Prepare .htaccess file Copy .htaccess-dist to .htaccess (be careful under Windows) to have working mod-rewrite again. If you have installed Friendica into a sub directory, like /friendica/ set this path in RewriteBase accordingly. @@ -145,6 +201,23 @@ Example: *Note*: Do **not** rename the .htaccess-dist file as it is tracked by GIT and renaming will cause a dirty working directory. +### Verify the "host-meta" page is working + +Friendica should respond automatically to important addresses under the /.well-known/ rewrite path. +One critical URL would look like, for example, https://example.com/.well-known/host-meta +It must be visible to the public and must respond with an XML file that is automatically customized to your site. + +If that URL is not working, it is possible that some other software is using the /.well-known/ path. +Other symptoms may include an error message in the Admin settings that says "host-meta is not reachable on your system. +This is a severe configuration issue that prevents server to server communication." +Another common error related to host-meta is the "Invalid profile URL." + +Check for a .well-known directory that did not come with Friendica. +The preferred configuration is to remove the directory, however this is not always possible. +If there is any /.well-known/.htaccess file, it could interfere with this Friendica core requirement. +You should remove any RewriteRules from that file, or remove that whole file if appropriate. +It may be necessary to chmod the /.well-known/.htaccess file if you were not given write permissions by default. + ### Set up the worker Set up a cron job or scheduled task to run the worker once every 5-10 minutes in order to perform background processing. diff --git a/doc/Move-Account.md b/doc/Move-Account.md index c34a93e949..2193c42c4b 100644 --- a/doc/Move-Account.md +++ b/doc/Move-Account.md @@ -1,31 +1,31 @@ -How to move your account between servers -============ - -* [Home](help) - - -! **This is an experimental feature** - -* Go to "Settings" -> "[Export personal data](uexport)" -* Click on "Export account" to save your account data. -* **Save the file in a secure place!** It contains your details, your contacts, groups, and personal settings. It also contains your secret keys to authenticate yourself to your contacts. -* Go to your new server, and open *http://newserver.com/uimport* (there is not a direct link to this page at the moment). -* Do NOT create a new account prior to importing your old settings - uimport should be used *instead* of register. -* Load your saved account file and click "Import". -* After the move, the account on the old server will not work reliably anymore, and should be not used. - - -Friendica contacts ---- -Friendica will recreate your account on the new server, with your contacts and groups. -A message is sent to Friendica contacts, to inform them about your move: -If your contacts are runnning on an updated server, your details on their side will be automatically updated. - -GNU Social contacts ---- -Contacts on GNU Social will be archived, as we can't inform them about your move. -You should ask them to remove your contact from their lists and re-add you, and you should do the same with their contact. - -Diaspora contacts ---- -Newer Diaspora servers are able to process "account migration" messages. +How to move your account between servers +============ + +* [Home](help) + + +! **This is an experimental feature** + +* Go to "Settings" -> "[Export personal data](uexport)" +* Click on "Export account" to save your account data. +* **Save the file in a secure place!** It contains your details, your contacts, groups, and personal settings. It also contains your secret keys to authenticate yourself to your contacts. +* Go to your new server, and open *http://newserver.com/uimport* (there is not a direct link to this page at the moment). Please consider that this is only possible on servers with open registration. On other systems only the administrator can add accounts with an uploaded file. +* Do NOT create a new account prior to importing your old settings - uimport should be used *instead* of register. +* Load your saved account file and click "Import". +* After the move, the account on the old server will not work reliably anymore, and should be not used. + + +Friendica contacts +--- +Friendica will recreate your account on the new server, with your contacts and groups. +A message is sent to Friendica contacts, to inform them about your move: +If your contacts are runnning on an updated server, your details on their side will be automatically updated. + +GNU Social contacts +--- +Contacts on GNU Social will be archived, as we can't inform them about your move. +You should ask them to remove your contact from their lists and re-add you, and you should do the same with their contact. + +Diaspora contacts +--- +Newer Diaspora servers are able to process "account migration" messages. diff --git a/doc/de/Install.md b/doc/de/Install.md index 84941d9282..05a4e1e465 100644 --- a/doc/de/Install.md +++ b/doc/de/Install.md @@ -112,29 +112,88 @@ Alle Registrierungsprobleme sollten automatisch behebbar sein. Wenn du irgendwelche **kritischen** Fehler zu diesen Zeitpunkt erhalten solltest, deutet das darauf hin, dass die Datenbank nicht korrekt installiert wurde. Du kannst bei Bedarf die Datei config/local.ini.php verschieben/umbenennen und die Datenbank leeren (als „Dropping“ bezeichnet), so dass du mit einem sauberen System neu starten kannst. -### Option B: Starte das manuelle Installationsscript +### Option B: Starte das automatische Installationsscript -Öffne die Datei htconfig.php im Friendica-Hauptordner mit einem Text-Editor. -Entferne die `die('...');` Zeile und bearbeite die Einstellungen so, das sie zu deinem System passen (MySQL, Sprache, Theme etc.). -Dann speichere die Datei (jedoch nicht umbenennen). +Es existieren folgende Varianten zur automatischen Installation von Friendica: +- Eine vorgefertigte Konfigurationsdatei erstellen (z.B. `prepared.ini.php`) +- Verwendung von Umgebungsvariablen (z.B. `MYSQL_HOST`) +- Verwendung von Optionen (z.B. `--dbhost `) -Gehe in den Friendica-Hauptordner und führe den Kommandozeilen Befehl aus: - - bin/console autoinstall - -Oder falls du alle optionalen Checks ausfürehn lassen möchtest, benutze diese Option: - - bin/console autoinstall -a - -*Wenn* die automatisierte Installation aus irgendeinem Grund fehlschlägt, dann prüfe das Folgende: -* Existiert die `config/local.ini.php`? Falls ja, wird die automatisierte Installation nicht gestartet. -* Sind Einstellungen in der `config/local.ini.php` korrekt? Falls nicht, bitte bearbeite diese Datei erneut. -* Ist die leere MySQL-Datenbank erstellt? Falls nicht, erstelle diese. +Umgebungsvariablen und Optionen können auch kombiniert werden. +Dabei ist jedoch darauf zu achten, dass etwaige Optionen immer die zugehörigen Umgebungsvariablen überschreiben. Für mehr Informationen kannst du diese Option verwenden: bin/console autoinstall -v +Falls du alle optionalen Checks ausfürehn lassen möchtest, benutze diese Option: + + bin/console autoinstall -a + +*Wenn* die automatisierte Installation aus irgendeinem Grund fehlschlägt, dann prüfe das Folgende: +* Existiert die `config/local.ini.php`? Falls ja, wird die automatisierte Installation nicht gestartet. +* Sind Einstellungen in der `config/local.ini.php` korrekt? Falls nicht, bitte bearbeite diese Datei erneut. +* Ist die leere MySQL-Datenbank erstellt? Falls nicht, erstelle diese. + +#### B.1: Konfigurationsdatei + +Für diese Variante muss ein Konfigurationsdatei bereits vor der Installation fertig definiert sein (z.B. [local-sample.ini.php](config/local-sample.ini.php). + +Gehe im Anschluss in den Friendica-Hauptordner und führe den Kommandozeilen Befehl aus: + + bin/console autoinstall -f + +#### B.2: Umgebungsvariablen + +Es existieren Zwei Arten von Umgebungsvariablen in Friendica: +- Jene, die auch im normalen Betrieb verwendet werden können (derzeit ausschließlich **Datenbank Einstellungen**) +- Jene, die nur während der Installation verwedent werden können (im normalen Betrieb werden sie ignoriert) + +Umgebungsvariablen können auch durch adäquate Optionen (z.B. `--dbhost `)übersteuert werden. + +**Datenbank Einstellungen** + +Nur wenn die Option `--savedb` gesetzt ist, werden diese Umgebungsvariablen auch in `config/local.ini.php` gespeichert! + +- `MYSQL_HOST` Der Host der MySQL/MariaDB Datenbank +- `MYSQL_PORT` Der Port der MySQL/MariaDB Datenbank +- `MYSQL_USERNAME` Der Benutzername des MySQL Datenbanklogins (MySql - Variante) +- `MYSQL_USER` Der Benutzername des MariaDB Datenbanklogins (MariaDB-Variante) +- `MYSQL_PASSWORD` Das Passwort der MySQL/MariaDB Datenbanklogins +- `MYSQL_DATABASE` Der Name der MySQL/MariaDB Datenbank + +**Friendica Einstellungen** + +Diese Umgebungsvariablen können nicht während des normalen Friendica Betriebs verwendet werden. +Sie werden stattdessen direkt in `config/local.ini.php` gespeichert. + +- `FRIENDICA_PHP_PATH` Der Pfad zur PHP-Datei +- `FRIENDICA_ADMIN_MAIL` Die Admin E-Mail Adresse dieses Friendica Knotens (wird auch für den Admin-Zugang benötigt) +- `FRIENDICA_TZ` Die Zeitzone von Friendica +- `FRIENDICA_LANG` Die Sprache von Friendica + +Gehe im Anschluss in den Friendica-Hauptordner und führe den Kommandozeilen Befehl aus: + + bin/console autoinstall [--savedb] + +#### B.3: Optionen + +Alle Optionen werden in `config/local.ini.php` gespeichert und überschreiben etwaige, zugehörige Umgebungsvariablen. + +- `-H|--dbhost ` Der Host der MySQL/MariaDB Datenbank (env `MYSQL_HOST`) +- `-p|--dbport ` Der Port der MySQL/MariaDB Datenbank (env `MYSQL_PORT`) +- `-U|--dbuser ` Der Benutzername des MySQL/MariaDB Datenbanklogins (env `MYSQL_USER` or `MYSQL_USERNAME`) +- `-P|--dbpass ` Das Passwort der MySQL/MariaDB Datenbanklogins (env `MYSQL_PASSWORD`) +- `-d|--dbdata ` Der Name der MySQL/MariaDB Datenbank (env `MYSQL_DATABASE`) +- `-b|--phppath ` Der Pfad zur PHP-Datei (env `FRIENDICA_PHP_PATH`) +- `-A|--admin ` Die Admin E-Mail Adresse dieses Friendica Knotens (env `FRIENDICA_ADMIN_MAIL`) +- `-T|--tz ` Die Zeitzone von Friendica (env `FRIENDICA_TZ`) +- `-L|--land ` Die Sprache von Friendica (env `FRIENDICA_LANG`) + +Gehe in den Friendica-Hauptordner und führe den Kommandozeilen Befehl aus: + + bin/console autoinstall [options] + ### Einen Worker einrichten Erstelle einen Cron job oder einen regelmäßigen Task, um den Poller alle 5-10 Minuten im Hintergrund ablaufen zu lassen. diff --git a/doc/de/Move-Account.md b/doc/de/Move-Account.md index 1b0c7eb8fb..79e7eae917 100644 --- a/doc/de/Move-Account.md +++ b/doc/de/Move-Account.md @@ -1,34 +1,38 @@ -Accounts Umziehen -================= - -* [Zur Startseite der Hilfe](help) - - -! **Dies ist ein experimentelles Feature** - -**Wie man einen Account von einem Server zu einem anderen umzieht.** - -Unter "Einstellungen" -> "[Persönliche Daten exportieren](uexport)" aufrufen. -"Account exportieren" anklicken und die Daten speichern. -Diese Datei enthält Details über dich, deine Kontakte, Gruppen und persönliche Einstellungen. -Außerdem enthält sie deinen geheimen Schlüssel mit dem du dich deinen Kontakten gegenüber ausweist. - -**Speichere diese Datei an einem sicheren Ort**! - -Rufe nun dem neuen Server die Seite *http://newserver.com/uimport* auf (es gibt derzeit keinen direkten Link auf diese Seite). - -Lege auf dem neuen Server auf keinen Fall einen gleichnamigen Account an! -uimport muss anstelle des Registrierens verwendet werden. - -Wähle die gesicherte Account Datei aus und klicke "Importieren". - -Friendica wird nun deinen Account auf dem neuen Server wiederherstellen, mit all deinen Friendica Kontakten und Gruppen. -An deine Friendica Kontakte wird außerdem eine Nachricht gesendet um sie über deine neue Adresse zu informieren. -Wenn deine Kontakte ihren Account auf einem aktuellen Server haben werden deine Kontaktdetails automatisch aktualisiert. - -Neuere Diaspora Server unterstützen ebenfalls eine Umzugsbenachrichtigung. - -Kontakte auf GNU Social werden archiviert, da wir ihnen keine Information über deinen Umzug zukommen lassen können. -Du solltest sie persönlich anschreiben deinen Eintrag aus ihren Kontaktlisten zu entfernen und dich neu hinzuzufügen, anschließend solltest du da gleiche mit ihren Accounts tun. - -Nach dem Umzug wird dein Account auf dem alten Server nicht mehr zuverlässig funktionieren und sollte deshalb gelöscht werden. +Accounts Umziehen +================= + +* [Zur Startseite der Hilfe](help) + + +! **Dies ist ein experimentelles Feature** + +**Wie man einen Account von einem Server zu einem anderen umzieht.** + +Unter "Einstellungen" -> "[Persönliche Daten exportieren](uexport)" aufrufen. +"Account exportieren" anklicken und die Daten speichern. +Diese Datei enthält Details über dich, deine Kontakte, Gruppen und persönliche Einstellungen. +Außerdem enthält sie deinen geheimen Schlüssel mit dem du dich deinen Kontakten gegenüber ausweist. + +**Speichere diese Datei an einem sicheren Ort**! + +Rufe nun dem neuen Server die Seite *http://newserver.com/uimport* auf (es gibt derzeit keinen direkten Link auf diese Seite). + +Bitte beachte, dass dies nur auf Servern möglich ist, an denen man sich offen anmelden kann. +Bei Servern, bei denen der Administrator Accounts freigeben muss, ist das Hochladen nicht möglich. +Hier kann dies nur der Administrator selber durchführen. + +Lege auf dem neuen Server auf keinen Fall einen gleichnamigen Account an! +uimport muss anstelle des Registrierens verwendet werden. + +Wähle die gesicherte Account Datei aus und klicke "Importieren". + +Friendica wird nun deinen Account auf dem neuen Server wiederherstellen, mit all deinen Friendica Kontakten und Gruppen. +An deine Friendica Kontakte wird außerdem eine Nachricht gesendet um sie über deine neue Adresse zu informieren. +Wenn deine Kontakte ihren Account auf einem aktuellen Server haben werden deine Kontaktdetails automatisch aktualisiert. + +Neuere Diaspora Server unterstützen ebenfalls eine Umzugsbenachrichtigung. + +Kontakte auf GNU Social werden archiviert, da wir ihnen keine Information über deinen Umzug zukommen lassen können. +Du solltest sie persönlich anschreiben deinen Eintrag aus ihren Kontaktlisten zu entfernen und dich neu hinzuzufügen, anschließend solltest du da gleiche mit ihren Accounts tun. + +Nach dem Umzug wird dein Account auf dem alten Server nicht mehr zuverlässig funktionieren und sollte deshalb gelöscht werden. diff --git a/include/conversation.php b/include/conversation.php index 5a26700fd7..ca01997f6a 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -517,6 +517,15 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o . "\r\n"; } + } elseif ($mode === 'contacts') { + $items = conversation_add_children($items, true, $order, $uid); + $profile_owner = 0; + + if (!$update) { + $live_update_div = '
' . "\r\n" + . "\r\n"; + } } elseif ($mode === 'search') { $live_update_div = '' . "\r\n"; } @@ -544,7 +553,7 @@ function conversation(App $a, array $items, $mode, $update, $preview = false, $o $page_template = get_markup_template("conversation.tpl"); if (!empty($items)) { - if ($mode === 'community') { + if (in_array($mode, ['community', 'contacts'])) { $writable = true; } else { $writable = ($items[0]['uid'] == 0) && in_array($items[0]['network'], [Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN]); diff --git a/mod/admin.php b/mod/admin.php index 30073c655b..d4fcc533f7 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -24,6 +24,7 @@ use Friendica\Module\Tos; use Friendica\Util\Arrays; use Friendica\Util\DateTimeFormat; use Friendica\Util\Temporal; +use Friendica\Util\Network; require_once 'include/enotify.php'; require_once 'include/text.php'; @@ -868,6 +869,14 @@ function admin_page_summary(App $a) $warningtext[] = L10n::t('Friendica\'s configuration now is stored in config/local.ini.php, please copy config/local-sample.ini.php and move your config from .htconfig.php. See the Config help page for help with the transition.', $a->get_baseurl() . '/help/Config'); } + // Check server vitality + if (!admin_page_server_vital()) { + $showwarning = true; + $well_known = $a->get_baseurl() . '/.well-known/host-meta'; + $warningtext[] = L10n::t('%s is not reachable on your system. This is a severe configuration issue that prevents server to server communication. See the installation page for help.', + $well_known, $well_known, $a->get_baseurl() . '/help/Install'); + } + $r = q("SELECT `page-flags`, COUNT(`uid`) AS `count` FROM `user` GROUP BY `page-flags`"); $accounts = [ [L10n::t('Normal Account'), 0], @@ -2544,3 +2553,10 @@ function admin_page_features(App $a) return $o; } } + +function admin_page_server_vital() +{ + // Fetch the host-meta to check if this really is a vital server + $serverret = Network::curl(System::baseUrl() . '/.well-known/host-meta'); + return $serverret["success"]; +} diff --git a/mod/allfriends.php b/mod/allfriends.php index 32cd23ec6b..7623a9cd06 100644 --- a/mod/allfriends.php +++ b/mod/allfriends.php @@ -35,7 +35,7 @@ function allfriends_content(App $a) $uid = $a->user['uid']; - $contact = DBA::selectFirst('contact', ['name', 'url', 'photo'], ['id' => $cid, 'uid' => local_user()]); + $contact = DBA::selectFirst('contact', ['name', 'url', 'photo', 'uid', 'id'], ['id' => $cid, 'uid' => local_user()]); if (!DBA::isResult($contact)) { return; @@ -96,7 +96,7 @@ function allfriends_content(App $a) $entries[] = $entry; } - $tab_str = contacts_tab($a, $cid, 3); + $tab_str = contacts_tab($a, $contact, 4); $tpl = get_markup_template('viewcontact_template.tpl'); diff --git a/mod/common.php b/mod/common.php index 5955b51436..afe78ce460 100644 --- a/mod/common.php +++ b/mod/common.php @@ -38,14 +38,14 @@ function common_content(App $a) } if ($cmd === 'loc' && $cid) { - $contact = DBA::selectFirst('contact', ['name', 'url', 'photo'], ['id' => $cid, 'uid' => $uid]); + $contact = DBA::selectFirst('contact', ['name', 'url', 'photo', 'uid', 'id'], ['id' => $cid, 'uid' => $uid]); if (DBA::isResult($contact)) { $a->page['aside'] = ""; Profile::load($a, "", 0, Contact::getDetailsByURL($contact["url"])); } } else { - $contact = DBA::selectFirst('contact', ['name', 'url', 'photo'], ['self' => true, 'uid' => $uid]); + $contact = DBA::selectFirst('contact', ['name', 'url', 'photo', 'uid', 'id'], ['self' => true, 'uid' => $uid]); if (DBA::isResult($contact)) { $vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"), [ @@ -137,7 +137,7 @@ function common_content(App $a) $title = ''; $tab_str = ''; if ($cmd === 'loc' && $cid && local_user() == $uid) { - $tab_str = contacts_tab($a, $cid, 4); + $tab_str = contacts_tab($a, $contact, 4); } else { $title = L10n::t('Common Friends'); } diff --git a/mod/contacts.php b/mod/contacts.php index 9800dbdc1a..4e87697172 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -21,6 +21,7 @@ use Friendica\Model\Profile; use Friendica\Network\Probe; use Friendica\Util\DateTimeFormat; use Friendica\Util\Proxy as ProxyUtils; +use Friendica\Core\ACL; function contacts_init(App $a) { @@ -39,14 +40,18 @@ function contacts_init(App $a) $contact_id = null; $contact = null; - if ((($a->argc == 2) && intval($a->argv[1])) || (($a->argc == 3) && intval($a->argv[1]) && ($a->argv[2] == "posts"))) { + if ((($a->argc == 2) && intval($a->argv[1])) || (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations']))) { $contact_id = intval($a->argv[1]); $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]); + + if (!DBA::isResult($contact)) { + $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => 0]); + } } if (DBA::isResult($contact)) { if ($contact['self']) { - if (($a->argc == 3) && intval($a->argv[1]) && ($a->argv[2] == "posts")) { + if (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations'])) { goaway('profile/' . $contact['nick']); } else { goaway('profile/' . $contact['nick'] . '?tab=profile'); @@ -87,7 +92,11 @@ function contacts_init(App $a) $findpeople_widget = Widget::findPeople(); } - $groups_widget = Group::sidebarWidget('contacts', 'group', 'full', 'everyone', $contact_id); + if ($contact['uid'] != 0) { + $groups_widget = Group::sidebarWidget('contacts', 'group', 'full', 'everyone', $contact_id); + } else { + $groups_widget = null; + } $a->page['aside'] .= replace_macros(get_markup_template("contacts-widget-sidebar.tpl"), [ '$vcard_widget' => $vcard_widget, @@ -131,16 +140,12 @@ function contacts_batch_actions(App $a) $count_actions++; } if (x($_POST, 'contacts_batch_block')) { - $r = _contact_block($contact_id, $orig_record); - if ($r) { - $count_actions++; - } + _contact_block($contact_id); + $count_actions++; } if (x($_POST, 'contacts_batch_ignore')) { - $r = _contact_ignore($contact_id, $orig_record); - if ($r) { - $count_actions++; - } + _contact_ignore($contact_id); + $count_actions++; } if (x($_POST, 'contacts_batch_archive')) { $r = _contact_archive($contact_id, $orig_record); @@ -327,26 +332,16 @@ function _contact_update_profile($contact_id) GContact::updateFromProbe($data["url"]); } -function _contact_block($contact_id, $orig_record) +function _contact_block($contact_id) { - $blocked = (($orig_record['blocked']) ? 0 : 1); - $r = q("UPDATE `contact` SET `blocked` = %d WHERE `id` = %d AND `uid` = %d", - intval($blocked), - intval($contact_id), - intval(local_user()) - ); - return DBA::isResult($r); + $blocked = !Contact::isBlockedByUser($contact_id, local_user()); + Contact::setBlockedForUser($contact_id, local_user(), $blocked); } -function _contact_ignore($contact_id, $orig_record) +function _contact_ignore($contact_id) { - $readonly = (($orig_record['readonly']) ? 0 : 1); - $r = q("UPDATE `contact` SET `readonly` = %d WHERE `id` = %d AND `uid` = %d", - intval($readonly), - intval($contact_id), - intval(local_user()) - ); - return DBA::isResult($r); + $ignored = !Contact::isIgnoredByUser($contact_id, local_user()); + Contact::setIgnoredForUser($contact_id, local_user(), $ignored); } function _contact_archive($contact_id, $orig_record) @@ -376,7 +371,7 @@ function _contact_drop($orig_record) Contact::remove($orig_record['id']); } -function contacts_content(App $a) +function contacts_content(App $a, $update = 0) { $sort_type = 0; $o = ''; @@ -395,48 +390,46 @@ function contacts_content(App $a) $cmd = $a->argv[2]; - $orig_record = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user(), 'self' => false]); + $orig_record = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => [0, local_user()], 'self' => false]); if (!DBA::isResult($orig_record)) { notice(L10n::t('Could not access contact record.') . EOL); goaway('contacts'); return; // NOTREACHED } - if ($cmd === 'update') { + if ($cmd === 'update' && ($orig_record['uid'] != 0)) { _contact_update($contact_id); goaway('contacts/' . $contact_id); // NOTREACHED } - if ($cmd === 'updateprofile') { + if ($cmd === 'updateprofile' && ($orig_record['uid'] != 0)) { _contact_update_profile($contact_id); goaway('crepair/' . $contact_id); // NOTREACHED } if ($cmd === 'block') { - $r = _contact_block($contact_id, $orig_record); - if ($r) { - $blocked = (($orig_record['blocked']) ? 0 : 1); - info((($blocked) ? L10n::t('Contact has been blocked') : L10n::t('Contact has been unblocked')) . EOL); - } + _contact_block($contact_id); + + $blocked = Contact::isBlockedByUser($contact_id, local_user()); + info(($blocked ? L10n::t('Contact has been blocked') : L10n::t('Contact has been unblocked')) . EOL); goaway('contacts/' . $contact_id); return; // NOTREACHED } if ($cmd === 'ignore') { - $r = _contact_ignore($contact_id, $orig_record); - if ($r) { - $readonly = (($orig_record['readonly']) ? 0 : 1); - info((($readonly) ? L10n::t('Contact has been ignored') : L10n::t('Contact has been unignored')) . EOL); - } + _contact_ignore($contact_id); + + $ignored = Contact::isIgnoredByUser($contact_id, local_user()); + info(($ignored ? L10n::t('Contact has been ignored') : L10n::t('Contact has been unignored')) . EOL); goaway('contacts/' . $contact_id); return; // NOTREACHED } - if ($cmd === 'archive') { + if ($cmd === 'archive' && ($orig_record['uid'] != 0)) { $r = _contact_archive($contact_id, $orig_record); if ($r) { $archived = (($orig_record['archive']) ? 0 : 1); @@ -447,7 +440,7 @@ function contacts_content(App $a) return; // NOTREACHED } - if ($cmd === 'drop') { + if ($cmd === 'drop' && ($orig_record['uid'] != 0)) { // Check if we should do HTML-based delete confirmation if (x($_REQUEST, 'confirm')) { //
can't take arguments in its "action" parameter @@ -496,6 +489,9 @@ function contacts_content(App $a) if ($cmd === 'posts') { return contact_posts($a, $contact_id); } + if ($cmd === 'conversations') { + return contact_conversations($a, $contact_id, $update); + } } $_SESSION['return_url'] = $a->query_string; @@ -511,6 +507,9 @@ function contacts_content(App $a) '$baseurl' => System::baseUrl(true), ]); + $contact['blocked'] = Contact::isBlockedByUser($contact['id'], local_user()); + $contact['readonly'] = Contact::isIgnoredByUser($contact['id'], local_user()); + $dir_icon = ''; $relation_text = ''; switch ($contact['rel']) { @@ -533,6 +532,10 @@ function contacts_content(App $a) break; } + if ($contact['uid'] == 0) { + $relation_text = ''; + } + if (!in_array($contact['network'], [Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA])) { $relation_text = ""; } @@ -560,7 +563,7 @@ function contacts_content(App $a) $nettype = L10n::t('Network type: %s', ContactSelector::networkToName($contact['network'], $contact["url"])); // tabs - $tab_str = contacts_tab($a, $contact_id, 2); + $tab_str = contacts_tab($a, $contact, 3); $lost_contact = (($contact['archive'] && $contact['term-date'] > NULL_DATE && $contact['term-date'] < DateTimeFormat::utcNow()) ? L10n::t('Communications lost with this contact!') : ''); @@ -593,26 +596,41 @@ function contacts_content(App $a) $follow = ''; $follow_text = ''; if (in_array($contact['network'], [Protocol::DIASPORA, Protocol::OSTATUS, Protocol::DFRN])) { - if ($contact['rel'] == Contact::FOLLOWER) { - $follow = System::baseUrl(true) . "/follow?url=" . urlencode($contact["url"]); - $follow_text = L10n::t("Connect/Follow"); - } elseif ($contact['rel'] == Contact::FRIEND) { + if (in_array($contact['rel'], [Contact::FRIEND, Contact::SHARING])) { $follow = System::baseUrl(true) . "/unfollow?url=" . urlencode($contact["url"]); $follow_text = L10n::t("Disconnect/Unfollow"); + } else { + $follow = System::baseUrl(true) . "/follow?url=" . urlencode($contact["url"]); + $follow_text = L10n::t("Connect/Follow"); } } + if ($contact['uid'] == 0) { + $follow = System::baseUrl(true) . "/follow?url=" . urlencode($contact["url"]); + $follow_text = L10n::t("Connect/Follow"); + } + // Load contactact related actions like hide, suggest, delete and others $contact_actions = contact_actions($contact); + if ($contact['uid'] != 0) { + $lbl_vis1 = L10n::t('Profile Visibility'); + $lbl_info1 = L10n::t('Contact Information / Notes'); + $contact_settings_label = L10n::t('Contact Settings'); + } else { + $lbl_vis1 = null; + $lbl_info1 = null; + $contact_settings_label = null; + } + $tpl = get_markup_template("contact_edit.tpl"); $o .= replace_macros($tpl, [ '$header' => L10n::t("Contact"), '$tab_str' => $tab_str, '$submit' => L10n::t('Submit'), - '$lbl_vis1' => L10n::t('Profile Visibility'), + '$lbl_vis1' => $lbl_vis1, '$lbl_vis2' => L10n::t('Please choose the profile you would like to display to %s when viewing your profile securely.', $contact['name']), - '$lbl_info1' => L10n::t('Contact Information / Notes'), + '$lbl_info1' => $lbl_info1, '$lbl_info2' => L10n::t('Their personal note'), '$reason' => trim(notags($contact['reason'])), '$infedit' => L10n::t('Edit contact notes'), @@ -669,7 +687,7 @@ function contacts_content(App $a) '$contact_action_button' => L10n::t("Actions"), '$contact_actions' => $contact_actions, '$contact_status' => L10n::t("Status"), - '$contact_settings_label' => L10n::t('Contact Settings'), + '$contact_settings_label' => $contact_settings_label, '$contact_profile_label' => L10n::t("Profile"), ]); @@ -806,6 +824,8 @@ function contacts_content(App $a) ); if (DBA::isResult($r)) { foreach ($r as $rr) { + $rr['blocked'] = Contact::isBlockedByUser($rr['id'], local_user()); + $rr['readonly'] = Contact::isIgnoredByUser($rr['id'], local_user()); $contacts[] = _contact_detail_for_template($rr); } } @@ -844,27 +864,35 @@ function contacts_content(App $a) * Available Pages are 'Status', 'Profile', 'Contacts' and 'Common Friends' * * @param App $a - * @param int $contact_id The ID of the contact + * @param array $contact The contact array * @param int $active_tab 1 if tab should be marked as active * * @return string */ -function contacts_tab($a, $contact_id, $active_tab) +function contacts_tab($a, $contact, $active_tab) { // tabs $tabs = [ [ 'label' => L10n::t('Status'), - 'url' => "contacts/" . $contact_id . "/posts", + 'url' => "contacts/" . $contact['id'] . "/conversations", 'sel' => (($active_tab == 1) ? 'active' : ''), - 'title' => L10n::t('Status Messages and Posts'), + 'title' => L10n::t('Conversations started by this contact'), 'id' => 'status-tab', 'accesskey' => 'm', ], [ - 'label' => L10n::t('Profile'), - 'url' => "contacts/" . $contact_id, + 'label' => L10n::t('Posts and Comments'), + 'url' => "contacts/" . $contact['id'] . "/posts", 'sel' => (($active_tab == 2) ? 'active' : ''), + 'title' => L10n::t('Status Messages and Posts'), + 'id' => 'posts-tab', + 'accesskey' => 'p', + ], + [ + 'label' => L10n::t('Profile'), + 'url' => "contacts/" . $contact['id'], + 'sel' => (($active_tab == 3) ? 'active' : ''), 'title' => L10n::t('Profile Details'), 'id' => 'profile-tab', 'accesskey' => 'o', @@ -872,35 +900,37 @@ function contacts_tab($a, $contact_id, $active_tab) ]; // Show this tab only if there is visible friend list - $x = GContact::countAllFriends(local_user(), $contact_id); + $x = GContact::countAllFriends(local_user(), $contact['id']); if ($x) { $tabs[] = ['label' => L10n::t('Contacts'), - 'url' => "allfriends/" . $contact_id, - 'sel' => (($active_tab == 3) ? 'active' : ''), + 'url' => "allfriends/" . $contact['id'], + 'sel' => (($active_tab == 4) ? 'active' : ''), 'title' => L10n::t('View all contacts'), 'id' => 'allfriends-tab', 'accesskey' => 't']; } // Show this tab only if there is visible common friend list - $common = GContact::countCommonFriends(local_user(), $contact_id); + $common = GContact::countCommonFriends(local_user(), $contact['id']); if ($common) { $tabs[] = ['label' => L10n::t('Common Friends'), - 'url' => "common/loc/" . local_user() . "/" . $contact_id, - 'sel' => (($active_tab == 4) ? 'active' : ''), + 'url' => "common/loc/" . local_user() . "/" . $contact['id'], + 'sel' => (($active_tab == 5) ? 'active' : ''), 'title' => L10n::t('View all common friends'), 'id' => 'common-loc-tab', 'accesskey' => 'd' ]; } - $tabs[] = ['label' => L10n::t('Advanced'), - 'url' => 'crepair/' . $contact_id, - 'sel' => (($active_tab == 5) ? 'active' : ''), - 'title' => L10n::t('Advanced Contact Settings'), - 'id' => 'advanced-tab', - 'accesskey' => 'r' - ]; + if (!empty($contact['uid'])) { + $tabs[] = ['label' => L10n::t('Advanced'), + 'url' => 'crepair/' . $contact['id'], + 'sel' => (($active_tab == 6) ? 'active' : ''), + 'title' => L10n::t('Advanced Contact Settings'), + 'id' => 'advanced-tab', + 'accesskey' => 'r' + ]; + } $tab_tpl = get_markup_template('common_tabs.tpl'); $tab_str = replace_macros($tab_tpl, ['$tabs' => $tabs]); @@ -908,15 +938,70 @@ function contacts_tab($a, $contact_id, $active_tab) return $tab_str; } -function contact_posts(App $a, $contact_id) +function contact_conversations(App $a, $contact_id, $update) { - $o = contacts_tab($a, $contact_id, 1); + $o = ''; - $contact = DBA::selectFirst('contact', ['url'], ['id' => $contact_id]); + if (!$update) { + // We need the editor here to be able to reshare an item. + if (local_user()) { + $x = [ + 'is_owner' => true, + 'allow_location' => $a->user['allow_location'], + 'default_location' => $a->user['default-location'], + 'nickname' => $a->user['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' => ACL::getFullSelectorHTML($a->user, true), + 'bang' => '', + 'visitor' => 'block', + 'profile_uid' => local_user(), + ]; + $o = status_editor($a, $x, 0, true); + } + } + + $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id]); + + if (!$update) { + $o .= contacts_tab($a, $contact, 1); + } if (DBA::isResult($contact)) { $a->page['aside'] = ""; - Profile::load($a, "", 0, Contact::getDetailsByURL($contact["url"])); + + $profiledata = Contact::getDetailsByURL($contact["url"]); + + if (local_user()) { + if (in_array($profiledata["network"], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { + $profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]); + } + } + + Profile::load($a, "", 0, $profiledata, true); + $o .= Contact::getPostsFromUrl($contact["url"], true, $update); + } + + return $o; +} + +function contact_posts(App $a, $contact_id) +{ + $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id]); + + $o = contacts_tab($a, $contact, 2); + + if (DBA::isResult($contact)) { + $a->page['aside'] = ""; + + $profiledata = Contact::getDetailsByURL($contact["url"]); + + if (local_user()) { + if (in_array($profiledata["network"], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { + $profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]); + } + } + + Profile::load($a, "", 0, $profiledata, true); $o .= Contact::getPostsFromUrl($contact["url"]); } @@ -1032,21 +1117,23 @@ function contact_actions($contact) 'id' => 'toggle-ignore', ]; - $contact_actions['archive'] = [ - 'label' => (intval($contact['archive']) ? L10n::t('Unarchive') : L10n::t('Archive') ), - 'url' => 'contacts/' . $contact['id'] . '/archive', - 'title' => L10n::t('Toggle Archive status'), - 'sel' => (intval($contact['archive']) ? 'active' : ''), - 'id' => 'toggle-archive', - ]; + if ($contact['uid'] != 0) { + $contact_actions['archive'] = [ + 'label' => (intval($contact['archive']) ? L10n::t('Unarchive') : L10n::t('Archive') ), + 'url' => 'contacts/' . $contact['id'] . '/archive', + 'title' => L10n::t('Toggle Archive status'), + 'sel' => (intval($contact['archive']) ? 'active' : ''), + 'id' => 'toggle-archive', + ]; - $contact_actions['delete'] = [ - 'label' => L10n::t('Delete'), - 'url' => 'contacts/' . $contact['id'] . '/drop', - 'title' => L10n::t('Delete contact'), - 'sel' => '', - 'id' => 'delete', - ]; + $contact_actions['delete'] = [ + 'label' => L10n::t('Delete'), + 'url' => 'contacts/' . $contact['id'] . '/drop', + 'title' => L10n::t('Delete contact'), + 'sel' => '', + 'id' => 'delete', + ]; + } return $contact_actions; } diff --git a/mod/crepair.php b/mod/crepair.php index 37956421f5..076c611db4 100644 --- a/mod/crepair.php +++ b/mod/crepair.php @@ -103,7 +103,7 @@ function crepair_content(App $a) $cid = (($a->argc > 1) ? intval($a->argv[1]) : 0); - $contact = null; + $contact = null; if ($cid) { $contact = DBA::selectFirst('contact', [], ['id' => $cid, 'uid' => local_user()]); } @@ -135,7 +135,7 @@ function crepair_content(App $a) $update_profile = in_array($contact['network'], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS]); - $tab_str = contacts_tab($a, $contact['id'], 5); + $tab_str = contacts_tab($a, $contact, 5); $tpl = get_markup_template('crepair.tpl'); $o = replace_macros($tpl, [ diff --git a/mod/dirfind.php b/mod/dirfind.php index fd31b2cbf1..f4ddba45d4 100644 --- a/mod/dirfind.php +++ b/mod/dirfind.php @@ -85,6 +85,7 @@ function dirfind_content(App $a, $prefix = "") { $contact = Contact::getDetailsByURL($user_data["url"], local_user()); $objresult->cid = $contact["cid"]; + $objresult->pcid = $contact["zid"]; $j->results[] = $objresult; @@ -163,6 +164,7 @@ function dirfind_content(App $a, $prefix = "") { $objresult = new stdClass(); $objresult->cid = $result["cid"]; + $objresult->pcid = $result["zid"]; $objresult->name = $result["name"]; $objresult->addr = $result["addr"]; $objresult->url = $result["url"]; @@ -217,10 +219,16 @@ function dirfind_content(App $a, $prefix = "") { } else { $connlnk = System::baseUrl().'/follow/?url='.(!empty($jj->connect) ? $jj->connect : $jj->url); $conntxt = L10n::t('Connect'); - $photo_menu = [ - 'profile' => [L10n::t("View Profile"), Contact::magicLink($jj->url)], - 'follow' => [L10n::t("Connect/Follow"), $connlnk] - ]; + + $contact = DBA::selectFirst('contact', [], ['id' => $jj->pcid]); + if (DBA::isResult($contact)) { + $photo_menu = Contact::photoMenu($contact); + } else { + $photo_menu = []; + } + + $photo_menu['profile'] = [L10n::t("View Profile"), Contact::magicLink($jj->url)]; + $photo_menu['follow'] = [L10n::t("Connect/Follow"), $connlnk]; } $jj->photo = str_replace("http:///photo/", get_server()."/photo/", $jj->photo); diff --git a/mod/events.php b/mod/events.php index b4516cded9..91474022fc 100644 --- a/mod/events.php +++ b/mod/events.php @@ -542,16 +542,14 @@ function events_content(App $a) { // Remove an event from the calendar and its related items if ($mode === 'drop' && $event_id) { - $del = 0; - $ev = Event::getListById(local_user(), $event_id); // Delete only real events (no birthdays) if (DBA::isResult($ev) && $ev[0]['type'] == 'event') { - $del = Item::deleteForUser(['id' => $ev[0]['itemid']], local_user()); + Item::deleteForUser(['id' => $ev[0]['itemid']], local_user()); } - if ($del == 0) { + if (Item::exists(['id' => $ev[0]['itemid']])) { notice(L10n::t('Failed to remove event') . EOL); } else { info(L10n::t('Event removed') . EOL); diff --git a/mod/group.php b/mod/group.php index 88b9830626..8f65eb643d 100644 --- a/mod/group.php +++ b/mod/group.php @@ -84,12 +84,12 @@ function group_content(App $a) { return; } - // Switch to text mode interface if we have more than 'n' contacts or group members - + // With no group number provided we jump to the unassigned contacts as a starting point if ($a->argc == 1) { - goaway(System::baseUrl() . '/contacts'); + goaway('group/none'); } + // Switch to text mode interface if we have more than 'n' contacts or group members $switchtotext = PConfig::get(local_user(), 'system', 'groupedit_image_limit'); if (is_null($switchtotext)) { $switchtotext = Config::get('system', 'groupedit_image_limit', 400); diff --git a/mod/install.php b/mod/install.php index fa20fd76cb..d2d322b3b9 100644 --- a/mod/install.php +++ b/mod/install.php @@ -26,8 +26,6 @@ function install_init(App $a) { $a->setConfigValue('system', 'value', '../install'); $a->theme['stylesheet'] = System::baseUrl()."/view/install/style.css"; - Install::setInstallMode(); - global $install_wizard_pass; if (x($_POST, 'pass')) { $install_wizard_pass = intval($_POST['pass']); diff --git a/mod/uimport.php b/mod/uimport.php index 1dbc571e2f..704439216b 100644 --- a/mod/uimport.php +++ b/mod/uimport.php @@ -11,39 +11,21 @@ use Friendica\Core\UserImport; function uimport_post(App $a) { - switch (Config::get('config', 'register_policy')) { - case REGISTER_OPEN: - $blocked = 0; - $verified = 1; - break; - - case REGISTER_APPROVE: - $blocked = 1; - $verified = 0; - break; - - default: - case REGISTER_CLOSED: - if ((!x($_SESSION, 'authenticated') && (!x($_SESSION, 'administrator')))) { - notice(L10n::t('Permission denied.') . EOL); - return; - } - $blocked = 1; - $verified = 0; - break; + if ((Config::get('config', 'register_policy') != REGISTER_OPEN) && !is_site_admin()) { + notice(L10n::t('Permission denied.') . EOL); + return; } - if (x($_FILES, 'accountfile')) { - /// @TODO Pass $blocked / $verified, send email to admin on REGISTER_APPROVE + if (!empty($_FILES['accountfile'])) { UserImport::importAccount($a, $_FILES['accountfile']); return; } } -function uimport_content(App $a) { - - if ((!local_user()) && (intval(Config::get('config', 'register_policy')) === REGISTER_CLOSED)) { - notice("Permission denied." . EOL); +function uimport_content(App $a) +{ + if ((Config::get('config', 'register_policy') != REGISTER_OPEN) && !is_site_admin()) { + notice(L10n::t('User imports on closed servers can only be done by an administrator.') . EOL); return; } diff --git a/src/App.php b/src/App.php index 55fa517342..2a5fba8541 100644 --- a/src/App.php +++ b/src/App.php @@ -174,40 +174,7 @@ class App $this->callstack['rendering'] = []; $this->callstack['parser'] = []; - // The order of the following calls is important to ensure proper initialization - $this->loadConfigFiles(); - - $this->loadDatabase(); - - $this->determineMode(); - - $this->determineUrlPath(); - - Config::load(); - - if ($this->mode & self::MODE_DBAVAILABLE) { - Core\Addon::loadHooks(); - - $this->loadAddonConfig(); - } - - $this->loadDefaultTimezone(); - - $this->page = [ - 'aside' => '', - 'bottom' => '', - 'content' => '', - 'end' => '', - 'footer' => '', - 'htmlhead' => '', - 'nav' => '', - 'page_title' => '', - 'right_aside' => '', - 'template' => '', - 'title' => '' - ]; - - $this->process_id = System::processID('log'); + $this->reload(); set_time_limit(0); @@ -314,6 +281,47 @@ class App $this->register_template_engine('Friendica\Render\FriendicaSmartyEngine'); } + /** + * Reloads the whole app instance + */ + public function reload() + { + // The order of the following calls is important to ensure proper initialization + $this->loadConfigFiles(); + + $this->loadDatabase(); + + $this->determineMode(); + + $this->determineUrlPath(); + + Config::load(); + + if ($this->mode & self::MODE_DBAVAILABLE) { + Core\Addon::loadHooks(); + + $this->loadAddonConfig(); + } + + $this->loadDefaultTimezone(); + + $this->page = [ + 'aside' => '', + 'bottom' => '', + 'content' => '', + 'end' => '', + 'footer' => '', + 'htmlhead' => '', + 'nav' => '', + 'page_title' => '', + 'right_aside' => '', + 'template' => '', + 'title' => '' + ]; + + $this->process_id = System::processID('log'); + } + /** * Load the configuration files * diff --git a/src/Content/ForumManager.php b/src/Content/ForumManager.php index 0e6b39e4d0..35df0aee9e 100644 --- a/src/Content/ForumManager.php +++ b/src/Content/ForumManager.php @@ -5,6 +5,7 @@ */ namespace Friendica\Content; +use Friendica\Core\Protocol; use Friendica\Content\Feature; use Friendica\Core\L10n; use Friendica\Core\System; @@ -36,25 +37,29 @@ class ForumManager */ public static function getList($uid, $lastitem, $showhidden = true, $showprivate = false) { - $forumlist = []; - - $order = (($showhidden) ? '' : ' AND NOT `hidden` '); - $order .= (($lastitem) ? ' ORDER BY `last-item` DESC ' : ' ORDER BY `name` ASC '); - $select = '`forum` '; - if ($showprivate) { - $select = '(`forum` OR `prv`)'; + if ($lastitem) { + $params = ['order' => ['last-item' => true]]; + } else { + $params = ['order' => ['name']]; } - $contacts = DBA::p( - "SELECT `contact`.`id`, `contact`.`url`, `contact`.`name`, `contact`.`micro`, `contact`.`thumb` - FROM `contact` - WHERE `network`= 'dfrn' AND $select AND `uid` = ? - AND NOT `blocked` AND NOT `pending` AND NOT `archive` - AND `success_update` > `failure_update` - $order ", - $uid - ); + $condition_str = "`network` = ? AND `uid` = ? AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `success_update` > `failure_update` AND "; + if ($showprivate) { + $condition_str .= '(`forum` OR `prv`)'; + } else { + $condition_str .= '`forum`'; + } + + if (!$showhidden) { + $condition_str .= ' AND NOT `hidden`'; + } + + $forumlist = []; + + $fields = ['id', 'url', 'name', 'micro', 'thumb']; + $condition = [$condition_str, Protocol::DFRN, $uid]; + $contacts = DBA::select('contact', $fields, $condition, $params); if (!$contacts) { return($forumlist); } diff --git a/src/Content/Widget.php b/src/Content/Widget.php index 9662e92718..f245f0d95e 100644 --- a/src/Content/Widget.php +++ b/src/Content/Widget.php @@ -49,7 +49,7 @@ class Widget if (Config::get('system', 'invitation_only')) { $x = PConfig::get(local_user(), 'system', 'invites_remaining'); if ($x || is_site_admin()) { - $a->page['aside'] .= ' @@ -63,6 +63,7 @@
+ {{if $contact_settings_label}}
@@ -100,7 +101,7 @@
- + {{/if}}
{{* End of the form *}} diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index b96e53fa1a..cd55dcadc4 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -3453,4 +3453,12 @@ section .profile-match-wrapper { top: 24px; left: 24px; } + + /* + Prevent automatic zoom on input focus on iOS + see https://stackoverflow.com/a/16255670 + */ + .form-control { + font-size: 16px; + } } diff --git a/view/theme/frio/templates/contact_edit.tpl b/view/theme/frio/templates/contact_edit.tpl index 8dc0df38fe..a72ac5c605 100644 --- a/view/theme/frio/templates/contact_edit.tpl +++ b/view/theme/frio/templates/contact_edit.tpl @@ -26,8 +26,8 @@ {{/if}}
  • {{$contact_actions.block.label}}
  • {{$contact_actions.ignore.label}}
  • -
  • {{$contact_actions.archive.label}}
  • -
  • + {{if $contact_actions.archive.url}}
  • {{$contact_actions.archive.label}}
  • {{/if}} + {{if $contact_actions.delete.url}}
  • {{/if}} @@ -119,6 +119,7 @@
    + {{if $contact_settings_label}}
    + {{/if}} + {{if $lbl_info1}}
    - + {{/if}} + {{if $lbl_vis1}}
    - + {{/if}} {{* End of the form *}} diff --git a/view/theme/frio/templates/nav.tpl b/view/theme/frio/templates/nav.tpl index f445190a8c..d64eae9c49 100644 --- a/view/theme/frio/templates/nav.tpl +++ b/view/theme/frio/templates/nav.tpl @@ -40,7 +40,7 @@ @@ -64,6 +64,7 @@
    + {{if $contact_settings_label}}
    @@ -99,8 +100,8 @@
    {{/if}}
    - + {{/if}}