Merge branch 'master' into develop

This commit is contained in:
Hypolite Petovan 2019-06-23 17:40:52 -04:00
commit b9ab613777
164 changed files with 30233 additions and 26266 deletions

View file

@ -87,7 +87,9 @@ class Federation extends BaseAdminModule
$part = array_pop($parts);
} while (!empty($parts) && ((strlen($part) >= 40) || (strlen($part) <= 3)));
// only take the x.x.x part of the version, not the "release" after the dash
$part = array_shift(explode('-', $part));
if (!empty($part) && strpos($part, '-')) {
$part = explode('-', $part)[0];
}
if (!empty($part)) {
if (empty($compacted[$part])) {
$compacted[$part] = $versionCounts[$key]['total'];

View file

@ -22,6 +22,12 @@ class Settings extends BaseAdminModule
$debugging = !empty($_POST['debugging']);
$loglevel = defaults($_POST, 'loglevel', LogLevel::ERROR);
if (is_file($logfile) &&
!is_writeable($logfile)) {
notice(L10n::t('The logfile \'%s\' is not writable. No logging possible', $logfile));
return;
}
Config::set('system', 'logfile', $logfile);
Config::set('system', 'debugging', $debugging);
Config::set('system', 'loglevel', $loglevel);

View file

@ -16,6 +16,7 @@ use Friendica\Protocol\PortableContact;
use Friendica\Util\BasePath;
use Friendica\Util\BaseURL;
use Friendica\Util\Strings;
use Friendica\Worker\Delivery;
require_once __DIR__ . '/../../../boot.php';
@ -99,7 +100,7 @@ class Site extends BaseAdminModule
// send relocate
$usersStmt = DBA::select('user', ['uid'], ['account_removed' => false, 'account_expired' => false]);
while ($user = DBA::fetch($usersStmt)) {
Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', $user['uid']);
Worker::add(PRIORITY_HIGH, 'Notifier', Delivery::RELOCATION, $user['uid']);
}
info("Relocation started. Could take a while to complete.");

View file

@ -26,7 +26,7 @@ class Summary extends BaseAdminModule
// are there MyISAM tables in the DB? If so, trigger a warning message
$warningtext = [];
if (DBA::count('`information_schema`.`tables`', ['engine' => 'myisam', 'table_schema' => DBA::databaseName()])) {
if (DBA::count(['information_schema' => 'tables'], ['engine' => 'myisam', 'table_schema' => DBA::databaseName()])) {
$warningtext[] = L10n::t('Your DB still runs with MyISAM tables. You should change the engine type to InnoDB. As Friendica will use InnoDB only features in the future, you should change this! See <a href="%s">here</a> for a guide that may be helpful converting the table engines. You may also use the command <tt>php bin/console.php dbstructure toinnodb</tt> of your Friendica installation for an automatic conversion.<br />', 'https://dev.mysql.com/doc/refman/5.7/en/converting-tables-to-innodb.html');
}
@ -74,6 +74,23 @@ class Summary extends BaseAdminModule
$well_known, $well_known, $a->getBaseURL() . '/help/Install');
}
// Check logfile permission
if (Config::get('system', 'debugging')) {
$stream = Config::get('system', 'logfile');
if (is_file($stream) &&
!is_writeable($stream)) {
$warningtext[] = L10n::t('The logfile \'%s\' is not writable. No logging possible', $stream);
}
$stream = Config::get('system', 'dlogfile');
if (is_file($stream) &&
!is_writeable($stream)) {
$warningtext[] = L10n::t('The logfile \'%s\' is not writable. No logging possible', $stream);
}
}
// check legacy basepath settings
$configLoader = new ConfigFileLoader($a->getBasePath(), $a->getMode());
$configCache = new Config\Cache\ConfigCache();
@ -129,8 +146,6 @@ class Summary extends BaseAdminModule
$pending = Register::getPendingCount();
$queue = DBA::count('queue', []);
$deferred = DBA::count('workerqueue', ['`executed` <= ? AND NOT `done` AND `next_try` > ?',
DBA::NULL_DATETIME, DateTimeFormat::utcNow()]);
@ -138,7 +153,7 @@ class Summary extends BaseAdminModule
DBA::NULL_DATETIME, DateTimeFormat::utcNow()]);
// We can do better, but this is a quick queue status
$queues = ['label' => L10n::t('Message queues'), 'queue' => $queue, 'deferred' => $deferred, 'workerq' => $workerqueue];
$queues = ['label' => L10n::t('Message queues'), 'deferred' => $deferred, 'workerq' => $workerqueue];
$variables = DBA::toArray(DBA::p('SHOW variables LIKE "max_allowed_packet"'));
$max_allowed_packet = $variables ? $variables[0]['Value'] : 0;

View file

