diff --git a/lib/classes/ACL.class.php b/lib/classes/ACL.class.php index 3f8ffd0ff0..26949a568f 100644 --- a/lib/classes/ACL.class.php +++ b/lib/classes/ACL.class.php @@ -47,6 +47,7 @@ class ACL implements cache_cacheableInterface * @var Array */ protected $_rights_records_preview; + /** * * @var Array @@ -242,47 +243,88 @@ class ACL implements cache_cacheableInterface if (count($base_ids) == 0) return $this; - $params = array( - ':usr_id' => $this->user->get_id() - , ':template_id' => $template_user->get_id() + $sbas_ids = array(); + + foreach ($base_ids as $base_id) + { + $sbas_ids[] = phrasea::sbasFromBas($base_id); + } + + $sbas_ids = array_unique($sbas_ids); + + $sbas_rights = array('bas_manage', 'bas_modify_struct', 'bas_modif_th', 'bas_chupub'); + + $sbas_to_acces = array(); + $rights_to_give = array(); + + foreach ($template_user->ACL()->get_granted_sbas() as $databox) + { + $sbas_id = $databox->get_sbas_id(); + + if (!in_array($sbas_id, $sbas_ids)) + continue; + + + if (!$this->has_access_to_sbas($sbas_id)) + { + $sbas_to_acces[] = $sbas_id; + } + + foreach ($sbas_rights as $right) + { + if ($template_user->ACL()->has_right_on_sbas($sbas_id, $right)) + { + $rights_to_give[$sbas_id][$right] = '1'; + } + } + } + + $this->give_access_to_sbas($sbas_to_acces); + + foreach ($rights_to_give as $sbas_id => $rights) + { + $this->update_rights_to_sbas($sbas_id, $rights); + } + + $bas_rights = array('canputinalbum', 'candwnldhd' + , 'candwnldpreview', 'cancmd' + , 'canadmin', 'actif', 'canreport', 'canpush' + , 'canaddrecord', 'canmodifrecord', 'candeleterecord' + , 'chgstatus', 'imgtools' + , 'manage', 'modify_struct' + , 'nowatermark', 'order_master' ); - $sql = 'INSERT INTO sbasusr - (SELECT distinct null as sbasusr_id, sb.sbas_id, :usr_id as usr_id, bas_manage - , bas_modify_struct,bas_modif_th,bas_chupub - FROM sbasusr sb, bas b - WHERE b.base_id IN (' . implode(', ', $base_ids) . ') - AND b.sbas_id = sb.sbas_id - AND usr_id = :template_id)'; + $bas_to_acces = array(); + $rights_to_give = array(); - $stmt = $this->appbox->get_connection()->prepare($sql); - $stmt->execute($params); - $stmt->closeCursor(); + foreach ($template_user->ACL()->get_granted_base() as $collection) + { + $base_id = $collection->get_base_id(); - $this->delete_data_from_cache(self::CACHE_RIGHTS_SBAS); + if (!in_array($base_id, $base_ids)) + continue; - $sql = "INSERT INTO basusr - (SELECT null as id, base_id, :usr_id as usr_id, canputinalbum - , candwnldhd, candwnldsubdef, candwnldpreview, cancmd - , canadmin, actif, canreport, canpush, now() as creationdate - , basusr_infousr, mask_and, mask_xor, restrict_dwnld - , month_dwnld_max, remain_dwnld, time_limited, limited_from - , limited_to, canaddrecord, canmodifrecord, candeleterecord - , chgstatus, '0000-00-00 00:00:00' as lastconn, imgtools - , manage, modify_struct, bas_manage, bas_modify_struct - , nowatermark, order_master - FROM basusr - WHERE usr_id = - (SELECT usr_id - FROM usr WHERE usr_id = :template_id) - AND base_id IN (" . implode(', ', $base_ids) . "))"; + if (!$this->has_access_to_base($base_id)) + { + $bas_to_acces[] = $base_id; + } - $stmt = $this->appbox->get_connection()->prepare($sql); - $stmt->execute($params); - $stmt->closeCursor(); + foreach ($bas_rights as $right) + { + if ($template_user->ACL()->has_right_on_base($base_id, $right)) + { + $rights_to_give[$base_id][$right] = '1'; + } + } + } - $this->inject_rights(); - $this->delete_data_from_cache(self::CACHE_RIGHTS_BAS); + $this->give_access_to_base($bas_to_acces); + + foreach ($rights_to_give as $sbas_id => $rights) + { + $this->update_rights_to_base($base_id, $rights); + } $this->user->set_last_template($template_user); @@ -315,7 +357,7 @@ class ACL implements cache_cacheableInterface { return false; } - + if (!isset($this->_rights_bas[$base_id][$right])) throw new Exception('right ' . $right . ' does not exists'); @@ -750,7 +792,7 @@ class ACL implements cache_cacheableInterface { if ($this->_rights_bas && $this->_global_rights && is_array($this->_limited)) return $this; - + try { $this->_rights_bas = $this->get_data_from_cache(self::CACHE_RIGHTS_BAS); @@ -1399,12 +1441,12 @@ class ACL implements cache_cacheableInterface $this->load_rights_bas(); $datetime = new DateTime(); - + if (!isset($this->_limited[$base_id])) { return false; } - + $ret = ($this->_limited[$base_id]['dmin'] > $datetime || $this->_limited[$base_id]['dmax'] < $datetime); diff --git a/lib/classes/Controller/Admin/Users.class.php b/lib/classes/Controller/Admin/Users.class.php index 1c7c57437f..7f76233759 100644 --- a/lib/classes/Controller/Admin/Users.class.php +++ b/lib/classes/Controller/Admin/Users.class.php @@ -180,7 +180,7 @@ class Controller_Admin_Users implements ControllerProviderInterface } ); - $controllers->post('/search/', function() use ($app) + $controllers->match('/search/', function() use ($app) { $request = $app['request']; $users = new module_admin_route_users($request); @@ -194,17 +194,14 @@ class Controller_Admin_Users implements ControllerProviderInterface } ); - $controllers->get('/search/', function() use ($app) + $controllers->post('/apply_template/', function() use ($app) { $request = $app['request']; - $users = new module_admin_route_users($request); - $template = 'admin/users.html'; + $users = new module_admin_route_users_edit($request); + + $users->apply_template(); - $twig = new supertwig(); - $twig->addFilter(array('floor' => 'floor')); - $twig->addFilter(array('getDate' => 'phraseadate::getDate')); - - return $twig->render($template, $users->search($request)); + return new Symfony\Component\HttpFoundation\RedirectResponse('/admin/users/search/'); } ); diff --git a/lib/classes/Controller/RSSFeeds.class.php b/lib/classes/Controller/RSSFeeds.class.php index 3b3e55205f..94d03d2ef6 100644 --- a/lib/classes/Controller/RSSFeeds.class.php +++ b/lib/classes/Controller/RSSFeeds.class.php @@ -40,15 +40,21 @@ class Controller_RSSFeeds implements ControllerProviderInterface $registry = registry::get_instance(); - if ($format == 'rss') + if ($format == Feed_Adapter::FORMAT_RSS) { $content = new Feed_XML_RSS(); } - if ($format == 'atom') + + if ($format == Feed_Adapter::FORMAT_ATOM) { $content = new Feed_XML_Atom(); } - + + if($format == Feed_Adapter::FORMAT_COOLIRIS) + { + $content = new Feed_XML_Cooliris(); + } + if ($user instanceof User_Adapter) $link = $feed->get_user_link($registry, $user, $format, $page); else @@ -76,7 +82,7 @@ class Controller_RSSFeeds implements ControllerProviderInterface } foreach ($entries->get_entries() as $entry) $content->set_item($entry); - + $render = $content->render(); $response = new Response($render, 200, array('Content-Type' => $content->get_mimetype())); $response->setCharset('UTF-8'); @@ -160,6 +166,17 @@ class Controller_RSSFeeds implements ControllerProviderInterface return $display_feed($feed, $format, $page); })->assert('format', '(rss|atom)'); + $controllers->get('/cooliris/', function() use ($app, $appbox, $display_feed) { + $feeds = Feed_Collection::load_public_feeds($appbox); + $feed = $feeds->get_aggregate(); + + $request = $app['request']; + $page = (int) $request->get('page'); + $page = $page < 1 ? 1 : $page; + + return $display_feed($feed, Feed_Adapter::FORMAT_COOLIRIS , $page); + }); + return $controllers; } diff --git a/lib/classes/Feed/Abstract.class.php b/lib/classes/Feed/Abstract.class.php index 32fc3c3753..b9450c260d 100644 --- a/lib/classes/Feed/Abstract.class.php +++ b/lib/classes/Feed/Abstract.class.php @@ -25,6 +25,10 @@ abstract class Feed_Abstract * */ const FORMAT_ATOM = 'atom'; + /** + * + */ + const FORMAT_COOLIRIS = 'cooliris'; /** * diff --git a/lib/classes/Feed/Adapter.class.php b/lib/classes/Feed/Adapter.class.php index eb55cbaee0..0a5a301ca8 100644 --- a/lib/classes/Feed/Adapter.class.php +++ b/lib/classes/Feed/Adapter.class.php @@ -57,6 +57,8 @@ class Feed_Adapter extends Feed_Abstract implements Feed_Interface, cache_cachea const CACHE_ENTRY_NUMBER = 'entrynumber'; const CACHE_USER_TOKEN = 'usr_token'; + + const MAX_ENTRIES = 20; /** * @@ -561,7 +563,7 @@ class Feed_Adapter extends Feed_Abstract implements Feed_Interface, cache_cachea public function get_entries($offset_start, $how_many) { $offset_start = (int) $offset_start; - $how_many = $how_many > 20 ? 20 : (int) $how_many; + $how_many = $how_many > self::MAX_ENTRIES ? self::MAX_ENTRIES : (int) $how_many; $sql = 'SELECT id FROM feed_entries diff --git a/lib/classes/Feed/Aggregate.class.php b/lib/classes/Feed/Aggregate.class.php index 4367eda24e..6d1c083e5c 100644 --- a/lib/classes/Feed/Aggregate.class.php +++ b/lib/classes/Feed/Aggregate.class.php @@ -158,6 +158,16 @@ class Feed_Aggregate extends Feed_Abstract implements Feed_Interface , 'application/atom+xml' ); break; + case self::FORMAT_COOLIRIS: + return new Feed_Link( + sprintf('%sfeeds/cooliris/%s' + , $registry->get('GV_ServerName') + , ($page ? '?page=' . $page : '') + ) + , sprintf('%s - %s', $this->get_title(), 'RSS') + , 'application/rss+xml' + ); + break; default: case self::FORMAT_RSS: return new Feed_Link( diff --git a/lib/classes/Feed/XML/Cooliris.class.php b/lib/classes/Feed/XML/Cooliris.class.php new file mode 100644 index 0000000000..36d2f3830c --- /dev/null +++ b/lib/classes/Feed/XML/Cooliris.class.php @@ -0,0 +1,459 @@ +language = $language; + + return $this; + } + + /** + * + * @param string $language + * @return Feed_XML_RSS + */ + public function set_copyright($copyright) + { + $this->copyright = $copyright; + + return $this; + } + + /** + * + * @param string $managingEditor + * @return Feed_XML_RSS + */ + public function set_managingEditor($managingEditor) + { + $this->managingEditor = $managingEditor; + + return $this; + } + + /** + * + * @param string $webMaster + * @return Feed_XML_RSS + */ + public function set_webMaster($webMaster) + { + $this->webMaster = $webMaster; + + return $this; + } + + /** + * + * @param DateTime $lastBuildDate + * @return Feed_XML_RSS + */ + public function set_lastBuildDate(DateTime $lastBuildDate) + { + $this->lastBuildDate = $lastBuildDate; + + return $this; + } + + /** + * + * @param string $category + * @return Feed_XML_RSS + */ + public function set_category($category) + { + $this->categories[] = $category; + + return $this; + } + + /** + * + * @param string $docs + * @return Feed_XML_RSS + */ + public function set_docs($docs) + { + $this->docs = $docs; + + return $this; + } + + /** + * + * @param int $ttl + * @return Feed_XML_RSS + */ + public function set_ttl($ttl) + { + $this->ttl = $ttl; + + return $this; + } + + /** + * + * @param Feed_XML_RSS_Image $image + * @return Feed_XML_RSS + */ + public function set_image(Feed_XML_RSS_Image $image) + { + $this->image = $image; + + return $this; + } + + /** + * + * @param string $skipHours + * @return Feed_XML_RSS + */ + public function set_skipHour($hour) + { + $this->skipHours[] = (int) $hour; + + return $this; + } + + /** + * + * @param string $skipDays + * @return Feed_XML_RSS + */ + public function set_skipDays($day) + { + $this->skipDays[] = $day; + + return $this; + } + + /** + * + * @return string + */ + public function render() + { + $doc = new DOMDocument('1.0', 'UTF-8'); + $doc->formatOutput = true; + $doc->standalone = true; + + + $root = $this->addTag($doc, $doc, 'rss'); + + $root->setAttribute('version', self::VERSION); + $root->setAttribute('xmlns:media', 'http://search.yahoo.com/mrss/'); + $root->setAttribute('xmlns:atom', 'http://www.w3.org/2005/Atom'); + $root->setAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + + $channel = $this->addTag($doc, $root, 'channel'); + + $this->addTag($doc, $channel, 'title', $this->title); + $this->addTag($doc, $channel, 'dc:title', $this->title); + $this->addTag($doc, $channel, 'description', $this->subtitle); + if ($this->link instanceof Feed_Link) + $this->addTag($doc, $channel, 'link', $this->link->get_href()); + + if ($this->language) + $this->addTag($doc, $channel, 'language', $this->language); + if ($this->copyright) + $this->addTag($doc, $channel, 'copyright', $this->copyright); + if ($this->managingEditor) + $this->addTag($doc, $channel, 'managingEditor', $this->managingEditor); + if ($this->webMaster) + $this->addTag($doc, $channel, 'webMaster', $this->webMaster); + if ($this->updated_on instanceof DateTime) + { + $updated_on = $this->updated_on->format(DATE_RFC2822); + $this->addTag($doc, $channel, 'pubDate', $updated_on); + } + if ($this->lastBuildDate instanceof DateTime) + { + $last_build = $this->lastBuildDate->format(DATE_RFC2822); + $this->addTag($doc, $channel, 'lastBuildDate', $last_build); + } + if (count($this->categories) > 0) + { + foreach ($this->categories as $category) + { + $this->addTag($doc, $channel, 'category', $category); + } + } + if ($this->generator) + $this->addTag($doc, $channel, 'generator', $this->generator); + if ($this->docs) + $this->addTag($doc, $channel, 'docs', $this->docs); + if ($this->ttl) + $this->addTag($doc, $channel, 'ttl', $this->ttl); + if ($this->image instanceof Feed_XML_RSS_Image) + { + $image = $this->addTag($doc, $channel, 'image'); + $this->addTag($doc, $image, 'url', $this->image->get_url()); + $this->addTag($doc, $image, 'title', $this->image->get_title()); + $this->addTag($doc, $image, 'link', $this->image->get_link()); + if ($this->image->get_width()) + $this->addTag($doc, $image, 'width', $this->image->get_width()); + if ($this->image->get_height()) + $this->addTag($doc, $image, 'height', $this->image->get_height()); + if ($this->image->get_description()) + $this->addTag($doc, $image, 'description', $this->image->get_description()); + } + if (count($this->skipHours)) + { + $skipHours = $this->addTag($doc, $channel, 'skipHours'); + foreach ($this->skipHours as $hour) + { + $this->addTag($doc, $skipHours, 'hour', $hour); + } + } + if (count($this->skipDays) > 0) + { + $skipDays = $this->addTag($doc, $channel, 'skipDays'); + foreach ($this->skipDays as $day) + { + $this->addTag($doc, $skipDays, 'day', $day); + } + } + if ($this->link instanceof Feed_Link) + { + $self_link = $this->addTag($doc, $channel, 'atom:link'); + $self_link->setAttribute('rel', 'self'); + $self_link->setAttribute('href', $this->link->get_href()); + } + + $this->add_navigation($doc, $channel, true); + + foreach ($this->items as $item) + { + $this->add_item($doc, $channel, $item); + } + + return $doc->saveXML(); + } + + /** + * + * @param DOMDocument $document + * @param DOMNode $node + * @param Feed_Entry_Adapter $entry + * @return DOMElement + */ + protected function add_item(DOMDocument $document, DOMNode $node, Feed_Entry_Adapter $entry) + { + foreach ($entry->get_content() as $content) + { + $this->addContent($document, $node, $entry, $content); + } + + return; + } + + /** + * + * @param DOMDocument $document + * @param DOMNode $item + * @param Feed_Entry_Item $content + * @return Feed_XML_Interface + */ + protected function addContent(DOMDocument $document, DOMNode $node, Feed_Entry_Adapter $entry, Feed_Entry_Item $content) + { + + $preview_sd = $content->get_record()->get_subdef('preview'); + $preview_permalink = $preview_sd->get_permalink(); + $thumbnail_sd = $content->get_record()->get_thumbnail(); + $thumbnail_permalink = $thumbnail_sd->get_permalink(); + + $medium = strtolower($content->get_record()->get_type()); + + if (!in_array($medium, array('image', 'audio', 'video'))) + return $this; + + if (!$preview_permalink || !$thumbnail_permalink) + return $this; + + //add item node to channel node + $item = $this->addTag($document, $node, 'item'); + + $title_field = $content->get_record()->get_caption()->get_dc_field(databox_Field_DCESAbstract::Title); + if ($title_field) + { + $str_title = $title_field->get_value(true, ' '); + } + else + { + $str_title = $content->get_record()->get_title(); + } + + //attach tile node to item node + $title = $this->addTag($document, $item, 'title', $str_title); + + $desc_field = $content->get_record()->get_caption()->get_dc_field(databox_Field_DCESAbstract::Description); + if ($desc_field) + { + $str_desc = $desc_field->get_value(true, ' '); + } + else + { + $str_desc = ''; + } + + //attach desc node to item node + $desc = $this->addTag($document, $item, 'description', $str_desc); + + $duration = $content->get_record()->get_duration(); + + if ($preview_permalink) + { + $preview = $this->addTag($document, $item, 'media:content'); + + $preview->setAttribute('url', $preview_permalink->get_url()); + $preview->setAttribute('fileSize', $preview_sd->get_size()); + $preview->setAttribute('type', $preview_sd->get_mime()); + $preview->setAttribute('medium', $medium); + $preview->setAttribute('expression', 'full'); + $preview->setAttribute('isDefault', 'true'); + + if ($preview_sd->get_width()) + $preview->setAttribute('width', $preview_sd->get_width()); + if ($preview_sd->get_height()) + $preview->setAttribute('height', $preview_sd->get_height()); + if ($duration) + $preview->setAttribute('duration', $duration); + } + + if ($thumbnail_permalink) + { + $thumbnail = $this->addTag($document, $item, 'media:thumbnail'); + + $thumbnail->setAttribute('url', $thumbnail_permalink->get_url()); + + if ($thumbnail_sd->get_width()) + $thumbnail->setAttribute('width', $thumbnail_sd->get_width()); + if ($thumbnail_sd->get_height()) + $thumbnail->setAttribute('height', $thumbnail_sd->get_height()); + + + $thumbnail = $this->addTag($document, $item, 'media:content'); + + $thumbnail->setAttribute('url', $thumbnail_permalink->get_url()); + $thumbnail->setAttribute('fileSize', $thumbnail_sd->get_size()); + $thumbnail->setAttribute('type', $thumbnail_sd->get_mime()); + $thumbnail->setAttribute('medium', $medium); + $thumbnail->setAttribute('isDefault', 'false'); + + if ($thumbnail_sd->get_width()) + $thumbnail->setAttribute('width', $thumbnail_sd->get_width()); + if ($thumbnail_sd->get_height()) + $thumbnail->setAttribute('height', $thumbnail_sd->get_height()); + if ($duration) + $thumbnail->setAttribute('duration', $duration); + } + + return $this; + } + +} diff --git a/lib/classes/PHPShortener.class.php b/lib/classes/PHPShortener.class.php new file mode 100644 index 0000000000..d0d62c8e4d --- /dev/null +++ b/lib/classes/PHPShortener.class.php @@ -0,0 +1,3 @@ +is_authenticated()) return; - $user = User_Adapter::getInstance($this->get_usr_id(), $this->appbox); - $user->ACL()->delete_injected_rights(); + $this->storage()->reset(); $this->close_phrasea_session(); diff --git a/lib/classes/User/Adapter.class.php b/lib/classes/User/Adapter.class.php index 8061239e92..e26e437097 100644 --- a/lib/classes/User/Adapter.class.php +++ b/lib/classes/User/Adapter.class.php @@ -894,6 +894,11 @@ class User_Adapter implements User_Interface, cache_cacheableInterface return $this->is_template; } + public function get_template_owner() + { + return $this->template_owner; + } + public static function get_usr_id_from_email($email) { if(is_null($email)) diff --git a/lib/classes/User/Query.class.php b/lib/classes/User/Query.class.php index 16a73a413a..4794c485c2 100644 --- a/lib/classes/User/Query.class.php +++ b/lib/classes/User/Query.class.php @@ -88,6 +88,11 @@ class User_Query implements User_QueryInterface * @var boolean */ protected $include_templates = false; + /** + * + * @var boolean + */ + protected $only_templates = false; /** * * @var Array @@ -123,10 +128,10 @@ class User_Query implements User_QueryInterface const SORT_FIRSTNAME= 'usr_prenom'; const SORT_LASTNAME= 'usr_nom'; const SORT_COMPANY = 'societe'; - const SORT_LOGIN = 'login'; + const SORT_LOGIN = 'usr_login'; const SORT_EMAIL = 'usr_mail'; const SORT_ID = 'usr_id'; - const SORT_CREATIONDATE = 'creationdate'; + const SORT_CREATIONDATE = 'usr_creationdate'; const SORT_COUNTRY = 'pays'; const SORT_LASTMODEL = 'lastModel'; @@ -191,18 +196,22 @@ class User_Query implements User_QueryInterface $sql .= ' AND usr_login NOT LIKE "(#deleted_%" '; - if ($this->include_invite) + if (!$this->include_invite) { $sql .= ' AND usr.invite=0 '; } - if ($this->include_templates === false) + if ($this->only_templates === true) + { + $sql .= ' AND model_of = ' . $session->get_usr_id(); + } + elseif ($this->include_templates === false) { $sql .= ' AND model_of=0'; } else { - $sql .= ' AND (model_of=0 OR model_of= ' . $session->get_usr_id() . ' ) '; + $sql .= ' AND (model_of=0 OR model_of = ' . $session->get_usr_id() . ' ) '; } $baslist = array(); @@ -355,6 +364,17 @@ class User_Query implements User_QueryInterface return $this; } + /** + * + * @param boolean $boolean + * @return User_Query + */ + public function only_templates($boolean) + { + $this->only_templates = !!$boolean; + + return $this; + } /** * @@ -390,6 +410,8 @@ class User_Query implements User_QueryInterface case self::SORT_COMPANY: case self::SORT_LOGIN: case self::SORT_EMAIL: + $sorter[$k] = ' usr.`' . $sort . '` COLLATE utf8_unicode_ci '; + break; case self::SORT_ID: case self::SORT_CREATIONDATE: case self::SORT_COUNTRY: @@ -410,7 +432,7 @@ class User_Query implements User_QueryInterface $sorter[$k] .= ' ASC '; break; case self::ORD_DESC: - $sorter[$k] .= ' ASC '; + $sorter[$k] .= ' DESC '; break; } } diff --git a/lib/classes/caption/field.class.php b/lib/classes/caption/field.class.php index 5cf9917ae2..1b343b8e9f 100644 --- a/lib/classes/caption/field.class.php +++ b/lib/classes/caption/field.class.php @@ -206,6 +206,9 @@ class caption_field implements cache_cacheableInterface */ protected static function serialize_value(Array $value, $separator) { + if(strlen($separator) > 1) + $separator = $separator[0]; + if (trim($separator) === '') $separator = ' '; else @@ -346,9 +349,9 @@ class caption_field implements cache_cacheableInterface if ($this->databox_field->is_multi() === true) { if ($as_string === true && $custom_separator === false) - + { return $this->value; - + } $separator = $this->databox_field->get_separator(); $array_values = self::get_multi_values($this->value, $separator); diff --git a/lib/classes/caption/record.class.php b/lib/classes/caption/record.class.php index fd608c404f..c5073e43f2 100644 --- a/lib/classes/caption/record.class.php +++ b/lib/classes/caption/record.class.php @@ -59,8 +59,7 @@ class caption_record implements caption_interface, cache_cacheableInterface protected function retrieve_fields() { - if(is_array($this->fields)) - + if (is_array($this->fields)) return $this->fields; $fields = array(); @@ -97,7 +96,7 @@ class caption_record implements caption_interface, cache_cacheableInterface } catch (Exception $e) { - + } } $this->fields = $rec_fields; @@ -134,7 +133,6 @@ class caption_record implements caption_interface, cache_cacheableInterface { $fields = $this->retrieve_fields(); if (isset($this->dces_elements[$label])) - return $fields[$this->dces_elements[$label]]; return null; } @@ -172,7 +170,10 @@ class caption_record implements caption_interface, cache_cacheableInterface , $field->highlight_thesaurus() ); - $fields[$field->get_name()] = $value; + $fields[$field->get_name()] = array( + 'value' => $value + , 'separator' => $field->get_databox_field()->get_separator() + ); } if ($searchEngine instanceof searchEngine_adapter) @@ -185,7 +186,7 @@ class caption_record implements caption_interface, cache_cacheableInterface foreach ($fields as $key => $value) { - $fields[$key] = $ret[$n]; + $fields[$key]['value'] = $ret[$n]; $n++; } } diff --git a/lib/classes/databox.class.php b/lib/classes/databox.class.php index 210fcad890..7ac6ee415f 100644 --- a/lib/classes/databox.class.php +++ b/lib/classes/databox.class.php @@ -142,7 +142,7 @@ class databox extends base } catch (Exception $e) { - + } } @@ -157,7 +157,7 @@ class databox extends base } catch (Exception $e) { - + } $conn = connection::getPDOConnection(); @@ -277,6 +277,7 @@ class databox extends base SUM(1) AS n, SUM(size) AS siz FROM (record, subdef) LEFT JOIN coll ON record.coll_id=coll.coll_id WHERE record.record_id = subdef.record_id + GROUP BY record.coll_id, name UNION SELECT coll.coll_id, 0, asciiname, '_' AS name, 0 AS n, 0 AS siz FROM coll LEFT JOIN record ON record.coll_id=coll.coll_id @@ -450,7 +451,6 @@ class databox extends base $stmt->closeCursor(); if ($row) - return self::get_instance((int) $row['sbas_id']); try @@ -463,7 +463,7 @@ class databox extends base } catch (Exception $e) { - + } $sql = 'USE `' . $dbname . '`'; @@ -575,7 +575,6 @@ class databox extends base public function get_meta_structure() { if ($this->meta_struct) - return $this->meta_struct; try @@ -698,7 +697,6 @@ class databox extends base } } if ($n > $limit) - return true; return false; @@ -960,15 +958,24 @@ class databox extends base $this->saveStructure($dom_struct); $type = isset($field['type']) ? $field['type'] : 'string'; - $type = in_array($type, array(databox_field::TYPE_DATE, databox_field::TYPE_NUMBER, databox_field::TYPE_TEXT)) ? $type : databox_field::TYPE_TEXT; + $type = in_array($type + , array( + databox_field::TYPE_DATE + , databox_field::TYPE_NUMBER + , databox_field::TYPE_STRING + , databox_field::TYPE_TEXT + ) + ) ? $type : databox_field::TYPE_STRING; $meta_struct_field = databox_field::create($this, $fname); $meta_struct_field ->set_readonly(isset($field['readonly']) ? $field['readonly'] : 0) ->set_indexable(isset($field['index']) ? $field['index'] : '1') + ->set_separator(isset($field['separator']) ? $field['separator'] : '') + ->set_required((isset($field['required']) && $field['required'] == 1)) ->set_type($type) ->set_tbranch(isset($field['tbranch']) ? $field['tbranch'] : '') - ->set_thumbtitle(isset($field['thumbtitle']) ? $field['thumbtitle'] : '0') + ->set_thumbtitle(isset($field['thumbtitle']) ? $field['thumbtitle'] : (isset($field['thumbTitle']) ? $field['thumbTitle'] : '0')) ->set_multi(isset($field['multi']) ? $field['multi'] : 0) ->set_report(isset($field['report']) ? $field['report'] : '1') ->save(); @@ -979,7 +986,7 @@ class databox extends base } catch (Exception $e) { - + } if (isset($field['regname'])) @@ -1213,7 +1220,6 @@ class databox extends base public function get_structure() { if ($this->structure) - return $this->structure; $this->structure = $this->retrieve_structure(); @@ -1228,7 +1234,7 @@ class databox extends base } catch (Exception $e) { - + } $structure = null; @@ -1254,7 +1260,6 @@ class databox extends base public function get_cterms() { if ($this->cterms) - return $this->cterms; $sql = "SELECT value FROM pref WHERE prop='cterms'"; @@ -1421,7 +1426,6 @@ class databox extends base public function get_cgus() { if ($this->cgus) - return $this->cgus; $this->load_cgus(); @@ -1439,7 +1443,7 @@ class databox extends base } catch (Exception $e) { - + } $sql = 'SELECT value, locale, updated_on FROM pref WHERE prop ="ToU"'; diff --git a/lib/classes/databox/field.class.php b/lib/classes/databox/field.class.php index cb83c8b037..7f36cab930 100644 --- a/lib/classes/databox/field.class.php +++ b/lib/classes/databox/field.class.php @@ -124,6 +124,7 @@ class databox_field implements cache_cacheableInterface const TYPE_TEXT = "text"; const TYPE_DATE = "date"; + const TYPE_STRING = "string"; const TYPE_NUMBER = "number"; /** @@ -176,7 +177,7 @@ class databox_field implements cache_cacheableInterface $this->required = !!$row['required']; $this->multi = !!$row['multi']; $this->report = !!$row['report']; - $this->type = $row['type']; + $this->type = $row['type'] ?: self::TYPE_STRING; $this->tbranch = $row['tbranch']; if ($row['dces_element']) { @@ -551,6 +552,9 @@ class databox_field implements cache_cacheableInterface */ public function set_separator($separator) { + if (strpos($separator, ';') === false) + $separator .= ';'; + $this->separator = $separator; return $this; diff --git a/lib/classes/module/admin/route/users.class.php b/lib/classes/module/admin/route/users.class.php index d7c5b1b88f..eefd77e8a8 100644 --- a/lib/classes/module/admin/route/users.class.php +++ b/lib/classes/module/admin/route/users.class.php @@ -106,12 +106,19 @@ class module_admin_route_users if (is_null($v)) $this->query_parms[$k] = false; } + + + $query = new User_Query($appbox); + $templates = $query + ->only_templates(true) + ->execute()->get_results(); return array( 'users' => $this->results, 'parm' => $this->query_parms, 'invite_user' => $invite, - 'autoregister_user' => $autoregister + 'autoregister_user' => $autoregister, + 'templates' => $templates ); } diff --git a/lib/classes/module/admin/route/users/edit.class.php b/lib/classes/module/admin/route/users/edit.class.php index c8f3472889..b9161d94ae 100644 --- a/lib/classes/module/admin/route/users/edit.class.php +++ b/lib/classes/module/admin/route/users/edit.class.php @@ -536,6 +536,13 @@ class module_admin_route_users_edit return $this; } + $user = User_adapter::getInstance(array_pop($this->users), appbox::get_instance()); + + if ($user->is_template()) + { + return $this; + } + $appbox = appbox::get_instance(); $session = $appbox->get_session(); $request = http_request::getInstance(); @@ -580,6 +587,36 @@ class module_admin_route_users_edit return $this; } + public function apply_template() + { + $appbox = appbox::get_instance(); + $session = $appbox->get_session(); + + $template = \User_adapter::getInstance($this->request->get('template'), $appbox); + + if ($template->get_template_owner()->get_id() != $session->get_usr_id()) + { + throw new \Exception_Forbidden('You are not the owner of the template'); + } + + $current_user = \User_adapter::getInstance($session->get_usr_id(), $appbox); + $base_ids = array_keys($current_user->ACL()->get_granted_base(array('canadmin'))); + + foreach ($this->users as $usr_id) + { + $user = \User_adapter::getInstance($usr_id, $appbox); + + if($user->is_template()) + { + continue; + } + + $user->ACL()->apply_model($template, $base_ids); + } + + return $this; + } + public function apply_quotas() { $this->base_id = (int) $this->request->get('base_id'); diff --git a/lib/classes/record/adapter.class.php b/lib/classes/record/adapter.class.php index 1167f5144b..0614dd0f32 100644 --- a/lib/classes/record/adapter.class.php +++ b/lib/classes/record/adapter.class.php @@ -180,7 +180,7 @@ class record_adapter implements record_Interface, cache_cacheableInterface } catch (Exception $e) { - + } $connbas = $this->databox->get_connection(); @@ -530,7 +530,7 @@ class record_adapter implements record_Interface, cache_cacheableInterface } catch (Exception $e) { - + } return null; @@ -580,7 +580,7 @@ class record_adapter implements record_Interface, cache_cacheableInterface } catch (Exception $e) { - + } $sql = 'SELECT BIN(status) as status FROM record WHERE record_id = :record_id'; @@ -617,7 +617,6 @@ class record_adapter implements record_Interface, cache_cacheableInterface throw new Exception_Media_SubdefNotFound (); if (isset($this->subdefs[$name])) - return $this->subdefs[$name]; if (!$this->subdefs) @@ -658,7 +657,7 @@ class record_adapter implements record_Interface, cache_cacheableInterface } catch (Exception $e) { - + } $connbas = $this->get_databox()->get_connection(); @@ -757,10 +756,8 @@ class record_adapter implements record_Interface, cache_cacheableInterface if ($data) { if (isset($this->technical_datas[$data])) - return $this->technical_datas[$data]; else - return false; } @@ -873,9 +870,9 @@ class record_adapter implements record_Interface, cache_cacheableInterface $titles = array(); foreach ($retrieved_fields as $key => $value) { - if (trim($value === '')) + if (trim($value['value'] === '')) continue; - $titles[] = $value; + $titles[] = $value['value']; } $title = trim(implode(' - ', $titles)); } @@ -951,7 +948,6 @@ class record_adapter implements record_Interface, cache_cacheableInterface $base_url = ''; $original_file = $subdef_def = false; - $subdefs = $this->get_databox()->get_subdef_structure(); foreach ($subdefs as $type => $datas) @@ -972,7 +968,7 @@ class record_adapter implements record_Interface, cache_cacheableInterface try { $value = $this->get_subdef($name); - $original_file = p4string::addEndSlash($value['path']) . $value['file']; + $original_file = p4string::addEndSlash($value->get_path()) . $value->get_file(); unlink($original_file); } catch (Exception $e) @@ -987,7 +983,9 @@ class record_adapter implements record_Interface, cache_cacheableInterface if (trim($subdef_def->get_baseurl()) !== '') { $base_url = str_replace( - array((string) $subdef_def->get_path(), $newfilename), array((string) $subdef_def->get_baseurl(), ''), $path_file_dest + array((string) $subdef_def->get_path(), $newfilename) + , array((string) $subdef_def->get_baseurl(), '') + , $path_file_dest ); } @@ -997,7 +995,12 @@ class record_adapter implements record_Interface, cache_cacheableInterface $sql = 'DELETE FROM subdef WHERE record_id= :record_id AND name=:name'; $stmt = $connbas->prepare($sql); - $stmt->execute(array(':record_id' => $this->record_id, ':name' => $name)); + $stmt->execute( + array( + ':record_id' => $this->record_id + , ':name' => $name + ) + ); $registry = registry::get_instance(); @@ -1032,7 +1035,7 @@ class record_adapter implements record_Interface, cache_cacheableInterface $sql = 'UPDATE record SET moddate=NOW() WHERE record_id=:record_id'; $stmt = $connbas->prepare($sql); - $stmt->bindParam(':record_id', $this->get_record_id()); + $stmt->execute(array(':record_id' => $this->get_record_id())); $stmt->execute(); $this->delete_data_from_cache(self::CACHE_SUBDEFS); @@ -1242,7 +1245,7 @@ class record_adapter implements record_Interface, cache_cacheableInterface } catch (Exception $e) { - + } $this->delete_data_from_cache(self::CACHE_STATUS); @@ -1257,7 +1260,6 @@ class record_adapter implements record_Interface, cache_cacheableInterface public function get_reg_name() { if (!$this->is_grouping()) - return false; $balisename = ''; @@ -1296,14 +1298,12 @@ class record_adapter implements record_Interface, cache_cacheableInterface $registry = registry::get_instance(); if ($this->bitly_link !== null) - return $this->bitly_link; $this->bitly_link = false; if (trim($registry->get('GV_bitly_user')) == '' && trim($registry->get('GV_bitly_key')) == '') - return $this->bitly_link; try @@ -1356,7 +1356,7 @@ class record_adapter implements record_Interface, cache_cacheableInterface else { $uuid = $system_file->read_uuid(); - if(!uuid::is_valid($uuid)) + if (!uuid::is_valid($uuid)) { $uuid = uuid::generate_v4(); } @@ -1504,7 +1504,6 @@ class record_adapter implements record_Interface, cache_cacheableInterface { $hd = $this->get_subdef('document'); if ($hd->is_physically_present()) - return new system_file(p4string::addEndSlash($hd->get_path()) . $hd->get_file()); return null; } @@ -1730,7 +1729,7 @@ class record_adapter implements record_Interface, cache_cacheableInterface } catch (Exception $e) { - + } $this->delete_data_from_cache(self::CACHE_SUBDEFS); } @@ -1824,7 +1823,7 @@ class record_adapter implements record_Interface, cache_cacheableInterface } catch (Exception $e) { - + } } @@ -1844,7 +1843,6 @@ class record_adapter implements record_Interface, cache_cacheableInterface public function get_container_baskets() { if ($this->container_basket) - return $this->container_basket; $appbox = appbox::get_instance(); diff --git a/lib/classes/searchEngine/adapter/phrasea/engine.class.php b/lib/classes/searchEngine/adapter/phrasea/engine.class.php index 965eb33c4a..416f5f0446 100644 --- a/lib/classes/searchEngine/adapter/phrasea/engine.class.php +++ b/lib/classes/searchEngine/adapter/phrasea/engine.class.php @@ -639,9 +639,20 @@ class searchEngine_adapter_phrasea_engine extends searchEngine_adapter_abstract foreach ($fields as $name => $field) { if ($sxe->description->$name) - $ret[] = str_replace(array('[[em]]', '[[/em]]'), array('', ''), (string) $sxe->description->$name); + { + $val = array(); + foreach($sxe->description->$name as $value) + { + $val[] = str_replace(array('[[em]]', '[[/em]]'), array('', ''), (string) $value); + } + $val = implode(' '.$field['separator'].' ', $val); + } else - $ret[] = $field; + { + $val = $field['value']; + } + + $ret[] = $val; } return $ret; diff --git a/lib/classes/searchEngine/adapter/sphinx/engine.class.php b/lib/classes/searchEngine/adapter/sphinx/engine.class.php index 29b2c72346..0967d8e8d2 100644 --- a/lib/classes/searchEngine/adapter/sphinx/engine.class.php +++ b/lib/classes/searchEngine/adapter/sphinx/engine.class.php @@ -752,8 +752,15 @@ class searchEngine_adapter_sphinx_engine extends searchEngine_adapter_abstract i 'before_match' => "", 'after_match' => "" ); + + $fields_to_send = array(); + + foreach($fields as $k=>$f) + { + $fields_to_send[$k] = $f['value']; + } - return $this->sphinx->BuildExcerpts($fields, $index, $query, $opts); + return $this->sphinx->BuildExcerpts($fields_to_send, $index, $query, $opts); } } diff --git a/lib/classes/task/Scheduler.class.php b/lib/classes/task/Scheduler.class.php index 782879a89b..0698886af4 100644 --- a/lib/classes/task/Scheduler.class.php +++ b/lib/classes/task/Scheduler.class.php @@ -108,11 +108,16 @@ class task_Scheduler foreach ($task_manager->get_tasks() as $task) { if (!$task->is_active()) + { continue; + } + $tid = $task->get_task_id(); if (!$task->is_running()) { + /* @var $task task_abstract */ + $task->reset_crash_counter(); $task->set_status(task_abstract::STATUS_TOSTART); } } diff --git a/lib/classes/task/appboxAbstract.class.php b/lib/classes/task/appboxAbstract.class.php index d33fc86554..80344bea4c 100644 --- a/lib/classes/task/appboxAbstract.class.php +++ b/lib/classes/task/appboxAbstract.class.php @@ -38,8 +38,9 @@ abstract class task_appboxAbstract extends task_abstract $this->log(("Warning : abox connection lost, restarting in 10 min.")); sleep(60 * 10); $this->running = false; + $this->return_value = self::RETURNSTATUS_TORESTART; - return(''); + return; } $this->set_last_exec_time(); @@ -85,7 +86,7 @@ abstract class task_appboxAbstract extends task_abstract $this->pause($duration); } - return($this->return_value); + return; } /** diff --git a/lib/classes/task/databoxAbstract.class.php b/lib/classes/task/databoxAbstract.class.php index f0559140d0..6049b7a48b 100644 --- a/lib/classes/task/databoxAbstract.class.php +++ b/lib/classes/task/databoxAbstract.class.php @@ -46,8 +46,9 @@ abstract class task_databoxAbstract extends task_abstract $this->log(("Warning : abox connection lost, restarting in 10 min.")); sleep(60 * 10); $this->running = false; + $this->return_value = self::RETURNSTATUS_TORESTART; - return(''); + return; } $this->set_last_exec_time(); @@ -104,7 +105,7 @@ abstract class task_databoxAbstract extends task_abstract $this->pause($duration); } - return($this->return_value); + return; } /** diff --git a/lib/classes/task/manager.class.php b/lib/classes/task/manager.class.php index 6c5c69ad37..51767999d7 100644 --- a/lib/classes/task/manager.class.php +++ b/lib/classes/task/manager.class.php @@ -112,5 +112,44 @@ class task_manager return $row; } + + public static function getAvailableTasks() + { + $registry = registry::get_instance(); + $taskdir = array( $registry->get('GV_RootPath') . "lib/classes/task/period/" + , $registry->get('GV_RootPath') . "config/classes/task/period/" + ); + $tasks = array(); + foreach($taskdir as $path) + { + if( ($hdir = @opendir($path)) ) + { + $tskin = array(); + $max = 9999; + while (($max-- > 0) && (($file = readdir($hdir)) !== false)) + { + if (!is_file($path . '/' . $file) || substr($file, 0, 1) == "." || substr($file, -10) != ".class.php") + continue; + + $classname = 'task_period_' . substr($file, 0, strlen($file) - 10); + + try + { + // $testclass = new $classname(null); + if ($classname::interfaceAvailable()) + { + $tasks[] = array("class" => $classname, "name" => $classname::getName(), "err" => null); + } + } + catch (Exception $e) + { + + } + } + closedir($hdir); + } + } + return $tasks; + } } diff --git a/lib/classes/task/period/upgradetov32.class.php b/lib/classes/task/period/upgradetov32.class.php index f61cd25c65..7d365b2a74 100644 --- a/lib/classes/task/period/upgradetov32.class.php +++ b/lib/classes/task/period/upgradetov32.class.php @@ -67,8 +67,8 @@ class task_period_upgradetov32 extends task_abstract if (!$this->sbas_id) { printf("sbas_id '" . $this->sbas_id . "' invalide\n"); - - return 'stopped'; + $this->return_value = self::RETURNSTATUS_STOPPED; + return; } try @@ -78,6 +78,8 @@ class task_period_upgradetov32 extends task_abstract } catch (Exception $e) { + $this->return_value = self::RETURNSTATUS_STOPPED; + return; } @@ -94,6 +96,7 @@ class task_period_upgradetov32 extends task_abstract catch (Exception $e) { printf("Please verify all your databox meta fields before migrating, It seems somes are wrong\n"); + $this->return_value = self::RETURNSTATUS_STOPPED; return 'stopped'; } @@ -194,7 +197,7 @@ class task_period_upgradetov32 extends task_abstract $sql = 'select record_id, coll_id, xml, BIN(status) as status FROM record - WHERE record_id NOT IN (select distinct record_id from technical_datas) + WHERE migrated="0" AND record_id NOT IN (select distinct record_id from technical_datas) LIMIT 0, 500'; $stmt = $connbas->prepare($sql); @@ -238,7 +241,7 @@ class task_period_upgradetov32 extends task_abstract } catch (Exception $e) { - + } } @@ -280,9 +283,6 @@ class task_period_upgradetov32 extends task_abstract { $record = new record_adapter($this->sbas_id, $row['record_id']); - -// $sbas_id = $this->sbas_id; - $metas = $databox->get_meta_structure(); $metadatas = array(); @@ -367,12 +367,16 @@ class task_period_upgradetov32 extends task_abstract $memory = memory_get_usage() >> 20; if ($n_done >= 5000) - - return task_abstract::RETURNSTATUS_TORESTART; + { + $this->return_value = task_abstract::RETURNSTATUS_TORESTART; + return; + } if ($memory > 100) - - return task_abstract::RETURNSTATUS_TORESTART; - } + { + $this->return_value = task_abstract::RETURNSTATUS_TORESTART; + return; + } + } catch (Exception $e) { @@ -393,8 +397,6 @@ class task_period_upgradetov32 extends task_abstract $conn = connection::getPDOConnection(); - $ret = 'stopped'; - printf("taskid %s ending." . PHP_EOL, $this->get_task_id()); sleep(1); printf("good bye world I was task upgrade to version 3.2" . PHP_EOL); @@ -406,11 +408,12 @@ class task_period_upgradetov32 extends task_abstract $stmt->closeCursor(); $this->setProgress(0, 0); - $ret = 'todelete'; - + + $this->return_value = self::RETURNSTATUS_TODELETE; + flush(); - return $ret; + return; } } diff --git a/lib/conf.d/bases_structure.xml b/lib/conf.d/bases_structure.xml index 702ceef86e..56efc01fbc 100644 --- a/lib/conf.d/bases_structure.xml +++ b/lib/conf.d/bases_structure.xml @@ -1349,16 +1349,6 @@ - - bas_manage - int(1) unsigned - - - - - 0 - - bas_modify_struct int(1) unsigned diff --git a/lib/unitTest/FeedValidator.inc b/lib/unitTest/FeedValidator.inc index cb54be21b2..ceea8f0227 100644 --- a/lib/unitTest/FeedValidator.inc +++ b/lib/unitTest/FeedValidator.inc @@ -41,7 +41,7 @@ abstract class W3CFeedValidator { const VALIDATOR_ENDPOINT = "http://validator.w3.org/feed/check.cgi"; const OUTPOUT = "soap12"; - const TIME_BETWEEN_REQUEST = 1; + const TIME_BETWEEN_REQUEST = 2; public abstract function validate(); } @@ -83,7 +83,7 @@ class W3CFeedUrlValidator extends W3CFeedValidator { $url_validator = sprintf("%s?url=%s&output=%s", self::VALIDATOR_ENDPOINT, $this->url, self::OUTPOUT); sleep(self::TIME_BETWEEN_REQUEST); - $response = file_get_contents($url_validator); + $response = @file_get_contents($url_validator); if (!$response) { throw new W3CFeedValidatorException("Unable to request W3C API"); @@ -146,7 +146,7 @@ class W3CFeedRawValidator extends W3CFeedValidator ), )); sleep(self::TIME_BETWEEN_REQUEST); - $response = file_get_contents(self::VALIDATOR_ENDPOINT, false, $context); + $response = @file_get_contents(self::VALIDATOR_ENDPOINT, false, $context); if (!$response) { throw new W3CFeedValidatorException("Unable to request W3C API"); diff --git a/lib/unitTest/api/v1/aplicationTest.php b/lib/unitTest/api/v1/aplicationTest.php index e5864bdf71..4e0d0d8bdd 100644 --- a/lib/unitTest/api/v1/aplicationTest.php +++ b/lib/unitTest/api/v1/aplicationTest.php @@ -246,7 +246,7 @@ class API_V1_test_adapter extends PhraseanetWebTestCaseAbstract $this->assertTrue((strlen($metadatas->separator) > 0)); $this->assertTrue(is_string($metadatas->thesaurus_branch)); - $this->assertTrue(in_array($metadatas->type, array(databox_field::TYPE_DATE, databox_field::TYPE_NUMBER, databox_field::TYPE_TEXT))); + $this->assertTrue(in_array($metadatas->type, array(databox_field::TYPE_DATE,databox_field::TYPE_STRING, databox_field::TYPE_NUMBER, databox_field::TYPE_TEXT))); $this->assertTrue(is_bool($metadatas->indexable)); $this->assertTrue(is_bool($metadatas->multivalue)); $this->assertTrue(is_bool($metadatas->readonly)); diff --git a/lib/unitTest/api/v1/aplicationYamlTest.php b/lib/unitTest/api/v1/aplicationYamlTest.php index 31fd492ad8..8f18e626c4 100644 --- a/lib/unitTest/api/v1/aplicationYamlTest.php +++ b/lib/unitTest/api/v1/aplicationYamlTest.php @@ -254,7 +254,7 @@ class API_V1_test_adapterYaml extends PhraseanetWebTestCaseAbstract $this->assertTrue((strlen($metadatas["separator"]) > 0)); $this->assertTrue(is_string($metadatas["thesaurus_branch"])); - $this->assertTrue(in_array($metadatas["type"], array(databox_field::TYPE_DATE, databox_field::TYPE_NUMBER, databox_field::TYPE_TEXT))); + $this->assertTrue(in_array($metadatas["type"], array(databox_field::TYPE_DATE,databox_field::TYPE_STRING, databox_field::TYPE_NUMBER, databox_field::TYPE_TEXT))); $this->assertTrue(is_bool($metadatas["indexable"])); $this->assertTrue(is_bool($metadatas["multivalue"])); $this->assertTrue(is_bool($metadatas["readonly"])); diff --git a/lib/unitTest/module/rssFeedTest.php b/lib/unitTest/module/rssFeedTest.php index 6b50a92b76..be285cf095 100644 --- a/lib/unitTest/module/rssFeedTest.php +++ b/lib/unitTest/module/rssFeedTest.php @@ -15,6 +15,13 @@ class Module_RssFeedTest extends PhraseanetWebTestCaseAbstract * @var Feed_Adapter */ public static $feed; + + /** + * + * @var Feed_Adapter_Entry + */ + public static $entry; + public static $publisher; public static $need_records = 1; protected $client; @@ -22,22 +29,30 @@ class Module_RssFeedTest extends PhraseanetWebTestCaseAbstract { parent::setUp(); $this->client = $this->createClient(); + self::$feed = Feed_Adapter::create(appbox::get_instance(), self::$user, 'title', 'subtitle'); + self::$publisher = Feed_Publisher_Adapter::getPublisher(appbox::get_instance(), self::$feed, self::$user); + self::$entry = Feed_Entry_Adapter::create(appbox::get_instance(), self::$feed, self::$publisher, 'title_entry', 'subtitle', 'hello', "test@mail.com"); + Feed_Entry_Item::create(appbox::get_instance(), self::$entry, self::$record_1); + self::$feed->set_public(true); + } + + public function tearDown() + { + self::$publisher->delete(); + self::$entry->delete(); + self::$feed->delete(); + parent::tearDown(); } public static function setUpBeforeClass() { parent::setUpBeforeClass(); - self::$feed = Feed_Adapter::create(appbox::get_instance(), self::$user, 'title', 'subtitle'); - $publisher = Feed_Publisher_Adapter::getPublisher(appbox::get_instance(), self::$feed, self::$user); - $entry = Feed_Entry_Adapter::create(appbox::get_instance(), self::$feed, $publisher, 'title_entry', 'subtitle', 'hello', "test@mail.com"); - Feed_Entry_Item::create(appbox::get_instance(), $entry, self::$record_1); - self::$feed->set_public(true); } public static function tearDownAfterClass() { + parent::tearDownAfterClass(); - self::$feed->delete(); } public function createApplication() @@ -45,6 +60,33 @@ class Module_RssFeedTest extends PhraseanetWebTestCaseAbstract return require dirname(__FILE__) . '/../../classes/module/Root.php'; } + public function testGetFeedFormat() + { + $feeds = Feed_Collection::load_public_feeds(appbox::get_instance()); + $feed = array_shift($feeds->get_feeds()); + + $crawler = $this->client->request("GET", "/feeds/feed/" . $feed->get_id() . "/rss/"); + $this->assertEquals("application/rss+xml", $this->client->getResponse()->headers->get("content-type")); + $xml = $this->client->getResponse()->getContent(); + $this->verifyXML($xml); + $this->verifyRSS($feed, $xml); + + $crawler = $this->client->request("GET", "/feeds/feed/" . $feed->get_id() . "/atom/"); + $this->assertEquals("application/atom+xml", $this->client->getResponse()->headers->get("content-type")); + $xml = $this->client->getResponse()->getContent(); + $this->verifyXML($xml); + $this->verifyATOM($feed, $xml); + } + + public function testCooliris() + { + $crawler = $this->client->request("GET", "/feeds/cooliris/"); + $this->assertTrue($this->client->getResponse()->isOk()); + $this->assertEquals("application/rss+xml", $this->client->getResponse()->headers->get("content-type")); + $xml = $this->client->getResponse()->getContent(); + $this->verifyXML($xml); + } + public function testAggregatedRss() { $feeds = Feed_Collection::load_public_feeds(appbox::get_instance()); @@ -56,7 +98,6 @@ class Module_RssFeedTest extends PhraseanetWebTestCaseAbstract $crawler = $this->client->request("GET", "/feeds/aggregated/rss/"); $this->assertTrue($this->client->getResponse()->isOk()); $this->assertEquals("application/rss+xml", $this->client->getResponse()->headers->get("content-type")); -// $this->assertEquals($feeds->get_aggregate()->get_count_total_entries(), $crawler->filterXPath("//channel/item")->count()); $xml = $this->client->getResponse()->getContent(); $this->verifyXML($xml); } @@ -86,35 +127,21 @@ class Module_RssFeedTest extends PhraseanetWebTestCaseAbstract $this->assertEquals(404, $this->client->getResponse()->getStatusCode()); } - public function testGetFeedFormat() - { - $feeds = Feed_Collection::load_public_feeds(appbox::get_instance()); - $feed = array_shift($feeds->get_feeds()); - $crawler = $this->client->request("GET", "/feeds/feed/" . $feed->get_id() . "/rss/"); - $this->assertEquals("application/rss+xml", $this->client->getResponse()->headers->get("content-type")); - $xml = $this->client->getResponse()->getContent(); - $this->verifyRSS($feed, $xml); - $crawler = $this->client->request("GET", "/feeds/feed/" . $feed->get_id() . "/atom/"); - $this->assertEquals("application/atom+xml", $this->client->getResponse()->headers->get("content-type")); - $xml = $this->client->getResponse()->getContent(); - $this->verifyATOM($feed, $xml); - } - public function testGetFeedId() { $feeds = Feed_Collection::load_public_feeds(appbox::get_instance()); $all_feeds = $feeds->get_feeds(); - foreach ($all_feeds as $feed) - { - $crawler = $this->client->request("GET", "/feeds/feed/" . $feed->get_id() . "/rss/"); - $this->assertTrue($this->client->getResponse()->isOk()); - $xml = $this->client->getResponse()->getContent(); - $this->verifyRSS($feed, $xml); - $crawler = $this->client->request("GET", "/feeds/feed/" . $feed->get_id() . "/atom/"); - $this->assertTrue($this->client->getResponse()->isOk()); - $xml = $this->client->getResponse()->getContent(); - $this->verifyATOM($feed, $xml); - } + $feed = array_shift($all_feeds); + + $crawler = $this->client->request("GET", "/feeds/feed/" . $feed->get_id() . "/rss/"); + $this->assertTrue($this->client->getResponse()->isOk()); + $xml = $this->client->getResponse()->getContent(); + $this->verifyRSS($feed, $xml); + + $crawler = $this->client->request("GET", "/feeds/feed/" . $feed->get_id() . "/atom/"); + $this->assertTrue($this->client->getResponse()->isOk()); + $xml = $this->client->getResponse()->getContent(); + $this->verifyATOM($feed, $xml); } public function testPrivateFeedAccess() @@ -129,7 +156,6 @@ class Module_RssFeedTest extends PhraseanetWebTestCaseAbstract public function verifyXML($xml) { - $this->markTestSkipped("En attente"); try { $validator = new W3CFeedRawValidator($xml); @@ -139,7 +165,7 @@ class Module_RssFeedTest extends PhraseanetWebTestCaseAbstract } catch (W3CFeedValidatorException $e) { - $this->fail($e->getMessage()); + print "\nCould not use W3C FEED VALIDATOR API : " . $e->getMessage() . "\n"; } } @@ -443,7 +469,8 @@ class Module_RssFeedTest extends PhraseanetWebTestCaseAbstract { if ($p4field = $entry_item->get_record()->get_caption()->get_dc_field($field["dc_field"])) { - $this->assertEquals($p4field->get_value(true, $field["separator"]), $node->nodeValue); + $this->assertEquals($p4field->get_value(true, $field["separator"]), $node->nodeValue + , sprintf('Asserting good value for DC %s', $field["dc_field"])); if (sizeof($field["media_field"]["attributes"]) > 0) { foreach ($node->attributes as $attribute) @@ -583,15 +610,26 @@ class Module_RssFeedTest extends PhraseanetWebTestCaseAbstract } $content = $entry->get_content(); - $available_medium = array('image', 'audio', 'video'); - array_walk($content, $this->removeBadItems($content, $available_medium)); - $media_group = $xpath->query("//media:group"); - $this->assertEquals(sizeof($content), $media_group->length); - foreach ($media_group as $media) + + $available_medium = array('image', 'audio', 'video'); + + array_walk($content, $this->removeBadItems($content, $available_medium)); + + + $media_group = $xpath->query("/Atom:feed/Atom:entry[0]/media:group"); + + if ($media_group->length > 0) { - $entry_item = array_shift($content); - $this->verifyMediaItem($entry_item, $media); + foreach ($media_group as $media) + { + + $entry_item = array_shift($content); + if ($entry_item instanceof Feed_Entry_Item) + { + $this->verifyMediaItem($entry_item, $media); + } + } } } diff --git a/lib/unitTest/userTest.php b/lib/unitTest/userTest.php index 82e4fc5a3d..4bcc3d3912 100644 --- a/lib/unitTest/userTest.php +++ b/lib/unitTest/userTest.php @@ -37,12 +37,22 @@ class userTest extends PhraseanetPHPUnitAbstract $this->assertFalse(User_Adapter::get_usr_id_from_email(null)); self::$user->set_email(''); $this->assertFalse(User_Adapter::get_usr_id_from_email(null)); - self::$user->set_email('noonealt1@example.com'); - $this->assertEquals(self::$user->get_id(), User_Adapter::get_usr_id_from_email('noonealt1@example.com')); + self::$user->set_email('noone@example.com'); + $this->assertEquals(self::$user->get_id(), User_Adapter::get_usr_id_from_email('noone@example.com')); } catch(Exception $e) { $this->fail($e->getMessage()); + } + try + { + + self::$user->set_email('noonealt1@example.com'); + $this->fail('A user already got this address'); + } + catch(Exception $e) + { + } $this->assertFalse(User_Adapter::get_usr_id_from_email(null)); } diff --git a/lib/version.inc b/lib/version.inc index 9a6acf9259..104f48509f 100644 --- a/lib/version.inc +++ b/lib/version.inc @@ -15,5 +15,5 @@ * @license http://opensource.org/licenses/gpl-3.0 GPLv3 * @link www.phraseanet.com */ -define('GV_version', '3.5.3.0'); +define('GV_version', '3.5.5.0'); define('GV_version_name', 'Baobab'); diff --git a/templates/web/admin/databox/doc_structure.twig b/templates/web/admin/databox/doc_structure.twig index 5819a174ae..f3fe059f73 100644 --- a/templates/web/admin/databox/doc_structure.twig +++ b/templates/web/admin/databox/doc_structure.twig @@ -252,12 +252,18 @@ {% trans 'Indexable' %} + + {% trans 'Required' %} + {% trans 'Lecture seule' %} {% trans 'Type' %} + + {% trans 'Separateur' %} + {% trans 'Branche Thesaurus' %} @@ -307,12 +313,15 @@ + + + - {{field.get_type()}} + + + + diff --git a/templates/web/admin/editusers.twig b/templates/web/admin/editusers.twig index 8e7a18f87e..dd36b33274 100644 --- a/templates/web/admin/editusers.twig +++ b/templates/web/admin/editusers.twig @@ -111,7 +111,7 @@
  • Droits
  • - {% if main_user is not empty %} + {% if main_user is not empty and main_user.is_template is empty %}
  • Fiche
  • @@ -142,7 +142,7 @@ - + @@ -402,7 +402,7 @@ - {% if main_user is not empty %} + {% if main_user is not empty and main_user.is_template is empty %}
    diff --git a/templates/web/admin/task.html b/templates/web/admin/task.html index eb35b69976..34ffc87d5d 100644 --- a/templates/web/admin/task.html +++ b/templates/web/admin/task.html @@ -1,440 +1,449 @@ - - - - - {{task.printInterfaceHEAD()}} - - + + + - - {{task.printInterfaceJS()}} - + + + {{task.printInterfaceJS()}} + - + - -
    -

    {{task.getName()}} id : {{task.get_task_id()}}

    - - - - - - -
    - {% trans 'admin::tasks: Nombre de crashes : ' %} {{task.get_crash_counter()}} - - - {% trans 'admin::tasks: reinitialiser el compteur de crashes' %} -
    -
    - -
    -
    -
    - {% if task.printInterfaceHTML %} -
    - {% trans 'boutton::vue graphique' %} -
    - {% endif %} -
    - {% trans 'boutton::vue xml' %} -
    -
    - {% if task.getGraphicForm %} -
    - {% if task.printInterfaceHTML %} - {{task.printInterfaceHTML()|raw}} - {% else %} -
    - {% endif %} -
    - - {% endif %} - -
    -
    - - - - - - + +
    +

    {{task.getName()}} id : {{task.get_task_id()}}

    + + + + + -
    - +
    + {% trans 'admin::tasks: Nombre de crashes : ' %} {{task.get_crash_counter()}} + + + {% trans 'admin::tasks: reinitialiser el compteur de crashes' %} +
    -
    +
    +
    +
    + {% if task.printInterfaceHTML %} +
    + {% trans 'boutton::vue graphique' %} +
    + {% endif %} +
    + {% trans 'boutton::vue xml' %} +
    +
    + {% if task.getGraphicForm %} +
    + {% if task.printInterfaceHTML %} + {{task.printInterfaceHTML()|raw}} + {% else %} +
    + {% endif %} +
    + + {% endif %} + +
    +
    + + + + + + + +
    + +
    -
    -
    -
    - - -
    -
    - -
    - - +
    +
    +
    + + + +
    +
    + +
    + + + \ No newline at end of file diff --git a/templates/web/admin/users.html b/templates/web/admin/users.html index e396f3c187..47c1ea5099 100644 --- a/templates/web/admin/users.html +++ b/templates/web/admin/users.html @@ -52,33 +52,91 @@

    +
    +

    + {% trans 'Apply a template' %} + + +

    +
    - - - - - - - - @@ -120,8 +178,8 @@ {{users.get_total}} resultats - {% set pages = users.get_total() / 20 %} - {% set modulo = users.get_total() % 20 %} + {% set pages = users.get_total() / parm['per_page'] %} + {% set modulo = users.get_total() % parm['per_page'] %} {% if modulo > 0 %}{% set pages = pages + 1 %}{% endif %} {{pages|floor}} pages @@ -188,6 +246,9 @@ el.addClass('selected'); } }); + $('#users_page_form select[name="per_page"]').bind('change', function(){ + $(this).closest('form').submit(); + }); }); diff --git a/templates/web/common/caption_templates/answer.html b/templates/web/common/caption_templates/answer.html index f1fb7e9bf2..3e219f8320 100644 --- a/templates/web/common/caption_templates/answer.html +++ b/templates/web/common/caption_templates/answer.html @@ -1,5 +1,5 @@ {% macro format_caption(record, highlight, searchEngine) %} {% for name, value in record.get_caption().get_highlight_fields(highlight, null, searchEngine) %} -
    {{name}} : {{value|raw}}
    +
    {{name}} : {{value.value|raw}}
    {% endfor %} {% endmacro %} \ No newline at end of file diff --git a/templates/web/common/caption_templates/basket_element.html b/templates/web/common/caption_templates/basket_element.html index 8e4e1afefb..1ed37f824d 100644 --- a/templates/web/common/caption_templates/basket_element.html +++ b/templates/web/common/caption_templates/basket_element.html @@ -1,5 +1,5 @@ {% macro format_caption(record) %} {% for name, value in record.get_caption().get_highlight_fields() %} -
    {{name}} : {{value|raw}}
    +
    {{name}} : {{value.value|raw}}
    {% endfor %} {% endmacro %} \ No newline at end of file diff --git a/templates/web/common/caption_templates/internal_publi.html b/templates/web/common/caption_templates/internal_publi.html index 8e4e1afefb..1ed37f824d 100644 --- a/templates/web/common/caption_templates/internal_publi.html +++ b/templates/web/common/caption_templates/internal_publi.html @@ -1,5 +1,5 @@ {% macro format_caption(record) %} {% for name, value in record.get_caption().get_highlight_fields() %} -
    {{name}} : {{value|raw}}
    +
    {{name}} : {{value.value|raw}}
    {% endfor %} {% endmacro %} \ No newline at end of file diff --git a/templates/web/common/caption_templates/lazaret.html b/templates/web/common/caption_templates/lazaret.html index 8e4e1afefb..1ed37f824d 100644 --- a/templates/web/common/caption_templates/lazaret.html +++ b/templates/web/common/caption_templates/lazaret.html @@ -1,5 +1,5 @@ {% macro format_caption(record) %} {% for name, value in record.get_caption().get_highlight_fields() %} -
    {{name}} : {{value|raw}}
    +
    {{name}} : {{value.value|raw}}
    {% endfor %} {% endmacro %} \ No newline at end of file diff --git a/templates/web/common/caption_templates/overview.html b/templates/web/common/caption_templates/overview.html index 04e2d1278b..55d1775e11 100644 --- a/templates/web/common/caption_templates/overview.html +++ b/templates/web/common/caption_templates/overview.html @@ -1,5 +1,5 @@ {% macro format_caption(record) %} {% for name, value in record.get_caption().get_highlight_fields() %} -
    {{name}} : {{value|raw}}
    +
    {{name}} : {{value.value|raw}}
    {% endfor %} {% endmacro %} \ No newline at end of file diff --git a/templates/web/common/caption_templates/preview.html b/templates/web/common/caption_templates/preview.html index f1fb7e9bf2..3e219f8320 100644 --- a/templates/web/common/caption_templates/preview.html +++ b/templates/web/common/caption_templates/preview.html @@ -1,5 +1,5 @@ {% macro format_caption(record, highlight, searchEngine) %} {% for name, value in record.get_caption().get_highlight_fields(highlight, null, searchEngine) %} -
    {{name}} : {{value|raw}}
    +
    {{name}} : {{value.value|raw}}
    {% endfor %} {% endmacro %} \ No newline at end of file diff --git a/templates/web/common/dialog_export.twig b/templates/web/common/dialog_export.twig index b18a55bab9..2990e8b452 100644 --- a/templates/web/common/dialog_export.twig +++ b/templates/web/common/dialog_export.twig @@ -376,7 +376,7 @@
    - {% for datas in download.ftp_datas %} + {% for datas in download.get_ftp_datas() %} {{ _self.print_ftp_form(datas) }} {% endfor %}
    diff --git a/templates/web/login/index_layout_displaycooliris.twig b/templates/web/login/index_layout_displaycooliris.twig index ec6d7404dd..4a0e325571 100644 --- a/templates/web/login/index_layout_displaycooliris.twig +++ b/templates/web/login/index_layout_displaycooliris.twig @@ -55,10 +55,10 @@ + value="feed=/feeds/cooliris/&glowColor=#0077BC&style=dark&backgroundColor=#000000&showChrome=false&showEMbed=false&showSearch=false" /> - - + diff --git a/templates/web/login/index_layout_displayx1.twig b/templates/web/login/index_layout_displayx1.twig index 5acc110401..d7092d3a64 100644 --- a/templates/web/login/index_layout_displayx1.twig +++ b/templates/web/login/index_layout_displayx1.twig @@ -9,7 +9,7 @@ - diff --git a/www/admin/description.php b/www/admin/description.php index 0900b4d7fe..b70f803d02 100644 --- a/www/admin/description.php +++ b/www/admin/description.php @@ -67,6 +67,8 @@ if (!empty($_POST)) , 'multi_' . $id , 'indexable_' . $id , 'readonly_' . $id + , 'required_' . $id + , 'separator_' . $id , 'type_' . $id , 'tbranch_' . $id , 'report_' . $id @@ -79,6 +81,8 @@ if (!empty($_POST)) $field->set_source($local_parms['src_' . $id]); $field->set_multi($local_parms['multi_' . $id]); $field->set_indexable($local_parms['indexable_' . $id]); + $field->set_required($local_parms['required_' . $id]); + $field->set_separator($local_parms['separator_' . $id]); $field->set_readonly($local_parms['readonly_' . $id]); $field->set_type($local_parms['type_' . $id]); $field->set_tbranch($local_parms['tbranch_' . $id]); diff --git a/www/admin/taskmanager.php b/www/admin/taskmanager.php index 2c59dc3b62..072d56e1f5 100644 --- a/www/admin/taskmanager.php +++ b/www/admin/taskmanager.php @@ -33,35 +33,6 @@ $registry = $appbox->get_registry(); $task_manager = new task_manager($appbox); -$tasks = array(); -$path = $registry->get('GV_RootPath') . "lib/classes/task/period/"; -if ($hdir = opendir($path)) -{ - $tskin = array(); - $max = 9999; - while (($max-- > 0) && (($file = readdir($hdir)) !== false)) - { - if (!is_file($path . '/' . $file) || substr($file, 0, 1) == "." || substr($file, -10) != ".class.php") - continue; - - $classname = 'task_period_' . substr($file, 0, strlen($file) - 10); - - try - { -// $testclass = new $classname(null); - if ($classname::interfaceAvailable()) - { - $tasks[] = array("class" => $classname, "name" => $classname::getName(), "err" => null); - } - } - catch (Exception $e) - { - - } - } - closedir($hdir); -} - ?> @@ -346,6 +317,7 @@ if ($hdir = opendir($path)) var menuNewTask = [ get('GV_maintenance')
    ' . _('login::captcha: recopier les mots ci dessous') . ' : -
    ' . recaptcha_get_html(GV_captcha_public_key) . '
    '; + ' . recaptcha_get_html($registry->get('GV_captcha_public_key')) . ''; } $public_feeds = Feed_Collection::load_public_feeds($appbox); diff --git a/www/skins/admin/admincolor.css b/www/skins/admin/admincolor.css index f45e65ee20..4733139710 100644 --- a/www/skins/admin/admincolor.css +++ b/www/skins/admin/admincolor.css @@ -48,6 +48,7 @@ FFFA00 9E9C3C 777400 FFFC65 FFFEB5 #left{ background-color:#fffbcd; + overflow:auto; } #FNDR{ overflow:auto; @@ -141,4 +142,20 @@ table.admintable tbody .dropdown{ .users_col.options{ cursor:pointer; color:#AFAFAF; +} +#users th.sortable span{ + margin:0 5px; +} +#users th.sortable{ + cursor:pointer; +} +#users th.sortable.hover, +#users th.sortable.sorted{ + background-color:#F0AD30; +} +#users th.sortable span.ord_notifier{ + display:none; +} +#users th.sortable.sorted span.ord_notifier{ + display:inline; } \ No newline at end of file diff --git a/www/skins/admin/flèche verte.png b/www/skins/admin/fleche_verte.png similarity index 100% rename from www/skins/admin/flèche verte.png rename to www/skins/admin/fleche_verte.png diff --git a/www/skins/lng/inclin-ar.gif b/www/skins/lng/inclin-ar.gif deleted file mode 100644 index 8ad6e70d9a..0000000000 Binary files a/www/skins/lng/inclin-ar.gif and /dev/null differ diff --git a/www/skins/lng/inclin-ar.png b/www/skins/lng/inclin-ar.png new file mode 100644 index 0000000000..3a95504d21 Binary files /dev/null and b/www/skins/lng/inclin-ar.png differ diff --git a/www/skins/lng/inclin-de.gif b/www/skins/lng/inclin-de.gif deleted file mode 100644 index 229f594a87..0000000000 Binary files a/www/skins/lng/inclin-de.gif and /dev/null differ diff --git a/www/skins/lng/inclin-de.png b/www/skins/lng/inclin-de.png new file mode 100644 index 0000000000..cb0a8c17f8 Binary files /dev/null and b/www/skins/lng/inclin-de.png differ diff --git a/www/skins/lng/inclin-en.gif b/www/skins/lng/inclin-en.gif deleted file mode 100644 index 5b7ce96b90..0000000000 Binary files a/www/skins/lng/inclin-en.gif and /dev/null differ diff --git a/www/skins/lng/inclin-en.png b/www/skins/lng/inclin-en.png new file mode 100644 index 0000000000..3a95504d21 Binary files /dev/null and b/www/skins/lng/inclin-en.png differ diff --git a/www/skins/lng/inclin-fr.gif b/www/skins/lng/inclin-fr.gif deleted file mode 100644 index 166e4aa9fb..0000000000 Binary files a/www/skins/lng/inclin-fr.gif and /dev/null differ diff --git a/www/skins/lng/inclin-fr.png b/www/skins/lng/inclin-fr.png new file mode 100644 index 0000000000..499c680c0a Binary files /dev/null and b/www/skins/lng/inclin-fr.png differ
    + {% trans 'admin::compte-utilisateur id utilisateur' %} + + {{ parm.ord == 'asc' ? '▼' : '▲' }} + + + + {% trans 'admin::compte-utilisateur identifiant' %} + + + {{ parm.ord == 'asc' ? '▼' : '▲' }} + + + + {% trans 'admin::compte-utilisateur nom/prenom' %} + + + {{ parm.ord == 'asc' ? '▼' : '▲' }} + + + + {% trans 'admin::compte-utilisateur societe' %} + + + {{ parm.ord == 'asc' ? '▼' : '▲' }} + + + + {% trans 'admin::compte-utilisateur email' %} + + + {{ parm.ord == 'asc' ? '▼' : '▲' }} + + + + {% trans 'admin::compte-utilisateur pays' %} + + + {{ parm.ord == 'asc' ? '▼' : '▲' }} + + + + {% trans 'admin::compte-utilisateur dernier modele applique' %} + + + {{ parm.ord == 'asc' ? '▼' : '▲' }} + + + + {% trans 'admin::compte-utilisateur date de creation' %} + + + {{ parm.ord == 'asc' ? '▼' : '▲' }} + +