mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-10-15 09:49:41 +00:00
Compare commits
8 Commits
43-wopi-us
...
export-202
Author | SHA1 | Date | |
---|---|---|---|
01790fa0cf
|
|||
582983f5ef
|
|||
1f48900434
|
|||
91494c07d5
|
|||
c05d153029
|
|||
5fea61c450
|
|||
e7ac8aafe1
|
|||
99455ca685
|
@@ -9,22 +9,18 @@
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4",
|
||||
"ext-json": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-redis": "*",
|
||||
"champs-libres/async-uploader-bundle": "dev-sf4#d57134aee8e504a83c902ff0cf9f8d36ac418290",
|
||||
"champs-libres/wopi-bundle": "dev-master@dev",
|
||||
"champs-libres/wopi-lib": "dev-master@dev",
|
||||
"champs-libres/wopi-bundle": "dev-master#6dd8e0a14e00131eb4b889ecc30270ee4a0e5224",
|
||||
"champs-libres/wopi-lib": "dev-master#8615f4a45a39fc2b6a98765ea835fcfd39618787",
|
||||
"doctrine/doctrine-bundle": "^2.1",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.0",
|
||||
"doctrine/orm": "^2.13.0",
|
||||
"doctrine/orm": "^2.7",
|
||||
"erusev/parsedown": "^1.7",
|
||||
"graylog2/gelf-php": "^1.5",
|
||||
"knplabs/knp-menu-bundle": "^3.0",
|
||||
"knplabs/knp-time-bundle": "^1.12",
|
||||
"knpuniversity/oauth2-client-bundle": "^2.10",
|
||||
"league/csv": "^9.7.1",
|
||||
"lexik/jwt-authentication-bundle": "^2.16",
|
||||
"nyholm/psr7": "^1.4",
|
||||
"ocramius/package-versions": "^1.10 || ^2",
|
||||
"odolbeau/phone-number-bundle": "^3.6",
|
||||
@@ -33,12 +29,12 @@
|
||||
"ramsey/uuid-doctrine": "^1.7",
|
||||
"sensio/framework-extra-bundle": "^5.5",
|
||||
"spomky-labs/base64url": "^2.0",
|
||||
"symfony/asset": "^4.4",
|
||||
"symfony/browser-kit": "^4.4",
|
||||
"symfony/css-selector": "^4.4",
|
||||
"symfony/expression-language": "^4.4",
|
||||
"symfony/form": "^4.4",
|
||||
"symfony/framework-bundle": "^4.4",
|
||||
"symfony/http-client": "^4.4 || ^5",
|
||||
"symfony/http-foundation": "^4.4",
|
||||
"symfony/intl": "^4.4",
|
||||
"symfony/mailer": "^5.4",
|
||||
@@ -76,7 +72,8 @@
|
||||
"symfony/maker-bundle": "^1.20",
|
||||
"symfony/phpunit-bridge": "^4.4",
|
||||
"symfony/stopwatch": "^4.4",
|
||||
"symfony/var-dumper": "^4.4"
|
||||
"symfony/var-dumper": "^4.4",
|
||||
"symfony/web-profiler-bundle": "^4.4"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/symfony": "*"
|
||||
|
@@ -60,7 +60,7 @@ class ByCreatorAggregator implements AggregatorInterface
|
||||
return 'Created by';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -65,7 +65,7 @@ class BySocialActionAggregator implements AggregatorInterface
|
||||
return 'Social action';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -65,7 +65,7 @@ class BySocialIssueAggregator implements AggregatorInterface
|
||||
return 'Social issues';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -65,7 +65,7 @@ class ByThirdpartyAggregator implements AggregatorInterface
|
||||
return 'Accepted thirdparty';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -65,7 +65,7 @@ class CreatorScopeAggregator implements AggregatorInterface
|
||||
return 'Scope';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -65,11 +65,13 @@ class LocationTypeAggregator implements AggregatorInterface
|
||||
return 'Accepted locationtype';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$lt = $this->locationTypeRepository->find($value);
|
||||
if (null === $lt = $this->locationTypeRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
$lt->getTitle()
|
||||
|
@@ -71,7 +71,7 @@ class ActivityTypeAggregator implements AggregatorInterface
|
||||
return 'Activity type';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -66,7 +66,7 @@ class ActivityUserAggregator implements AggregatorInterface
|
||||
return 'Activity user';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -64,7 +64,7 @@ class ActivityUsersAggregator implements AggregatorInterface
|
||||
return 'Activity users';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -63,7 +63,7 @@ class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorI
|
||||
return 'Users \'s job';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -63,7 +63,7 @@ class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\Aggregato
|
||||
return 'Users \'s scope';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -134,6 +134,10 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
|
||||
return 'reasons' === $data['level'] ? 'Group by reasons' : 'Group by categories of reason';
|
||||
}
|
||||
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
switch ($data['level']) {
|
||||
case 'reasons':
|
||||
$r = $this->activityReasonRepository->find($value);
|
||||
|
@@ -57,6 +57,7 @@ class SentReceivedAggregator implements AggregatorInterface
|
||||
|
||||
switch ($value) {
|
||||
case null:
|
||||
case '':
|
||||
return '';
|
||||
|
||||
case 'sent':
|
||||
|
@@ -17,11 +17,9 @@ use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class ActivityTypeFilter implements FilterInterface
|
||||
{
|
||||
@@ -44,14 +42,13 @@ class ActivityTypeFilter implements FilterInterface
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('activity', $qb->getAllAliases(), true)) {
|
||||
$qb->join(Activity::class, 'activity', Expr\Join::WITH, 'activity.accompanyingPeriod = acp');
|
||||
}
|
||||
|
||||
$clause = $qb->expr()->in('activity.activityType', ':selected_activity_types');
|
||||
|
||||
$qb->andWhere($clause);
|
||||
$qb->setParameter('selected_activity_types', $data['types']);
|
||||
$qb->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . Activity::class . ' act_type_filter_activity
|
||||
WHERE act_type_filter_activity.activityType IN (:act_type_filter_activity_types) AND act_type_filter_activity.accompanyingPeriod = acp'
|
||||
)
|
||||
);
|
||||
$qb->setParameter('act_type_filter_activity_types', $data['accepted_activitytypes']);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
|
@@ -66,6 +66,10 @@ final class AgentAggregator implements AggregatorInterface
|
||||
return 'Agent';
|
||||
}
|
||||
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$r = $this->userRepository->find($value);
|
||||
|
||||
return $this->userRender->renderString($r, []);
|
||||
|
@@ -67,6 +67,10 @@ class CancelReasonAggregator implements AggregatorInterface
|
||||
return 'Cancel reason';
|
||||
}
|
||||
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$j = $this->cancelReasonRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
|
@@ -66,6 +66,10 @@ final class JobAggregator implements AggregatorInterface
|
||||
return 'Job';
|
||||
}
|
||||
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$j = $this->jobRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
|
@@ -60,6 +60,10 @@ final class LocationAggregator implements AggregatorInterface
|
||||
return 'Location';
|
||||
}
|
||||
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$l = $this->locationRepository->find($value);
|
||||
|
||||
return $l->getName();
|
||||
|
@@ -66,7 +66,13 @@ final class LocationTypeAggregator implements AggregatorInterface
|
||||
return 'Location type';
|
||||
}
|
||||
|
||||
$j = $this->locationTypeRepository->find($value);
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (null === $j = $this->locationTypeRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
$j->getTitle()
|
||||
|
@@ -66,6 +66,10 @@ final class ScopeAggregator implements AggregatorInterface
|
||||
return 'Scope';
|
||||
}
|
||||
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$s = $this->scopeRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
|
@@ -60,7 +60,7 @@ final class StoredObjectManager implements StoredObjectManagerInterface
|
||||
$this
|
||||
->tempUrlGenerator
|
||||
->generate(
|
||||
Request::METHOD_HEAD,
|
||||
Request::METHOD_PUT,
|
||||
$document->getFilename()
|
||||
)
|
||||
->url
|
||||
|
@@ -15,7 +15,7 @@ use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
|
||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
@@ -31,7 +31,7 @@ use function in_array;
|
||||
* "user": User::class
|
||||
* })
|
||||
*/
|
||||
class User implements UserInterface
|
||||
class User implements AdvancedUserInterface
|
||||
{
|
||||
/**
|
||||
* @ORM\Id
|
||||
@@ -58,6 +58,8 @@ class User implements UserInterface
|
||||
private ?Location $currentLocation = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=150, nullable=true)
|
||||
*/
|
||||
private ?string $email = null;
|
||||
@@ -214,7 +216,7 @@ class User implements UserInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<GroupCenter>
|
||||
* @return GroupCenter
|
||||
*/
|
||||
public function getGroupCenters()
|
||||
{
|
||||
@@ -223,8 +225,10 @@ class User implements UserInterface
|
||||
|
||||
/**
|
||||
* Get id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getId(): int
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
@@ -483,7 +487,7 @@ class User implements UserInterface
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return User
|
||||
* @return Agent
|
||||
*/
|
||||
public function setUsername($name)
|
||||
{
|
||||
|
@@ -11,6 +11,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Security\Authorization;
|
||||
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
|
@@ -11,6 +11,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Security\Authorization;
|
||||
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
|
||||
interface AuthorizationHelperForCurrentUserInterface
|
||||
{
|
||||
/**
|
||||
|
@@ -65,7 +65,7 @@ class AdministrativeLocationAggregator implements AggregatorInterface
|
||||
return 'Administrative location';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -60,7 +60,7 @@ class ClosingMotiveAggregator implements AggregatorInterface
|
||||
return 'Closing motive';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -65,7 +65,7 @@ class CreatorJobAggregator implements AggregatorInterface
|
||||
return 'export.aggregator.course.by_creator_job.Creator\'s job';
|
||||
}
|
||||
|
||||
if (null === $value || null === $j = $this->jobRepository->find($value)) {
|
||||
if (null === $value || '' === $value || null === $j = $this->jobRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -69,7 +69,7 @@ final class EvaluationAggregator implements AggregatorInterface
|
||||
return 'Evaluation';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -143,7 +143,7 @@ final class GeographicalUnitStatAggregator implements AggregatorInterface
|
||||
return 'acp_geog_agg_unitname';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -65,7 +65,7 @@ final class JobAggregator implements AggregatorInterface
|
||||
return 'Job';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -67,7 +67,7 @@ final class OriginAggregator implements AggregatorInterface
|
||||
return 'Origin';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -94,7 +94,7 @@ final class ReferrerAggregator implements AggregatorInterface
|
||||
return 'Referrer';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -101,7 +101,7 @@ class ReferrerScopeAggregator implements AggregatorInterface
|
||||
return 'export.aggregator.course.by_user_scope.Referrer\'s scope';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -65,11 +65,13 @@ final class ScopeAggregator implements AggregatorInterface
|
||||
return 'Scope';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$s = $this->scopeRepository->find($value);
|
||||
if (null === $s = $this->scopeRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
$s->getName()
|
||||
|
@@ -66,11 +66,13 @@ final class SocialActionAggregator implements AggregatorInterface
|
||||
return 'Social action';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$sa = $this->actionRepository->find($value);
|
||||
if (null === $sa = $this->actionRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->actionRender->renderString($sa, []);
|
||||
};
|
||||
|
@@ -66,6 +66,10 @@ final class SocialIssueAggregator implements AggregatorInterface
|
||||
return 'Social issues';
|
||||
}
|
||||
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$i = $this->issueRepository->find($value);
|
||||
|
||||
return $this->issueRender->renderString($i, []);
|
||||
|
@@ -98,6 +98,7 @@ final class StepAggregator implements AggregatorInterface
|
||||
return 'Step';
|
||||
|
||||
case null:
|
||||
case '':
|
||||
return '';
|
||||
|
||||
default:
|
||||
|
@@ -60,7 +60,7 @@ class EvaluationTypeAggregator implements AggregatorInterface
|
||||
return 'Evaluation type';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -89,7 +89,7 @@ class CompositionAggregator implements AggregatorInterface
|
||||
return 'Composition';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -105,7 +105,7 @@ class ByHouseholdCompositionAggregator implements AggregatorInterface
|
||||
return 'export.aggregator.person.by_household_composition.Household composition';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -66,6 +66,7 @@ final class GenderAggregator implements AggregatorInterface
|
||||
return $this->translator->trans('unknown');
|
||||
|
||||
case null:
|
||||
case '':
|
||||
return $this->translator->trans('Not given');
|
||||
|
||||
case '_header':
|
||||
|
@@ -101,7 +101,7 @@ final class HouseholdPositionAggregator implements AggregatorInterface, ExportEl
|
||||
return 'Household position';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return $this->translator->trans('without data');
|
||||
}
|
||||
|
||||
|
@@ -63,6 +63,10 @@ final class MaritalStatusAggregator implements AggregatorInterface
|
||||
return 'Marital status';
|
||||
}
|
||||
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$g = $this->maritalStatusRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize($g->getName());
|
||||
|
@@ -85,7 +85,7 @@ final class ActionTypeAggregator implements AggregatorInterface
|
||||
return 'Social Action Type';
|
||||
}
|
||||
|
||||
if (null === $value || null === $sa = $this->socialActionRepository->find($value)) {
|
||||
if (null === $value || '' === $value || null === $sa = $this->socialActionRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -63,7 +63,7 @@ final class GoalAggregator implements AggregatorInterface
|
||||
return 'Goal Type';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -72,7 +72,7 @@ class GoalResultAggregator implements AggregatorInterface
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function ($value) use ($key): string {
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -65,7 +65,7 @@ final class JobAggregator implements AggregatorInterface
|
||||
return 'Job';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -65,7 +65,7 @@ final class ReferrerAggregator implements AggregatorInterface
|
||||
return 'Referrer';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -63,7 +63,7 @@ final class ResultAggregator implements AggregatorInterface
|
||||
return 'Result Type';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -65,7 +65,7 @@ final class ScopeAggregator implements AggregatorInterface
|
||||
return 'Scope';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
if (null === $value || '' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@@ -70,11 +70,11 @@ class GeographicalUnitStatFilter implements FilterInterface
|
||||
LEFT JOIN acp_geog_filter_address.geographicalUnits acp_geog_filter_units
|
||||
WHERE
|
||||
(acp_geog_filter_location_history.startDate <= :acp_geog_filter_date AND (
|
||||
acp_geog_filter_location_history.endDate IS NULL OR acp_geog_filter_location_history.endDate < :acp_geog_filter_date
|
||||
acp_geog_filter_location_history.endDate IS NULL OR acp_geog_filter_location_history.endDate > :acp_geog_filter_date
|
||||
))
|
||||
AND
|
||||
(acp_geog_filter_address_person_location.validFrom < :acp_geog_filter_date AND (
|
||||
acp_geog_filter_address_person_location.validTo IS NULL OR acp_geog_filter_address_person_location.validTo < :acp_geog_filter_date
|
||||
acp_geog_filter_address_person_location.validTo IS NULL OR acp_geog_filter_address_person_location.validTo > :acp_geog_filter_date
|
||||
))
|
||||
AND acp_geog_filter_units IN (:acp_geog_filter_units)
|
||||
AND acp_geog_filter_location_history.period = acp.id
|
||||
|
@@ -111,10 +111,10 @@ class GeographicalUnitFilter implements \Chill\MainBundle\Export\FilterInterface
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return [
|
||||
'exports.by_person.Filtered by person\'s geographical unit (based on address) computed at datecalc, only units',
|
||||
'export.filter.by_geog_unit.Filtered by person\'s geographical unit (based on address) computed at %datecalc%, only %units%',
|
||||
[
|
||||
'datecalc' => $this->rollingDateConverter->convert($data['date_calc'])->format('Y-m-d'),
|
||||
'units' => implode(
|
||||
'%datecalc%' => $this->rollingDateConverter->convert($data['date_calc'])->format('Y-m-d'),
|
||||
'%units%' => implode(
|
||||
', ',
|
||||
array_map(
|
||||
function (SimpleGeographicalUnitDTO $item) {
|
||||
|
@@ -1046,6 +1046,8 @@ export:
|
||||
Max date: Date d'échéance
|
||||
|
||||
filter:
|
||||
by_geog_unit:
|
||||
Filtered by person's geographical unit (based on address) computed at %datecalc%, only %units%: Filtré par unité géographique (sur base de l'adresse), calculé le %datecalc%, seulement %units%
|
||||
person:
|
||||
by_composition:
|
||||
Filter by household composition: Filtrer les personnes par composition du ménage
|
||||
|
@@ -15,13 +15,11 @@ use ChampsLibres\WopiLib\Contract\Service\Configuration\ConfigurationInterface;
|
||||
use ChampsLibres\WopiLib\Contract\Service\Discovery\DiscoveryInterface;
|
||||
use ChampsLibres\WopiLib\Contract\Service\DocumentManagerInterface;
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\WopiBundle\Service\Controller\ResponderInterface;
|
||||
use Exception;
|
||||
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
|
||||
use loophp\psr17\Psr17Interface;
|
||||
use Symfony\Component\Finder\Exception\AccessDeniedException;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
@@ -35,8 +33,6 @@ final class Editor
|
||||
{
|
||||
private DocumentManagerInterface $documentManager;
|
||||
|
||||
private JWTTokenManagerInterface $JWTTokenManager;
|
||||
|
||||
private Psr17Interface $psr17;
|
||||
|
||||
private ResponderInterface $responder;
|
||||
@@ -53,14 +49,12 @@ final class Editor
|
||||
ConfigurationInterface $wopiConfiguration,
|
||||
DiscoveryInterface $wopiDiscovery,
|
||||
DocumentManagerInterface $documentManager,
|
||||
JWTTokenManagerInterface $JWTTokenManager,
|
||||
ResponderInterface $responder,
|
||||
Security $security,
|
||||
Psr17Interface $psr17,
|
||||
RouterInterface $router
|
||||
) {
|
||||
$this->documentManager = $documentManager;
|
||||
$this->JWTTokenManager = $JWTTokenManager;
|
||||
$this->wopiConfiguration = $wopiConfiguration;
|
||||
$this->wopiDiscovery = $wopiDiscovery;
|
||||
$this->responder = $responder;
|
||||
@@ -71,12 +65,8 @@ final class Editor
|
||||
|
||||
public function __invoke(string $fileId): Response
|
||||
{
|
||||
if (null === $user = $this->security->getUser()) {
|
||||
throw new AccessDeniedHttpException('Please authenticate to access this feature');
|
||||
}
|
||||
|
||||
if (!$user instanceof User) {
|
||||
throw new AccessDeniedHttpException('Please authenticate as a user to access this feature');
|
||||
if (null === $user = $this->security->getUser()->getUsername()) {
|
||||
throw new AccessDeniedException('You must be logged in to access to this resource.');
|
||||
}
|
||||
|
||||
$configuration = $this->wopiConfiguration->jsonSerialize();
|
||||
@@ -92,19 +82,7 @@ final class Editor
|
||||
}
|
||||
|
||||
$configuration['favIconUrl'] = '';
|
||||
$configuration['access_token'] = $this->JWTTokenManager->createFromPayload($user, [
|
||||
'UserCanWrite' => true,
|
||||
'UserCanAttend' => true,
|
||||
'UserCanPresent' => true,
|
||||
'fileId' => $fileId,
|
||||
]);
|
||||
|
||||
// we parse the token back to get the access_token_ttl
|
||||
// reminder: access_token_ttl is a javascript epoch, not a number of seconds; it is the
|
||||
// time when the token will expire, not the time to live:
|
||||
// https://learn.microsoft.com/en-us/microsoft-365/cloud-storage-partner-program/rest/concepts#the-access_token_ttl-property
|
||||
$jwt = $this->JWTTokenManager->parse($configuration['access_token']);
|
||||
$configuration['access_token_ttl'] = $jwt['exp'] * 1000;
|
||||
$configuration['access_token'] = $user;
|
||||
|
||||
$configuration['server'] = $this
|
||||
->psr17
|
||||
|
@@ -12,15 +12,12 @@ declare(strict_types=1);
|
||||
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
||||
|
||||
use ChampsLibres\AsyncUploaderBundle\TempUrl\TempUrlGeneratorInterface;
|
||||
use ChampsLibres\WopiBundle\Contracts\AuthorizationManagerInterface;
|
||||
use ChampsLibres\WopiBundle\Contracts\UserManagerInterface;
|
||||
use ChampsLibres\WopiBundle\Service\Wopi as CLWopi;
|
||||
use ChampsLibres\WopiLib\Contract\Service\DocumentLockManagerInterface;
|
||||
use ChampsLibres\WopiLib\Contract\Service\DocumentManagerInterface;
|
||||
use Chill\WopiBundle\Service\Wopi\AuthorizationManager;
|
||||
use Chill\WopiBundle\Service\Wopi\ChillDocumentLockManager;
|
||||
use Chill\WopiBundle\Service\Wopi\ChillDocumentManager;
|
||||
use Chill\WopiBundle\Service\Wopi\ChillWopi;
|
||||
use Chill\WopiBundle\Service\Wopi\UserManager;
|
||||
|
||||
return static function (ContainerConfigurator $container) {
|
||||
$services = $container
|
||||
@@ -47,17 +44,8 @@ return static function (ContainerConfigurator $container) {
|
||||
->alias(DocumentManagerInterface::class, ChillDocumentManager::class);
|
||||
|
||||
$services
|
||||
->set(ChillDocumentLockManager::class);
|
||||
|
||||
$services
|
||||
->set(AuthorizationManager::class);
|
||||
|
||||
$services->alias(AuthorizationManagerInterface::class, AuthorizationManager::class);
|
||||
|
||||
$services
|
||||
->set(UserManager::class);
|
||||
|
||||
$services->alias(UserManagerInterface::class, UserManager::class);
|
||||
->set(ChillDocumentLockManager::class)
|
||||
->decorate(DocumentLockManagerInterface::class);
|
||||
|
||||
// TODO: Move this into the async bundle (low priority)
|
||||
$services
|
||||
|
@@ -1,88 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\WopiBundle\Service\Wopi;
|
||||
|
||||
use ChampsLibres\WopiLib\Contract\Entity\Document;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
class AuthorizationManager implements \ChampsLibres\WopiBundle\Contracts\AuthorizationManagerInterface
|
||||
{
|
||||
private Security $security;
|
||||
|
||||
private JWTTokenManagerInterface $tokenManager;
|
||||
|
||||
public function __construct(JWTTokenManagerInterface $tokenManager, Security $security)
|
||||
{
|
||||
$this->tokenManager = $tokenManager;
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
public function isRestrictedWebViewOnly(string $accessToken, Document $document, RequestInterface $request): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isTokenValid(string $accessToken, Document $document, RequestInterface $request): bool
|
||||
{
|
||||
$metadata = $this->tokenManager->parse($accessToken);
|
||||
|
||||
if (false === $metadata) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user = $this->security->getUser();
|
||||
|
||||
if (!$user instanceof User) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $document->getWopiDocId() === $metadata['fileId'];
|
||||
}
|
||||
|
||||
public function userCanAttend(string $accessToken, Document $document, RequestInterface $request): bool
|
||||
{
|
||||
return $this->isTokenValid($accessToken, $document, $request);
|
||||
}
|
||||
|
||||
public function userCanDelete(string $accessToken, Document $document, RequestInterface $request): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function userCannotWriteRelative(string $accessToken, Document $document, RequestInterface $request): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function userCanPresent(string $accessToken, Document $document, RequestInterface $request): bool
|
||||
{
|
||||
return $this->isTokenValid($accessToken, $document, $request);
|
||||
}
|
||||
|
||||
public function userCanRead(string $accessToken, Document $document, RequestInterface $request): bool
|
||||
{
|
||||
return $this->isTokenValid($accessToken, $document, $request);
|
||||
}
|
||||
|
||||
public function userCanRename(string $accessToken, Document $document, RequestInterface $request): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function userCanWrite(string $accessToken, Document $document, RequestInterface $request): bool
|
||||
{
|
||||
return $this->isTokenValid($accessToken, $document, $request);
|
||||
}
|
||||
}
|
@@ -24,12 +24,11 @@ use loophp\psr17\Psr17Interface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use RuntimeException;
|
||||
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\Mime\MimeTypes;
|
||||
|
||||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
||||
|
||||
use function strlen;
|
||||
|
||||
final class ChillDocumentManager implements DocumentManagerInterface
|
||||
@@ -191,12 +190,7 @@ final class ChillDocumentManager implements DocumentManagerInterface
|
||||
|
||||
public function remove(Document $document): void
|
||||
{
|
||||
throw new RuntimeException('this is not implemented and should not happens');
|
||||
}
|
||||
|
||||
public function rename(Document $document, string $requestedName): void
|
||||
{
|
||||
throw new RuntimeException('this is not implemented and should not happens');
|
||||
// TODO: To implement when we have a clearer view and API.
|
||||
}
|
||||
|
||||
public function write(Document $document, array $properties = []): void
|
||||
|
@@ -13,20 +13,39 @@ namespace Chill\WopiBundle\Service\Wopi;
|
||||
|
||||
use ChampsLibres\WopiLib\Contract\Service\DocumentManagerInterface;
|
||||
use ChampsLibres\WopiLib\Contract\Service\WopiInterface;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use loophp\psr17\Psr17Interface;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use function strlen;
|
||||
|
||||
final class ChillWopi implements WopiInterface
|
||||
{
|
||||
private CacheItemPoolInterface $cache;
|
||||
|
||||
private DocumentManagerInterface $documentManager;
|
||||
|
||||
private Psr17Interface $psr17;
|
||||
|
||||
private UserProviderInterface $userProvider;
|
||||
|
||||
private WopiInterface $wopi;
|
||||
|
||||
public function __construct(
|
||||
CacheItemPoolInterface $cache,
|
||||
DocumentManagerInterface $documentManager,
|
||||
Psr17Interface $psr17,
|
||||
UserProviderInterface $userProvider,
|
||||
WopiInterface $wopi
|
||||
) {
|
||||
$this->cache = $cache;
|
||||
$this->documentManager = $documentManager;
|
||||
$this->psr17 = $psr17;
|
||||
$this->userProvider = $userProvider;
|
||||
$this->wopi = $wopi;
|
||||
}
|
||||
|
||||
@@ -35,9 +54,55 @@ final class ChillWopi implements WopiInterface
|
||||
?string $accessToken,
|
||||
RequestInterface $request
|
||||
): ResponseInterface {
|
||||
return $this->wopi->checkFileInfo($fileId, $accessToken, $request, [
|
||||
'SupportsRename' => false,
|
||||
]);
|
||||
try {
|
||||
$user = $this->userProvider->loadUserByUsername($accessToken);
|
||||
} catch (UsernameNotFoundException $e) {
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse(401);
|
||||
}
|
||||
|
||||
// @ TODO : Replace this with a call to decorated object once authentication is done.
|
||||
$document = $this->documentManager->findByDocumentId($fileId);
|
||||
$userIdentifier = $user->getUsername();
|
||||
$userCacheKey = sprintf('wopi_putUserInfo_%s', $userIdentifier);
|
||||
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse()
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withBody($this->psr17->createStream((string) json_encode(
|
||||
[
|
||||
'BaseFileName' => $this->documentManager->getBasename($document),
|
||||
'OwnerId' => 'Symfony',
|
||||
'Size' => $this->documentManager->getSize($document),
|
||||
'UserId' => $userIdentifier,
|
||||
'ReadOnly' => false,
|
||||
'UserCanAttend' => true,
|
||||
'UserCanPresent' => true,
|
||||
'UserCanRename' => true,
|
||||
'UserCanWrite' => true,
|
||||
'UserCanNotWriteRelative' => false,
|
||||
'SupportsUserInfo' => true,
|
||||
'SupportsDeleteFile' => true,
|
||||
'SupportsLocks' => true,
|
||||
'SupportsGetLock' => true,
|
||||
'SupportsExtendedLockLength' => true,
|
||||
'UserFriendlyName' => $userIdentifier,
|
||||
'SupportsUpdate' => true,
|
||||
'SupportsRename' => true,
|
||||
'SupportsFolder' => false,
|
||||
'DisablePrint' => false,
|
||||
'AllowExternalMarketplace' => true,
|
||||
'SupportedShareUrlTypes' => [
|
||||
'ReadOnly',
|
||||
],
|
||||
'LastModifiedTime' => $this->documentManager->getLastModifiedDate($document)
|
||||
->format(DateTimeInterface::ATOM),
|
||||
'SHA256' => $this->documentManager->getSha256($document),
|
||||
'UserInfo' => (string) $this->cache->getItem($userCacheKey)->get(),
|
||||
]
|
||||
)));
|
||||
}
|
||||
|
||||
public function deleteFile(string $fileId, ?string $accessToken, RequestInterface $request): ResponseInterface
|
||||
@@ -87,7 +152,97 @@ final class ChillWopi implements WopiInterface
|
||||
string $xWopiEditors,
|
||||
RequestInterface $request
|
||||
): ResponseInterface {
|
||||
return $this->wopi->putFile($fileId, $accessToken, $xWopiLock, $xWopiEditors, $request);
|
||||
$document = $this->documentManager->findByDocumentId($fileId);
|
||||
$version = $this->documentManager->getVersion($document);
|
||||
|
||||
// File is unlocked, we must reject the document, except if collabora is autosaving
|
||||
if (false === $this->documentManager->hasLock($document) && 'true' !== ($request->getHeader('x-lool-wopi-isexitsave') ?? ['false'])[0]) {
|
||||
if (0 !== $this->documentManager->getSize($document)) {
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse(409)
|
||||
->withHeader(
|
||||
WopiInterface::HEADER_ITEM_VERSION,
|
||||
sprintf('v%s', $version)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// File is locked, we check for the lock
|
||||
if ($this->documentManager->hasLock($document)) {
|
||||
if ($xWopiLock !== $currentLock = $this->documentManager->getLock($document)) {
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse(409)
|
||||
->withHeader(
|
||||
WopiInterface::HEADER_LOCK,
|
||||
$currentLock
|
||||
)
|
||||
->withHeader(
|
||||
WopiInterface::HEADER_ITEM_VERSION,
|
||||
sprintf('v%s', $version)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// for collabora online editor, check timestamp if present
|
||||
/* delete because it seems that collabora send always the first wopi-timestamp, not the last known one
|
||||
// example:
|
||||
// load the doc: the last-wopi is 12:00 in FileInfo
|
||||
// save the doc: x-cool-wopi-timestamp is 12:00, but we replace the ts with the time of save (12:05)
|
||||
// save the doc again: x-cool-wopi-timestamp is still 12:00...
|
||||
if ($request->hasHeader('x-cool-wopi-timestamp')) {
|
||||
$date = DateTimeImmutable::createFromFormat(
|
||||
DateTimeImmutable::ATOM,
|
||||
$request->getHeader('x-cool-wopi-timestamp')[0]
|
||||
);
|
||||
|
||||
if (false === $date) {
|
||||
throw new RuntimeException('Error parsing date: ' . implode('', DateTimeImmutable::getLastErrors()));
|
||||
}
|
||||
|
||||
if ($this->documentManager->getLastModifiedDate($document)->getTimestamp() < $date->getTimestamp()) {
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse(409)
|
||||
->withHeader(
|
||||
WopiInterface::HEADER_LOCK,
|
||||
$currentLock
|
||||
)
|
||||
->withHeader(
|
||||
WopiInterface::HEADER_ITEM_VERSION,
|
||||
sprintf('v%s', $version)
|
||||
)
|
||||
->withBody(
|
||||
$this->psr17->createStream(
|
||||
json_encode(['COOLStatusCode' => 1010])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
$body = (string) $request->getBody();
|
||||
$this->documentManager->write(
|
||||
$document,
|
||||
[
|
||||
'content' => $body,
|
||||
'size' => (string) strlen($body),
|
||||
]
|
||||
);
|
||||
$version = $this->documentManager->getVersion($document);
|
||||
|
||||
return $this
|
||||
->psr17
|
||||
->createResponse()
|
||||
->withHeader(
|
||||
WopiInterface::HEADER_LOCK,
|
||||
$xWopiLock
|
||||
)
|
||||
->withHeader(
|
||||
WopiInterface::HEADER_ITEM_VERSION,
|
||||
sprintf('v%s', $version)
|
||||
);
|
||||
}
|
||||
|
||||
public function putRelativeFile(string $fileId, string $accessToken, ?string $suggestedTarget, ?string $relativeTarget, bool $overwriteRelativeTarget, int $size, RequestInterface $request): ResponseInterface
|
||||
|
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\WopiBundle\Service\Wopi;
|
||||
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
class UserManager implements \ChampsLibres\WopiBundle\Contracts\UserManagerInterface
|
||||
{
|
||||
private Security $security;
|
||||
|
||||
public function __construct(Security $security)
|
||||
{
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
public function getUserFriendlyName(string $accessToken, string $fileId, RequestInterface $request): ?string
|
||||
{
|
||||
$user = $this->security->getUser();
|
||||
|
||||
if (!$user instanceof User) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (string) $user->getLabel();
|
||||
}
|
||||
|
||||
public function getUserId(string $accessToken, string $fileId, RequestInterface $request): ?string
|
||||
{
|
||||
$user = $this->security->getUser();
|
||||
|
||||
if (!$user instanceof User) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (string) $user->getId();
|
||||
}
|
||||
|
||||
public function isAnonymousUser(string $accessToken, string $fileId, RequestInterface $request): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user