Przeglądaj źródła

create stubs for the solarium package indexing command and the search controller

Igor Wiedler 13 lat temu
rodzic
commit
3a34c139f8

+ 86 - 0
src/Packagist/WebBundle/Command/IndexPackagesCommand.php

@@ -0,0 +1,86 @@
+<?php
+
+/*
+ * This file is part of Packagist.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *     Nils Adermann <naderman@naderman.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Packagist\WebBundle\Command;
+
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * @author Igor Wiedler <igor@wiedler.ch>
+ */
+class IndexPackagesCommand extends ContainerAwareCommand
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function configure()
+    {
+        $this
+            ->setName('packagist:index')
+            ->setDefinition(array(
+                new InputOption('force', null, InputOption::VALUE_NONE, 'Force a re-indexing of all packages'),
+                new InputOption('package', null, InputOption::VALUE_NONE, 'Package name to index (implicitly enables --force)'),
+            ))
+            ->setDescription('Indexes packages')
+            ->setHelp(<<<EOF
+
+EOF
+            )
+        ;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        $verbose = $input->getOption('verbose');
+        $doctrine = $this->getContainer()->get('doctrine');
+        $solarium = $this->getContainer()->get('solarium.client');
+
+        if ($input->getOption('package')) {
+            $packages = array($doctrine->getRepository('PackagistWebBundle:Package')->findOneByName($input->getOption('package')));
+        } elseif ($input->getOption('force')) {
+            $packages = $doctrine->getRepository('PackagistWebBundle:Package')->findAll();
+        } else {
+            // TODO: query for unindexed packages
+            $packages = $doctrine->getRepository('PackagistWebBundle:Package')->getStalePackages();
+        }
+
+        foreach ($packages as $package) {
+            if ($verbose) {
+                $output->writeln('Indexing '.$package->getName());
+            }
+
+            try {
+                $update = $solarium->createUpdate();
+
+                $document = $update->createDocument();
+                $document->id = $package->getId();
+                $document->name = $package->getName();
+                $document->description = $package->getDescription();
+
+                $update->addDocument($document);
+                $update->addCommit();
+
+                $result = $solarium->update($update);
+
+                var_dump($result->getStatus());
+            } catch (\Exception $e) {
+                $output->writeln('<error>Exception: '.$e->getMessage().', skipping package '.$package->getName().'.</error>');
+            }
+        }
+    }
+}

+ 44 - 0
src/Packagist/WebBundle/Controller/WebController.php

@@ -14,6 +14,8 @@ namespace Packagist\WebBundle\Controller;
 
 use Packagist\WebBundle\Form\Type\AddMaintainerRequestType;
 use Packagist\WebBundle\Form\Model\AddMaintainerRequest;
+use Packagist\WebBundle\Form\Type\SearchQueryType;
+use Packagist\WebBundle\Form\Model\SearchQuery;
 use Symfony\Bundle\FrameworkBundle\Controller\Controller;
 use Packagist\WebBundle\Entity\Package;
 use Packagist\WebBundle\Entity\Version;
@@ -24,6 +26,7 @@ use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
 use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
+use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
 use Symfony\Component\Security\Core\Exception\AccessDeniedException;
 use Pagerfanta\Pagerfanta;
 use Pagerfanta\Adapter\DoctrineORMAdapter;
@@ -76,6 +79,47 @@ class WebController extends Controller
         return $this->render('PackagistWebBundle:Web:browse.html.twig', array('packages' => $paginator));
     }
 
+    /**
+     * @Template()
+     * @Route("/search/", name="search")
+     */
+    public function searchAction(Request $req)
+    {
+        $searchQuery = new SearchQuery;
+        $form = $this->createForm(new SearchQueryType, $searchQuery);
+
+        if ('POST' === $req->getMethod()) {
+            $form->bindRequest($req);
+            if ($form->isValid()) {
+                $solarium = $this->get('solarium.client');
+
+                $query = $solarium->createSelect();
+                $query->setQuery($searchQuery->getQuery());
+
+                $resultset = $solarium->select($query);
+
+                $packageIds = array_map(
+                    function ($document) {
+                        return $document->id;
+                    },
+                    iterator_to_array($resultset)
+                );
+
+                $packages = $this->getDoctrine()
+                    ->getRepository('PackagistWebBundle:Package')
+                    ->findByIds($packageIds);
+
+                $paginator = new Pagerfanta(new DoctrineORMAdapter($packages, true));
+                $paginator->setMaxPerPage(15);
+                $paginator->setCurrentPage($req->query->get('page', 1), false, true);
+
+                return $this->render('PackagistWebBundle:Web:search.html.twig', array('packages' => $paginator, 'form' => $form->createView()));
+            }
+        }
+
+        return $this->render('PackagistWebBundle:Web:search.html.twig', array('form' => $form->createView()));
+    }
+
     /**
      * @Template()
      * @Route("/packages/submit", name="submit")

+ 9 - 0
src/Packagist/WebBundle/Entity/PackageRepository.php

@@ -47,6 +47,15 @@ class PackageRepository extends EntityRepository
             ->setParameters(array($name));
     }
 
+    public function findByIds(array $ids)
+    {
+        $qb = $this->getBaseQueryBuilder();
+
+        return $qb->where(
+            $qb->expr()->in('p.id', $ids)
+        );
+    }
+
     public function getQueryBuilderByMaintainer(User $user)
     {
         $qb = $this->getBaseQueryBuilder()

+ 28 - 0
src/Packagist/WebBundle/Form/Model/SearchQuery.php

@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of Packagist.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *     Nils Adermann <naderman@naderman.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Packagist\WebBundle\Form\Model;
+
+class SearchQuery
+{
+    protected $query;
+
+    public function setQuery($query)
+    {
+        $this->query = $query;
+    }
+
+    public function getQuery()
+    {
+        return $this->query;
+    }
+}

+ 39 - 0
src/Packagist/WebBundle/Form/Type/SearchQueryType.php

@@ -0,0 +1,39 @@
+<?php
+
+/*
+ * This file is part of Packagist.
+ *
+ * (c) Jordi Boggiano <j.boggiano@seld.be>
+ *     Nils Adermann <naderman@naderman.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Packagist\WebBundle\Form\Type;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormBuilder;
+
+/**
+ * @author Igor Wiedler <igor@wiedler.ch>
+ */
+class SearchQueryType extends AbstractType
+{
+    public function buildForm(FormBuilder $builder, array $options)
+    {
+        $builder->add('query');
+    }
+
+    public function getDefaultOptions(array $options)
+    {
+        return array(
+            'data_class' => 'Packagist\WebBundle\Form\Model\SearchQuery',
+        );
+    }
+
+    public function getName()
+    {
+        return 'search_query';
+    }
+}

+ 21 - 0
src/Packagist/WebBundle/Resources/views/Web/search.html.twig

@@ -0,0 +1,21 @@
+{% extends "PackagistWebBundle:Web:list.html.twig" %}
+
+{% block content %}
+    <div class="box clearfix">
+        <h1>Search packages</h1>
+        <form id="search-form" action="{{ path('search') }}" method="POST" {{ form_enctype(form) }}>
+            <div>
+                <p>
+                    {{ form_errors(form.query) }}
+                    {{ form_widget(form.query) }}
+                </p>
+                {{ form_rest(form) }}
+                <input id="submit" type="submit" value="Search" />
+            </div>
+        </form>
+    </div>
+
+    {% if packages is defined %}
+        {{ parent() }}
+    {% endif %}
+{% endblock %}