Merge branch 'master' into notification/completion

This commit is contained in:
Mathieu Jaumotte 2022-01-05 11:15:49 +01:00
commit 1e0c62b09d
45 changed files with 474 additions and 217 deletions

View File

@ -11,6 +11,15 @@ and this project adheres to
## Unreleased
<!-- write down unreleased development here -->
* [household] change translations (champs-libres/departement-de-la-vendee/accent-suivi-developpement#109)
* [household] add address i18n in household component (champs-libres/departement-de-la-vendee/accent-suivi-developpement#158)
* [household] add on the fly i18n in household component
* [household] redirect to the household page when a household is created from a person (champs-libres/departement-de-la-vendee/accent-suivi-developpement#175)
* [household] household member editor: display alert if some members have already an household (champs-libres/departement-de-la-vendee/accent-suivi-developpement#172)
* [household] household member editor: do not add in new members if the member is included in the members of household (champs-libres/departement-de-la-vendee/accent-suivi-developpement#123)
* [household] household member editor: remove markNoAddress button (champs-libres/departement-de-la-vendee/accent-suivi-developpement#109)
* [person]: ordering fields in add person (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/61)
* [person]: Add email and alt names in add person (https://gitlab.com/champs-libres/departement-de-la-vendee/accent-suivi-developpement/-/issues/61)
* AddAddress: optimize loading: wait for the user finish typing;
* UserPicker: fix bug with deprecated role
* docgen: add base context + tests
@ -25,6 +34,7 @@ and this project adheres to
* Household: show date validFrom and validTo when moving
* address reference: add index for refid
* [accompanyingCourse_work] fix styles conflicts + fix bug with remove goal (remove goals one at a time)
* [accompanyingCourse] improve masonry on resume page, add origin
## Test releases

View File

@ -1,22 +1,22 @@
{
"name": "chill-project/chill-bundles",
"type": "library",
"description": "Most used bundles for chill-project",
"license": "AGPL-3.0-only",
"type": "library",
"keywords": [
"chill",
"social worker"
],
"license": "AGPL-3.0-only",
"require": {
"php": "^7.4",
"champs-libres/async-uploader-bundle": "dev-sf4#d57134aee8e504a83c902ff0cf9f8d36ac418290",
"champs-libres/wopi-bundle": "dev-master#59b468503b9413f8d588ef9e626e7675560db3d8",
"champs-libres/wopi-lib": "dev-master#0e1da19bb6de820080b8651867a7e475be590060",
"doctrine/doctrine-bundle": "^2.1",
"doctrine/doctrine-migrations-bundle": "^3.0",
"doctrine/orm": "^2.7",
"erusev/parsedown": "^1.7",
"graylog2/gelf-php": "^1.5",
"knplabs/knp-menu": "^3.1",
"knplabs/knp-menu-bundle": "^3.0",
"knplabs/knp-time-bundle": "^1.12",
"league/csv": "^9.7.1",
@ -31,6 +31,7 @@
"symfony/css-selector": "^4.4",
"symfony/expression-language": "^4.4",
"symfony/form": "^4.4",
"symfony/framework-bundle": "^4.4",
"symfony/intl": "^4.4",
"symfony/mailer": "^5.4",
"symfony/mime": "^4.4",
@ -67,8 +68,7 @@
"symfony/phpunit-bridge": "^4.4",
"symfony/stopwatch": "^4.4",
"symfony/var-dumper": "^4.4",
"symfony/web-profiler-bundle": "^4.4",
"vimeo/psalm": "^4.15"
"symfony/web-profiler-bundle": "^4.4"
},
"config": {
"bin-dir": "bin",
@ -107,8 +107,19 @@
"Chill\\DocGeneratorBundle\\Tests\\": "src/Bundle/ChillDocGeneratorBundle/tests"
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"config": {
"allow-plugins": {
"composer/package-versions-deprecated": true,
"phpstan/extension-installer": true,
"ergebnis/composer-normalize": true,
"phpro/grumphp": true,
"ocramius/package-versions": true
},
"bin-dir": "bin",
"optimize-autoloader": true,
"sort-packages": true,
"vendor-dir": "tests/app/vendor"
},
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",

View File

@ -859,11 +859,6 @@ parameters:
count: 1
path: src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverEvent.php
-
message: "#^Call to deprecated method setTimeout\\(\\) of class Redis\\.$#"
count: 1
path: src/Bundle/ChillMainBundle/Security/PasswordRecover/PasswordRecoverLocker.php
-
message:
"""

View File

@ -66,7 +66,7 @@ final class ActivityReasonCategoryControllerTest extends WebTestCase
$crawler = $client->followRedirect();
// Check the entity has been delete on the list
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
$this->assertDoesNotMatchRegularExpression('/Foo/', $client->getResponse()->getContent());
}
*/

View File

@ -66,7 +66,7 @@ final class ActivityReasonControllerTest extends WebTestCase
$crawler = $client->followRedirect();
// Check the entity has been delete on the list
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
$this->assertDoesNotMatchRegularExpression('/Foo/', $client->getResponse()->getContent());
}
*/

View File

@ -66,7 +66,7 @@ final class ActivityTypeControllerTest extends WebTestCase
$crawler = $client->followRedirect();
// Check the entity has been delete on the list
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
$this->assertDoesNotMatchRegularExpression('/Foo/', $client->getResponse()->getContent());
}
*/

View File

@ -33,11 +33,11 @@ final class ConfigCustomizablesEntitiesTest extends KernelTestCase
$customizableEntities = self::$kernel->getContainer()
->getParameter('chill_custom_fields.customizables_entities');
$this->assertInternalType('array', $customizableEntities);
$this->assertIsArray($customizableEntities);
$this->assertCount(2, $customizableEntities);
foreach ($customizableEntities as $key => $config) {
$this->assertInternalType('array', $config);
$this->assertIsArray($config);
$this->assertArrayHasKey('name', $config);
$this->assertArrayHasKey('class', $config);
}
@ -56,7 +56,7 @@ final class ConfigCustomizablesEntitiesTest extends KernelTestCase
$customizableEntities = self::$kernel->getContainer()
->getParameter('chill_custom_fields.customizables_entities');
$this->assertInternalType('array', $customizableEntities);
$this->assertIsArray($customizableEntities);
$this->assertCount(1, $customizableEntities);
}
}

View File

@ -61,7 +61,7 @@ final class CustomFieldControllerTest_TODO extends WebTestCase
$crawler = $client->followRedirect();
// Check the entity has been delete on the list
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
$this->assertDoesNotMatchRegularExpression('/Foo/', $client->getResponse()->getContent());
}
*/

View File

@ -66,7 +66,7 @@ final class EventControllerTest extends WebTestCase
$crawler = $client->followRedirect();
// Check the entity has been delete on the list
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
$this->assertDoesNotMatchRegularExpression('/Foo/', $client->getResponse()->getContent());
}
*/

View File

@ -66,7 +66,7 @@ final class EventTypeControllerTest extends WebTestCase
$crawler = $client->followRedirect();
// Check the entity has been delete on the list
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
$this->assertDoesNotMatchRegularExpression('/Foo/', $client->getResponse()->getContent());
}
*/

View File

@ -66,7 +66,7 @@ final class RoleControllerTest extends WebTestCase
$crawler = $client->followRedirect();
// Check the entity has been delete on the list
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
$this->assertDoesNotMatchRegularExpression('/Foo/', $client->getResponse()->getContent());
}
*/

View File

@ -66,7 +66,7 @@ final class StatusControllerTest extends WebTestCase
$crawler = $client->followRedirect();
// Check the entity has been delete on the list
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
$this->assertDoesNotMatchRegularExpression('/Foo/', $client->getResponse()->getContent());
}
*/

View File

@ -140,8 +140,7 @@ abstract class AbstractAggregatorTest extends KernelTestCase
{
$filter = $this->getAggregator();
$this->assertInternalType(
'string',
$this->assertIsString(
$filter->applyOn(),
'test that the internal type of "applyOn" is a string'
);
@ -160,8 +159,7 @@ abstract class AbstractAggregatorTest extends KernelTestCase
{
$queryKeys = $this->getAggregator()->getQueryKeys($data);
$this->assertInternalType(
'array',
$this->assertIsArray(
$queryKeys,
'test that the query keys returned are an array'
);
@ -252,7 +250,7 @@ abstract class AbstractAggregatorTest extends KernelTestCase
{
$title = $this->getAggregator()->getTitle();
$this->assertInternalType('string', $title);
$this->assertIsString($title);
$this->assertNotEmpty(
$title,
'test that the title is not empty'

View File

@ -151,8 +151,7 @@ abstract class AbstractExportTest extends WebTestCase
{
$export = $this->getExport();
$this->assertInternalType(
'string',
$this->assertIsString(
$export->getDescription(),
'Assert that the `getDescription` method return a string'
);
@ -214,8 +213,7 @@ abstract class AbstractExportTest extends WebTestCase
$results = $this->getExport()->getResult($query, $data);
$this->assertInternalType(
'array',
$this->assertIsArray(
$results,
'assert that the returned result is an array'
);
@ -271,8 +269,7 @@ abstract class AbstractExportTest extends WebTestCase
{
$export = $this->getExport();
$this->assertInternalType(
'string',
$this->assertIsString(
$export->getType(),
'Assert that the `getType` method return a string'
);

View File

@ -126,7 +126,7 @@ abstract class AbstractFilterTest extends KernelTestCase
{
$filter = $this->getFilter();
$this->assertInternalType('string', $filter->applyOn());
$this->assertIsString($filter->applyOn());
}
/**
@ -149,8 +149,7 @@ abstract class AbstractFilterTest extends KernelTestCase
'test that the description is not empty'
);
} elseif (is_array($description)) {
$this->assertInternalType(
'string',
$this->assertIsString(
$description[0],
'test that the first element in the description array is a string'
);
@ -191,7 +190,7 @@ abstract class AbstractFilterTest extends KernelTestCase
{
$title = $this->getFilter()->getTitle();
$this->assertInternalType('string', $title);
$this->assertIsString($title);
$this->assertNotEmpty(
$title,
'test that the title is not empty'

View File

@ -72,6 +72,6 @@ final class CenterControllerTest extends WebTestCase
$crawler = $client->request('GET', '/fr/admin/center/');
// Check the entity has been delete on the list
$this->assertRegExp('/Foo/', $client->getResponse()->getContent());
$this->assertMatchesRegularExpression('/Foo/', $client->getResponse()->getContent());
}
}

View File

@ -40,7 +40,7 @@ final class LoginControllerTest extends WebTestCase
$this->assertTrue($client->getResponse()->isRedirect());
//the response is not a login page, but on a new page
$this->assertNotRegExp('/\/login$/', $client->getResponse()
$this->assertDoesNotMatchRegularExpression('/\/login$/', $client->getResponse()
->headers
->get('location'));
@ -48,7 +48,7 @@ final class LoginControllerTest extends WebTestCase
$client->followRedirects(true);
$crawler = $client->request('GET', '/');
$this->assertRegExp('/center a_social/', $client->getResponse()
$this->assertMatchesRegularExpression('/center a_social/', $client->getResponse()
->getContent());
$logoutLinkFilter = $crawler->filter('a:contains("Se déconnecter")');
@ -63,7 +63,7 @@ final class LoginControllerTest extends WebTestCase
$client->followRedirect(); //redirect to login page
//check we are back on login page
$this->assertRegExp('/\/login$/', $client->getResponse()
$this->assertMatchesRegularExpression('/\/login$/', $client->getResponse()
->headers
->get('location'));
}

View File

@ -66,7 +66,7 @@ final class PermissionsGroupControllerTest extends WebTestCase
$crawler = $client->followRedirect();
// Check the entity has been delete on the list
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
$this->assertDoesNotMatchRegularExpression('/Foo/', $client->getResponse()->getContent());
}
*/

View File

@ -48,7 +48,7 @@ final class TokenManagerTest extends KernelTestCase
$tokens = $tokenManager->generate($user, $expiration);
$this->assertInternalType('array', $tokens);
$this->assertIsArray($tokens);
$this->assertArrayHasKey('h', $tokens);
$this->assertArrayHasKey('t', $tokens);
$this->assertNotEmpty($tokens['h']);

View File

@ -48,6 +48,6 @@ final class MenuComposerTest extends KernelTestCase
$routes = $this->menuComposer->getRoutesFor('dummy0');
$this->assertInternalType('array', $routes);
$this->assertIsArray($routes);
}
}

View File

@ -11,8 +11,6 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Config;
use function count;
/**
* Give help to interact with the config for alt names.
*/
@ -69,6 +67,6 @@ class ConfigPersonAltNamesHelper
*/
public function hasAltNames(): bool
{
return count($this->config) > 0;
return [] !== $this->config;
}
}

View File

@ -14,23 +14,52 @@ namespace Chill\PersonBundle\Controller;
use Chill\MainBundle\CRUD\Controller\ApiController;
use Chill\MainBundle\Entity\Address;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use function array_filter;
use function array_values;
use function in_array;
class PersonApiController extends ApiController
{
private AuthorizationHelper $authorizationHelper;
public function __construct(AuthorizationHelper $authorizationHelper)
{
private ConfigPersonAltNamesHelper $configPersonAltNameHelper;
public function __construct(
AuthorizationHelper $authorizationHelper,
ConfigPersonAltNamesHelper $configPersonAltNameHelper
) {
$this->authorizationHelper = $authorizationHelper;
$this->configPersonAltNameHelper = $configPersonAltNameHelper;
}
/**
* @Route("/api/1.0/person/config/alt_names.{_format}",
* name="chill_person_config_alt_names",
* requirements={
* "_format": "json"
* }
* )
*/
public function configAltNames(Request $request, string $_format): Response
{
$configAltNamesChoices = $this->configPersonAltNameHelper->getChoices();
return $this->json(
array_map(
static fn (array $data, string $key): array => ['key' => $key, 'labels' => $data],
$configAltNamesChoices,
array_keys($configAltNamesChoices)
),
Response::HTTP_OK,
[],
['groups' => ['read']]
);
}
public function personAddressApi($id, Request $request, string $_format): Response
@ -51,22 +80,51 @@ class PersonApiController extends ApiController
{
$this->denyAccessUnlessGranted(PersonVoter::SEE, $person);
$addresses = [];
$seenAddressIds = [];
// collect addresses from location in courses
foreach ($person->getAccompanyingPeriodParticipations() as $participation) {
if (null !== $participation->getAccompanyingPeriod()->getAddressLocation()) {
$a = $participation->getAccompanyingPeriod()->getAddressLocation();
$addresses[$a->getId()] = $a;
$addresses = $person
->getAccompanyingPeriodParticipations()
->filter(
static function (AccompanyingPeriodParticipation $accompanyingPeriodParticipation): bool {
return null !== $accompanyingPeriodParticipation->getAccompanyingPeriod()->getAddressLocation();
}
)
->map(
static function (AccompanyingPeriodParticipation $accompanyingPeriodParticipation): ?Address {
return $accompanyingPeriodParticipation->getAccompanyingPeriod()->getAddressLocation();
}
)
->filter(
// We remove potential null addresses.
static fn (?Address $address): bool => null !== $address
)
->filter(
static function (Address $address) use (&$seenAddressIds): bool {
$id = $address->getId();
if (in_array($id, $seenAddressIds, true)) {
return false;
}
$seenAddressIds[] = $id;
return true;
}
);
// remove the actual address
$actual = $person->getCurrentHouseholdAddress();
if (null !== $actual) {
$addresses = array_filter($addresses, static fn ($a) => $a !== $actual);
$addresses = $addresses->filter(static fn (Address $address): bool => $address !== $actual);
}
return $this->json(array_values($addresses), Response::HTTP_OK, [], ['groups' => ['read']]);
return $this->json(
$addresses->getValues(),
Response::HTTP_OK,
[],
['groups' => ['read']]
);
}
}

View File

@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* PersonAltName.
@ -34,6 +35,7 @@ class PersonAltName
* @var string
*
* @ORM\Column(name="key", type="string", length=255)
* @Groups({"write"})
*/
private $key;
@ -41,6 +43,7 @@ class PersonAltName
* @var string
*
* @ORM\Column(name="label", type="text")
* @Groups({"write"})
*/
private $label;

View File

@ -254,3 +254,24 @@ abbr.referrer { // still used ?
border: 1px solid black;
padding: 10px;
}
/// Masonry blocs on AccompanyingCourse resume page
div#dashboards {
div.mbloc {
& > div:not(.warnings) {
border: 1px solid $chill-light-gray;
background-color: $chill-llight-gray;
border-radius: 0.35rem;
padding: 1rem;
}
& > div.warnings .alert {
margin-bottom: 0;
}
blockquote.chill-user-quote {
margin: -1.2em;
p {
margin: 0;
}
}
}
}

View File

@ -33,7 +33,7 @@ const fetchHouseholdSuggestionByAccompanyingPeriod = (personId) => {
throw Error ({m: 'Error while fetching household suggestion', status: response.status});
}).then(data => Promise.resolve(data.results))
.catch(e => console.err(e));
.catch(e => console.error(e));
;
};

View File

@ -9,7 +9,7 @@
<div v-else>
<p>
{{ $t('household_members_editor.concerned.persons_will_be_moved') }}&nbsp;:
<span v-for="c in concerned">
<span v-for="c in concerned" :key=c.person.id>
<person-render-box render="badge" :options="{addLink: false}" :person="c.person"></person-render-box>
<button class="btn" @click="removePerson(c.person)" v-if="c.allowRemove" style="padding-left:0;">
<span class="fa-stack fa-lg" :title="$t('household_members_editor.concerned.remove_concerned')">
@ -19,6 +19,17 @@
</button>
</span>
</p>
<div class="alert alert-info" v-if="concernedPersonsWithHouseholds.length > 0">
<p>{{ $t('household_members_editor.concerned.persons_with_household') }}</p>
<ul v-for="c in concernedPersonsWithHouseholds" :key=c.person.id>
<li>
{{ c.person.text }}
{{ $t('household_members_editor.concerned.already_belongs_to_household') }}
<a target="_blank" :href="this.makeHouseholdLink(c.person.current_household_id)">{{c.person.current_household_id}}</a>.
</li>
</ul>
</div>
</div>
<ul class="record_actions">
@ -59,7 +70,7 @@ export default {
},
computed: {
...mapState([
'concerned'
'concerned', 'household'
]),
...mapGetters([
'persons',
@ -67,6 +78,15 @@ export default {
noPerson () {
return this.$store.getters.persons.length === 0;
},
concernedPersonsWithHouseholds () {
if (this.$store.state.household) {
return this.$store.state.concerned.filter(c =>
c.person.current_household_id !== null && c.person.current_household_id !== this.$store.state.household.id
)
} else {
return [];
}
}
},
data() {
return {
@ -92,6 +112,9 @@ export default {
console.log('remove person in concerned', person);
this.$store.dispatch('removePerson', person);
},
makeHouseholdLink(id) {
return `/fr/person/household/${id}/summary`
}
}
}
</script>

View File

@ -2,11 +2,11 @@
<current-household></current-household>
<ul class="record_actions">
<li v-if="!hasHouseholdAddress && !isHouseholdForceAddress">
<!-- <li v-if="!hasHouseholdAddress && !isHouseholdForceAddress">
<button class="btn btn-misc" @click="markNoAddress">
{{ $t('household_members_editor.household_address.mark_no_address') }}
</button>
</li>
</li> -->
<li v-if="!hasHouseholdAddress">
<add-address
:context="getAddressContext"

View File

@ -1,3 +1,4 @@
import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n';
import { ontheflyMessages } from 'ChillMainAssets/vuejs/OnTheFly/i18n';
import { addressMessages } from 'ChillMainAssets/vuejs/Address/i18n';
@ -35,7 +36,7 @@ const appMessages = {
create_new_address: "Créer une nouvelle adresse",
},
concerned: {
title: "Usagers déplacés",
title: "Usager(s) à (re)positionner dans un ménage",
persons_will_be_moved: "Les usagers suivants vont être déplacés",
add_at_least_onePerson: "Indiquez au moins un usager à déplacer",
remove_concerned: "Ne plus transférer",
@ -45,6 +46,8 @@ const appMessages = {
move_to: "Déplacer vers",
persons_leaving: "Usagers quittant leurs ménages",
no_person_in_position: "Aucun usager ne sera ajouté à cette position",
persons_with_household: "Les usagers suivants sont associés à ces ménages:",
already_belongs_to_household: "est associé au ménage"
},
positioning: {
persons_to_positionnate: 'Usagers à positionner',

View File

@ -224,6 +224,7 @@ const store = createStore({
}
state.concerned.forEach((c, index) => {
if (!(h.members.map((m) => m.person.id)).includes(c.person.id)) {
let m = {
id: index * -1,
person: c.person,
@ -236,6 +237,8 @@ const store = createStore({
}
}
h.new_members.push(m);
}
})
console.log('fake household', h);
@ -307,7 +310,7 @@ const store = createStore({
comment: "",
});
} else {
console.err("person already included");
console.error("person already included");
}
},
markPosition(state, { person_id, position_id}) {
@ -533,11 +536,15 @@ const store = createStore({
// nothing to do anymore here, bye-bye !
let params = new URLSearchParams(window.location.search);
if (params.has('followAfter')) {
window.location.replace(`/fr/person/household/${household_id}/summary`);
} else {
if (params.has('returnPath')) {
window.location.replace(params.get('returnPath'));
} else {
window.location.replace(`/fr/person/household/${household_id}/summary`);
}
}
} else {
// we assume the answer was 422...
error = household;

View File

@ -10,6 +10,13 @@ const getPerson = (id) => {
});
};
const getPersonAltNames = () =>
fetch('/api/1.0/person/config/alt_names.json').then(response => {
if (response.ok) { return response.json(); }
throw Error('Error with request resource response');
});;
/*
* POST a new person
*/
@ -48,6 +55,7 @@ const patchPerson = (id, body) => {
export {
getPerson,
getPersonAltNames,
postPerson,
patchPerson
};

View File

@ -21,14 +21,19 @@
<div v-else-if="action === 'edit' || action === 'create'">
<div class="form-floating mb-3">
<input class="form-control form-control-lg" id="lastname" v-model="lastName" v-bind:placeholder="$t('person.lastname')" />
<label for="lastname">{{ $t('person.lastname') }}</label>
</div>
<div class="form-floating mb-3">
<input class="form-control form-control-lg" id="firstname" v-model="firstName" v-bind:placeholder="$t('person.firstname')" />
<label for="firstname">{{ $t('person.firstname') }}</label>
</div>
<div class="form-floating mb-3">
<input class="form-control form-control-lg" id="lastname" v-model="lastName" v-bind:placeholder="$t('person.lastname')" />
<label for="lastname">{{ $t('person.lastname') }}</label>
<div v-for="(a) in config.altNames" :key="a.key" class="form-floating mb-3">
<input class="form-control form-control-lg" :id="a.key" @input="onAltNameInput" />
<label :for="a.key">{{ a.labels.fr }}</label>
</div>
<!-- TODO fix placeholder if undefined
@ -71,11 +76,20 @@
aria-describedby="mobilenumber" />
</div>
<div class="input-group mb-3">
<span class="input-group-text" id="email"><i class="fa fa-fw fa-at"></i></span>
<input class="form-control form-control-lg"
v-model="email"
v-bind:placeholder="$t('person.email')"
v-bind:aria-label="$t('person.email')"
aria-describedby="email" />
</div>
</div>
</template>
<script>
import { getPerson } from '../../_api/OnTheFly';
import { getPerson, getPersonAltNames } from '../../_api/OnTheFly';
import PersonRenderBox from '../Entity/PersonRenderBox.vue';
export default {
@ -88,13 +102,19 @@ export default {
data() {
return {
person: {
type: 'person'
}
type: 'person',
altNames: []
},
config: {
altNames: []
},
}
},
computed: {
firstName: {
set(value) { this.person.firstName = value; },
set(value) {
this.person.firstName = value;
},
get() { return this.person.firstName; }
},
lastName: {
@ -125,6 +145,10 @@ export default {
set(value) { this.person.mobilenumber = value; },
get() { return this.person.mobilenumber; }
},
email: {
set(value) { this.person.email = value; },
get() { return this.person.email; }
},
genderClass() {
switch (this.person.gender) {
case 'woman':
@ -150,6 +174,10 @@ export default {
}
},
mounted() {
getPersonAltNames()
.then(altNames => {
this.config.altNames = altNames;
});
if (this.action !== 'create') {
this.loadData();
}
@ -162,7 +190,16 @@ export default {
console.log('get person', this.person);
resolve();
}));
}
},
onAltNameInput(event) {
const key = event.target.id;
const label = event.target.value;
let updateAltNames = this.person.altNames.filter((a) => a.key !== key);
updateAltNames.push(
{'key': key, 'label': label}
)
this.person.altNames = updateAltNames;
},
}
}
</script>

View File

@ -30,6 +30,7 @@ const personMessages = {
phonenumber: "Téléphone",
mobilenumber: "Mobile",
altnames: "Autres noms",
email: "Courriel",
gender: {
title: "Genre",
placeholder: "Choisissez le genre de l'usager",

View File

@ -29,29 +29,37 @@
{{ chill_list_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', accompanyingCourse.id) }}
<div id="dashboards" class="row" data-masonry='{"percentPosition": true }'>
<div id="dashboards" class="row g-3" data-masonry='{"percentPosition": true }'>
{% if 'DRAFT' == accompanyingCourse.step %}
<div class="col-4 warnings mb-4">
<div class="mbloc col col-sm-6 col-lg-4">
<div class="warnings">
{% include '@ChillPerson/AccompanyingCourse/_still_draft.html.twig' %}
</div>
</div>
{% endif %}
{% if 'DRAFT' != accompanyingCourse.step %}
{% if withoutHousehold|length > 0 %}
<div class="col-4 warnings mb-4">
<div class="mbloc col col-sm-6 col-lg-4">
<div class="warnings">
{% include '@ChillPerson/AccompanyingCourse/_join_household.html.twig' %}
</div>
</div>
{% endif %}
{% endif %}
{% if accompanyingCourse.locationStatus == 'address'
or accompanyingCourse.locationStatus == 'none' %}
<div class="col-4 warnings mb-4">
<div class="mbloc col col-sm-6 col-lg-4">
<div class="warnings">
{% include '@ChillPerson/AccompanyingCourse/_warning_address.html.twig' %}
</div>
</div>
{% endif %}
<div class="col col-sm-6 col-lg-4 location mb-4">
<div class="mbloc col col-sm-6 col-lg-4">
<div class="location">
{% if accompanyingCourse.locationStatus == 'person' %}
<h2>{{ 'This course is located by'|trans }}</h2>
<h4>{{ accompanyingCourse.personLocation|chill_entity_render_string }}</h4>
@ -63,34 +71,15 @@
{{ accompanyingCourse.location|chill_entity_render_box }}
{% endif %}
</div>
{% if accompanyingCourse.participations is not empty %}
<div class="col col-sm-6 col-lg-4 persons mb-4">
<h4 class="item-key">{{ 'Persons associated'|trans }}</h4>
{% for r in accompanyingCourse.participations %}
{{ _self.insert_onthefly('person', r.person) }}
{% endfor %}
</div>
{% endif %}
{% if accompanyingCourse.resources is not empty %}
<div class="col col-sm-6 col-lg-4 resources mb-4">
<h4 class="item-key">{{ 'Resources'|trans }}</h4>
{% for r in accompanyingCourse.resources %}
{% if r.person is not null %}
{{ _self.insert_onthefly('person', r.person) }}
{% elseif r.thirdParty is not null %}
{{ _self.insert_onthefly('thirdparty', r.thirdParty) }}
{% endif %}
{% endfor %}
</div>
{% endif %}
{% if accompanyingCourse.pinnedComment is not empty %}
<div class="col col-sm-6 col-lg-4 comment mb-4">
<h4 class="item-key">{{ 'Pinned comment'|trans }}</h4>
<div class="mbloc col col-sm-6 col-lg-8">
<div class="comment">
<h4 class="item-key visually-hidden">{{ 'Pinned comment'|trans }}</h4>
<blockquote class="chill-user-quote">
{{ accompanyingCourse.pinnedComment.content }}
<i class="fa fa-flag float-end text-chill-gray" title="{{ 'pinned'|trans }}"></i>
{{ accompanyingCourse.pinnedComment.content|chill_markdown_to_html }}
<div class="metadata">
{{ 'Last updated by'| trans }}
<span class="user">
@ -103,10 +92,38 @@
</div>
</blockquote>
</div>
</div>
{% endif %}
{% if accompanyingCourse.participations is not empty %}
<div class="mbloc col col-sm-6 col-lg-4">
<div class="persons">
<h4 class="item-key">{{ 'Persons associated'|trans }}</h4>
{% for r in accompanyingCourse.participations %}
{{ _self.insert_onthefly('person', r.person) }}
{% endfor %}
</div>
</div>
{% endif %}
{% if accompanyingCourse.resources is not empty %}
<div class="mbloc col col-sm-6 col-lg-4">
<div class="resources">
<h4 class="item-key">{{ 'Resources'|trans }}</h4>
{% for r in accompanyingCourse.resources %}
{% if r.person is not null %}
{{ _self.insert_onthefly('person', r.person) }}
{% elseif r.thirdParty is not null %}
{{ _self.insert_onthefly('thirdparty', r.thirdParty) }}
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
{% if accompanyingCourse.scopes is not empty %}
<div class="col col-sm-6 col-lg-4 scopes mb-4">
<div class="mbloc col col-sm-6 col-lg-4">
<div class="scopes">
<h4 class="item-key">{{ 'Scopes'|trans }}</h4>
<div>
{% for s in accompanyingCourse.scopes %}
@ -114,6 +131,7 @@
{% endfor %}
</div>
</div>
</div>
{% endif %}
<div class="col col-sm-4 col-lg-4 notify mb-4">
@ -121,7 +139,8 @@
</div>
{% if accompanyingCourse.requestorPerson is not null or accompanyingCourse.requestorThirdParty is not null %}
<div class="col col-sm-6 col-lg-4 requestor mb-4">
<div class="mbloc col col-sm-6 col-lg-4">
<div class="requestor">
{% if accompanyingCourse.requestorPerson is not null %}
<h4 class="item-key">{{ 'Requestor'|trans }}</h4>
{{ _self.insert_onthefly('person', accompanyingCourse.requestorPerson) }}
@ -130,7 +149,18 @@
{{ _self.insert_onthefly('thirdparty', accompanyingCourse.requestorThirdParty) }}
{% endif %}
</div>
</div>
{% endif %}
{% if accompanyingCourse.origin is not empty %}
<div class="mbloc col col-sm-6 col-lg-4">
<div class="origin">
<h4 class="item-key">{{ 'Origin'|trans }}</h4>
{{ accompanyingCourse.origin.label|localize_translatable_string|capitalize }}
</div>
</div>
{% endif %}
</div>
<div class="social-actions my-4">

View File

@ -124,7 +124,7 @@
{% if not person.isSharingHousehold() %}
<ul class="record_actions">
<li>
<a class="btn btn-misc" href="{{ chill_path_add_return_path('chill_person_household_members_editor', { 'persons': [ person.id ]}) }}">
<a class="btn btn-misc" href="{{chill_path_add_return_path('chill_person_household_members_editor', { 'persons': [ person.id ], 'followAfter': 'true'}) }}">
<i class="fa fa-sign-in fa-fw"></i>
{{ 'household.Join'|trans }}
</a>

View File

@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Serializer\Normalizer;
use Chill\DocGeneratorBundle\Serializer\Helper\NormalizeNullValueHelper;
use Chill\MainBundle\Entity\Address;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Security\Resolver\ScopeResolverDispatcher;
@ -65,6 +66,8 @@ class AccompanyingPeriodDocGenNormalizer implements ContextAwareNormalizerInterf
'requestorPerson' => Person::class,
'requestorThirdParty' => ThirdParty::class,
'resources' => Collection::class,
'location' => Address::class,
'locationPerson' => Person::class,
];
private ClosingMotiveRender $closingMotiveRender;
@ -104,6 +107,7 @@ class AccompanyingPeriodDocGenNormalizer implements ContextAwareNormalizerInterf
$scopes = [$scopes];
}
$addressContext = array_merge($context, ['docgen:expects' => Address::class, 'groups' => 'docgen:read']);
$dateContext = array_merge($context, ['docgen:expects' => DateTime::class, 'groups' => 'docgen:read']);
$userContext = array_merge($context, ['docgen:expects' => User::class, 'groups' => 'docgen:read']);
$participationContext = array_merge($context, ['docgen:expects' => AccompanyingPeriodParticipation::class, 'groups' => 'docgen:read']);
@ -147,6 +151,10 @@ class AccompanyingPeriodDocGenNormalizer implements ContextAwareNormalizerInterf
}, $scopes)),
'hasRequestor' => $period->getRequestor() !== null,
'requestorKind' => $period->getRequestorKind(),
'hasLocation' => $period->getLocation() !== null,
'hasLocationPerson' => $period->getPersonLocation() !== null,
'locationPerson' => $this->normalizer->normalize($period->getPersonLocation(), $format, array_merge($context, ['docgen:expects' => Person::class])),
'location' => $this->normalizer->normalize($period->getLocation(), $format, $addressContext),
];
}
@ -162,6 +170,8 @@ class AccompanyingPeriodDocGenNormalizer implements ContextAwareNormalizerInterf
'hasRequestorThirdParty' => false,
'isClosed' => false,
'confidential' => false,
'hasLocation' => false,
'hasLocationPerson' => false,
]
);
}

View File

@ -15,10 +15,11 @@ use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\PersonAltName;
use Chill\PersonBundle\Repository\PersonRepository;
use DateTime;
use DateTimeImmutable;
use LogicException;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
@ -78,13 +79,24 @@ class PersonJsonNormalizer implements
$person = new Person();
}
foreach (['firstName', 'lastName', 'phonenumber', 'mobilenumber', 'gender',
'birthdate', 'deathdate', 'center', ]
as $item) {
if (!array_key_exists($item, $data)) {
continue;
}
$fields = [
'firstName',
'lastName',
'phonenumber',
'mobilenumber',
'gender',
'birthdate',
'deathdate',
'center',
'altNames',
];
$fields = array_filter(
$fields,
static fn (string $field): bool => array_key_exists($field, $data)
);
foreach ($fields as $item) {
switch ($item) {
case 'firstName':
$person->setFirstName($data[$item]);
@ -131,8 +143,23 @@ class PersonJsonNormalizer implements
break;
default:
throw new LogicException("item not defined: {$item}");
case 'altNames':
foreach ($data[$item] as $altName) {
$oldAltName = $person
->getAltNames()
->filter(static fn (PersonAltName $n): bool => $n->getKey() === $altName['key'])->first();
if (false === $oldAltName) {
$newAltName = new PersonAltName();
$newAltName->setKey($altName['key']);
$newAltName->setLabel($altName['label']);
$person->addAltName($newAltName);
} else {
$oldAltName->setLabel($altName['label']);
}
}
break;
}
}
@ -175,14 +202,22 @@ class PersonJsonNormalizer implements
return $data instanceof Person && 'json' === $format;
}
protected function normalizeAltNames($altNames): array
/**
* @param Collection<array-key, PersonAltName> $altNames
*
* @return array<array-key, array<string, string>>
*/
protected function normalizeAltNames(Collection $altNames): array
{
$r = [];
foreach ($altNames as $n) {
$r[] = ['key' => $n->getKey(), 'label' => $n->getLabel()];
return $altNames
->map(
static function (PersonAltName $personAltName): array {
return [
'key' => $personAltName->getKey(),
'label' => $personAltName->getLabel(),
];
}
return $r;
)
->toArray();
}
}

View File

@ -11,7 +11,6 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Tests\AccompanyingPeriod;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\User;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
@ -45,13 +44,13 @@ final class AccompanyingPeriodConfidentialTest extends WebTestCase
public function dataGenerateRandomAccompanyingCourse()
{
// Disabling this dataprovider to avoid having errors while running the test.
return yield from [];
$maxGenerated = 3;
$maxResults = $maxGenerated * 8;
self::bootKernel();
$em = self::$kernel->getContainer()->get('doctrine.orm.entity_manager');
$center = $em->getRepository(Center::class)
->findOneBy(['name' => 'Center A']);
$qb = $em->createQueryBuilder();
$personIds = $qb
@ -80,8 +79,7 @@ final class AccompanyingPeriodConfidentialTest extends WebTestCase
while ($nbGenerated < $maxGenerated) {
$id = array_pop($personIds)['id'];
$person = $em->getRepository(Person::class)
->find($id);
$person = $em->getRepository(Person::class)->find($id);
$periods = $person->getAccompanyingPeriods();
yield [array_pop($personIds)['id'], $periods[array_rand($periods)]->getId()];
@ -95,6 +93,10 @@ final class AccompanyingPeriodConfidentialTest extends WebTestCase
*/
public function testRemoveUserWhenConfidential(int $periodId)
{
$this->markTestIncomplete(
'Marked as incomplete because of a problem in the dataprovider, at line 81.'
);
$period = self::$container->get(AccompanyingPeriodRepository::class)
->find($periodId);
$em = self::$kernel->getContainer()->get('doctrine.orm.entity_manager');

View File

@ -111,7 +111,7 @@ final class PersonAddressControllerTest extends WebTestCase
$crawler = $this->client->followRedirect();
$this->assertRegexp(
$this->assertMatchesRegularExpression(
'|/fr/person/[0-9]{1,}/address/list|',
$this->client->getHistory()->current()->getUri(),
'assert that the current page is on |/fr/person/[0-9]{1,}/address/list|'
@ -169,7 +169,7 @@ final class PersonAddressControllerTest extends WebTestCase
$crawler = $this->client->followRedirect();
$this->assertRegexp(
$this->assertMatchesRegularExpression(
'|/fr/person/[0-9]{1,}/address/list|',
$this->client->getHistory()->current()->getUri(),
'assert that the current page is on |/fr/person/[0-9]{1,}/address/list|'

View File

@ -206,7 +206,7 @@ final class PersonControllerCreateTest extends WebTestCase
$client->followRedirect();
// visualize regexp here : http://jex.im/regulex/#!embed=false&flags=&re=%2Ffr%2Fperson%2F[1-9][0-9]*%2Fgeneral%2Fedit%24
$this->assertRegExp(
$this->assertMatchesRegularExpression(
'|/fr/person/[1-9][0-9]*/general/edit$|',
$client->getHistory()->current()->getUri(),
'a valid form redirect to url /{_locale}/person/{personId}/general/edit'
@ -259,7 +259,7 @@ final class PersonControllerCreateTest extends WebTestCase
'a valid form redirect to url /{_locale}/person/{personId}/general/edit'
);
$client->followRedirect();
$this->assertRegExp(
$this->assertMatchesRegularExpression(
'|/fr/person/[1-9][0-9]*/general/edit$|',
$client->getHistory()->current()->getUri(),
'a valid form redirect to url /{_locale}/person/{personId}/general/edit'

View File

@ -26,19 +26,19 @@ final class PersonSearchTest extends WebTestCase
$this->markTestSkipped('skipped until adapted to new fixtures');
$crawlerSpecial = $this->generateCrawlerForSearch('@person manço');
$this->assertRegExp('/MANÇO/', $crawlerSpecial->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/MANÇO/', $crawlerSpecial->filter('.list-with-period')->text());
$crawlerNoSpecial = $this->generateCrawlerForSearch('@person manco');
$this->assertRegExp('/MANÇO/', $crawlerNoSpecial->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/MANÇO/', $crawlerNoSpecial->filter('.list-with-period')->text());
$crawlerSpecial = $this->generateCrawlerForSearch('@person Étienne');
$this->assertRegExp('/Étienne/', $crawlerSpecial->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/Étienne/', $crawlerSpecial->filter('.list-with-period')->text());
$crawlerNoSpecial = $this->generateCrawlerForSearch('@person etienne');
$this->assertRegExp('/Étienne/', $crawlerNoSpecial->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/Étienne/', $crawlerNoSpecial->filter('.list-with-period')->text());
}
public function testExpected()
@ -49,7 +49,7 @@ final class PersonSearchTest extends WebTestCase
'q' => '@person Depardieu',
]);
$this->assertRegExp('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
}
public function testExpectedNamed()
@ -60,79 +60,79 @@ final class PersonSearchTest extends WebTestCase
'q' => '@person Depardieu', 'name' => 'person_regular',
]);
$this->assertRegExp('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
}
public function testLastNameAccentued()
{
$crawlerSpecial = $this->generateCrawlerForSearch('@person lastname:manço');
$this->assertRegExp('/MANÇO/', $crawlerSpecial->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/MANÇO/', $crawlerSpecial->filter('.list-with-period')->text());
$crawlerNoSpecial = $this->generateCrawlerForSearch('@person lastname:manco');
$this->assertRegExp('/MANÇO/', $crawlerNoSpecial->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/MANÇO/', $crawlerNoSpecial->filter('.list-with-period')->text());
}
public function testSearchBirthdate()
{
$crawler = $this->generateCrawlerForSearch('@person birthdate:1948-12-27');
$this->assertRegExp('/Gérard/', $crawler->filter('.list-with-period')->text());
$this->assertRegExp('/Bart/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/Gérard/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/Bart/', $crawler->filter('.list-with-period')->text());
}
public function testSearchByFirstName()
{
$crawler = $this->generateCrawlerForSearch('@person firstname:Jean');
$this->assertRegExp('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
}
public function testSearchByFirstNameAccented()
{
$crawlerSpecial = $this->generateCrawlerForSearch('@person firstname:Gérard');
$this->assertRegExp('/Gérard/', $crawlerSpecial->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/Gérard/', $crawlerSpecial->filter('.list-with-period')->text());
$crawlerNoSpecial = $this->generateCrawlerForSearch('@person firstname:Gerard');
$this->assertRegExp('/Gérard/', $crawlerNoSpecial->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/Gérard/', $crawlerNoSpecial->filter('.list-with-period')->text());
}
public function testSearchByFirstNameLower()
{
$crawler = $this->generateCrawlerForSearch('@person firstname:Gérard');
$this->assertRegExp('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
}
public function testSearchByFirstNameLower2()
{
$crawler = $this->generateCrawlerForSearch('@person firstname:jean');
$this->assertRegExp('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
}
public function testSearchByFirstNamePartim()
{
$crawler = $this->generateCrawlerForSearch('@person firstname:Ger');
$this->assertRegExp('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
}
public function testSearchByFirstNamePartim2()
{
$crawler = $this->generateCrawlerForSearch('@person firstname:ean');
$this->assertRegExp('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
}
public function testSearchByLastName()
{
$crawler = $this->generateCrawlerForSearch('@person lastname:Depardieu');
$this->assertRegExp('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
}
public function testSearchCombineBirthdateAndLastName()
@ -140,8 +140,8 @@ final class PersonSearchTest extends WebTestCase
$this->markTestSkipped('skipped until adapted to new fixtures');
$crawler = $this->generateCrawlerForSearch('@person birthdate:1948-12-27 lastname:(Van Snick)');
$this->assertRegExp('/Bart/', $crawler->filter('.list-with-period')->text());
$this->assertNotRegExp('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/Bart/', $crawler->filter('.list-with-period')->text());
$this->assertDoesNotMatchRegularExpression('/DEPARDIEU/', $crawler->filter('.list-with-period')->text());
}
public function testSearchCombineGenderAndLastName()
@ -149,8 +149,8 @@ final class PersonSearchTest extends WebTestCase
$this->markTestSkipped('skipped until adapted to new fixtures');
$crawler = $this->generateCrawlerForSearch('@person gender:woman lastname:(Depardieu)');
$this->assertRegExp('/Charline/', $crawler->filter('.list-with-period')->text());
$this->assertNotRegExp('/Gérard/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/Charline/', $crawler->filter('.list-with-period')->text());
$this->assertDoesNotMatchRegularExpression('/Gérard/', $crawler->filter('.list-with-period')->text());
}
public function testSearchCombineLastnameAndFirstName()
@ -158,9 +158,9 @@ final class PersonSearchTest extends WebTestCase
$this->markTestSkipped('skipped until adapted to new fixtures');
$crawler = $this->generateCrawlerForSearch('@person lastname:Depardieu firstname:Jean');
$this->assertRegExp('/Depardieu/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/Depardieu/', $crawler->filter('.list-with-period')->text());
//if this is a AND clause, Jean Depardieu should not appears
$this->assertNotRegExp(
$this->assertDoesNotMatchRegularExpression(
'/Gérard/',
$crawler->filter('.list-with-period')->text(),
'assert clause firstname and nationality are AND'
@ -172,9 +172,9 @@ final class PersonSearchTest extends WebTestCase
$this->markTestSkipped('skipped until adapted to new fixtures');
$crawler = $this->generateCrawlerForSearch('@person lastname:Depardieu nationality:RU');
$this->assertRegExp('/Gérard/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/Gérard/', $crawler->filter('.list-with-period')->text());
//if this is a AND clause, Jean Depardieu should not appears
$this->assertNotRegExp(
$this->assertDoesNotMatchRegularExpression(
'/Jean/',
$crawler->filter('.list-with-period')->text(),
'assert clause firstname and nationality are AND'
@ -186,9 +186,9 @@ final class PersonSearchTest extends WebTestCase
$this->markTestSkipped('skipped until adapted to new fixtures');
$crawler = $this->generateCrawlerForSearch('@person cha dep');
$this->assertRegExp('/Charline/', $crawler->filter('.list-with-period')->text());
$this->assertNotRegExp('/Gérard/', $crawler->filter('.list-with-period')->text());
$this->assertNotRegExp('/Jean/', $crawler->filter('.list-with-period')->text());
$this->assertMatchesRegularExpression('/Charline/', $crawler->filter('.list-with-period')->text());
$this->assertDoesNotMatchRegularExpression('/Gérard/', $crawler->filter('.list-with-period')->text());
$this->assertDoesNotMatchRegularExpression('/Jean/', $crawler->filter('.list-with-period')->text());
}
/**
@ -199,12 +199,12 @@ final class PersonSearchTest extends WebTestCase
$crawlerCanSee = $this->generateCrawlerForSearch('Gérard', 'center a_social');
$crawlerCannotSee = $this->generateCrawlerForSearch('Gérard', 'center b_social');
$this->assertRegExp(
$this->assertMatchesRegularExpression(
'/DEPARDIEU/',
$crawlerCanSee->text(),
'center a_social may see "Depardieu" in center a'
);
$this->assertNotRegExp(
$this->assertDoesNotMatchRegularExpression(
'/DEPARDIEU/',
$crawlerCannotSee->text(),
'center b_social may not see "Depardieu" in center b'

View File

@ -1820,3 +1820,12 @@ paths:
description: "Unauthorized"
200:
description: "OK"
/1.0/person/config/alt_names.json:
get:
tags:
- person
summary: Return a list of possible altNames that are defined in the config
responses:
200:
description: "OK"

View File

@ -44,6 +44,7 @@ services:
Chill\PersonBundle\Controller\PersonApiController:
arguments:
$authorizationHelper: '@Chill\MainBundle\Security\Authorization\AuthorizationHelper'
$configPersonAltNameHelper: '@Chill\PersonBundle\Config\ConfigPersonAltNamesHelper'
tags: ['controller.service_arguments']
Chill\PersonBundle\Controller\AccompanyingCourseWorkApiController:

View File

@ -215,6 +215,7 @@ Some peoples does not belong to any household currently. Add them to an househol
Add to household now: Ajouter à un ménage
Any resource for this accompanying course: Aucun interlocuteur privilégié pour ce parcours
course.draft: Brouillon
Origin: Origine de la demande
# pickAPersonType
Pick a person: Choisir une personne

View File

@ -212,7 +212,7 @@ final class ReportControllerTest extends WebTestCase
$linkSee = $crawler->filter('.bt-view')->links();
$this->assertGreaterThan(0, count($linkSee));
$this->assertRegExp(sprintf(
$this->assertMatchesRegularExpression(sprintf(
'|/fr/person/%s/report/[0-9]*/view$|',
self::$person->getId(),
$reportId
@ -220,7 +220,7 @@ final class ReportControllerTest extends WebTestCase
$linkUpdate = $crawler->filter('.bt-update')->links();
$this->assertGreaterThan(0, count($linkUpdate));
$this->assertRegExp(sprintf(
$this->assertMatchesRegularExpression(sprintf(
'|/fr/person/%s/report/[0-9]*/edit$|',
self::$person->getId(),
$reportId
@ -372,7 +372,7 @@ final class ReportControllerTest extends WebTestCase
);
$client->followRedirect();
$this->assertRegExp(
$this->assertMatchesRegularExpression(
'|/fr/person/' . self::$person->getId() . '/report/[0-9]*/view$|',
$client->getHistory()->current()->getUri(),
"The next page is a redirection to the new report's view page"

View File

@ -43,7 +43,7 @@ final class ReportSearchTest extends WebTestCase
]);
$this->assertTrue($client->getResponse()->isSuccessful());
$this->assertRegExp('/Situation de logement/i', $crawler->text());
$this->assertMatchesRegularExpression('/Situation de logement/i', $crawler->text());
}
public function testSearchDoubleDate()
@ -77,7 +77,7 @@ final class ReportSearchTest extends WebTestCase
]);
$this->assertTrue($client->getResponse()->isSuccessful());
$this->assertRegExp('/Situation de logement/i', $crawler->text());
$this->assertMatchesRegularExpression('/Situation de logement/i', $crawler->text());
}
/**