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.

235 lines
6.6 KiB

9 years ago
9 years ago
9 years ago
  1. <?php
  2. use Symfony\Component\HttpFoundation\Request;
  3. use Symfony\Component\HttpFoundation\Response;
  4. class Controller {
  5. public $http;
  6. public function __construct() {
  7. $this->http = new Telegraph\HTTP();
  8. }
  9. private function _is_logged_in(Request $request, Response $response) {
  10. session_start();
  11. if(!session('user_id')) {
  12. session_destroy();
  13. $response->setStatusCode(302);
  14. $response->headers->set('Location', '/login?return_to='.$request->getRequestURI());
  15. return false;
  16. } else {
  17. return true;
  18. }
  19. }
  20. private function _get_role(Request $request) {
  21. // Default to load their first site, but let the query string override it
  22. $role = ORM::for_table('roles')->join('sites', 'roles.site_id = sites.id')
  23. ->where('user_id', session('user_id'))->order_by_asc('sites.created_at')->find_one();
  24. if($request->get('account')) {
  25. $role = ORM::for_table('roles')->where('user_id', session('user_id'))->where('site_id', $request->get('account'))->find_one();
  26. // Check that the user has permission to access this account
  27. if(!$role) {
  28. $response->setStatusCode(302);
  29. $response->headers->set('Location', '/dashboard');
  30. return false;
  31. }
  32. }
  33. return $role;
  34. }
  35. public function index(Request $request, Response $response) {
  36. $response->setContent(view('index', [
  37. 'title' => 'Telegraph'
  38. ]));
  39. return $response;
  40. }
  41. private static function _icon_for_status($status) {
  42. switch($status) {
  43. case 'success':
  44. case 'accepted':
  45. return 'green checkmark';
  46. case 'not_supported':
  47. return 'yellow x';
  48. case 'error':
  49. return 'red x';
  50. case 'pending':
  51. return 'orange wait';
  52. default:
  53. return '';
  54. }
  55. }
  56. public function dashboard(Request $request, Response $response) {
  57. if(!$this->_is_logged_in($request, $response)) {
  58. return $response;
  59. }
  60. if(!$role=$this->_get_role($request, $response)) {
  61. return $response;
  62. }
  63. $site = ORM::for_table('sites')->where_id_is($role->site_id)->find_one();
  64. $query = ORM::for_table('webmentions')->where('site_id', $site->id)
  65. ->order_by_desc('created_at')
  66. ->limit(20)
  67. ->find_many();
  68. $webmentions = [];
  69. foreach($query as $m) {
  70. $statuses = ORM::for_table('webmention_status')->where('webmention_id', $m->id)->order_by_desc('created_at')->find_many();
  71. if(count($statuses) == 0) {
  72. $status = 'pending';
  73. } else {
  74. $status = $statuses[0]->status;
  75. }
  76. $icon = self::_icon_for_status($status);
  77. $webmentions[] = [
  78. 'webmention' => $m,
  79. 'statuses' => $statuses,
  80. 'status' => $status,
  81. 'icon' => $icon
  82. ];
  83. }
  84. $response->setContent(view('dashboard', [
  85. 'title' => 'Telegraph Dashboard',
  86. 'user' => $this->_user(),
  87. 'accounts' => $this->_accounts(),
  88. 'site' => $site,
  89. 'role' => $role,
  90. 'webmentions' => $webmentions
  91. ]));
  92. return $response;
  93. }
  94. public function webmention_details(Request $request, Response $response, $args) {
  95. if(!$this->_is_logged_in($request, $response)) {
  96. return $response;
  97. }
  98. // Look up the webmention by its token
  99. $webmention = ORM::for_table('webmentions')->where('token', $args['code'])->find_one();
  100. if(!$webmention) {
  101. $response->setContent(view('not-found'));
  102. return $response;
  103. }
  104. $site = ORM::for_table('sites')->where_id_is($webmention->site_id)->find_one();
  105. $statuses = ORM::for_table('webmention_status')->where('webmention_id', $webmention->id)->order_by_desc('created_at')->find_many();
  106. if(count($statuses) == 0) {
  107. $status = 'pending';
  108. } else {
  109. $status = $statuses[0]->status;
  110. }
  111. $icon = self::_icon_for_status($status);
  112. $response->setContent(view('webmention-details', [
  113. 'title' => 'Webmention Details',
  114. 'user' => $this->_user(),
  115. 'accounts' => $this->_accounts(),
  116. 'site' => $site,
  117. 'webmention' => $webmention,
  118. 'statuses' => $statuses,
  119. 'icon' => $icon,
  120. 'status' => $status
  121. ]));
  122. return $response;
  123. }
  124. public function dashboard_send(Request $request, Response $response) {
  125. if(!$this->_is_logged_in($request, $response)) {
  126. return $response;
  127. }
  128. if(!$role=$this->_get_role($request, $response)) {
  129. return $response;
  130. }
  131. $site = ORM::for_table('sites')->where_id_is($role->site_id)->find_one();
  132. $response->setContent(view('webmention-send', [
  133. 'title' => 'Webmention Details',
  134. 'user' => $this->_user(),
  135. 'accounts' => $this->_accounts(),
  136. 'site' => $site,
  137. 'role' => $role,
  138. 'url' => $request->get('url')
  139. ]));
  140. return $response;
  141. }
  142. public function get_outgoing_links(Request $request, Response $response) {
  143. if(!$this->_is_logged_in($request, $response)) {
  144. return $response;
  145. }
  146. $sourceURL = $request->get('url');
  147. $client = new IndieWeb\MentionClient();
  148. $source = $this->http->get($sourceURL);
  149. $parsed = \Mf2\parse($source['body'], $sourceURL);
  150. $links = $client->findOutgoingLinks($parsed);
  151. $response->headers->set('Content-Type', 'application/json');
  152. $response->setContent(json_encode([
  153. 'links' => array_values($links)
  154. ]));
  155. return $response;
  156. }
  157. public function discover_endpoint(Request $request, Response $response) {
  158. if(!$this->_is_logged_in($request, $response)) {
  159. return $response;
  160. }
  161. $targetURL = $request->get('target');
  162. // Cache the discovered result
  163. $cacheKey = 'telegraph:discover_endpoint:'.$targetURL;
  164. if($request->get('ignore_cache') == 'true' || (!$status = redis()->get($cacheKey))) {
  165. $client = new IndieWeb\MentionClient();
  166. $endpoint = $client->discoverWebmentionEndpoint($targetURL);
  167. if($endpoint) {
  168. $status = 'webmention';
  169. } else {
  170. $endpoint = $client->discoverPingbackEndpoint($targetURL);
  171. if($endpoint) {
  172. $status = 'pingback';
  173. } else {
  174. $status = 'none';
  175. }
  176. }
  177. $cached = false;
  178. redis()->setex($cacheKey, 600, $status);
  179. } else {
  180. $cached = true;
  181. }
  182. $response->headers->set('Content-Type', 'application/json');
  183. $response->setContent(json_encode([
  184. 'status' => $status,
  185. 'cached' => $cached
  186. ]));
  187. return $response;
  188. }
  189. private function _user() {
  190. return ORM::for_table('users')->where_id_is(session('user_id'))->find_one();
  191. }
  192. private function _accounts() {
  193. return ORM::for_table('sites')->join('roles', 'roles.site_id = sites.id')
  194. ->where('roles.user_id', session('user_id'))
  195. ->find_many();
  196. }
  197. }