Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
7.0KB

  1. <?php
  2. /**
  3. * @file mod/community.php
  4. */
  5. use Friendica\App;
  6. use Friendica\Content\Nav;
  7. use Friendica\Content\Pager;
  8. use Friendica\Core\ACL;
  9. use Friendica\Core\Config;
  10. use Friendica\Core\L10n;
  11. use Friendica\Core\PConfig;
  12. use Friendica\Core\Renderer;
  13. use Friendica\Database\DBA;
  14. use Friendica\Model\Contact;
  15. use Friendica\Model\Item;
  16. function community_init(App $a)
  17. {
  18. if (!local_user()) {
  19. unset($_SESSION['theme']);
  20. unset($_SESSION['mobile-theme']);
  21. }
  22. }
  23. function community_content(App $a, $update = 0)
  24. {
  25. $o = '';
  26. if (Config::get('system', 'block_public') && !local_user() && !remote_user()) {
  27. notice(L10n::t('Public access denied.') . EOL);
  28. return;
  29. }
  30. $page_style = Config::get('system', 'community_page_style');
  31. if ($page_style == CP_NO_INTERNAL_COMMUNITY) {
  32. notice(L10n::t('Access denied.') . EOL);
  33. return;
  34. }
  35. $accounttype = null;
  36. if ($a->argc > 2) {
  37. switch ($a->argv[2]) {
  38. case 'person':
  39. $accounttype = Contact::ACCOUNT_TYPE_PERSON;
  40. break;
  41. case 'organisation':
  42. $accounttype = Contact::ACCOUNT_TYPE_ORGANISATION;
  43. break;
  44. case 'news':
  45. $accounttype = Contact::ACCOUNT_TYPE_NEWS;
  46. break;
  47. case 'community':
  48. $accounttype = Contact::ACCOUNT_TYPE_COMMUNITY;
  49. break;
  50. }
  51. }
  52. if ($a->argc > 1) {
  53. $content = $a->argv[1];
  54. } else {
  55. if (!empty(Config::get('system', 'singleuser'))) {
  56. // On single user systems only the global page does make sense
  57. $content = 'global';
  58. } else {
  59. // When only the global community is allowed, we use this as default
  60. $content = $page_style == CP_GLOBAL_COMMUNITY ? 'global' : 'local';
  61. }
  62. }
  63. if (!in_array($content, ['local', 'global'])) {
  64. notice(L10n::t('Community option not available.') . EOL);
  65. return;
  66. }
  67. // Check if we are allowed to display the content to visitors
  68. if (!local_user()) {
  69. $available = $page_style == CP_USERS_AND_GLOBAL;
  70. if (!$available) {
  71. $available = ($page_style == CP_USERS_ON_SERVER) && ($content == 'local');
  72. }
  73. if (!$available) {
  74. $available = ($page_style == CP_GLOBAL_COMMUNITY) && ($content == 'global');
  75. }
  76. if (!$available) {
  77. notice(L10n::t('Not available.') . EOL);
  78. return;
  79. }
  80. }
  81. if (!$update) {
  82. $tabs = [];
  83. if ((local_user() || in_array($page_style, [CP_USERS_AND_GLOBAL, CP_USERS_ON_SERVER])) && empty(Config::get('system', 'singleuser'))) {
  84. $tabs[] = [
  85. 'label' => L10n::t('Local Community'),
  86. 'url' => 'community/local',
  87. 'sel' => $content == 'local' ? 'active' : '',
  88. 'title' => L10n::t('Posts from local users on this server'),
  89. 'id' => 'community-local-tab',
  90. 'accesskey' => 'l'
  91. ];
  92. }
  93. if (local_user() || in_array($page_style, [CP_USERS_AND_GLOBAL, CP_GLOBAL_COMMUNITY])) {
  94. $tabs[] = [
  95. 'label' => L10n::t('Global Community'),
  96. 'url' => 'community/global',
  97. 'sel' => $content == 'global' ? 'active' : '',
  98. 'title' => L10n::t('Posts from users of the whole federated network'),
  99. 'id' => 'community-global-tab',
  100. 'accesskey' => 'g'
  101. ];
  102. }
  103. $tab_tpl = Renderer::getMarkupTemplate('common_tabs.tpl');
  104. $o .= Renderer::replaceMacros($tab_tpl, ['$tabs' => $tabs]);
  105. Nav::setSelected('community');
  106. // We need the editor here to be able to reshare an item.
  107. if (local_user()) {
  108. $x = [
  109. 'is_owner' => true,
  110. 'allow_location' => $a->user['allow_location'],
  111. 'default_location' => $a->user['default-location'],
  112. 'nickname' => $a->user['nickname'],
  113. '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'),
  114. 'acl' => ACL::getFullSelectorHTML($a->user, true),
  115. 'bang' => '',
  116. 'visitor' => 'block',
  117. 'profile_uid' => local_user(),
  118. ];
  119. $o .= status_editor($a, $x, 0, true);
  120. }
  121. }
  122. // check if we serve a mobile device and get the user settings accordingly
  123. if ($a->is_mobile) {
  124. $itemspage_network = PConfig::get(local_user(), 'system', 'itemspage_mobile_network', 20);
  125. } else {
  126. $itemspage_network = PConfig::get(local_user(), 'system', 'itemspage_network', 40);
  127. }
  128. // now that we have the user settings, see if the theme forces
  129. // a maximum item number which is lower then the user choice
  130. if (($a->force_max_items > 0) && ($a->force_max_items < $itemspage_network)) {
  131. $itemspage_network = $a->force_max_items;
  132. }
  133. $pager = new Pager($a->query_string, $itemspage_network);
  134. $r = community_getitems($pager->getStart(), $pager->getItemsPerPage(), $content, $accounttype);
  135. if (!DBA::isResult($r)) {
  136. info(L10n::t('No results.') . EOL);
  137. return $o;
  138. }
  139. $maxpostperauthor = (int) Config::get('system', 'max_author_posts_community_page');
  140. if (($maxpostperauthor != 0) && ($content == 'local')) {
  141. $count = 1;
  142. $previousauthor = "";
  143. $numposts = 0;
  144. $s = [];
  145. do {
  146. foreach ($r as $item) {
  147. if ($previousauthor == $item["author-link"]) {
  148. ++$numposts;
  149. } else {
  150. $numposts = 0;
  151. }
  152. $previousauthor = $item["author-link"];
  153. if (($numposts < $maxpostperauthor) && (count($s) < $pager->getItemsPerPage())) {
  154. $s[] = $item;
  155. }
  156. }
  157. if (count($s) < $pager->getItemsPerPage()) {
  158. $r = community_getitems($pager->getStart() + ($count * $pager->getItemsPerPage()), $pager->getItemsPerPage(), $content, $accounttype);
  159. }
  160. } while ((count($s) < $pager->getItemsPerPage()) && ( ++$count < 50) && (count($r) > 0));
  161. } else {
  162. $s = $r;
  163. }
  164. $o .= conversation($a, $s, $pager, 'community', $update, false, 'commented', local_user());
  165. if (!$update) {
  166. $o .= $pager->renderMinimal(count($r));
  167. }
  168. $t = Renderer::getMarkupTemplate("community.tpl");
  169. return Renderer::replaceMacros($t, [
  170. '$content' => $o,
  171. '$header' => '',
  172. '$show_global_community_hint' => ($content == 'global') && Config::get('system', 'show_global_community_hint'),
  173. '$global_community_hint' => L10n::t("This community stream shows all public posts received by this node. They may not reflect the opinions of this node’s users.")
  174. ]);
  175. }
  176. function community_getitems($start, $itemspage, $content, $accounttype)
  177. {
  178. if ($content == 'local') {
  179. if (!is_null($accounttype)) {
  180. $sql_accounttype = " AND `user`.`account-type` = ?";
  181. $values = [$accounttype, $start, $itemspage];
  182. } else {
  183. $sql_accounttype = "";
  184. $values = [$start, $itemspage];
  185. }
  186. $r = DBA::p("SELECT `item`.`uri`, `author`.`url` AS `author-link` FROM `thread`
  187. INNER JOIN `user` ON `user`.`uid` = `thread`.`uid` AND NOT `user`.`hidewall`
  188. INNER JOIN `item` ON `item`.`id` = `thread`.`iid`
  189. INNER JOIN `contact` AS `author` ON `author`.`id`=`item`.`author-id`
  190. WHERE `thread`.`visible` AND NOT `thread`.`deleted` AND NOT `thread`.`moderated`
  191. AND NOT `thread`.`private` AND `thread`.`wall` AND `thread`.`origin` $sql_accounttype
  192. ORDER BY `thread`.`commented` DESC LIMIT ?, ?", $values);
  193. return DBA::toArray($r);
  194. } elseif ($content == 'global') {
  195. if (!is_null($accounttype)) {
  196. $condition = ["`uid` = ? AND `owner`.`contact-type` = ?", 0, $accounttype];
  197. } else {
  198. $condition = ['uid' => 0];
  199. }
  200. $r = Item::selectThreadForUser(0, ['uri'], $condition, ['order' => ['commented' => true], 'limit' => [$start, $itemspage]]);
  201. return DBA::toArray($r);
  202. }
  203. // Should never happen
  204. return [];
  205. }