diff --git a/mod/directory.php b/mod/directory.php deleted file mode 100644 index 256c9bbbd5..0000000000 --- a/mod/directory.php +++ /dev/null @@ -1,230 +0,0 @@ -page['aside'] .= Widget::findPeople(); - $a->page['aside'] .= Widget::follow(); - } else { - unset($_SESSION['theme']); - unset($_SESSION['mobile-theme']); - } -} - -function directory_post(App $a) -{ - if (!empty($_POST['search'])) { - $a->data['search'] = $_POST['search']; - } -} - -function directory_content(App $a) -{ - if ((Config::get('system', 'block_public') && !local_user() && !remote_user()) - || (Config::get('system', 'block_local_dir') && !local_user() && !remote_user()) - ) { - notice(L10n::t('Public access denied.') . EOL); - return; - } - - $o = ''; - $entries = []; - - Nav::setSelected('directory'); - - if (!empty($a->data['search'])) { - $search = Strings::escapeTags(trim($a->data['search'])); - } else { - $search = (!empty($_GET['search']) ? Strings::escapeTags(trim(rawurldecode($_GET['search']))) : ''); - } - - $gdirpath = ''; - $dirurl = Config::get('system', 'directory'); - if (strlen($dirurl)) { - $gdirpath = Profile::zrl($dirurl, true); - } - - if ($search) { - $search = DBA::escape($search); - - $sql_extra = " AND ((`profile`.`name` LIKE '%$search%') OR - (`user`.`nickname` LIKE '%$search%') OR - (`profile`.`pdesc` LIKE '%$search%') OR - (`profile`.`locality` LIKE '%$search%') OR - (`profile`.`region` LIKE '%$search%') OR - (`profile`.`country-name` LIKE '%$search%') OR - (`profile`.`gender` LIKE '%$search%') OR - (`profile`.`marital` LIKE '%$search%') OR - (`profile`.`sexual` LIKE '%$search%') OR - (`profile`.`about` LIKE '%$search%') OR - (`profile`.`romance` LIKE '%$search%') OR - (`profile`.`work` LIKE '%$search%') OR - (`profile`.`education` LIKE '%$search%') OR - (`profile`.`pub_keywords` LIKE '%$search%') OR - (`profile`.`prv_keywords` LIKE '%$search%'))"; - } else { - $sql_extra = ''; - } - - $publish = (Config::get('system', 'publish_all') ? '' : " AND `publish` = 1 " ); - - - $total = 0; - $cnt = DBA::fetchFirst("SELECT COUNT(*) AS `total` FROM `profile` - LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid` - WHERE `is-default` $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` $sql_extra"); - if (DBA::isResult($cnt)) { - $total = $cnt['total']; - } - $pager = new Pager($a->query_string, 60); - - $order = " ORDER BY `name` ASC "; - - $limit = $pager->getStart()."," . $pager->getItemsPerPage(); - - $r = DBA::p("SELECT `profile`.*, `profile`.`uid` AS `profile_uid`, `user`.`nickname`, `user`.`timezone` , `user`.`page-flags`, - `contact`.`addr`, `contact`.`url` AS `profile_url` FROM `profile` - LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid` - LEFT JOIN `contact` ON `contact`.`uid` = `user`.`uid` - WHERE `is-default` $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `contact`.`self` - $sql_extra $order LIMIT $limit" - ); - if (DBA::isResult($r)) { - if (in_array('small', $a->argv)) { - $photo = 'thumb'; - } else { - $photo = 'photo'; - } - - while ($rr = DBA::fetch($r)) { - $entries[] = format_directory_entry($rr, $photo); - } - DBA::close($r); - } else { - info(L10n::t("No entries \x28some entries may be hidden\x29.") . EOL); - } - - $tpl = Renderer::getMarkupTemplate('directory_header.tpl'); - - $o .= Renderer::replaceMacros($tpl, [ - '$search' => $search, - '$globaldir' => L10n::t('Global Directory'), - '$gdirpath' => $gdirpath, - '$desc' => L10n::t('Find on this site'), - '$contacts' => $entries, - '$finding' => L10n::t('Results for:'), - '$findterm' => (strlen($search) ? $search : ""), - '$title' => L10n::t('Site Directory'), - '$search_mod' => 'directory', - '$submit' => L10n::t('Find'), - '$paginate' => $pager->renderFull($total), - ]); - - return $o; -} - -/** - * Format contact/profile/user data from the database into an usable - * array for displaying directory entries. - * - * @param array $arr The directory entry from the database. - * @param string $photo_size Avatar size (thumb, photo or micro). - * - * @return array - */ -function format_directory_entry(array $arr, $photo_size = 'photo') -{ - $itemurl = (($arr['addr'] != "") ? $arr['addr'] : $arr['profile_url']); - - $profile_link = $arr['profile_url']; - - $pdesc = (($arr['pdesc']) ? $arr['pdesc'] . '
' : ''); - - $details = ''; - if (strlen($arr['locality'])) { - $details .= $arr['locality']; - } - if (strlen($arr['region'])) { - if (strlen($arr['locality'])) { - $details .= ', '; - } - $details .= $arr['region']; - } - if (strlen($arr['country-name'])) { - if (strlen($details)) { - $details .= ', '; - } - $details .= $arr['country-name']; - } - - $profile = $arr; - - if (!empty($profile['address']) - || !empty($profile['locality']) - || !empty($profile['region']) - || !empty($profile['postal-code']) - || !empty($profile['country-name']) - ) { - $location = L10n::t('Location:'); - } else { - $location = ''; - } - - $gender = (!empty($profile['gender']) ? L10n::t('Gender:') : false); - $marital = (!empty($profile['marital']) ? L10n::t('Status:') : false); - $homepage = (!empty($profile['homepage']) ? L10n::t('Homepage:') : false); - $about = (!empty($profile['about']) ? L10n::t('About:') : false); - - $location_e = $location; - - $photo_menu = [ - 'profile' => [L10n::t("View Profile"), Contact::magicLink($profile_link)] - ]; - - $entry = [ - 'id' => $arr['id'], - 'url' => Contact::magicLInk($profile_link), - 'itemurl' => $itemurl, - 'thumb' => ProxyUtils::proxifyUrl($arr[$photo_size], false, ProxyUtils::SIZE_THUMB), - 'img_hover' => $arr['name'], - 'name' => $arr['name'], - 'details' => $details, - 'account_type' => Contact::getAccountType($arr), - 'profile' => $profile, - 'location' => $location_e, - 'tags' => $arr['pub_keywords'], - 'gender' => $gender, - 'pdesc' => $pdesc, - 'marital' => $marital, - 'homepage' => $homepage, - 'about' => $about, - 'photo_menu' => $photo_menu, - - ]; - - $hook = ['contact' => $arr, 'entry' => $entry]; - - Hook::callAll('directory_item', $hook); - - unset($profile); - unset($location); - - return $hook['entry']; -} diff --git a/src/App/Router.php b/src/App/Router.php index e2a6719f6c..2c68374441 100644 --- a/src/App/Router.php +++ b/src/App/Router.php @@ -64,6 +64,7 @@ class Router $collector->addRoute(['GET'], '/{nickname}/replies', Module\Feed::class); $collector->addRoute(['GET'], '/{nickname}/activity', Module\Feed::class); }); + $this->routeCollector->addRoute(['GET'], '/directory', Module\Directory::class); $this->routeCollector->addRoute(['GET'], '/feedtest', Module\Feedtest::class); $this->routeCollector->addRoute(['GET'], '/filer[/{id:\d+}]', Module\Filer::class); $this->routeCollector->addRoute(['GET'], '/followers/{owner}', Module\Followers::class); diff --git a/src/Model/Profile.php b/src/Model/Profile.php index 7028934d19..84ad0153c0 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -1235,4 +1235,74 @@ class Profile { return preg_replace('/[\?&]' . $param . '=(.*?)(&|$)/ism', '$2', $s); } + + /** + * search for Profiles + * + * @param int $start + * @param int $count + * @param null $search + * + * @return array [ 'total' => 123, 'entries' => [...] ]; + * + * @throws \Exception + */ + public static function searchProfiles($start = 0, $count = 100, $search = null) + { + if ($search) { + $search = DBA::escape($search); + + $sql_extra = " AND ((`profile`.`name` LIKE '%$search%') OR + (`user`.`nickname` LIKE '%$search%') OR + (`profile`.`pdesc` LIKE '%$search%') OR + (`profile`.`locality` LIKE '%$search%') OR + (`profile`.`region` LIKE '%$search%') OR + (`profile`.`country-name` LIKE '%$search%') OR + (`profile`.`gender` LIKE '%$search%') OR + (`profile`.`marital` LIKE '%$search%') OR + (`profile`.`sexual` LIKE '%$search%') OR + (`profile`.`about` LIKE '%$search%') OR + (`profile`.`romance` LIKE '%$search%') OR + (`profile`.`work` LIKE '%$search%') OR + (`profile`.`education` LIKE '%$search%') OR + (`profile`.`pub_keywords` LIKE '%$search%') OR + (`profile`.`prv_keywords` LIKE '%$search%'))"; + } else { + $sql_extra = ''; + } + + $publish = (Config::get('system', 'publish_all') ? '' : " AND `publish` = 1 "); + + + $total = 0; + $cnt = DBA::fetchFirst("SELECT COUNT(*) AS `total` FROM `profile` + LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid` + WHERE `is-default` $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` $sql_extra"); + if (DBA::isResult($cnt)) { + $total = $cnt['total']; + } + + $order = " ORDER BY `name` ASC "; + $limit = $start . ',' . $count; + + $profiles = DBA::p("SELECT `profile`.*, `profile`.`uid` AS `profile_uid`, `user`.`nickname`, `user`.`timezone` , `user`.`page-flags`, + `contact`.`addr`, `contact`.`url` AS `profile_url` FROM `profile` + LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid` + LEFT JOIN `contact` ON `contact`.`uid` = `user`.`uid` + WHERE `is-default` $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `contact`.`self` + $sql_extra $order LIMIT $limit" + ); + + if (DBA::isResult($profiles)) { + return [ + 'total' => $total, + 'entries' => DBA::toArray($profiles), + ]; + } else { + return [ + 'total' => $total, + 'entries' => [], + ]; + } + } } diff --git a/src/Module/Directory.php b/src/Module/Directory.php new file mode 100644 index 0000000000..b47bfd43e9 --- /dev/null +++ b/src/Module/Directory.php @@ -0,0 +1,197 @@ +page['aside'] .= Widget::findPeople(); + $app->page['aside'] .= Widget::follow(); + } else { + unset($_SESSION['theme']); + unset($_SESSION['mobile-theme']); + } + } + + public static function post() + { + if (!empty($_POST['search'])) { + self::getApp()->data['search'] = $_POST['search']; + } + } + + public static function content() + { + $app = self::getApp(); + $config = $app->getConfig(); + + if (($config->get('system', 'block_public') && !local_user() && !remote_user()) || + ($config->get('system', 'block_local_dir') && !local_user() && !remote_user())) { + notice(L10n::t('Public access denied.') . EOL); + return ''; + } + + $output = ''; + $entries = []; + + Nav::setSelected('directory'); + + if (!empty($app->data['search'])) { + $search = Strings::escapeTags(trim($app->data['search'])); + } else { + $search = (!empty($_GET['search']) ? Strings::escapeTags(trim(rawurldecode($_GET['search']))) : ''); + } + + $gDirPath = ''; + $dirURL = $config->get('system', 'directory'); + if (strlen($dirURL)) { + $gDirPath = Profile::zrl($dirURL, true); + } + + $pager = new Pager($app->query_string, 60); + + $profiles = Profile::searchProfiles($pager->getStart(), $pager->getItemsPerPage(), $search); + + if ($profiles['total'] === 0) { + info(L10n::t('No entries (some entries may be hidden).') . EOL); + } else { + if (in_array('small', $app->argv)) { + $photo = 'thumb'; + } else { + $photo = 'photo'; + } + + foreach ($profiles['entries'] as $entry) { + $entries[] = self::formatEntry($entry, $photo); + } + } + + $tpl = Renderer::getMarkupTemplate('directory_header.tpl'); + + $output .= Renderer::replaceMacros($tpl, [ + '$search' => $search, + '$globaldir' => L10n::t('Global Directory'), + '$gDirPath' => $gDirPath, + '$desc' => L10n::t('Find on this site'), + '$contacts' => $profiles['entries'], + '$finding' => L10n::t('Results for:'), + '$findterm' => (strlen($search) ? $search : ""), + '$title' => L10n::t('Site Directory'), + '$search_mod' => 'directory', + '$submit' => L10n::t('Find'), + '$paginate' => $pager->renderFull($profiles['total']), + ]); + + return $output; + } + + /** + * Format contact/profile/user data from the database into an usable + * array for displaying directory entries. + * + * @param array $contact The directory entry from the database. + * @param string $photo_size Avatar size (thumb, photo or micro). + * + * @return array + * + * @throws \Exception + */ + public static function formatEntry(array $contact, $photo_size = 'photo') + { + $itemurl = (($contact['addr'] != "") ? $contact['addr'] : $contact['profile_url']); + + $profile_link = $contact['profile_url']; + + $pdesc = (($contact['pdesc']) ? $contact['pdesc'] . '
' : ''); + + $details = ''; + if (strlen($contact['locality'])) { + $details .= $contact['locality']; + } + if (strlen($contact['region'])) { + if (strlen($contact['locality'])) { + $details .= ', '; + } + $details .= $contact['region']; + } + if (strlen($contact['country-name'])) { + if (strlen($details)) { + $details .= ', '; + } + $details .= $contact['country-name']; + } + + $profile = $contact; + + if (!empty($profile['address']) + || !empty($profile['locality']) + || !empty($profile['region']) + || !empty($profile['postal-code']) + || !empty($profile['country-name']) + ) { + $location = L10n::t('Location:'); + } else { + $location = ''; + } + + $gender = (!empty($profile['gender']) ? L10n::t('Gender:') : false); + $marital = (!empty($profile['marital']) ? L10n::t('Status:') : false); + $homepage = (!empty($profile['homepage']) ? L10n::t('Homepage:') : false); + $about = (!empty($profile['about']) ? L10n::t('About:') : false); + + $location_e = $location; + + $photo_menu = [ + 'profile' => [L10n::t("View Profile"), Contact::magicLink($profile_link)] + ]; + + $entry = [ + 'id' => $contact['id'], + 'url' => Contact::magicLInk($profile_link), + 'itemurl' => $itemurl, + 'thumb' => ProxyUtils::proxifyUrl($contact[$photo_size], false, ProxyUtils::SIZE_THUMB), + 'img_hover' => $contact['name'], + 'name' => $contact['name'], + 'details' => $details, + 'account_type' => Contact::getAccountType($contact), + 'profile' => $profile, + 'location' => $location_e, + 'tags' => $contact['pub_keywords'], + 'gender' => $gender, + 'pdesc' => $pdesc, + 'marital' => $marital, + 'homepage' => $homepage, + 'about' => $about, + 'photo_menu' => $photo_menu, + + ]; + + $hook = ['contact' => $contact, 'entry' => $entry]; + + Hook::callAll('directory_item', $hook); + + unset($profile); + unset($location); + + return $hook['entry']; + } +}