Commit 4d052607 authored by Marc Ducobu's avatar Marc Ducobu
Browse files

Merge branch 'master' of git://github.com/Chill-project/Main

parents 3a2a649e d94c6434
......@@ -3,7 +3,14 @@
namespace Chill\MainBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Chill\MainBundle\DependencyInjection\SearchableServicesCompilerPass;
class ChillMainBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new SearchableServicesCompilerPass());
}
}
<?php
/*
* Chill is a software for social workers
*
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Chill\MainBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
/**
*
*
* @author julien.fastre@champs-libres.coop
* @author marc@champs-libres.coop
*/
class SearchController extends Controller
{
public function searchAction(Request $request)
{
$searches = $this->get('chill.main.search_provider')->getByOrder();
$results = array();
foreach ($searches as $search ) {
$results[] = $search->renderResult($request->get('q'));
}
return $this->render('ChillMainBundle:Search:list.html.twig', array('results' => $results) );
}
}
\ No newline at end of file
<?php
/*
* Chill is a software for social workers
*
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Chill\MainBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;
class SearchableServicesCompilerPass implements CompilerPassInterface
{
/*
* (non-PHPdoc)
* @see \Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface::process()
*/
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('chill.main.search_provider')) {
throw new \LogicException('service chill.main.search_provider '
. 'is not defined.');
}
$definition = $container->getDefinition(
'chill.main.search_provider'
);
$taggedServices = $container->findTaggedServiceIds(
'chill.search'
);
$knownAliases = array();
foreach ($taggedServices as $id => $tagAttributes) {
foreach ($tagAttributes as $attributes) {
if (!isset($attributes["alias"])) {
throw new \LogicException("the 'name' attribute is missing in your ".
"service '$id' definition");
}
if (array_search($attributes["alias"], $knownAliases)) {
throw new \LogicException("There is already a chill.search service with alias "
.$attributes["alias"].". Choose another alias.");
}
$knownAliases[] = $attributes["alias"];
$definition->addMethodCall(
'addSearchService',
array(new Reference($id), $attributes["alias"])
);
}
}
}
}
\ No newline at end of file
......@@ -28,6 +28,10 @@ chill_main_admin_central:
order: 20
label: Admin Menu
icons: [gears]
chill_main_search:
pattern: /{_locale}/person/search
defaults: { _controller: ChillMainBundle:Search:search }
login:
path: /login
......
......@@ -54,3 +54,7 @@ services:
- "@request_stack"
tags:
- { name: form.type, alias: select2_chill_country }
chill.main.search_provider:
class: Chill\MainBundle\Search\SearchProvider
Search a person: Rechercher une personne
Search: Rechercher
'Search persons, ...': 'Recherche des personnes, ...'
Person name: Nom / Prénom de la personne
Login: Connexion
Logout: Se déconnecter
......
......@@ -35,7 +35,7 @@
<input type="password" name="_password" />
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}" />
<br/>
<button type="submit">{{ 'Login'|trans }}</button>
<button type="submit" name="login">{{ 'Login'|trans }}</button>
</form>
......
{#
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
{% extends "ChillMainBundle::layout.html.twig" %}
{% block content %}
{% for result in results %}
{{ result|raw }}
{% endfor %}
{% endblock %}
\ No newline at end of file
......@@ -32,8 +32,8 @@
</ul>
</div>
<div class="grid-4 navigation-search">
<form action="{{ path('chill_person_search') }}" method="get">
<input name="q" type="search" placeholder="{{ 'Search a person'|trans }}" />
<form action="{{ path('chill_main_search') }}" method="get">
<input name="q" type="search" placeholder="{{ 'Search'|trans }}" />
<button type="submit" class="sc-button white border"><i class="fa fa-search"></i></button>
</form>
</div>
......@@ -98,12 +98,12 @@
{% block content %}
<div class="container">
<div class="grid-8 centered">
<h2>{{ 'Search a person'|trans }}</h2>
<h2>{{ 'Search'|trans }}</h2>
<form action="{{ path('chill_person_search') }}" method="get">
<input name="q" type="search" placeholder="{{ 'Person name'|trans }}" />
<form action="{{ path('chill_main_search') }}" method="get">
<input name="q" type="search" placeholder="{{ 'Search persons, ...'|trans }}" />
<center>
<button type="submit" class="sc-button orange"><i class="fa fa-search"></i> {{ 'Search a person'|trans }}</button>
<button type="submit" class="sc-button orange"><i class="fa fa-search"></i> {{ 'Search'|trans }}</button>
</center>
</form>
</div>
......
<?php
/*
*
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Chill\MainBundle\Search;
use Chill\MainBundle\Search\SearchInterface;
/**
* This class implements abstract search with most common responses.
*
* you should use this abstract class instead of SearchInterface : if the signature of
* search interface change, the generic method will be implemented here.
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*
*/
abstract class AbstractSearch implements SearchInterface
{
}
\ No newline at end of file
<?php
/*
*
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Chill\MainBundle\Search;
/**
* This interface must be implemented on services which provide search results.
*
* @todo : write doc and add a link to documentation
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*
*/
interface SearchInterface #-> good name ?
{
/*
* return the result in a html string. The string will be inclued (as raw)
* into a global view.
*
* The global view may be :
* {% for result as resultsFromDifferentSearchInterface %}
* {{ result|raw }}
* {% endfor %}
*
* @param string $pattern the string to search
* @param int $start the first result (for pagination)
* @param int $limit the number of result (for pagination)
* @param array $option the options, specific for each search
* @return string, an HTML string
*/
public function renderResult($pattern, $start=0, $limit=50, array $options = array());
/*
* we may desactive the search interface by default. in this case,
* the search will be launch and rendered only with "advanced search"
*
* this may be activated/desactived from bundle definition in config.yml
*
* @return boolean
*/
public function isActiveByDefault();
/*
* a string used in advanced search to activate the search
*
* @return string a string which will be translated by twig
*/
public function getLabel();
/*
* the order in which the results will appears in the global view
*
* (this may be eventually defined in config.yml)
*
* @return int
*/
public function getOrder();
}
<?php
namespace Chill\MainBundle\Search;
use Chill\MainBundle\Search\SearchInterface;
/**
* a service which gather all search services defined into the bundles
* installed into the app.
* the service is callable from the container with
* $container->get('chill.main.search_provider')
*/
class SearchProvider
{
/**
*
* @var SearchInterface[]
*/
private $searchServices = array();
/*
* return search services in an array, ordered by
* the order key (defined in service definition)
* the conflicts in keys (twice the same order) are resolved
* within the compiler : the function will preserve all services
* defined (if two services have the same order, the will increment
* the order of the second one.
*
* @return SearchInterface[], with an int as array key
*/
public function getByOrder()
{
//sort the array
uasort($this->searchServices, function(SearchInterface $a, SearchInterface $b) {
if ($a->getOrder() == $b->getOrder()) {
return 0;
}
return ($a->getOrder() < $b->getOrder()) ? -1 : 1;
});
return $this->searchServices;
}
/*
* return search services with a specific name, defined in service
* definition.
*
* @return SearchInterface
*/
public function getByName($name)
{
return $this->searchServices[$name];
}
public function addSearchService(SearchInterface $service, $name)
{
$this->searchServices[$name] = $service;
}
}
\ No newline at end of file
......@@ -9,13 +9,21 @@ class LoginControllerTest extends WebTestCase
{
public function testLogin()
{
$client = static::createClient();
$client = static::createClient(array(
'framework' => array(
'default_locale' => 'en',
'translator' => array(
'fallback' => 'en'
)
),
));
//load login page and submit form
$crawler = $client->request('GET', '/login');
$this->assertTrue($client->getResponse()->isSuccessful());
$buttonCrawlerNode = $crawler->selectButton('Login');
$buttonCrawlerNode = $crawler->selectButton('login');
$form = $buttonCrawlerNode->form();
$client->submit($form, array(
......@@ -40,7 +48,7 @@ class LoginControllerTest extends WebTestCase
$logoutLinkFilter = $crawler->filter('a:contains("Logout")');
//check there is > 0 logout link
$this->assertGreaterThan(0, $logoutLinkFilter->count());
$this->assertGreaterThan(0, $logoutLinkFilter->count(), 'check that a logout link is present');
//click on logout link
$client->followRedirects(false);
......
......@@ -7,8 +7,8 @@ framework:
form: true
csrf_protection: true
session: ~
default_locale: fr
translator: { fallback: fr }
default_locale: en
translator: { fallback: en }
profiler: { only_exceptions: false }
templating:
engines: ['twig']
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment