|
@@ -57,7 +57,7 @@ class WebController extends Controller
|
|
|
*/
|
|
|
public function indexAction()
|
|
|
{
|
|
|
- return array('page' => 'home', 'searchForm' => $this->createSearchForm()->createView());
|
|
|
+ return array('page' => 'home');
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -81,7 +81,6 @@ class WebController extends Controller
|
|
|
|
|
|
$data['packages'] = $this->setupPager($packages, $page);
|
|
|
$data['meta'] = $this->getPackagesMetadata($data['packages']);
|
|
|
- $data['searchForm'] = $this->createSearchForm()->createView();
|
|
|
|
|
|
return $data;
|
|
|
}
|
|
@@ -118,7 +117,6 @@ class WebController extends Controller
|
|
|
'newlyReleased' => $newReleases,
|
|
|
'random' => $random,
|
|
|
'popular' => $popular,
|
|
|
- 'searchForm' => $this->createSearchForm()->createView(),
|
|
|
);
|
|
|
|
|
|
return $data;
|
|
@@ -166,7 +164,6 @@ class WebController extends Controller
|
|
|
|
|
|
$data = array(
|
|
|
'packages' => $packages,
|
|
|
- 'searchForm' => $this->createSearchForm()->createView(),
|
|
|
);
|
|
|
$data['meta'] = $this->getPackagesMetadata($data['packages']);
|
|
|
|
|
@@ -236,20 +233,24 @@ class WebController extends Controller
|
|
|
return new JsonResponse(array('packageNames' => $names));
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Initializes the pager for a query.
|
|
|
- *
|
|
|
- * @param \Doctrine\ORM\QueryBuilder $query Query for packages
|
|
|
- * @param int $page Page number to retrieve.
|
|
|
- * @return \Pagerfanta\Pagerfanta
|
|
|
- */
|
|
|
- protected function setupPager($query, $page)
|
|
|
+ public function searchFormAction(Request $req)
|
|
|
{
|
|
|
- $paginator = new Pagerfanta(new DoctrineORMAdapter($query, true));
|
|
|
- $paginator->setMaxPerPage(15);
|
|
|
- $paginator->setCurrentPage($page, false, true);
|
|
|
+ $form = $this->createForm(new SearchQueryType, new SearchQuery);
|
|
|
|
|
|
- return $paginator;
|
|
|
+ $filteredOrderBys = $this->getFilteredOrderedBys($req);
|
|
|
+ $normalizedOrderBys = $this->getNormalizedOrderBys($filteredOrderBys);
|
|
|
+
|
|
|
+ $this->computeSearchQuery($req, $filteredOrderBys);
|
|
|
+
|
|
|
+ if ($req->query->has('search_query')) {
|
|
|
+ $form->bind($req);
|
|
|
+ }
|
|
|
+
|
|
|
+ $orderBysViewModel = $this->getOrderBysViewModel($req, $normalizedOrderBys);
|
|
|
+ return $this->render('PackagistWebBundle:Web:searchForm.html.twig', array(
|
|
|
+ 'searchForm' => $form->createView(),
|
|
|
+ 'orderBys' => $orderBysViewModel
|
|
|
+ ));
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -258,12 +259,12 @@ class WebController extends Controller
|
|
|
*/
|
|
|
public function searchAction(Request $req)
|
|
|
{
|
|
|
- $form = $this->createSearchForm();
|
|
|
+ $form = $this->createForm(new SearchQueryType, new SearchQuery);
|
|
|
|
|
|
- // transform q=search shortcut
|
|
|
- if ($req->query->has('q')) {
|
|
|
- $req->query->set('search_query', array('query' => $req->query->get('q')));
|
|
|
- }
|
|
|
+ $filteredOrderBys = $this->getFilteredOrderedBys($req);
|
|
|
+ $normalizedOrderBys = $this->getNormalizedOrderBys($filteredOrderBys);
|
|
|
+
|
|
|
+ $this->computeSearchQuery($req, $filteredOrderBys);
|
|
|
|
|
|
$typeFilter = $req->query->get('type');
|
|
|
$tagsFilter = $req->query->get('tags');
|
|
@@ -299,8 +300,13 @@ class WebController extends Controller
|
|
|
$select->addFilterQuery($filterQuery);
|
|
|
}
|
|
|
|
|
|
+ if (!empty($filteredOrderBys)) {
|
|
|
+ $select->addSorts($normalizedOrderBys);
|
|
|
+ }
|
|
|
+
|
|
|
if ($req->query->has('search_query')) {
|
|
|
$form->bind($req);
|
|
|
+
|
|
|
if ($form->isValid()) {
|
|
|
$escapedQuery = $select->getHelper()->escapeTerm($form->getData()->getQuery());
|
|
|
$escapedQuery = preg_replace('/(^| )\\\\-(\S)/', '$1-$2', $escapedQuery);
|
|
@@ -317,10 +323,10 @@ class WebController extends Controller
|
|
|
$perPage = $req->query->getInt('per_page', 15);
|
|
|
if ($perPage <= 0 || $perPage > 100) {
|
|
|
if ($req->getRequestFormat() === 'json') {
|
|
|
- return new JsonResponse(array(
|
|
|
+ return JsonResponse::create(array(
|
|
|
'status' => 'error',
|
|
|
'message' => 'The optional packages per_page parameter must be an integer between 1 and 100 (default: 15)',
|
|
|
- ), 400);
|
|
|
+ ), 400)->setCallback($req->query->get('callback'));
|
|
|
}
|
|
|
|
|
|
$perPage = max(0, min(100, $perPage));
|
|
@@ -329,13 +335,13 @@ class WebController extends Controller
|
|
|
|
|
|
$paginator->setCurrentPage($req->query->get('page', 1), false, true);
|
|
|
|
|
|
- try {
|
|
|
- $metadata = $this->getPackagesMetadata($paginator);
|
|
|
- } catch (\Solarium_Client_HttpException $e) {
|
|
|
- return new JsonResponse(array(
|
|
|
- 'status' => 'error',
|
|
|
- 'message' => 'Could not connect to the search server',
|
|
|
- ), 500);
|
|
|
+ $metadata = array();
|
|
|
+
|
|
|
+ foreach ($paginator as $package) {
|
|
|
+ if (is_numeric($package->id)) {
|
|
|
+ $metadata['downloads'][$package->id] = $package->downloads;
|
|
|
+ $metadata['favers'][$package->id] = $package->favers;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if ($req->getRequestFormat() === 'json') {
|
|
@@ -345,10 +351,10 @@ class WebController extends Controller
|
|
|
'total' => $paginator->getNbResults(),
|
|
|
);
|
|
|
} catch (\Solarium_Client_HttpException $e) {
|
|
|
- return new JsonResponse(array(
|
|
|
+ return JsonResponse::create(array(
|
|
|
'status' => 'error',
|
|
|
'message' => 'Could not connect to the search server',
|
|
|
- ), 500);
|
|
|
+ ), 500)->setCallback($req->query->get('callback'));
|
|
|
}
|
|
|
|
|
|
foreach ($paginator as $package) {
|
|
@@ -391,7 +397,7 @@ class WebController extends Controller
|
|
|
$result['next'] = $this->generateUrl('search', $params, true);
|
|
|
}
|
|
|
|
|
|
- return new JsonResponse($result);
|
|
|
+ return JsonResponse::create($result)->setCallback($req->query->get('callback'));
|
|
|
}
|
|
|
|
|
|
if ($req->isXmlHttpRequest()) {
|
|
@@ -405,25 +411,24 @@ class WebController extends Controller
|
|
|
if (!$e->getPrevious() instanceof \Solarium_Client_HttpException) {
|
|
|
throw $e;
|
|
|
}
|
|
|
- return new JsonResponse(array(
|
|
|
+ return JsonResponse::create(array(
|
|
|
'status' => 'error',
|
|
|
'message' => 'Could not connect to the search server',
|
|
|
- ), 500);
|
|
|
+ ), 500)->setCallback($req->query->get('callback'));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return $this->render('PackagistWebBundle:Web:search.html.twig', array(
|
|
|
'packages' => $paginator,
|
|
|
'meta' => $metadata,
|
|
|
- 'searchForm' => $form->createView(),
|
|
|
));
|
|
|
+ } elseif ($req->getRequestFormat() === 'json') {
|
|
|
+ return JsonResponse::create(array(
|
|
|
+ 'error' => 'Missing search query, example: ?q=example'
|
|
|
+ ), 400)->setCallback($req->query->get('callback'));
|
|
|
}
|
|
|
|
|
|
- if ($req->getRequestFormat() === 'json') {
|
|
|
- return new JsonResponse(array('error' => 'Missing search query, example: ?q=example'), 400);
|
|
|
- }
|
|
|
-
|
|
|
- return $this->render('PackagistWebBundle:Web:search.html.twig', array('searchForm' => $form->createView(), 'packages' => array()));
|
|
|
+ return $this->render('PackagistWebBundle:Web:search.html.twig');
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -436,13 +441,13 @@ class WebController extends Controller
|
|
|
$package->setEntityRepository($this->getDoctrine()->getRepository('PackagistWebBundle:Package'));
|
|
|
$package->setRouter($this->get('router'));
|
|
|
$form = $this->createForm(new PackageType, $package);
|
|
|
+ $user = $this->getUser();
|
|
|
+ $package->addMaintainer($user);
|
|
|
|
|
|
if ('POST' === $req->getMethod()) {
|
|
|
$form->bind($req);
|
|
|
if ($form->isValid()) {
|
|
|
try {
|
|
|
- $user = $this->getUser();
|
|
|
- $package->addMaintainer($user);
|
|
|
$em = $this->getDoctrine()->getManager();
|
|
|
$em->persist($package);
|
|
|
$em->flush();
|
|
@@ -457,7 +462,7 @@ class WebController extends Controller
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return array('form' => $form->createView(), 'page' => 'submit', 'searchForm' => $this->createSearchForm()->createView());
|
|
|
+ return array('form' => $form->createView(), 'page' => 'submit');
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -469,6 +474,8 @@ class WebController extends Controller
|
|
|
$package->setEntityRepository($this->getDoctrine()->getRepository('PackagistWebBundle:Package'));
|
|
|
$package->setRouter($this->get('router'));
|
|
|
$form = $this->createForm(new PackageType, $package);
|
|
|
+ $user = $this->getUser();
|
|
|
+ $package->addMaintainer($user);
|
|
|
|
|
|
$response = array('status' => 'error', 'reason' => 'No data posted.');
|
|
|
if ('POST' === $req->getMethod()) {
|
|
@@ -537,8 +544,7 @@ class WebController extends Controller
|
|
|
'packages' => $packages,
|
|
|
'meta' => $this->getPackagesMetadata($packages),
|
|
|
'vendor' => $vendor,
|
|
|
- 'paginate' => false,
|
|
|
- 'searchForm' => $this->createSearchForm()->createView()
|
|
|
+ 'paginate' => false
|
|
|
);
|
|
|
}
|
|
|
|
|
@@ -584,8 +590,7 @@ class WebController extends Controller
|
|
|
'name' => $name,
|
|
|
'packages' => $providers,
|
|
|
'meta' => $this->getPackagesMetadata($providers),
|
|
|
- 'paginate' => false,
|
|
|
- 'searchForm' => $this->createSearchForm()->createView()
|
|
|
+ 'paginate' => false
|
|
|
));
|
|
|
}
|
|
|
|
|
@@ -662,10 +667,19 @@ class WebController extends Controller
|
|
|
$version = $versionRepo->getFullVersion(reset($versions)->getId());
|
|
|
}
|
|
|
|
|
|
+ $expandedVersion = reset($versions);
|
|
|
+ foreach ($versions as $v) {
|
|
|
+ if (!$v->isDevelopment()) {
|
|
|
+ $expandedVersion = $v;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
$data = array(
|
|
|
'package' => $package,
|
|
|
'version' => $version,
|
|
|
'versions' => $versions,
|
|
|
+ 'expandedVersion' => $expandedVersion,
|
|
|
);
|
|
|
|
|
|
try {
|
|
@@ -677,7 +691,6 @@ class WebController extends Controller
|
|
|
} catch (ConnectionException $e) {
|
|
|
}
|
|
|
|
|
|
- $data['searchForm'] = $this->createSearchForm()->createView();
|
|
|
if ($maintainerForm = $this->createAddMaintainerForm($package)) {
|
|
|
$data['addMaintainerForm'] = $maintainerForm->createView();
|
|
|
}
|
|
@@ -986,7 +999,6 @@ class WebController extends Controller
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- $data['searchForm'] = $this->createSearchForm()->createView();
|
|
|
return $data;
|
|
|
}
|
|
|
|
|
@@ -1042,7 +1054,6 @@ class WebController extends Controller
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- $data['searchForm'] = $this->createSearchForm()->createView();
|
|
|
return $data;
|
|
|
}
|
|
|
|
|
@@ -1149,15 +1160,6 @@ class WebController extends Controller
|
|
|
return new RedirectResponse('http://getcomposer.org/', 301);
|
|
|
}
|
|
|
|
|
|
- public function render($view, array $parameters = array(), Response $response = null)
|
|
|
- {
|
|
|
- if (!isset($parameters['searchForm'])) {
|
|
|
- $parameters['searchForm'] = $this->createSearchForm()->createView();
|
|
|
- }
|
|
|
-
|
|
|
- return parent::render($view, $parameters, $response);
|
|
|
- }
|
|
|
-
|
|
|
private function createAddMaintainerForm($package)
|
|
|
{
|
|
|
if (!$user = $this->getUser()) {
|
|
@@ -1210,8 +1212,156 @@ class WebController extends Controller
|
|
|
return $this->createFormBuilder(array())->getForm();
|
|
|
}
|
|
|
|
|
|
- private function createSearchForm()
|
|
|
+ /**
|
|
|
+ * Initializes the pager for a query.
|
|
|
+ *
|
|
|
+ * @param \Doctrine\ORM\QueryBuilder $query Query for packages
|
|
|
+ * @param int $page Pagenumber to retrieve.
|
|
|
+ * @return \Pagerfanta\Pagerfanta
|
|
|
+ */
|
|
|
+ protected function setupPager($query, $page)
|
|
|
+ {
|
|
|
+ $paginator = new Pagerfanta(new DoctrineORMAdapter($query, true));
|
|
|
+ $paginator->setMaxPerPage(15);
|
|
|
+ $paginator->setCurrentPage($page, false, true);
|
|
|
+
|
|
|
+ return $paginator;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param array $orderBys
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ protected function getFilteredOrderedBys(Request $req)
|
|
|
+ {
|
|
|
+ $orderBys = $req->query->get('orderBys', array());
|
|
|
+ if (!$orderBys) {
|
|
|
+ $orderBys = $req->query->get('search_query');
|
|
|
+ $orderBys = isset($orderBys['orderBys']) ? $orderBys['orderBys'] : array();
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($orderBys) {
|
|
|
+ $allowedSorts = array(
|
|
|
+ 'downloads' => 1,
|
|
|
+ 'favers' => 1
|
|
|
+ );
|
|
|
+
|
|
|
+ $allowedOrders = array(
|
|
|
+ 'asc' => 1,
|
|
|
+ 'desc' => 1,
|
|
|
+ );
|
|
|
+
|
|
|
+ $filteredOrderBys = array();
|
|
|
+
|
|
|
+ foreach ($orderBys as $orderBy) {
|
|
|
+ if (isset($orderBy['sort'])
|
|
|
+ && isset($allowedSorts[$orderBy['sort']])
|
|
|
+ && isset($orderBy['order'])
|
|
|
+ && isset($allowedOrders[$orderBy['order']])) {
|
|
|
+ $filteredOrderBys[] = $orderBy;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ $filteredOrderBys = array();
|
|
|
+ }
|
|
|
+
|
|
|
+ return $filteredOrderBys;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param array $orderBys
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ protected function getNormalizedOrderBys(array $orderBys)
|
|
|
+ {
|
|
|
+ $normalizedOrderBys = array();
|
|
|
+
|
|
|
+ foreach ($orderBys as $sort) {
|
|
|
+ $normalizedOrderBys[$sort['sort']] = $sort['order'];
|
|
|
+ }
|
|
|
+
|
|
|
+ return $normalizedOrderBys;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function getOrderBysViewModel(Request $req, $normalizedOrderBys)
|
|
|
{
|
|
|
- return $this->createForm(new SearchQueryType, new SearchQuery);
|
|
|
+ $makeDefaultArrow = function ($sort) use ($normalizedOrderBys) {
|
|
|
+ if (isset($normalizedOrderBys[$sort])) {
|
|
|
+ if (strtolower($normalizedOrderBys[$sort]) === 'asc') {
|
|
|
+ $val = 'icon-arrow-up';
|
|
|
+ } else {
|
|
|
+ $val = 'icon-arrow-down';
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ $val = '';
|
|
|
+ }
|
|
|
+
|
|
|
+ return $val;
|
|
|
+ };
|
|
|
+
|
|
|
+ $makeDefaultHref = function ($sort) use ($req, $normalizedOrderBys) {
|
|
|
+ if (isset($normalizedOrderBys[$sort])) {
|
|
|
+ if (strtolower($normalizedOrderBys[$sort]) === 'asc') {
|
|
|
+ $order = 'desc';
|
|
|
+ } else {
|
|
|
+ $order = 'asc';
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ $order = 'desc';
|
|
|
+ }
|
|
|
+
|
|
|
+ $query = $req->query->get('search_query');
|
|
|
+ $query = isset($query['query']) ? $query['query'] : '';
|
|
|
+
|
|
|
+ return '?' . http_build_query(array(
|
|
|
+ 'q' => $query,
|
|
|
+ 'orderBys' => array(
|
|
|
+ array(
|
|
|
+ 'sort' => $sort,
|
|
|
+ 'order' => $order
|
|
|
+ )
|
|
|
+ )
|
|
|
+ ));
|
|
|
+ };
|
|
|
+
|
|
|
+ return array(
|
|
|
+ 'downloads' => array(
|
|
|
+ 'title' => 'Sort by downloads',
|
|
|
+ 'class' => 'icon-download',
|
|
|
+ 'arrowClass' => $makeDefaultArrow('downloads'),
|
|
|
+ 'href' => $makeDefaultHref('downloads')
|
|
|
+ ),
|
|
|
+ 'favers' => array(
|
|
|
+ 'title' => 'Sort by favorites',
|
|
|
+ 'class' => 'icon-star',
|
|
|
+ 'arrowClass' => $makeDefaultArrow('favers'),
|
|
|
+ 'href' => $makeDefaultHref('favers')
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ private function computeSearchQuery(Request $req, array $filteredOrderBys)
|
|
|
+ {
|
|
|
+ // transform q=search shortcut
|
|
|
+ if ($req->query->has('q') || $req->query->has('orderBys')) {
|
|
|
+ $searchQuery = array();
|
|
|
+
|
|
|
+ $q = $req->query->get('q');
|
|
|
+
|
|
|
+ if ($q !== null) {
|
|
|
+ $searchQuery['query'] = $q;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!empty($filteredOrderBys)) {
|
|
|
+ $searchQuery['orderBys'] = $filteredOrderBys;
|
|
|
+ }
|
|
|
+
|
|
|
+ $req->query->set(
|
|
|
+ 'search_query',
|
|
|
+ $searchQuery
|
|
|
+ );
|
|
|
+ }
|
|
|
}
|
|
|
}
|