@ -6,7 +6,10 @@ use Friendica\BaseModule;
use Friendica\Core\Addon;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Core\Session;
use Friendica\Network\HTTPException\ForbiddenException;
require_once 'boot.php';
/**
* This abstract module is meant to be extended by all modules that are reserved to administrator users.
@ -35,11 +38,11 @@ abstract class BaseAdminModule extends BaseModule
public static function rawContent()
{
if (!is_site_admin()) {
System::httpExit(403);
return '';
}
if (!empty($_SESSION['submanage'])) {
System::httpExit(403);
return '';
}
return '';
@ -47,21 +50,18 @@ abstract class BaseAdminModule extends BaseModule
public static function content()
{
$a = self::getApp();
if (!is_site_admin()) {
return Login::form();
notice(L10n::t('Please login to continue.'));
Session::set('return_path', $a->query_string);
$a->internalRedirect('login');
}
if (!empty($_SESSION['submanage'])) {
return '';
throw new ForbiddenException(L10n::t('Submanaged account can\'t access the administation pages. Please log back in as the master account.'));
}
$a = self::getApp();
// APC deactivated, since there are problems with PHP 5.5
//if (function_exists("apc_delete")) {
// $toDelete = new APCIterator('user', APC_ITER_VALUE);
// apc_delete($toDelete);
//}
// Header stuff
$a->page['htmlhead'] .= Renderer::replaceMacros(Renderer::getMarkupTemplate('admin/settings_head.tpl'), []);

View file

@ -0,0 +1,167 @@
<?php
namespace Friendica\Module;
use Friendica\BaseModule;
use Friendica\Content\ContactSelector;
use Friendica\Content\Pager;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Core\Search;
use Friendica\Model;
use Friendica\Network\HTTPException;
use Friendica\Object\Search\ContactResult;
use Friendica\Object\Search\ResultList;
use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Util\Strings;
/**
* Base class for search modules
*/
class BaseSearchModule extends BaseModule
{
/**
* Performs a search with an optional prefix
*
* @param string $prefix A optional prefix (e.g. @ or !) for searching
*
* @return string
* @throws HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function performSearch($prefix = '')
{
$a = self::getApp();
$config = $a->getConfig();
$type = Search::TYPE_ALL;
$localSearch = $config->get('system', 'poco_local_search');
$search = $prefix . Strings::escapeTags(trim(defaults($_REQUEST, 'search', '')));
if (!$search) {
return '';
}
$header = '';
if (strpos($search, '@') === 0) {
$search = substr($search, 1);
$type = Search::TYPE_PEOPLE;
$header = L10n::t('People Search - %s', $search);
if (strrpos($search, '@') > 0) {
$results = Search::getContactsFromProbe($search);
}
}
if (strpos($search, '!') === 0) {
$search = substr($search, 1);
$type = Search::TYPE_FORUM;
$header = L10n::t('Forum Search - %s', $search);
}
$pager = new Pager($a->query_string);
if ($localSearch && empty($results)) {
$pager->setItemsPerPage(80);
$results = Search::getContactsFromLocalDirectory($search, $type, $pager->getStart(), $pager->getItemsPerPage());
} elseif (strlen($config->get('system', 'directory')) && empty($results)) {
$results = Search::getContactsFromGlobalDirectory($search, $type, $pager->getPage());
$pager->setItemsPerPage($results->getItemsPage());
}
return self::printResult($results, $pager, $header);
}
/**
* Prints a human readable search result
*
* @param ResultList $results
* @param Pager $pager
* @param string $header
*
* @return string The result
* @throws HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
protected static function printResult(ResultList $results, Pager $pager, $header = '')
{
if ($results->getTotal() == 0) {
info(L10n::t('No matches'));
return '';
}
$a = self::getApp();
$id = 0;
$entries = [];
foreach ($results->getResults() as $result) {
// in case the result is a contact result, add a contact-specific entry
if ($result instanceof ContactResult) {
$alt_text = '';
$location = '';
$about = '';
$accountType = '';
$photo_menu = [];
// If We already know this contact then don't show the "connect" button
if ($result->getCid() > 0 || $result->getPCid() > 0) {
$connLink = "";
$connTxt = "";
$contact = Model\Contact::getById(
($result->getCid() > 0) ? $result->getCid() : $result->getPCid()
);
if (!empty($contact)) {
$photo_menu = Model\Contact::photoMenu($contact);
$details = Contact::getContactTemplateVars($contact);
$alt_text = $details['alt_text'];
$location = $contact['location'];
$about = $contact['about'];
$accountType = Model\Contact::getAccountType($contact);
} else {
$photo_menu = [];
}
} else {
$connLink = $a->getBaseURL() . '/follow/?url=' . $result->getUrl();
$connTxt = L10n::t('Connect');
$photo_menu['profile'] = [L10n::t("View Profile"), Model\Contact::magicLink($result->getUrl())];
$photo_menu['follow'] = [L10n::t("Connect/Follow"), $connLink];
}
$photo = str_replace("http:///photo/", get_server() . "/photo/", $result->getPhoto());
$entry = [
'alt_text' => $alt_text,
'url' => Model\Contact::magicLink($result->getUrl()),
'itemurl' => $result->getItem(),
'name' => $result->getName(),
'thumb' => ProxyUtils::proxifyUrl($photo, false, ProxyUtils::SIZE_THUMB),
'img_hover' => $result->getTags(),
'conntxt' => $connTxt,
'connlnk' => $connLink,
'photo_menu' => $photo_menu,
'details' => $location,
'tags' => $result->getTags(),
'about' => $about,
'account_type' => $accountType,
'network' => ContactSelector::networkToName($result->getNetwork(), $result->getUrl()),
'id' => ++$id,
];
$entries[] = $entry;
}
}
$tpl = Renderer::getMarkupTemplate('viewcontact_template.tpl');
return Renderer::replaceMacros($tpl, [
'title' => $header,
'$contacts' => $entries,
'$paginate' => $pager->renderFull($results->getTotal()),
]);
}
}

View file

@ -260,12 +260,13 @@ class Contact extends BaseModule
public static function content($update = 0)
{
if (!local_user()) {
return Login::form($_SERVER['REQUET_URI']);
return Login::form($_SERVER['REQUEST_URI']);
}
$a = self::getApp();
$nets = defaults($_GET, 'nets', '');
$rel = defaults($_GET, 'rel' , '');
if (empty($a->page['aside'])) {
$a->page['aside'] = '';
@ -308,6 +309,21 @@ class Contact extends BaseModule
$network_link = '';
}
$follow_link = '';
$unfollow_link = '';
if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) {
if ($contact['uid'] && in_array($contact['rel'], [Model\Contact::SHARING, Model\Contact::FRIEND])) {
$unfollow_link = 'unfollow?url=' . urlencode($contact['url']);
} elseif(!$contact['pending']) {
$follow_link = 'follow?url=' . urlencode($contact['url']);
}
}
$wallmessage_link = '';
if ($contact['uid'] && Model\Contact::canReceivePrivateMessages($contact)) {
$wallmessage_link = 'message/new/' . $contact['id'];
}
$vcard_widget = Renderer::replaceMacros(Renderer::getMarkupTemplate('widget/vcard.tpl'), [
'$name' => $contact['name'],
'$photo' => $contact['photo'],
@ -315,12 +331,19 @@ class Contact extends BaseModule
'$addr' => defaults($contact, 'addr', ''),
'$network_link' => $network_link,
'$network' => L10n::t('Network:'),
'$account_type' => Model\Contact::getAccountType($contact)
'$account_type' => Model\Contact::getAccountType($contact),
'$follow' => L10n::t('Follow'),
'$follow_link' => $follow_link,
'$unfollow' => L10n::t('Unfollow'),
'$unfollow_link' => $unfollow_link,
'$wallmessage' => L10n::t('Message'),
'$wallmessage_link' => $wallmessage_link,
]);
$findpeople_widget = '';
$follow_widget = '';
$networks_widget = '';
$rel_widget = '';
} else {
$vcard_widget = '';
$findpeople_widget = Widget::findPeople();
@ -331,6 +354,7 @@ class Contact extends BaseModule
}
$networks_widget = Widget::networks($_SERVER['REQUEST_URI'], $nets);
$rel_widget = Widget::contactRels($_SERVER['REQUEST_URI'], $rel);
}
if ($contact['uid'] != 0) {
@ -339,7 +363,7 @@ class Contact extends BaseModule
$groups_widget = null;
}
$a->page['aside'] .= $vcard_widget . $findpeople_widget . $follow_widget . $groups_widget . $networks_widget;
$a->page['aside'] .= $vcard_widget . $findpeople_widget . $follow_widget . $groups_widget . $networks_widget . $rel_widget;
$tpl = Renderer::getMarkupTemplate('contacts-head.tpl');
$a->page['htmlhead'] .= Renderer::replaceMacros($tpl, [
@ -554,19 +578,6 @@ class Contact extends BaseModule
$profile_select = ContactSelector::profileAssign($contact['profile-id'], $contact['network'] !== Protocol::DFRN);
}
/// @todo Only show the following link with DFRN when the remote version supports it
$follow = '';
$follow_text = '';
if ($contact['uid'] && in_array($contact['rel'], [Model\Contact::FRIEND, Model\Contact::SHARING])) {
if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) {
$follow = $a->getBaseURL(true) . '/unfollow?url=' . urlencode($contact['url']);
$follow_text = L10n::t('Disconnect/Unfollow');
}
} elseif(!$contact['pending']) {
$follow = $a->getBaseURL(true) . '/follow?url=' . urlencode($contact['url']);
$follow_text = L10n::t('Connect/Follow');
}
// Load contactact related actions like hide, suggest, delete and others
$contact_actions = self::getContactActions($contact);
@ -607,8 +618,6 @@ class Contact extends BaseModule
'$updpub' => L10n::t('Update public posts'),
'$last_update' => $last_update,
'$udnow' => L10n::t('Update now'),
'$follow' => $follow,
'$follow_text' => $follow_text,
'$profile_select' => $profile_select,
'$contact_id' => $contact['id'],
'$block_text' => ($contact['blocked'] ? L10n::t('Unblock') : L10n::t('Block')),
@ -678,6 +687,7 @@ class Contact extends BaseModule
$search = Strings::escapeTags(trim(defaults($_GET, 'search', '')));
$nets = Strings::escapeTags(trim(defaults($_GET, 'nets' , '')));
$rel = Strings::escapeTags(trim(defaults($_GET, 'rel' , '')));
$tabs = [
[
@ -747,6 +757,12 @@ class Contact extends BaseModule
$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)) : '');
@ -777,6 +793,13 @@ class Contact extends BaseModule
}
}
switch ($rel) {
case 'followers': $header = L10n::t('Followers'); break;
case 'following': $header = L10n::t('Following'); break;
case 'mutuals': $header = L10n::t('Mutual friends'); break;
default: $header = L10n::t('Contacts');
}
switch ($type) {
case 'blocked': $header .= ' - ' . L10n::t('Blocked'); break;
case 'hidden': $header .= ' - ' . L10n::t('Hidden'); break;
@ -927,10 +950,6 @@ class Contact extends BaseModule
$profiledata = Model\Contact::getDetailsByURL($contact['url']);
if (local_user() && in_array($profiledata['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) {
$profiledata['remoteconnect'] = System::baseUrl() . '/follow?url=' . urlencode($profiledata['url']);
}
Model\Profile::load($a, '', 0, $profiledata, true);
$o .= Model\Contact::getPostsFromUrl($contact['url'], true, $update);
}

View file

@ -41,6 +41,9 @@ class Fetch extends BaseModule
$item = Item::selectFirst(['author-link'], $condition);
if (empty($item)) {
$parts = parse_url($item["author-link"]);
if (empty($parts["scheme"]) || empty($parts["host"])) {
throw new HTTPException\InternalServerErrorException();
}
$host = $parts["scheme"] . "://" . $parts["host"];
if (Strings::normaliseLink($host) != Strings::normaliseLink($app->getBaseURL())) {

View file

@ -20,19 +20,6 @@ use Friendica\Util\Strings;
*/
class Directory extends BaseModule
{
public static function init()
{
$app = self::getApp();
if (local_user()) {
$app->page['aside'] .= Widget::findPeople();
$app->page['aside'] .= Widget::follow();
} else {
unset($_SESSION['theme']);
unset($_SESSION['mobile-theme']);
}
}
public static function content()
{
$app = self::getApp();
@ -43,6 +30,14 @@ class Directory extends BaseModule
throw new HTTPException\ForbiddenException(L10n::t('Public access denied.'));
}
if (local_user()) {
$app->page['aside'] .= Widget::findPeople();
$app->page['aside'] .= Widget::follow();
} else {
unset($_SESSION['theme']);
unset($_SESSION['mobile-theme']);
}
$output = '';
$entries = [];
@ -83,7 +78,7 @@ class Directory extends BaseModule
'$globaldir' => L10n::t('Global Directory'),
'$gDirPath' => $gDirPath,
'$desc' => L10n::t('Find on this site'),
'$contacts' => $profiles['entries'],
'$contacts' => $entries,
'$finding' => L10n::t('Results for:'),
'$findterm' => (strlen($search) ? $search : ""),
'$title' => L10n::t('Site Directory'),
@ -157,7 +152,7 @@ class Directory extends BaseModule
$entry = [
'id' => $contact['id'],
'url' => Contact::magicLInk($profile_link),
'url' => Contact::magicLink($profile_link),
'itemurl' => $itemurl,
'thumb' => ProxyUtils::proxifyUrl($contact[$photo_size], false, ProxyUtils::SIZE_THUMB),
'img_hover' => $contact['name'],

View file

@ -46,6 +46,6 @@ class RemoveTag extends BaseModule
info('Item was not deleted');
}
$app->internalRedirect('/network?f=&file=' . rawurlencode($term));
$app->internalRedirect('network?file=' . rawurlencode($term));
}
}

