diff --git a/Controller/Administration/FacetController.php b/Controller/Administration/FacetController.php index 51478fe03..26ae382ac 100644 --- a/Controller/Administration/FacetController.php +++ b/Controller/Administration/FacetController.php @@ -19,8 +19,11 @@ use Claroline\CoreBundle\Manager\ToolManager; use Claroline\CoreBundle\Manager\RoleManager; use Claroline\CoreBundle\Manager\FacetManager; +use Claroline\CoreBundle\Manager\ProfilePropertyManager; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Form\FormFactoryInterface; +use Claroline\CoreBundle\Entity\User; +use Claroline\CoreBundle\Entity\ProfileProperty; use Claroline\CoreBundle\Entity\Facet\Facet; use Claroline\CoreBundle\Entity\Facet\FieldFacet; use Claroline\CoreBundle\Entity\Facet\PanelFacet; @@ -38,16 +41,18 @@ class FacetController extends Controller private $roleManager; private $userAdminTool; private $facetManager; + private $profilePropertyManager; /** * @DI\InjectParams({ - * "router" = @DI\Inject("router"), - * "sc" = @DI\Inject("security.context"), - * "toolManager" = @DI\Inject("claroline.manager.tool_manager"), - * "roleManager" = @DI\Inject("claroline.manager.role_manager"), - * "facetManager" = @DI\Inject("claroline.manager.facet_manager"), - * "formFactory" = @DI\Inject("form.factory"), - * "request" = @DI\Inject("request") + * "router" = @DI\Inject("router"), + * "sc" = @DI\Inject("security.context"), + * "toolManager" = @DI\Inject("claroline.manager.tool_manager"), + * "roleManager" = @DI\Inject("claroline.manager.role_manager"), + * "facetManager" = @DI\Inject("claroline.manager.facet_manager"), + * "formFactory" = @DI\Inject("form.factory"), + * "request" = @DI\Inject("request"), + * "profilePropertyManager" = @DI\Inject("claroline.manager.profile_property_manager") * }) */ public function __construct( @@ -57,17 +62,19 @@ public function __construct( FacetManager $facetManager, RoleManager $roleManager, FormFactoryInterface $formFactory, - Request $request + Request $request, + ProfilePropertyManager $profilePropertyManager ) { - $this->sc = $sc; - $this->toolManager = $toolManager; - $this->userAdminTool = $this->toolManager->getAdminToolByName('user_management'); - $this->facetManager = $facetManager; - $this->formFactory = $formFactory; - $this->request = $request; - $this->roleManager = $roleManager; - $this->router = $router; + $this->sc = $sc; + $this->toolManager = $toolManager; + $this->userAdminTool = $this->toolManager->getAdminToolByName('user_management'); + $this->facetManager = $facetManager; + $this->formFactory = $formFactory; + $this->request = $request; + $this->roleManager = $roleManager; + $this->router = $router; + $this->profilePropertyManager = $profilePropertyManager; } /** @@ -79,6 +86,21 @@ public function __construct( * @return Response */ public function indexAction() + { + $this->checkOpen(); + + return array(); + } + + /** + * Returns the facet list. + * + * @EXT\Route("/facet", name="claro_admin_facet") + * @EXT\Template + * + * @return Response + */ + public function facetsAction() { $this->checkOpen(); $facets = $this->facetManager->getFacets(); @@ -92,6 +114,43 @@ public function indexAction() ); } + /** + * Returns the facet list. + * + * @EXT\Route("/properties", name="claro_admin_profile_properties") + * @EXT\Template + * + * @return Response + */ + public function profilePropertiesAction() + { + $this->checkOpen(); + $platformRoles = $this->roleManager->getPlatformNonAdminRoles(false); + $labels = User::getEditableProperties(); + $properties = $this->profilePropertyManager->getAllProperties(); + + return array( + 'platformRoles' => $platformRoles, + 'labels' => $labels, + 'properties' => $properties + ); + } + + /** + * @EXT\Route("/property/{property}/invert", + * name="claro_admin_invert_user_properties_edition", + * options = {"expose"=true} + * ) + * + */ + public function invertPropertiesEditableAction(ProfileProperty $property) + { + $this->checkOpen(); + $this->profilePropertyManager->invertProperty($property); + + return new JsonResponse(array(), 200); + } + /** * Returns the facet creation form in a modal * diff --git a/Controller/ProfileController.php b/Controller/ProfileController.php index 2ae251433..97b8e87d3 100644 --- a/Controller/ProfileController.php +++ b/Controller/ProfileController.php @@ -24,6 +24,7 @@ use Claroline\CoreBundle\Manager\RoleManager; use Claroline\CoreBundle\Manager\ToolManager; use Claroline\CoreBundle\Manager\UserManager; +use Claroline\CoreBundle\Manager\ProfilePropertyManager; use Doctrine\ORM\NoResultException; use JMS\DiExtraBundle\Annotation as DI; use JMS\SecurityExtraBundle\Annotation as SEC; @@ -55,6 +56,7 @@ class ProfileController extends Controller private $facetManager; private $ch; private $authenticationManager; + private $profilePropertyManager; /** * @DI\InjectParams({ @@ -68,7 +70,8 @@ class ProfileController extends Controller * "toolManager" = @DI\Inject("claroline.manager.tool_manager"), * "facetManager" = @DI\Inject("claroline.manager.facet_manager"), * "ch" = @DI\Inject("claroline.config.platform_config_handler"), - * "authenticationManager" = @DI\Inject("claroline.common.authentication_manager") + * "authenticationManager" = @DI\Inject("claroline.common.authentication_manager"), + * "profilePropertyManager" = @DI\Inject("claroline.manager.profile_property_manager") * }) */ public function __construct( @@ -82,7 +85,8 @@ public function __construct( ToolManager $toolManager, FacetManager $facetManager, PlatformConfigurationHandler $ch, - AuthenticationManager $authenticationManager + AuthenticationManager $authenticationManager, + ProfilePropertyManager $profilePropertyManager ) { $this->userManager = $userManager; @@ -96,6 +100,7 @@ public function __construct( $this->facetManager = $facetManager; $this->ch = $ch; $this->authenticationManager = $authenticationManager; + $this->profilePropertyManager = $profilePropertyManager; } private function isInRoles($role, $roles) @@ -206,6 +211,7 @@ public function editProfileAction(User $loggedUser, User $user = null) } $userRole = $this->roleManager->getUserRoleByUser($user); $roles = $this->roleManager->getPlatformRoles($user); + $accesses = $this->profilePropertyManager->getAccessesForCurrentUser(); $form = $this->createForm( new ProfileType( @@ -213,6 +219,7 @@ public function editProfileAction(User $loggedUser, User $user = null) $isAdmin, $isGrantedUserAdmin, $this->localeManager->getAvailableLocales(), + $accesses, $this->authenticationManager->getDrivers() ), $user @@ -475,6 +482,16 @@ public function editFacet(User $user, Facet $facet) return new JsonResponse($data); } + public function propertiesFormAction() + { + + } + + public function editPropertiesAction() + { + + } + private function encodePassword(User $user) { return $this->encoderFactory diff --git a/DataFixtures/Required/Data/LoadProfilePropertiesData.php b/DataFixtures/Required/Data/LoadProfilePropertiesData.php new file mode 100644 index 000000000..9b18a3c71 --- /dev/null +++ b/DataFixtures/Required/Data/LoadProfilePropertiesData.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Claroline\CoreBundle\DataFixtures\Required\Data; + +use Claroline\CoreBundle\Persistence\ObjectManager; +use Claroline\CoreBundle\DataFixtures\Required\RequiredFixture; + +class LoadProfilePropertiesData implements RequiredFixture +{ + public function load(ObjectManager $manager) + { + $this->container->get('claroline.manager.profile_property_manager') + ->addDefaultProperties(); + } + + public function setContainer($container) + { + $this->container = $container; + } +} diff --git a/Entity/ProfileProperty.php b/Entity/ProfileProperty.php new file mode 100644 index 000000000..919005b94 --- /dev/null +++ b/Entity/ProfileProperty.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Claroline\CoreBundle\Entity; + +use Doctrine\ORM\Mapping as ORM; + +/** + * @ORM\Entity(repositoryClass="Claroline\CoreBundle\Repository\ProfilePropertyRepository") + * @ORM\Table(name="claro_profile_property") + */ +class ProfileProperty +{ + /** + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue(strategy="AUTO") + */ + protected $id; + + /** + * @ORM\Column(name="is_editable", type="boolean") + */ + protected $isEditable; + + /** + * @ORM\ManyToOne( + * targetEntity="Claroline\CoreBundle\Entity\Role", + * inversedBy="profileProperties", + * cascade={"persist"} + * ) + * @ORM\JoinColumn(onDelete="CASCADE") + */ + protected $role; + + /** + * @ORM\Column(name="property", length=256) + */ + protected $property; + + public function getId() + { + return $this->id; + } + + public function setIsEditable($bool) + { + $this->isEditable = $bool; + } + + public function isEditable() + { + return $this->isEditable; + } + + public function getIsEditable() + { + return $this->isEditable; + } + + public function setRole(Role $role) + { + $this->role = $role; + } + + public function getRole() + { + return $this->role; + } + + public function setProperty($property) + { + $this->property = $property; + } + + public function getProperty() + { + return $this->property; + } +} diff --git a/Entity/Role.php b/Entity/Role.php index 74ab98fa6..cb39eac31 100644 --- a/Entity/Role.php +++ b/Entity/Role.php @@ -164,15 +164,24 @@ class Role implements RoleInterface */ protected $personalWorkspaceCreationEnabled = false; + /** + * @ORM\OneToMany( + * targetEntity="Claroline\CoreBundle\Entity\ProfileProperty", + * mappedBy="role" + * ) + */ + protected $profileProperties; + public function __construct() { - $this->users = new ArrayCollection(); - $this->resourceContext = new ArrayCollection(); - $this->groups = new ArrayCollection(); - $this->facets = new ArrayCollection(); - $this->fieldFacetsRoles = new ArrayCollection(); - $this->toolRights = new ArrayCollection(); - $this->pwsToolConfig = new ArrayCollection(); + $this->users = new ArrayCollection(); + $this->resourceContext = new ArrayCollection(); + $this->groups = new ArrayCollection(); + $this->facets = new ArrayCollection(); + $this->fieldFacetsRoles = new ArrayCollection(); + $this->toolRights = new ArrayCollection(); + $this->pwsToolConfig = new ArrayCollection(); + $this->profileProperties = new ArrayCollection(); } public function getId() @@ -347,4 +356,14 @@ public function setPersonalWorkspaceCreationEnabled($boolean) { $this->personalWorkspaceCreationEnabled = $boolean; } + + public function getProfileProperties() + { + return $this->profileProperties; + } + + public function addProfileProperty(ProfileProperty $property) + { + $this->profileProperties->add($property); + } } diff --git a/Entity/User.php b/Entity/User.php index becdde787..b35999420 100644 --- a/Entity/User.php +++ b/Entity/User.php @@ -1074,4 +1074,18 @@ public function getAuthentication() { return $this->authentication; } + + public static function getEditableProperties() + { + return array( + 'username' => false, + 'firstName' => false, + 'lastName' => false, + 'administrativeCode' => false, + 'email' => false, + 'phone' => true, + 'picture' => true, + 'description' => true + ); + } } diff --git a/Form/ProfileType.php b/Form/ProfileType.php index 623697347..ab506aab0 100644 --- a/Form/ProfileType.php +++ b/Form/ProfileType.php @@ -26,6 +26,7 @@ class ProfileType extends AbstractType private $isGrantedUserAdministration; private $langs; private $authenticationDrivers; + private $accesses; /** * Constructor. @@ -35,9 +36,15 @@ class ProfileType extends AbstractType * @param string[] $langs */ public function __construct( - array $platformRoles, $isAdmin, $isGrantedUserAdministration, array $langs, $authenticationDrivers = null + array $platformRoles, + $isAdmin, + $isGrantedUserAdministration, + array $langs, + $accesses, + $authenticationDrivers = null ) { + $this->accesses = $accesses; $this->platformRoles = new ArrayCollection($platformRoles); $this->isAdmin = $isAdmin; $this->isGrantedUserAdministration = $isGrantedUserAdministration; @@ -56,34 +63,60 @@ public function buildForm(FormBuilderInterface $builder, array $options) parent::buildForm($builder, $options); $builder - ->add('firstName', 'text', array('label' => 'First name')) - ->add('lastName', 'text', array('label' => 'Last name')) - ->add('username', 'text', array('read_only' => true, 'disabled' => true, 'label' => 'User name')) + ->add('firstName', 'text', array('label' => 'First name', 'read_only' => !$this->accesses['firstName'], 'disabled' => !$this->accesses['firstName'])) + ->add('lastName', 'text', array('label' => 'Last name', 'read_only' => !$this->accesses['lastName'], 'disabled' => !$this->accesses['lastName'])) + ->add('username', 'text', array('read_only' => true, 'disabled' => true, 'label' => 'User name', 'read_only' => !$this->accesses['username'], 'disabled' => !$this->accesses['username'])) ->add( 'administrativeCode', 'text', - array('required' => false, 'read_only' => true, 'disabled' => true, 'label' => 'administrative_code') + array('required' => false, 'read_only' => !$this->accesses['administrativeCode'], 'disabled' => !$this->accesses['administrativeCode'], 'label' => 'administrative_code') ) - ->add('mail', 'email', array('required' => false, 'label' => 'email')) - ->add('phone', 'text', array('required' => false, 'label' => 'phone')) + ->add('mail', 'email', array('required' => false, 'label' => 'email', 'read_only' => !$this->accesses['email'], 'disabled' => !$this->accesses['email'])) + ->add('phone', 'text', array('required' => false, 'label' => 'phone', 'read_only' => !$this->accesses['phone'], 'disabled' => !$this->accesses['phone'])) ->add('locale', 'choice', array('choices' => $this->langs, 'required' => false, 'label' => 'Language')) ->add( - 'authentication', - 'choice', + 'pictureFile', + 'file', array( - 'choices' => $this->authenticationDrivers, 'required' => false, - 'label' => 'authentication' + 'constraints' => new Image( + array( + 'minWidth' => 50, + 'maxWidth' => 800, + 'minHeight' => 50, + 'maxHeight' => 800, + ) + ), + 'label' => 'picture_profile', + 'read_only' => !$this->accesses['picture'], + 'disabled' => !$this->accesses['picture'] ) + ) + ->add( + 'description', + 'tinymce', + array('required' => false, 'label' => 'description', 'read_only' => !$this->accesses['description'], 'disabled' => !$this->accesses['description']) ); if ($this->isAdmin || $this->isGrantedUserAdministration) { $isAdmin = $this->isAdmin; - $builder->add('username', 'text', array('label' => 'User name')) + $builder + ->add('firstName', 'text', array('label' => 'First name')) + ->add('lastName', 'text', array('label' => 'Last name')) + ->add('username', 'text', array('label' => 'User name')) ->add('administrativeCode', 'text', array('required' => false, 'label' => 'administrative_code')) ->add('mail', 'email', array('required' => false, 'label' => 'email')) ->add('phone', 'text', array('required' => false, 'label' => 'phone')) ->add('locale', 'choice', array('choices' => $this->langs, 'required' => false, 'label' => 'Language')) + ->add( + 'authentication', + 'choice', + array( + 'choices' => $this->authenticationDrivers, + 'required' => false, + 'label' => 'authentication' + ) + ) ->add( 'platformRoles', 'entity', @@ -107,30 +140,29 @@ public function buildForm(FormBuilderInterface $builder, array $options) }, 'label' => 'roles' ) - ); - } - $builder->add( - 'pictureFile', - 'file', - array( - 'required' => false, - 'constraints' => new Image( + ) + ->add( + 'pictureFile', + 'file', array( - 'minWidth' => 50, - 'maxWidth' => 800, - 'minHeight' => 50, - 'maxHeight' => 800, + 'required' => false, + 'constraints' => new Image( + array( + 'minWidth' => 50, + 'maxWidth' => 800, + 'minHeight' => 50, + 'maxHeight' => 800, + ) + ), + 'label' => 'picture_profile' ) - ), - 'label' => 'picture_profile' - ) - ) - - ->add( - 'description', - 'tinymce', - array('required' => false, 'label' => 'description') - ); + ) + ->add( + 'description', + 'tinymce', + array('required' => false, 'label' => 'description') + ); + } } public function getName() diff --git a/Library/Installation/Updater/Updater040200.php b/Library/Installation/Updater/Updater040200.php index 9166a8d28..62ee10920 100644 --- a/Library/Installation/Updater/Updater040200.php +++ b/Library/Installation/Updater/Updater040200.php @@ -33,6 +33,7 @@ public function postUpdate() { $this->updateBaseRoles(); $this->updateFacets(); + $this->setProfileProperties(); } private function updateBaseRoles() @@ -51,17 +52,29 @@ private function updateBaseRoles() private function updateFacets() { + $this->log('Updating facets...'); $facets = $this->om->getRepository('ClarolineCoreBundle:Facet\Facet')->findAll(); $this->om->startFlushSuite(); foreach ($facets as $facet) { - $this->container->get('claroline.manager.facet_manager') - ->addPanel($facet, $facet->getName()); + $panel = $this->om->getRepository('ClarolineCoreBundle:Facet\PanelFacet') + ->findByName($facet->getName()); + if (!$panel) { + $this->container->get('claroline.manager.facet_manager') + ->addPanel($facet, $facet->getName()); + } } $this->om->endFlushSuite(); } + private function setProfileProperties() + { + $this->log('Updating profile properties...'); + $manager = $this->container->get('claroline.manager.profile_property_manager'); + $manager->addDefaultProperties(); + } + public function setLogger($logger) { $this->logger = $logger; diff --git a/Manager/ProfilePropertyManager.php b/Manager/ProfilePropertyManager.php new file mode 100644 index 000000000..502fbda56 --- /dev/null +++ b/Manager/ProfilePropertyManager.php @@ -0,0 +1,135 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Claroline\CoreBundle\Manager; + +use JMS\DiExtraBundle\Annotation as DI; +use Claroline\CoreBundle\Entity\User; +use Claroline\CoreBundle\Entity\Role; +use Claroline\CoreBundle\Entity\ProfileProperty; +use Claroline\CoreBundle\Persistence\ObjectManager; +use Claroline\CoreBundle\Library\Security\Utilities; + +/** + * @DI\Service("claroline.manager.profile_property_manager") + */ +class ProfilePropertyManager +{ + private $om; + private $roleManager; + private $profileTypeRepo; + private $secUtils; + private $container; + + /** + * @DI\InjectParams({ + * "om" = @DI\Inject("claroline.persistence.object_manager"), + * "roleManager" = @DI\Inject("claroline.manager.role_manager"), + * "secUtils" = @DI\Inject("claroline.security.utilities"), + * "container" = @DI\Inject("service_container") + * }) + */ + public function __construct( + ObjectManager $om, + RoleManager $roleManager, + Utilities $secUtils, + $container + ) + { + $this->om = $om; + $this->roleManager = $roleManager; + $this->secUtils = $secUtils; + $this->container = $container; + $this->profilePropertyRepo = $om->getRepository('ClarolineCoreBundle:ProfileProperty'); + } + + /** + * Add the default properties accesses for each roles + */ + public function addDefaultProperties() + { + $properties = User::getEditableProperties(); + $this->om->startFlushSuite(); + + foreach ($properties as $property => $editable) { + $this->addProperties($property, $editable); + } + + $this->om->endFlushSuite(); + } + + /** + * Public function add a property for each roles + * + * @param string $property + * @param boolean $editable + */ + public function addProperties($property, $editable) + { + $platformRoles = $this->roleManager->getAllPlatformRoles(); + + foreach ($platformRoles as $role) { + $prop = $this->profilePropertyRepo + ->findBy(array('property' => $property, 'role' => $role)); + + if (count($prop) === 0) $this->addProperty($property, $editable, $role); + } + } + + /** + * Create a property entity + * + * @param string $property + * @param boolean $editable + * @param Role $role + */ + public function addProperty($property, $editable, Role $role) + { + $propertyEntity = new ProfileProperty(); + $propertyEntity->setProperty($property); + $propertyEntity->setIsEditable($editable); + $propertyEntity->setRole($role); + $this->om->persist($propertyEntity); + $this->om->flush(); + } + + public function getAccessesForCurrentUser() + { + $roles = $this->container->get('security.context')->getToken(); + $rolenames = $this->secUtils->getRoles($roles); + + return $this->getAccessessByRoles($rolenames); + } + + /** + * Get the property access for an list of roles + * + * @param array $rolenames + */ + public function getAccessessByRoles(array $rolenames) + { + $properties = $this->profilePropertyRepo->findAccessesByRoles($rolenames); + + return $properties; + } + + public function getAllProperties() + { + return $this->profilePropertyRepo->findAll(); + } + + public function invertProperty(ProfileProperty $property) + { + $property->setIsEditable(!$property->isEditable()); + $this->om->persist($property); + $this->om->flush(); + } +} diff --git a/Manager/RoleManager.php b/Manager/RoleManager.php index b013392e6..6d425d640 100644 --- a/Manager/RoleManager.php +++ b/Manager/RoleManager.php @@ -119,6 +119,8 @@ public function createBaseRole($name, $translationKey, $isReadOnly = true) $role->setType(Role::PLATFORM_ROLE); $this->om->persist($role); $this->om->flush(); + $this->container->get('claroline.manager.profile_property_manager') + ->addDefaultProperties(); return $role; } diff --git a/Migrations/drizzle_pdo_mysql/Version20150213094501.php b/Migrations/drizzle_pdo_mysql/Version20150213094501.php new file mode 100644 index 000000000..7af895dfb --- /dev/null +++ b/Migrations/drizzle_pdo_mysql/Version20150213094501.php @@ -0,0 +1,41 @@ +addSql(" + CREATE TABLE claro_profile_property ( + id INT AUTO_INCREMENT NOT NULL, + role_id INT DEFAULT NULL, + is_editable BOOLEAN NOT NULL, + property VARCHAR(256) NOT NULL, + INDEX IDX_C2B93182D60322AC (role_id), + PRIMARY KEY(id) + ) COLLATE utf8_unicode_ci ENGINE = InnoDB + "); + $this->addSql(" + ALTER TABLE claro_profile_property + ADD CONSTRAINT FK_C2B93182D60322AC FOREIGN KEY (role_id) + REFERENCES claro_role (id) + ON DELETE CASCADE + "); + } + + public function down(Schema $schema) + { + $this->addSql(" + DROP TABLE claro_profile_property + "); + } +} \ No newline at end of file diff --git a/Migrations/ibm_db2/Version20150213094501.php b/Migrations/ibm_db2/Version20150213094501.php new file mode 100644 index 000000000..35333f7dc --- /dev/null +++ b/Migrations/ibm_db2/Version20150213094501.php @@ -0,0 +1,43 @@ +addSql(" + CREATE TABLE claro_profile_property ( + id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, + role_id INTEGER DEFAULT NULL, + is_editable SMALLINT NOT NULL, + property VARCHAR(256) NOT NULL, + PRIMARY KEY(id) + ) + "); + $this->addSql(" + CREATE INDEX IDX_C2B93182D60322AC ON claro_profile_property (role_id) + "); + $this->addSql(" + ALTER TABLE claro_profile_property + ADD CONSTRAINT FK_C2B93182D60322AC FOREIGN KEY (role_id) + REFERENCES claro_role (id) + ON DELETE CASCADE + "); + } + + public function down(Schema $schema) + { + $this->addSql(" + DROP TABLE claro_profile_property + "); + } +} \ No newline at end of file diff --git a/Migrations/mysqli/Version20150213094501.php b/Migrations/mysqli/Version20150213094501.php new file mode 100644 index 000000000..6ff36d622 --- /dev/null +++ b/Migrations/mysqli/Version20150213094501.php @@ -0,0 +1,41 @@ +addSql(" + CREATE TABLE claro_profile_property ( + id INT AUTO_INCREMENT NOT NULL, + role_id INT DEFAULT NULL, + is_editable TINYINT(1) NOT NULL, + property VARCHAR(256) NOT NULL, + INDEX IDX_C2B93182D60322AC (role_id), + PRIMARY KEY(id) + ) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB + "); + $this->addSql(" + ALTER TABLE claro_profile_property + ADD CONSTRAINT FK_C2B93182D60322AC FOREIGN KEY (role_id) + REFERENCES claro_role (id) + ON DELETE CASCADE + "); + } + + public function down(Schema $schema) + { + $this->addSql(" + DROP TABLE claro_profile_property + "); + } +} \ No newline at end of file diff --git a/Migrations/oci8/Version20150213094501.php b/Migrations/oci8/Version20150213094501.php new file mode 100644 index 000000000..a8da82cd5 --- /dev/null +++ b/Migrations/oci8/Version20150213094501.php @@ -0,0 +1,71 @@ +addSql(" + CREATE TABLE claro_profile_property ( + id NUMBER(10) NOT NULL, + role_id NUMBER(10) DEFAULT NULL NULL, + is_editable NUMBER(1) NOT NULL, + property VARCHAR2(256) NOT NULL, + PRIMARY KEY(id) + ) + "); + $this->addSql(" + DECLARE constraints_Count NUMBER; BEGIN + SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count + FROM USER_CONSTRAINTS + WHERE TABLE_NAME = 'CLARO_PROFILE_PROPERTY' + AND CONSTRAINT_TYPE = 'P'; IF constraints_Count = 0 + OR constraints_Count = '' THEN EXECUTE IMMEDIATE 'ALTER TABLE CLARO_PROFILE_PROPERTY ADD CONSTRAINT CLARO_PROFILE_PROPERTY_AI_PK PRIMARY KEY (ID)'; END IF; END; + "); + $this->addSql(" + CREATE SEQUENCE CLARO_PROFILE_PROPERTY_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1 + "); + $this->addSql(" + CREATE TRIGGER CLARO_PROFILE_PROPERTY_AI_PK BEFORE INSERT ON CLARO_PROFILE_PROPERTY FOR EACH ROW DECLARE last_Sequence NUMBER; last_InsertID NUMBER; BEGIN + SELECT CLARO_PROFILE_PROPERTY_SEQ.NEXTVAL INTO : NEW.ID + FROM DUAL; IF ( + : NEW.ID IS NULL + OR : NEW.ID = 0 + ) THEN + SELECT CLARO_PROFILE_PROPERTY_SEQ.NEXTVAL INTO : NEW.ID + FROM DUAL; ELSE + SELECT NVL(Last_Number, 0) INTO last_Sequence + FROM User_Sequences + WHERE Sequence_Name = 'CLARO_PROFILE_PROPERTY_SEQ'; + SELECT : NEW.ID INTO last_InsertID + FROM DUAL; WHILE (last_InsertID > last_Sequence) LOOP + SELECT CLARO_PROFILE_PROPERTY_SEQ.NEXTVAL INTO last_Sequence + FROM DUAL; END LOOP; END IF; END; + "); + $this->addSql(" + CREATE INDEX IDX_C2B93182D60322AC ON claro_profile_property (role_id) + "); + $this->addSql(" + ALTER TABLE claro_profile_property + ADD CONSTRAINT FK_C2B93182D60322AC FOREIGN KEY (role_id) + REFERENCES claro_role (id) + ON DELETE CASCADE + "); + } + + public function down(Schema $schema) + { + $this->addSql(" + DROP TABLE claro_profile_property + "); + } +} \ No newline at end of file diff --git a/Migrations/pdo_mysql/Version20150213094501.php b/Migrations/pdo_mysql/Version20150213094501.php new file mode 100644 index 000000000..f5356f90c --- /dev/null +++ b/Migrations/pdo_mysql/Version20150213094501.php @@ -0,0 +1,41 @@ +addSql(" + CREATE TABLE claro_profile_property ( + id INT AUTO_INCREMENT NOT NULL, + role_id INT DEFAULT NULL, + is_editable TINYINT(1) NOT NULL, + property VARCHAR(256) NOT NULL, + INDEX IDX_C2B93182D60322AC (role_id), + PRIMARY KEY(id) + ) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB + "); + $this->addSql(" + ALTER TABLE claro_profile_property + ADD CONSTRAINT FK_C2B93182D60322AC FOREIGN KEY (role_id) + REFERENCES claro_role (id) + ON DELETE CASCADE + "); + } + + public function down(Schema $schema) + { + $this->addSql(" + DROP TABLE claro_profile_property + "); + } +} \ No newline at end of file diff --git a/Migrations/pdo_oci/Version20150213094501.php b/Migrations/pdo_oci/Version20150213094501.php new file mode 100644 index 000000000..8bd78eb3e --- /dev/null +++ b/Migrations/pdo_oci/Version20150213094501.php @@ -0,0 +1,71 @@ +addSql(" + CREATE TABLE claro_profile_property ( + id NUMBER(10) NOT NULL, + role_id NUMBER(10) DEFAULT NULL NULL, + is_editable NUMBER(1) NOT NULL, + property VARCHAR2(256) NOT NULL, + PRIMARY KEY(id) + ) + "); + $this->addSql(" + DECLARE constraints_Count NUMBER; BEGIN + SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count + FROM USER_CONSTRAINTS + WHERE TABLE_NAME = 'CLARO_PROFILE_PROPERTY' + AND CONSTRAINT_TYPE = 'P'; IF constraints_Count = 0 + OR constraints_Count = '' THEN EXECUTE IMMEDIATE 'ALTER TABLE CLARO_PROFILE_PROPERTY ADD CONSTRAINT CLARO_PROFILE_PROPERTY_AI_PK PRIMARY KEY (ID)'; END IF; END; + "); + $this->addSql(" + CREATE SEQUENCE CLARO_PROFILE_PROPERTY_SEQ START WITH 1 MINVALUE 1 INCREMENT BY 1 + "); + $this->addSql(" + CREATE TRIGGER CLARO_PROFILE_PROPERTY_AI_PK BEFORE INSERT ON CLARO_PROFILE_PROPERTY FOR EACH ROW DECLARE last_Sequence NUMBER; last_InsertID NUMBER; BEGIN + SELECT CLARO_PROFILE_PROPERTY_SEQ.NEXTVAL INTO : NEW.ID + FROM DUAL; IF ( + : NEW.ID IS NULL + OR : NEW.ID = 0 + ) THEN + SELECT CLARO_PROFILE_PROPERTY_SEQ.NEXTVAL INTO : NEW.ID + FROM DUAL; ELSE + SELECT NVL(Last_Number, 0) INTO last_Sequence + FROM User_Sequences + WHERE Sequence_Name = 'CLARO_PROFILE_PROPERTY_SEQ'; + SELECT : NEW.ID INTO last_InsertID + FROM DUAL; WHILE (last_InsertID > last_Sequence) LOOP + SELECT CLARO_PROFILE_PROPERTY_SEQ.NEXTVAL INTO last_Sequence + FROM DUAL; END LOOP; END IF; END; + "); + $this->addSql(" + CREATE INDEX IDX_C2B93182D60322AC ON claro_profile_property (role_id) + "); + $this->addSql(" + ALTER TABLE claro_profile_property + ADD CONSTRAINT FK_C2B93182D60322AC FOREIGN KEY (role_id) + REFERENCES claro_role (id) + ON DELETE CASCADE + "); + } + + public function down(Schema $schema) + { + $this->addSql(" + DROP TABLE claro_profile_property + "); + } +} \ No newline at end of file diff --git a/Migrations/pdo_pgsql/Version20150213094501.php b/Migrations/pdo_pgsql/Version20150213094501.php new file mode 100644 index 000000000..891f8e76f --- /dev/null +++ b/Migrations/pdo_pgsql/Version20150213094501.php @@ -0,0 +1,43 @@ +addSql(" + CREATE TABLE claro_profile_property ( + id SERIAL NOT NULL, + role_id INT DEFAULT NULL, + is_editable BOOLEAN NOT NULL, + property VARCHAR(256) NOT NULL, + PRIMARY KEY(id) + ) + "); + $this->addSql(" + CREATE INDEX IDX_C2B93182D60322AC ON claro_profile_property (role_id) + "); + $this->addSql(" + ALTER TABLE claro_profile_property + ADD CONSTRAINT FK_C2B93182D60322AC FOREIGN KEY (role_id) + REFERENCES claro_role (id) + ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE + "); + } + + public function down(Schema $schema) + { + $this->addSql(" + DROP TABLE claro_profile_property + "); + } +} \ No newline at end of file diff --git a/Migrations/pdo_sqlite/Version20150213094501.php b/Migrations/pdo_sqlite/Version20150213094501.php new file mode 100644 index 000000000..c1b9a0981 --- /dev/null +++ b/Migrations/pdo_sqlite/Version20150213094501.php @@ -0,0 +1,37 @@ +addSql(" + CREATE TABLE claro_profile_property ( + id INTEGER NOT NULL, + role_id INTEGER DEFAULT NULL, + is_editable BOOLEAN NOT NULL, + property VARCHAR(256) NOT NULL, + PRIMARY KEY(id) + ) + "); + $this->addSql(" + CREATE INDEX IDX_C2B93182D60322AC ON claro_profile_property (role_id) + "); + } + + public function down(Schema $schema) + { + $this->addSql(" + DROP TABLE claro_profile_property + "); + } +} \ No newline at end of file diff --git a/Migrations/pdo_sqlsrv/Version20150213094501.php b/Migrations/pdo_sqlsrv/Version20150213094501.php new file mode 100644 index 000000000..1db15b7b5 --- /dev/null +++ b/Migrations/pdo_sqlsrv/Version20150213094501.php @@ -0,0 +1,43 @@ +addSql(" + CREATE TABLE claro_profile_property ( + id INT IDENTITY NOT NULL, + role_id INT, + is_editable BIT NOT NULL, + property NVARCHAR(256) NOT NULL, + PRIMARY KEY (id) + ) + "); + $this->addSql(" + CREATE INDEX IDX_C2B93182D60322AC ON claro_profile_property (role_id) + "); + $this->addSql(" + ALTER TABLE claro_profile_property + ADD CONSTRAINT FK_C2B93182D60322AC FOREIGN KEY (role_id) + REFERENCES claro_role (id) + ON DELETE CASCADE + "); + } + + public function down(Schema $schema) + { + $this->addSql(" + DROP TABLE claro_profile_property + "); + } +} \ No newline at end of file diff --git a/Migrations/sqlanywhere/Version20150213094501.php b/Migrations/sqlanywhere/Version20150213094501.php new file mode 100644 index 000000000..f433b2c60 --- /dev/null +++ b/Migrations/sqlanywhere/Version20150213094501.php @@ -0,0 +1,43 @@ +addSql(" + CREATE TABLE claro_profile_property ( + id INT IDENTITY NOT NULL, + role_id INT DEFAULT NULL, + is_editable BIT NOT NULL, + property VARCHAR(256) NOT NULL, + PRIMARY KEY (id) + ) + "); + $this->addSql(" + CREATE INDEX IDX_C2B93182D60322AC ON claro_profile_property (role_id) + "); + $this->addSql(" + ALTER TABLE claro_profile_property + ADD CONSTRAINT FK_C2B93182D60322AC FOREIGN KEY (role_id) + REFERENCES claro_role (id) + ON DELETE CASCADE + "); + } + + public function down(Schema $schema) + { + $this->addSql(" + DROP TABLE claro_profile_property + "); + } +} \ No newline at end of file diff --git a/Migrations/sqlsrv/Version20150213094501.php b/Migrations/sqlsrv/Version20150213094501.php new file mode 100644 index 000000000..f7f4801be --- /dev/null +++ b/Migrations/sqlsrv/Version20150213094501.php @@ -0,0 +1,43 @@ +addSql(" + CREATE TABLE claro_profile_property ( + id INT IDENTITY NOT NULL, + role_id INT, + is_editable BIT NOT NULL, + property NVARCHAR(256) NOT NULL, + PRIMARY KEY (id) + ) + "); + $this->addSql(" + CREATE INDEX IDX_C2B93182D60322AC ON claro_profile_property (role_id) + "); + $this->addSql(" + ALTER TABLE claro_profile_property + ADD CONSTRAINT FK_C2B93182D60322AC FOREIGN KEY (role_id) + REFERENCES claro_role (id) + ON DELETE CASCADE + "); + } + + public function down(Schema $schema) + { + $this->addSql(" + DROP TABLE claro_profile_property + "); + } +} \ No newline at end of file diff --git a/Persistence/ObjectManager.php b/Persistence/ObjectManager.php index ffe1fb29f..41fdebb9c 100644 --- a/Persistence/ObjectManager.php +++ b/Persistence/ObjectManager.php @@ -84,7 +84,7 @@ public function flush() parent::flush(); } } - + /** * Starts a flush suite. Until the suite is ended by a call to "endFlushSuite", * all the flush operations are suspended. Flush suites can be nested, which means diff --git a/Repository/ProfilePropertyRepository.php b/Repository/ProfilePropertyRepository.php new file mode 100644 index 000000000..c6e494562 --- /dev/null +++ b/Repository/ProfilePropertyRepository.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Claroline\CoreBundle\Repository; + +use Doctrine\ORM\EntityRepository; + +class ProfilePropertyRepository extends EntityRepository +{ + /** + * Returns the accesses for a list of roles + */ + public function findAccessesByRoles(array $roles) + { + $dql = ' + SELECT pp.property as property, MAX(pp.isEditable) as isEditable + FROM Claroline\CoreBundle\Entity\ProfileProperty pp + JOIN pp.role role + WHERE role.name in (:roleNames) + GROUP BY pp.property + '; + + $query = $this->_em->createQuery($dql); + $query->setParameter('roleNames', $roles); + + $results = $query->getResult(); + $properties = array(); + + foreach ($results as $result) { + $properties[$result['property']] = (boolean) $result['isEditable']; + } + + return $properties; + } +} diff --git a/Resources/public/js/administration/profileProperties.js b/Resources/public/js/administration/profileProperties.js new file mode 100644 index 000000000..5ee965cd9 --- /dev/null +++ b/Resources/public/js/administration/profileProperties.js @@ -0,0 +1,11 @@ +$('.property-chk').on('change', function(event) { + var route = Routing.generate( + 'claro_admin_invert_user_properties_edition', + {'property': $(this).attr('data-property-id')} + ); + $.ajax({ + url: route, + success: function() { + } + }); +}); diff --git a/Resources/translations/platform.en.yml b/Resources/translations/platform.en.yml index 92f58a4f7..6187a8c83 100644 --- a/Resources/translations/platform.en.yml +++ b/Resources/translations/platform.en.yml @@ -1121,3 +1121,8 @@ add_panel_to_facet: Add a panel create_pane: Create a pane collapse: Collapse edit_panel_facet: Edit a panel +administrativeCode: administrativeCode +property: Property +picture: User picture +profile_properties_management: Profile properties management +facet_management: Facet management diff --git a/Resources/translations/platform.es.yml b/Resources/translations/platform.es.yml index 1fb559b2f..896fbe3c1 100644 --- a/Resources/translations/platform.es.yml +++ b/Resources/translations/platform.es.yml @@ -968,3 +968,8 @@ add_panel_to_facet: add_panel_to_facet create_pane: create_pane collapse: collapse edit_panel_facet: edit_panel_facet +administrativeCode: administrativeCode +property: property +picture: picture +profile_properties_management: profile_properties_management +facet_management: facet_management diff --git a/Resources/translations/platform.fr.yml b/Resources/translations/platform.fr.yml index 6c1d50b14..43cc2ac2a 100644 --- a/Resources/translations/platform.fr.yml +++ b/Resources/translations/platform.fr.yml @@ -1128,3 +1128,8 @@ add_panel_to_facet: Ajouter un panel create_pane: Créer un panel collapse: Replier edit_panel_facet: Modifier un panel +administrativeCode: Code administratif +property: Propriété +picture: Photo de profil +profile_properties_management: Gestion des propriétés du profil +facet_management: Gestion des facets diff --git a/Resources/views/Administration/Facet/facets.html.twig b/Resources/views/Administration/Facet/facets.html.twig new file mode 100644 index 000000000..faaedf152 --- /dev/null +++ b/Resources/views/Administration/Facet/facets.html.twig @@ -0,0 +1,140 @@ +{% extends "ClarolineCoreBundle:Administration:layout.html.twig" %} + +{% block title %}{{ parent() ~ ' - ' ~ 'users_management' | trans({}, 'platform') | striptags | raw }}{% endblock %} + +{% block breadcrumb %} + {{ + macros.breadcrumbs([ + { + 'icon': 'fa fa-cog', + 'name': 'administration'|trans({}, 'platform'), + 'href': path('claro_admin_index') + }, + { + 'name': 'users_management'|trans({}, 'platform'), + 'href': path('claro_admin_users_management') + }, + { + 'name': 'profile_management'|trans({}, 'platform'), + 'href': path('claro_admin_facet_index') + }, + { + 'name': 'facet_management'|trans({}, 'platform'), + 'href': '' + } + ]) + }} +{% endblock %} + +{% block section_content %} +
{{ 'property'|trans({}, 'platform') }} + {% for role in platformRoles %} + | {{ role.getTranslationKey()|trans({}, 'platform') }} | + {% endfor %} +
---|---|
{{ label|trans({}, 'platform') }} | + {% for role in platformRoles %} + {% for property in properties %} + {% if property.getProperty() == label and property.getRole() == role %} ++ + + | + {% endif %} + {% endfor %} + {% endfor %} +