Loading project_browser.services.yml +6 −0 Original line number Diff line number Diff line Loading @@ -12,3 +12,9 @@ services: class: '\Drupal\project_browser\EventSubscriber\UpdateFixtureSubscriber' tags: - { name: 'event_subscriber' } cache.project_browser: class: Drupal\Core\Cache\CacheBackendInterface tags: - { name: cache.bin } factory: cache_factory:get arguments: [project_browser] src/Controller/ProjectBrowserEndpointController.php +84 −7 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ namespace Drupal\project_browser\Controller; use Drupal\Component\Utility\Xss; use Drupal\Core\Cache\CacheableResponseInterface; use Drupal\Core\Controller\ControllerBase; use Drupal\project_browser\EnabledSourceHandler; Loading @@ -22,6 +23,13 @@ class ProjectBrowserEndpointController extends ControllerBase { */ protected $enabledSource; /** * ProjectBrowser cache bin. * * @var \Drupal\Core\Cache\CacheBackendInterface */ protected $cacheBin; /** * ProjectBrowserEndpointController constructor. * Loading @@ -30,6 +38,15 @@ class ProjectBrowserEndpointController extends ControllerBase { */ public function __construct(EnabledSourceHandler $enabled_source) { $this->enabledSource = $enabled_source; $this->cacheBin = $this->cache('project_browser'); $plugin_id = $this->enabledSource->getCurrentSource()->getPluginId(); $cache_key = 'project_browser:enabled_source'; $cached_enabled_source = $this->cacheBin->get($cache_key); if ($cached_enabled_source === FALSE || ($cached_enabled_source->data != $plugin_id)) { $this->cacheBin->deleteAll(); $this->cacheBin->set($cache_key, $plugin_id); } } /** Loading Loading @@ -57,8 +74,53 @@ class ProjectBrowserEndpointController extends ControllerBase { if (!$current_source) { return new JsonResponse([], Response::HTTP_ACCEPTED); } $all_projects = $current_source->getProjects($request->query->all()); return new JsonResponse($all_projects); // Validate and build query. $direction = $request->query->get('direction'); $query = [ // Page and limit are checked against a valid list in in_array, below. 'page' => (int) $request->query->get('page', 0), 'limit' => (int) $request->query->get('limit', 12), 'sort' => Xss::filter($request->query->get('sort')), 'direction' => in_array($direction, ['ASC', 'DESC']) ? $direction : 'ASC', ]; $title = $request->query->get('search', NULL); if ($title) { $query['search'] = Xss::filter($title); } $categories = $request->query->get('categories', NULL); if ($categories) { $query['categories'] = Xss::filter($categories); } $maintenance_status = $request->query->get('maintenance_status', NULL); if ($maintenance_status) { $query['maintenance_status'] = Xss::filter($maintenance_status); } $development_status = $request->query->get('development_status', NULL); if ($development_status) { $query['development_status'] = Xss::filter($development_status); } $security_advisory_coverage = $request->query->get('security_advisory_coverage', NULL); if ($security_advisory_coverage) { $query['security_advisory_coverage'] = Xss::filter($security_advisory_coverage); } // Cache only exact query, down to the page number. $cache_key = 'project_browser:projects:' . md5(json_encode($query)); if ($projects = $this->cacheBin->get($cache_key)) { $projects = $projects->data; } else { $projects = $current_source->getProjects($query); $this->cacheBin->set($cache_key, $projects); } return new JsonResponse($projects); } /** Loading @@ -75,11 +137,18 @@ class ProjectBrowserEndpointController extends ControllerBase { return new JsonResponse([], Response::HTTP_ACCEPTED); } $project = $request->query->get('project'); $project = Xss::filter($request->query->get('project')); if ($project) { $cache_key = 'project_browser:releases:' . $project; if ($releases = $this->cacheBin->get($cache_key)) { $releases = $releases->data; } else { $releases = $current_source->getProjectReleases($project); $this->cacheBin->set($cache_key, $releases); } if (count($releases)) { $response = new JsonResponse((array) $releases, Response::HTTP_ACCEPTED); $response = new JsonResponse((array) $releases); if ($response instanceof CacheableResponseInterface) { $response->addCacheableDependency($releases); } Loading @@ -103,8 +172,16 @@ class ProjectBrowserEndpointController extends ControllerBase { return new JsonResponse([], Response::HTTP_ACCEPTED); } $cache_key = 'project_browser:categories'; if ($categories = $this->cacheBin->get($cache_key)) { $categories = $categories->data; } else { $categories = $current_source->getCategories(); return new JsonResponse($categories, Response::HTTP_ACCEPTED); $this->cacheBin->set($cache_key, $categories); } return new JsonResponse($categories); } } src/Plugin/ProjectBrowserSource/MockDrupalDotOrg.php +11 −13 Original line number Diff line number Diff line Loading @@ -144,15 +144,13 @@ class MockDrupalDotOrg extends PluginBase implements ProjectBrowserSourceInterfa public function getProjects(array $query = []) : ProjectsResultsPage { $api_response = $this->fetchProjects($query); // Iterate through and turn each into a // \Drupal\project_browser\ProjectBrowser\Project. $returned_list = []; if ($api_response) { foreach ($api_response['list'] as $project) { if (is_object($project)) { $project = (array) $project; } // @todo Map any properties from the mock to the expected in Project. // Map any properties from the mock to the expected in Project. $project['field_maintenance_status'] = $project['taxonomy_vocabulary_44']; $project['field_module_categories'] = $project['taxonomy_vocabulary_3']; $project['field_development_status'] = $project['taxonomy_vocabulary_46']; Loading Loading @@ -187,26 +185,26 @@ class MockDrupalDotOrg extends PluginBase implements ProjectBrowserSourceInterfa } // Filter by maintenance status. if (array_key_exists('field_maintenance_status', $query)) { $tids = explode(',', $query['field_maintenance_status']); if (array_key_exists('maintenance_status', $query)) { $tids = explode(',', $query['maintenance_status']); $db_query->condition('maintenance_status', $tids, 'IN'); } // Filter by development status. if (array_key_exists('field_development_status', $query)) { $tids = explode(',', $query['field_development_status']); if (array_key_exists('development_status', $query)) { $tids = explode(',', $query['development_status']); $db_query->condition('development_status', $tids, 'IN'); } // Filter by security advisory coverage. if (array_key_exists('field_security_advisory_coverage', $query)) { $tids = explode(',', $query['field_security_advisory_coverage']); if (array_key_exists('security_advisory_coverage', $query)) { $tids = explode(',', $query['security_advisory_coverage']); $db_query->condition('field_security_advisory_coverage', $tids, 'IN'); } // Filter by category. if (array_key_exists('field_module_categories', $query)) { $tids = explode(',', $query['field_module_categories']); if (array_key_exists('categories', $query)) { $tids = explode(',', $query['categories']); if (count($tids) === 1) { $db_query->join('project_browser_categories', 'cat', 'pbp.nid = cat.pid AND cat.tid = :tid', [ ':tid' => $tids[0], Loading @@ -227,8 +225,8 @@ class MockDrupalDotOrg extends PluginBase implements ProjectBrowserSourceInterfa } // Filter by search term. if (array_key_exists('title', $query)) { $title = $query['title']; if (array_key_exists('search', $query)) { $title = $query['search']; $db_query->condition('pbp.title', "%$title%", 'LIKE'); } Loading src/Plugin/ProjectBrowserSourceInterface.php +11 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,17 @@ interface ProjectBrowserSourceInterface { * @param array $query * The query string params from the frontend request. * * The expected parameters will be: * - page: Page number. * - limit: Number of elements per page. * - sort: Field to do the sorting on. * - direction: 'ASC' or 'DESC'. * - search: Search term. * - categories: Comma separated list of term names or IDs. * - maintenance_status: Comma separated list of term names or IDs. * - development_status: Comma separated list of term names or IDs. * - security_advisory_coverage: Comma separated list of term names or IDs. * * @return \Drupal\project_browser\ProjectBrowser\ProjectsResultsPage * Returns a \Drupal\project_browser\ProjectBrowser\ProjectsResultsPage */ Loading sveltejs/public/build/bundle.css +0 −0 File changed.Preview suppressed by a .gitattributes entry or the file's encoding is unsupported. View original file View changed file Loading
project_browser.services.yml +6 −0 Original line number Diff line number Diff line Loading @@ -12,3 +12,9 @@ services: class: '\Drupal\project_browser\EventSubscriber\UpdateFixtureSubscriber' tags: - { name: 'event_subscriber' } cache.project_browser: class: Drupal\Core\Cache\CacheBackendInterface tags: - { name: cache.bin } factory: cache_factory:get arguments: [project_browser]
src/Controller/ProjectBrowserEndpointController.php +84 −7 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ namespace Drupal\project_browser\Controller; use Drupal\Component\Utility\Xss; use Drupal\Core\Cache\CacheableResponseInterface; use Drupal\Core\Controller\ControllerBase; use Drupal\project_browser\EnabledSourceHandler; Loading @@ -22,6 +23,13 @@ class ProjectBrowserEndpointController extends ControllerBase { */ protected $enabledSource; /** * ProjectBrowser cache bin. * * @var \Drupal\Core\Cache\CacheBackendInterface */ protected $cacheBin; /** * ProjectBrowserEndpointController constructor. * Loading @@ -30,6 +38,15 @@ class ProjectBrowserEndpointController extends ControllerBase { */ public function __construct(EnabledSourceHandler $enabled_source) { $this->enabledSource = $enabled_source; $this->cacheBin = $this->cache('project_browser'); $plugin_id = $this->enabledSource->getCurrentSource()->getPluginId(); $cache_key = 'project_browser:enabled_source'; $cached_enabled_source = $this->cacheBin->get($cache_key); if ($cached_enabled_source === FALSE || ($cached_enabled_source->data != $plugin_id)) { $this->cacheBin->deleteAll(); $this->cacheBin->set($cache_key, $plugin_id); } } /** Loading Loading @@ -57,8 +74,53 @@ class ProjectBrowserEndpointController extends ControllerBase { if (!$current_source) { return new JsonResponse([], Response::HTTP_ACCEPTED); } $all_projects = $current_source->getProjects($request->query->all()); return new JsonResponse($all_projects); // Validate and build query. $direction = $request->query->get('direction'); $query = [ // Page and limit are checked against a valid list in in_array, below. 'page' => (int) $request->query->get('page', 0), 'limit' => (int) $request->query->get('limit', 12), 'sort' => Xss::filter($request->query->get('sort')), 'direction' => in_array($direction, ['ASC', 'DESC']) ? $direction : 'ASC', ]; $title = $request->query->get('search', NULL); if ($title) { $query['search'] = Xss::filter($title); } $categories = $request->query->get('categories', NULL); if ($categories) { $query['categories'] = Xss::filter($categories); } $maintenance_status = $request->query->get('maintenance_status', NULL); if ($maintenance_status) { $query['maintenance_status'] = Xss::filter($maintenance_status); } $development_status = $request->query->get('development_status', NULL); if ($development_status) { $query['development_status'] = Xss::filter($development_status); } $security_advisory_coverage = $request->query->get('security_advisory_coverage', NULL); if ($security_advisory_coverage) { $query['security_advisory_coverage'] = Xss::filter($security_advisory_coverage); } // Cache only exact query, down to the page number. $cache_key = 'project_browser:projects:' . md5(json_encode($query)); if ($projects = $this->cacheBin->get($cache_key)) { $projects = $projects->data; } else { $projects = $current_source->getProjects($query); $this->cacheBin->set($cache_key, $projects); } return new JsonResponse($projects); } /** Loading @@ -75,11 +137,18 @@ class ProjectBrowserEndpointController extends ControllerBase { return new JsonResponse([], Response::HTTP_ACCEPTED); } $project = $request->query->get('project'); $project = Xss::filter($request->query->get('project')); if ($project) { $cache_key = 'project_browser:releases:' . $project; if ($releases = $this->cacheBin->get($cache_key)) { $releases = $releases->data; } else { $releases = $current_source->getProjectReleases($project); $this->cacheBin->set($cache_key, $releases); } if (count($releases)) { $response = new JsonResponse((array) $releases, Response::HTTP_ACCEPTED); $response = new JsonResponse((array) $releases); if ($response instanceof CacheableResponseInterface) { $response->addCacheableDependency($releases); } Loading @@ -103,8 +172,16 @@ class ProjectBrowserEndpointController extends ControllerBase { return new JsonResponse([], Response::HTTP_ACCEPTED); } $cache_key = 'project_browser:categories'; if ($categories = $this->cacheBin->get($cache_key)) { $categories = $categories->data; } else { $categories = $current_source->getCategories(); return new JsonResponse($categories, Response::HTTP_ACCEPTED); $this->cacheBin->set($cache_key, $categories); } return new JsonResponse($categories); } }
src/Plugin/ProjectBrowserSource/MockDrupalDotOrg.php +11 −13 Original line number Diff line number Diff line Loading @@ -144,15 +144,13 @@ class MockDrupalDotOrg extends PluginBase implements ProjectBrowserSourceInterfa public function getProjects(array $query = []) : ProjectsResultsPage { $api_response = $this->fetchProjects($query); // Iterate through and turn each into a // \Drupal\project_browser\ProjectBrowser\Project. $returned_list = []; if ($api_response) { foreach ($api_response['list'] as $project) { if (is_object($project)) { $project = (array) $project; } // @todo Map any properties from the mock to the expected in Project. // Map any properties from the mock to the expected in Project. $project['field_maintenance_status'] = $project['taxonomy_vocabulary_44']; $project['field_module_categories'] = $project['taxonomy_vocabulary_3']; $project['field_development_status'] = $project['taxonomy_vocabulary_46']; Loading Loading @@ -187,26 +185,26 @@ class MockDrupalDotOrg extends PluginBase implements ProjectBrowserSourceInterfa } // Filter by maintenance status. if (array_key_exists('field_maintenance_status', $query)) { $tids = explode(',', $query['field_maintenance_status']); if (array_key_exists('maintenance_status', $query)) { $tids = explode(',', $query['maintenance_status']); $db_query->condition('maintenance_status', $tids, 'IN'); } // Filter by development status. if (array_key_exists('field_development_status', $query)) { $tids = explode(',', $query['field_development_status']); if (array_key_exists('development_status', $query)) { $tids = explode(',', $query['development_status']); $db_query->condition('development_status', $tids, 'IN'); } // Filter by security advisory coverage. if (array_key_exists('field_security_advisory_coverage', $query)) { $tids = explode(',', $query['field_security_advisory_coverage']); if (array_key_exists('security_advisory_coverage', $query)) { $tids = explode(',', $query['security_advisory_coverage']); $db_query->condition('field_security_advisory_coverage', $tids, 'IN'); } // Filter by category. if (array_key_exists('field_module_categories', $query)) { $tids = explode(',', $query['field_module_categories']); if (array_key_exists('categories', $query)) { $tids = explode(',', $query['categories']); if (count($tids) === 1) { $db_query->join('project_browser_categories', 'cat', 'pbp.nid = cat.pid AND cat.tid = :tid', [ ':tid' => $tids[0], Loading @@ -227,8 +225,8 @@ class MockDrupalDotOrg extends PluginBase implements ProjectBrowserSourceInterfa } // Filter by search term. if (array_key_exists('title', $query)) { $title = $query['title']; if (array_key_exists('search', $query)) { $title = $query['search']; $db_query->condition('pbp.title', "%$title%", 'LIKE'); } Loading
src/Plugin/ProjectBrowserSourceInterface.php +11 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,17 @@ interface ProjectBrowserSourceInterface { * @param array $query * The query string params from the frontend request. * * The expected parameters will be: * - page: Page number. * - limit: Number of elements per page. * - sort: Field to do the sorting on. * - direction: 'ASC' or 'DESC'. * - search: Search term. * - categories: Comma separated list of term names or IDs. * - maintenance_status: Comma separated list of term names or IDs. * - development_status: Comma separated list of term names or IDs. * - security_advisory_coverage: Comma separated list of term names or IDs. * * @return \Drupal\project_browser\ProjectBrowser\ProjectsResultsPage * Returns a \Drupal\project_browser\ProjectBrowser\ProjectsResultsPage */ Loading
sveltejs/public/build/bundle.css +0 −0 File changed.Preview suppressed by a .gitattributes entry or the file's encoding is unsupported. View original file View changed file