View file

@ -40,9 +40,8 @@ class SaveTag extends BaseModule
}
// return filer dialog
$filetags = PConfig::get(local_user(), 'system', 'filetags');
$filetags = Model\FileTag::fileToList($filetags, 'file');
$filetags = explode(",", $filetags);
$filetags = PConfig::get(local_user(), 'system', 'filetags', '');
$filetags = Model\FileTag::fileToArray($filetags);
$tpl = Renderer::getMarkupTemplate("filer_dialog.tpl");
echo Renderer::replaceMacros($tpl, [

View file

@ -1,34 +0,0 @@
<?php
namespace Friendica\Module\GnuSocial;
use Friendica\BaseModule;
use Friendica\Core\L10n;
use Friendica\Database\DBA;
use Friendica\Network\HTTPException;
/**
* GNU Social -> friendica items permanent-url compatibility
*/
class Notice extends BaseModule
{
public static function content()
{
$a = self::getApp();
// @TODO: Replace with parameter from router
$id = ($a->argc > 1) ? $a->argv[1] : 0;
if (empty($id)) {
throw new HTTPException\NotFoundException(L10n::t('Item not found.'));
}
$item = DBA::selectFirst('item', ['guid'], ['id' => $id]);
if (empty($item )) {
throw new HTTPException\NotFoundException(L10n::t('Item not found.'));
} else {
$a->internalRedirect('display/' . $item['guid']);
}
}
}

View file

@ -9,6 +9,8 @@ use Friendica\BaseModule;
use Friendica\Core\Authentication;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Model\Profile;
/**
* Logout module
@ -22,9 +24,19 @@ class Logout extends BaseModule
*/
public static function init()
{
$visitor_home = null;
if (remote_user()) {
$visitor_home = Profile::getMyURL();
}
Hook::callAll("logging_out");
Authentication::deleteSession();
info(L10n::t('Logged out.') . EOL);
self::getApp()->internalRedirect();
if ($visitor_home) {
System::externalRedirect($visitor_home);
} else {
info(L10n::t('Logged out.'));
self::getApp()->internalRedirect();
}
}
}

View file

@ -85,7 +85,7 @@ class Magic extends BaseModule
);
// Try to get an authentication token from the other instance.
$curlResult = Network::curl($basepath . '/owa', false, $redirects, ['headers' => $headers]);
$curlResult = Network::curl($basepath . '/owa', false, ['headers' => $headers]);
if ($curlResult->isSuccess()) {
$j = json_decode($curlResult->getBody(), true);

View file

@ -179,12 +179,9 @@ class Profile extends BaseModule
}
if (!$update) {
$tab = false;
if (!empty($_GET['tab'])) {
$tab = Strings::escapeTags(trim($_GET['tab']));
}
$tab = Strings::escapeTags(trim(defaults($_GET, 'tab', '')));
$o .= ProfileModel::getTabs($a, $is_owner, $a->profile['nickname']);
$o .= ProfileModel::getTabs($a, $tab, $is_owner, $a->profile['nickname']);
if ($tab === 'profile') {
$o .= ProfileModel::getAdvanced($a);
@ -197,8 +194,8 @@ class Profile extends BaseModule
$commpage = $a->profile['page-flags'] == User::PAGE_FLAGS_COMMUNITY;
$commvisitor = $commpage && $remote_contact;
$a->page['aside'] .= posted_date_widget(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], $a->profile['profile_uid'], true);
$a->page['aside'] .= Widget::categories(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], (!empty($category) ? XML::escape($category) : ''));
$a->page['aside'] .= Widget::postedByYear(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], $a->profile['profile_uid'] ?? 0, true);
$a->page['aside'] .= Widget::categories(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], XML::escape($category));
$a->page['aside'] .= Widget::tagCloud();
if (Security::canWriteToUserWall($a->profile['profile_uid'])) {

View file

@ -0,0 +1,136 @@
<?php
namespace Friendica\Module\Profile;
use Friendica\BaseModule;
use Friendica\Content\ContactSelector;
use Friendica\Content\Nav;
use Friendica\Content\Pager;
use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\Protocol;
use Friendica\Core\Renderer;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Profile;
use Friendica\Util\Proxy as ProxyUtils;
class Contacts extends BaseModule
{
public static function content()
{
if (Config::get('system', 'block_public') && !local_user() && !remote_user()) {
throw new \Friendica\Network\HTTPException\NotFoundException(L10n::t('User not found.'));
}
$a = self::getApp();
//@TODO: Get value from router parameters
$nickname = $a->argv[1];
$type = defaults($a->argv, 3, 'all');
Nav::setSelected('home');
$user = DBA::selectFirst('user', [], ['nickname' => $nickname, 'blocked' => false]);
if (!DBA::isResult($user)) {
throw new \Friendica\Network\HTTPException\NotFoundException(L10n::t('User not found.'));
}
$a->data['user'] = $user;
$a->profile_uid = $user['uid'];
Profile::load($a, $nickname);
$is_owner = $a->profile['profile_uid'] == local_user();
// tabs
$o = Profile::getTabs($a, 'contacts', $is_owner, $nickname);
if (!count($a->profile) || $a->profile['hide-friends']) {
notice(L10n::t('Permission denied.') . EOL);
return $o;
}
$condition = [
'uid' => $a->profile['uid'],
'blocked' => false,
'pending' => false,
'hidden' => false,
'archive' => false,
'network' => [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, Protocol::FEED]
];
switch ($type) {
case 'followers': $condition['rel'] = [1, 3]; break;
case 'following': $condition['rel'] = [2, 3]; break;
case 'mutuals': $condition['rel'] = 3; break;
}
$total = DBA::count('contact', $condition);
$pager = new Pager($a->query_string);
$params = ['order' => ['name' => false], 'limit' => [$pager->getStart(), $pager->getItemsPerPage()]];
$contacts_stmt = DBA::select('contact', [], $condition, $params);
if (!DBA::isResult($contacts_stmt)) {
info(L10n::t('No contacts.') . EOL);
return $o;
}
$contacts = [];
while ($contact = DBA::fetch($contacts_stmt)) {
if ($contact['self']) {
continue;
}
$contact_details = Contact::getDetailsByURL($contact['url'], $a->profile['uid'], $contact);
$contacts[] = [
'id' => $contact['id'],
'img_hover' => L10n::t('Visit %s\'s profile [%s]', $contact_details['name'], $contact['url']),
'photo_menu' => Contact::photoMenu($contact),
'thumb' => ProxyUtils::proxifyUrl($contact_details['thumb'], false, ProxyUtils::SIZE_THUMB),
'name' => substr($contact_details['name'], 0, 20),
'username' => $contact_details['name'],
'details' => $contact_details['location'],
'tags' => $contact_details['keywords'],
'about' => $contact_details['about'],
'account_type' => Contact::getAccountType($contact_details),
'url' => Contact::magicLink($contact['url']),
'sparkle' => '',
'itemurl' => $contact_details['addr'] ? : $contact['url'],
'network' => ContactSelector::networkToName($contact['network'], $contact['url']),
];
}
DBA::close($contacts_stmt);
switch ($type) {
case 'followers': $title = L10n::tt('Follower (%s)', 'Followers (%s)', $total); break;
case 'following': $title = L10n::tt('Following (%s)', 'Following (%s)', $total); break;
case 'mutuals': $title = L10n::tt('Mutual friend (%s)', 'Mutual friends (%s)', $total); break;
case 'all': default: $title = L10n::tt('Contact (%s)', 'Contacts (%s)', $total); break;
}
$tpl = Renderer::getMarkupTemplate('profile/contacts.tpl');
$o .= Renderer::replaceMacros($tpl, [
'$title' => $title,
'$nickname' => $nickname,
'$type' => $type,
'$all_label' => L10n::t('All contacts'),
'$followers_label' => L10n::t('Followers'),
'$following_label' => L10n::t('Following'),
'$mutuals_label' => L10n::t('Mutual friends'),
'$contacts' => $contacts,
'$paginate' => $pager->renderFull($total),
]);
return $o;
}
}

View file

@ -0,0 +1,32 @@
<?php
namespace Friendica\Module\Search;
use Friendica\Content\Widget;
use Friendica\Core\L10n;
use Friendica\Module\BaseSearchModule;
/**
* Directory search module
*/
class Directory extends BaseSearchModule
{
public static function content()
{
if (!local_user()) {
notice(L10n::t('Permission denied.'));
return Login::form();
}
$a = self::getApp();
if (empty($a->page['aside'])) {
$a->page['aside'] = '';
}
$a->page['aside'] .= Widget::findPeople();
$a->page['aside'] .= Widget::follow();
return self::performSearch();
}
}

69
src/Module/Welcome.php Normal file
View file

@ -0,0 +1,69 @@
<?php
namespace Friendica\Module;
use Friendica\BaseModule;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
/**
* Prints the welcome page for new users
*/
class Welcome extends BaseModule
{
public static function content()
{
$config = self::getApp()->getConfig();
$mail_disabled = ((function_exists('imap_open') &&
(!$config->get('system', 'imap_disabled'))));
$newuser_private = $config->get('system', 'newuser_private');
$tpl = Renderer::getMarkupTemplate('welcome.tpl');
return Renderer::replaceMacros($tpl, [
'$welcome' => L10n::t('Welcome to Friendica'),
'$checklist' => L10n::t('New Member Checklist'),
'$description' => L10n::t('We would like to offer some tips and links to help make your experience enjoyable. Click any item to visit the relevant page. A link to this page will be visible from your home page for two weeks after your initial registration and then will quietly disappear.'),
'$started' => L10n::t('Getting Started'),
'$quickstart_link' => L10n::t('Friendica Walk-Through'),
'$quickstart_txt' => L10n::t('On your <em>Quick Start</em> page - find a brief introduction to your profile and network tabs, make some new connections, and find some groups to join.'),
'$settings' => L10n::t('Settings'),
'$settings_link' => L10n::t('Go to Your Settings'),
'$settings_txt' => L10n::t('On your <em>Settings</em> page - change your initial password. Also make a note of your Identity Address. This looks just like an email address - and will be useful in making friends on the free social web.'),
'$settings_other' => L10n::t('Review the other settings, particularly the privacy settings. An unpublished directory listing is like having an unlisted phone number. In general, you should probably publish your listing - unless all of your friends and potential friends know exactly how to find you.'),
'$profile' => L10n::t('Profile'),
'$profile_photo_link' => L10n::t('Upload Profile Photo'),
'$profile_photo_txt' => L10n::t('Upload a profile photo if you have not done so already. Studies have shown that people with real photos of themselves are ten times more likely to make friends than people who do not.'),
'$profiles_link' => L10n::t('Edit Your Profile'),
'$profiles_txt' => L10n::t('Edit your <strong>default</strong> profile to your liking. Review the settings for hiding your list of friends and hiding the profile from unknown visitors.'),
'$profiles_keywords_link' => L10n::t('Profile Keywords'),
'$profiles_keywords_txt' => L10n::t('Set some public keywords for your default profile which describe your interests. We may be able to find other people with similar interests and suggest friendships.'),
'$connecting' => L10n::t('Connecting'),
'$mail_disabled' => $mail_disabled,
'$import_mail_link' => L10n::t('Importing Emails'),
'$import_mail_txt' => L10n::t('Enter your email access information on your Connector Settings page if you wish to import and interact with friends or mailing lists from your email INBOX'),
'$contact_link' => L10n::t('Go to Your Contacts Page'),
'$contact_txt' => L10n::t('Your Contacts page is your gateway to managing friendships and connecting with friends on other networks. Typically you enter their address or site URL in the <em>Add New Contact</em> dialog.'),
'$directory_link' => L10n::t('Go to Your Site\'s Directory'),
'$directory_txt' => L10n::t('The Directory page lets you find other people in this network or other federated sites. Look for a <em>Connect</em> or <em>Follow</em> link on their profile page. Provide your own Identity Address if requested.'),
'$finding_link' => L10n::t('Finding New People'),
'$finding_txt' => L10n::t('On the side panel of the Contacts page are several tools to find new friends. We can match people by interest, look up people by name or interest, and provide suggestions based on network relationships. On a brand new site, friend suggestions will usually begin to be populated within 24 hours.'),
'$groups' => L10n::t('Groups'),
'$group_contact_link' => L10n::t('Group Your Contacts'),
'$group_contact_txt' => L10n::t('Once you have made some friends, organize them into private conversation groups from the sidebar of your Contacts page and then you can interact with each group privately on your Network page.'),
'$newuser_private' => $newuser_private,
'$private_link' => L10n::t('Why Aren\'t My Posts Public?'),
'$private_txt' => L10n::t('Friendica respects your privacy. By default, your posts will only show up to people you\'ve added as friends. For more information, see the help section from the link above.'),
'$help' => L10n::t('Getting Help'),
'$help_link' => L10n::t('Go to the Help Section'),
'$help_txt' => L10n::t('Our <strong>help</strong> pages may be consulted for detail on other program features and resources.'),
]);
}
}

View file

@ -4,9 +4,11 @@ namespace Friendica\Module;
use Friendica\BaseModule;
use Friendica\Core\Hook;
use Friendica\Database\DBA;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Model\User;
use Friendica\Model\Photo;
use Friendica\Protocol\Salmon;
use Friendica\Util\Strings;
@ -61,67 +63,69 @@ class Xrd extends BaseModule
throw new \Friendica\Network\HTTPException\NotFoundException();
}
$profileURL = $app->getBaseURL() . '/profile/' . $user['nickname'];
$alias = str_replace('/profile/', '/~', $profileURL);
$owner = User::getOwnerDataById($user['uid']);
$addr = 'acct:' . $user['nickname'] . '@' . $app->getHostName();
if ($app->getURLPath()) {
$addr .= '/' . $app->getURLPath();
$alias = str_replace('/profile/', '/~', $owner['url']);
$avatar = Photo::selectFirst(['type'], ['uid' => $owner['uid'], 'profile' => true]);
if (!DBA::isResult($avatar)) {
$avatar = ['type' => 'image/jpeg'];
}
if ($mode == 'xml') {
self::printXML($addr, $alias, $profileURL, $app->getBaseURL(), $user);
self::printXML($alias, $app->getBaseURL(), $user, $owner, $avatar);
} else {
self::printJSON($addr, $alias, $profileURL, $app->getBaseURL(), $user);
self::printJSON($alias, $app->getBaseURL(), $owner, $avatar);
}
}
private static function printJSON($uri, $alias, $orofileURL, $baseURL, $user)
private static function printJSON($alias, $baseURL, $owner, $avatar)
{
$salmon_key = Salmon::salmonKey($user['spubkey']);
$salmon_key = Salmon::salmonKey($owner['spubkey']);
header('Access-Control-Allow-Origin: *');
header('Content-type: application/json; charset=utf-8');
$json = [
'subject' => $uri,
'subject' => 'acct:' . $owner['addr'],
'aliases' => [
$alias,
$orofileURL,
$owner['url'],
],
'links' => [
[
'rel' => NAMESPACE_DFRN,
'href' => $orofileURL,
'href' => $owner['url'],
],
[
'rel' => NAMESPACE_FEED,
'type' => 'application/atom+xml',
'href' => $baseURL . '/dfrn_poll/' . $user['nickname'],
'href' => $owner['poll'],
],
[
'rel' => 'http://webfinger.net/rel/profile-page',
'type' => 'text/html',
'href' => $orofileURL,
'href' => $owner['url'],
],
[
'rel' => 'self',
'type' => 'application/activity+json',
'href' => $orofileURL,
'href' => $owner['url'],
],
[
'rel' => 'http://microformats.org/profile/hcard',
'type' => 'text/html',
'href' => $baseURL . '/hcard/' . $user['nickname'],
'href' => $baseURL . '/hcard/' . $owner['nickname'],
],
[
'rel' => NAMESPACE_POCO,
'href' => $baseURL . '/poco/' . $user['nickname'],
'href' => $owner['poco'],
],
[
'rel' => 'http://webfinger.net/rel/avatar',
'type' => 'image/jpeg',
'href' => $baseURL . '/photo/profile/' . $user['uid'] . '.jpg',
'type' => $avatar['type'],
'href' => $owner['photo'],
],
[
'rel' => 'http://joindiaspora.com/seed_location',
@ -130,15 +134,15 @@ class Xrd extends BaseModule
],
[
'rel' => 'salmon',
'href' => $baseURL . '/salmon/' . $user['nickname'],
'href' => $baseURL . '/salmon/' . $owner['nickname'],
],
[
'rel' => 'http://salmon-protocol.org/ns/salmon-replies',
'href' => $baseURL . '/salmon/' . $user['nickname'],
'href' => $baseURL . '/salmon/' . $owner['nickname'],
],
[
'rel' => 'http://salmon-protocol.org/ns/salmon-mention',
'href' => $baseURL . '/salmon/' . $user['nickname'] . '/mention',
'href' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention',
],
[
'rel' => 'http://ostatus.org/schema/1.0/subscribe',
@ -160,9 +164,9 @@ class Xrd extends BaseModule
exit();
}
private static function printXML($uri, $alias, $profileURL, $baseURL, $user)
private static function printXML($alias, $baseURL, $user, $owner, $avatar)
{
$salmon_key = Salmon::salmonKey($user['spubkey']);
$salmon_key = Salmon::salmonKey($owner['spubkey']);
header('Access-Control-Allow-Origin: *');
header('Content-type: text/xml');
@ -170,16 +174,17 @@ class Xrd extends BaseModule
$tpl = Renderer::getMarkupTemplate('xrd_person.tpl');
$o = Renderer::replaceMacros($tpl, [
'$nick' => $user['nickname'],
'$accturi' => $uri,
'$nick' => $owner['nickname'],
'$accturi' => 'acct:' . $owner['addr'],
'$alias' => $alias,
'$profile_url' => $profileURL,
'$hcard_url' => $baseURL . '/hcard/' . $user['nickname'],
'$atom' => $baseURL . '/dfrn_poll/' . $user['nickname'],
'$poco_url' => $baseURL . '/poco/' . $user['nickname'],
'$photo' => $baseURL . '/photo/profile/' . $user['uid'] . '.jpg',
'$salmon' => $baseURL . '/salmon/' . $user['nickname'],
'$salmen' => $baseURL . '/salmon/' . $user['nickname'] . '/mention',
'$profile_url' => $owner['url'],
'$hcard_url' => $baseURL . '/hcard/' . $owner['nickname'],
'$atom' => $owner['poll'],
'$poco_url' => $owner['poco'],
'$photo' => $owner['photo'],
'$type' => $avatar['type'],
'$salmon' => $baseURL . '/salmon/' . $owner['nickname'],
'$salmen' => $baseURL . '/salmon/' . $owner['nickname'] . '/mention',
'$subscribe' => $baseURL . '/follow?url={uri}',
'$openwebauth' => $baseURL . '/owa',
'$modexp' => 'data:application/magic-public-key,' . $salmon_key