]> git.agnieray.net Git - galette.git/commitdiff
Advanced search, fixes #370
authorJohan Cwiklinski <johan@x-tnd.be>
Thu, 11 Oct 2012 02:54:38 +0000 (04:54 +0200)
committerJohan Cwiklinski <johan@x-tnd.be>
Fri, 30 Nov 2012 18:11:59 +0000 (19:11 +0100)
Several options:
- search on various predefined fields (such as creation date, etc),
- free custom search into all members table fields, and also into
  attached dynamic fields.

12 files changed:
galette/advanced_search.php [new file with mode: 0644]
galette/gestion_adherents.php
galette/includes/common.js
galette/lib/Galette/Entity/Adherent.php
galette/lib/Galette/Filters/AdvancedMembersList.php [new file with mode: 0644]
galette/lib/Galette/Filters/MembersList.php
galette/lib/Galette/Repository/Members.php
galette/templates/default/advanced_search.tpl [new file with mode: 0644]
galette/templates/default/galette.css
galette/templates/default/gestion_adherents.tpl
galette/templates/default/member.tpl
galette/templates/default/page.tpl

diff --git a/galette/advanced_search.php b/galette/advanced_search.php
new file mode 100644 (file)
index 0000000..0c2581a
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Advanced search form
+ *
+ * PHP version 5
+ *
+ * Copyright © 2012 The Galette Team
+ *
+ * This file is part of Galette (http://galette.tuxfamily.org).
+ *
+ * Galette is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Galette is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Galette. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Main
+ * @package   Galette
+ *
+ * @author    Johan Cwiklinski <johan@x-tnd.be>
+ * @copyright 2012 The Galette Team
+ * @license   http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
+ * @version   SVN: $Id$
+ * @link      http://galette.tuxfamily.org
+ * @since     Available since 0.7.3dev - 2012-10-11
+ */
+
+use Galette\Filters\MembersList as MembersList;
+use Galette\Filters\AdvancedMembersList as AdvancedMembersList;
+use Galette\Entity\Adherent as Adherent;
+use Galette\Entity\DynamicFields as DynamicFields;
+
+/** @ignore */
+require_once 'includes/galette.inc.php';
+
+if ( !$login->isLogged() ) {
+    header('location: index.php');
+    die();
+}
+
+if ( isset($session['filters']['members']) ) {
+    $filters = unserialize($session['filters']['members']);
+    if ( !$filters instanceof AdvancedMembersList ) {
+        $filters = new AdvancedMembersList($filters);
+    }
+} else {
+    $filters = new AdvancedMembersList();
+}
+
+$groups = new Galette\Repository\Groups();
+$groups_list = $groups->getList();
+
+$tpl->assign('page_title', _T("Advanced search"));
+$tpl->assign('require_dialog', true);
+$tpl->assign('require_calendar', true);
+$tpl->assign('require_sorter', true);
+$tpl->assign('filter_groups_options', $groups_list);
+if ( isset($error_detected) ) {
+    $tpl->assign('error_detected', $error_detected);
+}
+if (isset($warning_detected)) {
+    $tpl->assign('warning_detected', $warning_detected);
+}
+
+//TODO: filter that? Only visibles?
+$a = new Adherent();
+$tpl->assign('search_fields', $a->fields);
+
+//dynamic fields
+$df = new DynamicFields();
+$dynamic_fields = $df->prepareForDisplay(
+    'adh',
+    array(),
+    array(),
+    0
+);
+$tpl->assign('dynamic_fields', $dynamic_fields);
+
+//Status
+$statuts = new Galette\Entity\Status();
+$tpl->assign('statuts', $statuts->getList());
+
+$tpl->assign('filters', $filters);
+
+$filters->setTplCommonsFilters($tpl);
+
+$content = $tpl->fetch('advanced_search.tpl');
+$tpl->assign('content', $content);
+$tpl->display('page.tpl');
index f343c1b2c21c06598ecc1df18dd16f5b17c0d761..f0bfe0e5b2153a522a14200be6e6ff96a7bcaa53 100644 (file)
@@ -45,6 +45,7 @@
 
 use Galette\Repository\Members as Members;
 use Galette\Filters\MembersList as MembersList;
+use Galette\Filters\AdvancedMembersList as AdvancedMembersList;
 
 /** @ignore */
 require_once 'includes/galette.inc.php';
@@ -63,6 +64,7 @@ if ( isset($session['filters']['members'])
     && !isset($_POST['mailing'])
     && !isset($_POST['mailing_new'])
 ) {
+    //CAUTION: this one may be simple or advanced, display must change
     $filters = unserialize($session['filters']['members']);
 } else {
     $filters = new MembersList();
@@ -75,6 +77,7 @@ if (   isset($_POST['cards'])
     || isset($_POST['labels'])
     || isset($_POST['mailing'])
     || isset($_POST['attendance_sheet'])
+    || isset($_GET['adv_criterias'])
 ) {
     if (isset($_POST['member_sel'])) {
         $filters->selected = $_POST['member_sel'];
@@ -100,10 +103,55 @@ if (   isset($_POST['cards'])
             }
         }
         header('location: '.$qstring);
+    } elseif ($_GET['adv_criterias']) {
+        header('location: advanced_search.php');
     } else {
         $error_detected[]
             = _T("No member was selected, please check at least one name.");
     }
+} else if ( isset($_POST['advanced_filtering']) ) {
+    if ( !$filters instanceof AdvancedMembersList ) {
+        $filters = new AdvancedMembersList($filters);
+    }
+    //Advanced filters
+    $posted = $_POST;
+    $filters->reinit();
+    unset($posted['advanced_filtering']);
+    $freed = false;
+    foreach ( $posted as $k=>$v ) {
+        if ( strpos($k, 'free_', 0) === 0 ) {
+            if ( !$freed ) {
+                $i = 0;
+                foreach ( $posted['free_field'] as $f ) {
+                    if ( trim($f) !== '' && trim($posted['free_text'][$i]) !== '' ) {
+                        $fs = array(
+                            'idx'       => $i,
+                            'field'     => $f,
+                            'search'    => $posted['free_text'][$i],
+                            'log_op'    => (int)$posted['free_logical_operator'][$i],
+                            'qry_op'    => (int)$posted['free_query_operator'][$i]
+                        );
+                        $filters->free_search = $fs;
+                    }
+                    $i++;
+                }
+                $freed = true;
+            }
+        } else {
+            switch($k) {
+            case 'filter_field':
+                $k = 'field_filter';
+                break;
+            case 'filter_membership':
+                $k= 'membership_filter';
+                break;
+            case 'filter_account':
+                $k = 'account_status_filter';
+                break;
+            }
+            $filters->$k = $v;
+        }
+    }
 }
 
 if (isset($session['pdf_error']) && $session['pdf_error']) {
@@ -112,13 +160,16 @@ if (isset($session['pdf_error']) && $session['pdf_error']) {
     unset($session['pdf_error']);
 }
 
-// Filters
+// Simple filters
 if (isset($_GET['page'])) {
     $filters->current_page = (int)$_GET['page'];
 }
 
 if ( isset($_GET['clear_filter']) ) {
     $filters->reinit();
+    if ($filters instanceof AdvancedMembersList) {
+        $filters = new MembersList();
+    }
 } else {
     //string to filter
     if ( isset($_GET['filter_str']) ) { //filter search string
@@ -185,7 +236,7 @@ if ( $login->isAdmin() || $login->isStaff() ) {
 $groups = new Galette\Repository\Groups();
 $groups_list = $groups->getList();
 
-//cannot use $session here :/
+//store current filters in session
 $session['filters']['members'] = serialize($filters);
 
 //assign pagination variables to the template and add pagination links
@@ -203,37 +254,12 @@ $tpl->assign('filter_groups_options', $groups_list);
 $tpl->assign('nb_members', $members->getCount());
 $tpl->assign('filters', $filters);
 $tpl->assign(
-    'filter_field_options',
-    array(
-        Members::FILTER_NAME            => _T("Name"),
-        Members::FILTER_COMPANY_NAME    => _T("Company name"),
-        Members::FILTER_ADRESS          => _T("Address"),
-        Members::FILTER_MAIL            => _T("Email,URL,IM"),
-        Members::FILTER_JOB             => _T("Job"),
-        Members::FILTER_INFOS           => _T("Infos")
-    )
-);
-$tpl->assign(
-    'filter_membership_options',
-    array(
-        0 => _T("All members"),
-        3 => _T("Up to date members"),
-        1 => _T("Close expiries"),
-        2 => _T("Latecomers"),
-        4 => _T("Never contributed"),
-        5 => _T("Staff members"),
-        6 => _T("Administrators")
-    )
-);
-$tpl->assign(
-    'filter_accounts_options',
-    array(
-        0 => _T("All accounts"),
-        1 => _T("Active accounts"),
-        2 => _T("Inactive accounts")
-    )
+    'adv_filters',
+    ($filters instanceof AdvancedMembersList) ? true : false
 );
 
+$filters->setTplCommonsFilters($tpl);
+
 $content = $tpl->fetch('gestion_adherents.tpl');
 $tpl->assign('content', $content);
 $tpl->display('page.tpl');
index f9e6c066b10639bc79dbc2af419c60ebcc9cf94b..aa7bf0fd48fa4b1c744a64fb8987072ea2314095 100644 (file)
@@ -52,6 +52,28 @@ var _collapsibleFieldsets = function(){
     });
 }
 
+var _fieldsInSortable = function(){
+    //so our forms elements continue to work as expected
+    $('.fields_list input, .fields_list select').bind(
+        'click.sortable mousedown.sortable',
+        function(ev) {
+            ev.target.focus();
+        }
+    );
+}
+
+var _initSortable = function(){
+    $('.fields_list').sortable({
+        items: 'li:not(.listing)'
+    }).disableSelection();
+
+    _fieldsInSortable();
+
+    $('#members_tab').sortable({
+        items: 'fieldset'
+    });
+}
+
 /* On document ready
 -------------------------------------------------------- */
 
index 5c20985a560146362552acb6bbe93f9e0fd0b851..f35c1437a445fd866418825d7a658dc8a1472896 100644 (file)
@@ -1390,7 +1390,8 @@ class Adherent
     */
     public function __get($name)
     {
-        global $log;
+        global $log, $login;
+
         $forbidden = array(
             'admin', 'staff', 'due_free', 'appears_in_list', 'active',
             'row_classes'
@@ -1421,6 +1422,24 @@ class Adherent
                     }
                 }
                 break;
+            case 'fields':
+                //filter according to logged user ACLs
+                $fc = new FieldsConfig(Adherent::TABLE, $member->fields);
+                // fields visibility
+                $visibles = $fc->getVisibilities();
+                $fields = array();
+                foreach ( $this->_fields as $k=>$f ) {
+                    if ( $visibles[$k] === FieldsConfig::VISIBLE ) {
+                        $fields[$k] = $f;
+                    } else if ( ($login->isAdmin()
+                        || $login->isStaff()
+                        || $login->isSuperAdmin())
+                        && $visibles[$k] === FieldsConfig::ADMIN
+                    ) {
+                        $fields[$k] = $f;
+                    }
+                }
+                return $this->_fields;
             default:
                 return $this->$rname;
                 break;
diff --git a/galette/lib/Galette/Filters/AdvancedMembersList.php b/galette/lib/Galette/Filters/AdvancedMembersList.php
new file mode 100644 (file)
index 0000000..0c34b20
--- /dev/null
@@ -0,0 +1,342 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Members list advanced filters
+ *
+ * PHP version 5
+ *
+ * Copyright © 2012 The Galette Team
+ *
+ * This file is part of Galette (http://galette.tuxfamily.org).
+ *
+ * Galette is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Galette is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Galette. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Filters
+ * @package   Galette
+ *
+ * @author    Johan Cwiklinski <johan@x-tnd.be>
+ * @copyright 2012 The Galette Team
+ * @license   http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
+ * @version   SVN: $Id$
+ * @link      http://galette.tuxfamily.org
+ * @since     0.73dev 2012-10-16
+ */
+
+namespace Galette\Filters;
+
+use Galette\Common\KLogger as KLogger;
+use Galette\Entity\Status as Status;
+use Galette\Repository\Members as Members;
+
+/**
+ * Members list filters and paginator
+ *
+ * @name      AdvancedMembersList
+ * @category  Filters
+ * @package   Galette
+ *
+ * @author    Johan Cwiklinski <johan@x-tnd.be>
+ * @copyright 2012 The Galette Team
+ * @license   http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
+ * @link      http://galette.tuxfamily.org
+ */
+
+class AdvancedMembersList extends MembersList
+{
+
+    const OP_AND = 0;
+    const OP_OR = 1;
+
+    const OP_EQUALS = 0;
+    const OP_CONTAINS = 1;
+    const OP_NOT_EQUALS = 2;
+    const OP_NOT_CONTAINS = 3;
+    const OP_STARTS_WITH = 4;
+    const OP_ENDS_WITH = 5;
+
+    private $_creation_date_begin;
+    private $_creation_date_end;
+    private $_modif_date_begin;
+    private $_modif_date_end;
+    private $_due_date_begin;
+    private $_due_date_end;
+    private $_show_public_infos = Members::FILTER_DC_PUBINFOS;
+    private $_status = array();
+
+    protected $advancedmemberslist_fields = array(
+        'creation_date_begin',
+        'creation_date_end',
+        'modif_date_begin',
+        'modif_date_end',
+        'due_date_begin',
+        'due_date_end',
+        'show_public_infos',
+        'status',
+        'free_search'
+    );
+
+    protected $virtuals_advancedmemberslist_fields = array(
+        'rcreation_date_begin',
+        'rcreation_date_end',
+        'rmodif_date_begin',
+        'rmodif_date_end',
+        'rdue_date_begin',
+        'rdue_date_end'
+    );
+
+    //an empty free search criteria to begin
+    private $_free_search = array(
+        'empty' => array(
+            'field'     => '',
+            'search'    => '',
+            'log_op'    => self::OP_AND,
+            'qry_op'    => self::OP_EQUALS
+        )
+    );
+
+    /**
+     * Default constructor
+     *
+     * @param MembersList $simple A simple filter search to keep
+     */
+    public function __construct($simple = null)
+    {
+        parent::__construct();
+        if ( $simple instanceof MembersList ) {
+            foreach ( $this->pagination_fields as $pf ) {
+                $this->$pf = $simple->$pf;
+            }
+            foreach ( $this->memberslist_fields as $mlf ) {
+                $this->$mlf = $simple->$mlf;
+            }
+        }
+    }
+
+    /**
+     * Reinit default parameters
+     *
+     * @return void
+     */
+    public function reinit()
+    {
+        parent::reinit();
+
+        $this->_creation_date_begin = null;
+        $this->_creation_date_end = null;
+        $this->_modif_date_begin = null;
+        $this->_modif_date_end = null;
+        $this->_due_date_begin = null;
+        $this->_due_date_end = null;
+        $this->_show_public_infos = Members::FILTER_DC_PUBINFOS;
+        $this->_status = array();
+
+        $this->_free_search = array(
+            'empty' => array(
+                'field'     => '',
+                'search'    => '',
+                'log_op'    => self::OP_AND,
+                'qry_op'    => self::OP_EQUALS
+            )
+        );
+    }
+
+    /**
+     * Global getter method
+     *
+     * @param string $name name of the property we want to retrive
+     *
+     * @return object the called property
+     */
+    public function __get($name)
+    {
+        global $log;
+
+        $log->log(
+            '[AdvancedMembersList] Getting property `' . $name . '`',
+            KLogger::DEBUG
+        );
+
+        if ( in_array($name, $this->pagination_fields)
+            || in_array($name, $this->memberslist_fields)
+        ) {
+            return parent::__get($name);
+        } else {
+            if (in_array($name, $this->advancedmemberslist_fields)
+                || in_array($name, $this->virtuals_advancedmemberslist_fields)
+            ) {
+                $rname = '_' . $name;
+                switch ( $name ) {
+                case 'creation_date_begin':
+                case 'creation_date_end':
+                case 'modif_date_begin':
+                case 'modif_date_end':
+                case 'due_date_begin':
+                case 'due_date_end':
+                    try {
+                        if ( $this->$rname !== null ) {
+                            $d = new \DateTime($this->$rname);
+                            return $d->format(_T("Y-m-d"));
+                        }
+                    } catch (\Exception $e) {
+                        //oops, we've got a bad date :/
+                        $log->log(
+                            'Bad date (' . $this->$rname . ') | ' .
+                            $e->getMessage(),
+                            PER_LOG_INFO
+                        );
+                        return $this->$rname;
+                    }
+                    break;
+                case 'rcreation_date_begin':
+                case 'rcreation_date_end':
+                case 'rmodif_date_begin':
+                case 'rmodif_date_end':
+                case 'rdue_date_begin':
+                case 'rdue_date_end':
+                    //same as above, but raw format
+                    $rname = '_' . substr($name, 1);
+                    return $this->$rname;
+                }
+                return $this->$rname;
+            } else {
+                $log->log(
+                    '[AdvancedMembersList] Unable to get proprety `' .$name . '`',
+                    KLogger::WARN
+                );
+            }
+        }
+    }
+
+    /**
+     * Global setter method
+     *
+     * @param string $name  name of the property we want to assign a value to
+     * @param object $value a relevant value for the property
+     *
+     * @return void
+     */
+    public function __set($name, $value)
+    {
+        global $log;
+
+        if ( in_array($name, $this->pagination_fields)
+            || in_array($name, $this->memberslist_fields)
+        ) {
+            parent::__set($name, $value);
+        } else {
+            $log->log(
+                '[AdvancedMembersList] Setting property `' . $name . '`',
+                KLogger::DEBUG
+            );
+
+            $prop = '_' . $name;
+
+            switch($name) {
+            case 'creation_date_begin':
+            case 'creation_date_end':
+            case 'modif_date_begin':
+            case 'modif_date_end':
+            case 'due_date_begin':
+            case 'due_date_end':
+                try {
+                    $d = \DateTime::createFromFormat(_T("Y-m-d"), $value);
+                    if ( $d === false ) {
+                        throw new \Exception('Incorrect format');
+                    }
+                    $this->$prop = $d->format('Y-m-d');
+                } catch ( \Exception $e ) {
+                    $log->log(
+                        'Incorrect date format! was: ' . $value,
+                        KLogger::WARN
+                    );
+                }
+                break;
+            case 'show_public_infos':
+                if ( is_numeric($value) ) {
+                    $this->$prop = $value;
+                } else {
+                    $log->log(
+                        '[AdvancedMembersList] Value for property `' . $name .
+                        '` should be an integer (' . gettype($value) . ' given)',
+                        KLogger::WARN
+                    );
+                }
+                break;
+            case 'status':
+                if ( !is_array($value) ) {
+                    $value = array($value);
+                }
+                $this->_status = array();
+                foreach ( $value as $v ) {
+                    if ( is_numeric($v) ) {
+                        //check group existence
+                        $s = new Status();
+                        $res = $s->get($v);
+                        if ( $res !== false ) {
+                            $this->_status[] = $v;
+                        } else {
+                            $log->log(
+                                'Status #' . $v . ' does not exists!',
+                                KLogger::WARN
+                            );
+                        }
+                    } else {
+                        $log->log(
+                            '[AdvancedMembersList] Value for status filter should be an '
+                            .'integer (' . gettype($v) . ' given',
+                            KLogger::WARN
+                        );
+                    }
+                }
+                break;
+            case 'free_search':
+                if ( isset($this->_free_search['empty']) ) {
+                    unset($this->_free_search['empty']);
+                }
+                if ( is_array($value) ) {
+                    if ( isset($value['field'])
+                        && isset($value['search'])
+                        && isset($value['log_op'])
+                        && isset($value['qry_op'])
+                        && isset($value['idx'])
+                    ) {
+                        $id = $value['idx'];
+                        unset($value['idx']);
+                        $this->_free_search[$id] = $value;
+                    } else {
+                        $log->log(
+                            '[AdvancedMembersList] bad construct for free filter',
+                            KLogger::WARN
+                        );
+                    }
+                } else {
+                    $log->log(
+                        '[AdvancedMembersList] Value for free filter should be an '
+                        .'array (' . gettype($value) . ' given',
+                        KLogger::WARN
+                    );
+                }
+                break;
+            default:
+                $log->log(
+                    '[AdvancedMembersList] Unable to set proprety `' . $name . '`',
+                    KLogger::WARN
+                );
+                break;
+            }
+        }
+    }
+}
\ No newline at end of file
index 28988f45ec1c397556a47ad7f785e96c238def7a..52938b26fe3e4138976708fee52498c4e0604d4e 100644 (file)
@@ -68,6 +68,20 @@ class MembersList extends Pagination
     private $_selected;
     private $_unreachable;
 
+    protected $query;
+
+    protected $memberslist_fields = array(
+        'filter_str',
+        'field_filter',
+        'membership_filter',
+        'account_status_filter',
+        'email_filter',
+        'group_filter',
+        'selected',
+        'unreachable',
+        'query'
+    );
+
     /**
     * Default constructor
     */
@@ -122,19 +136,13 @@ class MembersList extends Pagination
         if ( in_array($name, $this->pagination_fields) ) {
             return parent::__get($name);
         } else {
-            $return_ok = array(
-                'filter_str',
-                'field_filter',
-                'membership_filter',
-                'account_status_filter',
-                'email_filter',
-                'group_filter',
-                'selected',
-                'unreachable'
-            );
-            if (in_array($name, $return_ok)) {
-                $name = '_' . $name;
-                return $this->$name;
+            if (in_array($name, $this->memberslist_fields)) {
+                if ( $name === 'query' ) {
+                    return $this->$name;
+                } else {
+                    $name = '_' . $name;
+                    return $this->$name;
+                }
             } else {
                 $log->log(
                     '[MembersList] Unable to get proprety `' .$name . '`',
@@ -235,6 +243,9 @@ class MembersList extends Pagination
                     );
                 }
                 break;
+            case 'query':
+                $this->$name = $value;
+                break;
             default:
                 $log->log(
                     '[MembersList] Unable to set proprety `' . $name . '`',
@@ -269,4 +280,50 @@ class MembersList extends Pagination
         $this->counter = (int)$c;
         $this->countPages();
     }
+
+    /**
+     * Set commons filters for templates
+     *
+     * @param Smarty $tpl Smarty template reference
+     *
+     * @return void
+     */
+    public function setTplCommonsFilters($tpl)
+    {
+        $tpl->assign(
+            'filter_field_options',
+            array(
+                Members::FILTER_NAME            => _T("Name"),
+                Members::FILTER_COMPANY_NAME    => _T("Company name"),
+                Members::FILTER_ADRESS          => _T("Address"),
+                Members::FILTER_MAIL            => _T("Email,URL,IM"),
+                Members::FILTER_JOB             => _T("Job"),
+                Members::FILTER_INFOS           => _T("Infos")
+            )
+        );
+
+        $tpl->assign(
+            'filter_membership_options',
+            array(
+                Members::MEMBERSHIP_ALL     => _T("All members"),
+                Members::MEMBERSHIP_UP2DATE => _T("Up to date members"),
+                Members::MEMBERSHIP_NEARLY  => _T("Close expiries"),
+                Members::MEMBERSHIP_LATE    => _T("Latecomers"),
+                Members::MEMBERSHIP_NEVER   => _T("Never contributed"),
+                Members::MEMBERSHIP_STAFF   => _T("Staff members"),
+                Members::MEMBERSHIP_ADMIN   => _T("Administrators")
+            )
+        );
+
+        $tpl->assign(
+            'filter_accounts_options',
+            array(
+                Members::ALL_ACCOUNTS       => _T("All accounts"),
+                Members::ACTIVE_ACCOUNT     => _T("Active accounts"),
+                Members::INACTIVE_ACCOUNT   => _T("Inactive accounts")
+            )
+        );
+
+
+    }
 }
index 18bd918591cfccc306890fc17c95df1571e490b9..381b1a06a79a58acb03e803fa7a7a2bab547ffe8 100644 (file)
 
 namespace Galette\Repository;
 
+use Galette\Entity\DynamicFields;
+
 use Galette\Common\KLogger as KLogger;
 use Galette\Entity\Adherent as Adherent;
 use Galette\Entity\Contribution as Contribution;
 use Galette\Entity\Transaction as Transaction;
 use Galette\Filters\MembersList as MembersList;
+use Galette\Filters\AdvancedMembersList as AdvancedMembersList;
 use Galette\Core\Picture as Picture;
 use Galette\Entity\Group as Group;
 use Galette\Repository\Groups as Groups;
@@ -64,6 +67,10 @@ class Members
     const TABLE = Adherent::TABLE;
     const PK = Adherent::PK;
 
+    const ALL_ACCOUNTS = 0;
+    const ACTIVE_ACCOUNT = 1;
+    const INACTIVE_ACCOUNT = 2;
+
     const SHOW_LIST = 0;
     const SHOW_PUBLIC_LIST = 1;
     const SHOW_ARRAY_LIST = 2;
@@ -79,6 +86,9 @@ class Members
     const FILTER_W_EMAIL = 6;
     const FILTER_WO_EMAIL = 7;
     const FILTER_COMPANY_NAME = 8;
+    const FILTER_DC_PUBINFOS = 9;
+    const FILTER_W_PUBINFOS = 10;
+    const FILTER_WO_PUBINFOS = 11;
 
     const MEMBERSHIP_ALL = 0;
     const MEMBERSHIP_UP2DATE = 3;
@@ -215,9 +225,11 @@ class Members
                 $filters->setLimit($select);
             }
 
+            $filters->query = $select->__toString();
+
             $log->log(
                 "The following query will be executed: \n" .
-                $select->__toString(),
+                $filters->query,
                 KLogger::DEBUG
             );
 
@@ -505,7 +517,7 @@ class Members
     */
     private function _buildSelect($mode, $fields, $filter, $photos, $count = false)
     {
-        global $zdb, $log, $login;
+        global $zdb, $log, $login, $filters;
 
         try {
             $fieldsList = ( $fields != null )
@@ -550,6 +562,44 @@ class Members
                 break;
             }
 
+            //check if there are dynamic fields in the filter
+            $hasDf = false;
+            $hasCdf = false;
+            $cdfs = array();
+            if ( count($filters->free_search) > 0
+                && !isset($filters->free_search['empty'])
+            ) {
+                foreach ( $filters->free_search as $fs ) {
+                    if ( strpos($fs['field'], 'dyn_') === 0 ) {
+                        $hasDf = true;
+                    }
+                    if ( strpos($fs['field'], 'dync_') === 0 ) {
+                        $hasCdf = true;
+                        $cdfs[] = str_replace('dync_', '', $fs['field']);
+                    }
+                }
+            }
+
+            if ( $hasDf === true || $hasCdf === true ) {
+                $select->joinLeft(
+                    array('df' => PREFIX_DB . DynamicFields::TABLE),
+                    'df.item_id=a.' . self::PK
+                );
+            }
+
+            if ( $hasCdf === true ) {
+                $cdf_field = 'cdf.id';
+                if ( TYPE_DB === 'pgsql' ) {
+                    $cdf_field .= '::text';
+                }
+                foreach ( $cdfs as $cdf ) {
+                    $select->joinLeft(
+                        array('cdf' => DynamicFields::getFixedValuesTableName($cdf)),
+                        $cdf_field . '=df.field_val'
+                    );
+                }
+            }
+
             if ( $mode == self::SHOW_LIST || $mode == self::SHOW_MANAGED ) {
                 if ( $filter ) {
                     self::_buildWhereClause($select);
@@ -666,7 +716,7 @@ class Members
      */
     private function _buildWhereClause($select)
     {
-        global $zdb, $login, $filters;
+        global $zdb, $login, $filters, $log;
 
         try {
             if ( $filters->email_filter == self::FILTER_W_EMAIL) {
@@ -771,6 +821,7 @@ class Members
             if ( $filters->membership_filter ) {
                 switch($filters->membership_filter) {
                 case self::MEMBERSHIP_NEARLY:
+                    //TODO: use PHP Date objects
                     $select->where('date_echeance > ?', date('Y-m-d', time()))
                         ->where(
                             'date_echeance < ?',
@@ -807,10 +858,10 @@ class Members
 
             if ( $filters->account_status_filter ) {
                 switch($filters->account_status_filter) {
-                case 1:
+                case self::ACTIVE_ACCOUNT:
                     $select->where('activite_adh=true');
                     break;
-                case 2:
+                case self::INACTIVE_ACCOUNT:
                     $select->where('activite_adh=false');
                     break;
                 }
@@ -829,6 +880,123 @@ class Members
                     $filters->group_filter
                 );
             }
+
+            if ( $filters->rcreation_date_begin || $filters->rcreation_date_end ) {
+                if ( $filters->rcreation_date_begin ) {
+                    $d = new \DateTime($filters->rcreation_date_begin);
+                    $select->where('date_crea_adh >= ?', $d->format('Y-m-d'));
+                }
+                if ( $filters->rcreation_date_end ) {
+                    $d = new \DateTime($filters->rcreation_date_end);
+                    $select->where('date_crea_adh <= ?', $d->format('Y-m-d'));
+                }
+            }
+
+            if ( $filters->rmodif_date_begin || $filters->rmodif_date_end ) {
+                if ( $filters->rmodif_date_begin ) {
+                    $d = new \DateTime($filters->rmodif_date_begin);
+                    $select->where('date_modif_adh >= ?', $d->format('Y-m-d'));
+                }
+                if ( $filters->rmodif_date_end ) {
+                    $d = new \DateTime($filters->rmodif_date_end);
+                    $select->where('date_modif_adh <= ?', $d->format('Y-m-d'));
+                }
+            }
+
+            if ( $filters->rdue_date_begin || $filters->rdue_date_end ) {
+                if ( $filters->rdue_date_begin ) {
+                    $d = new \DateTime($filters->rdue_date_begin);
+                    $select->where('date_echeance >= ?', $d->format('Y-m-d'));
+                }
+                if ( $filters->rdue_date_end ) {
+                    $d = new \DateTime($filters->rdue_date_end);
+                    $select->where('date_echeance <= ?', $d->format('Y-m-d'));
+                }
+            }
+
+            if ( $filters->show_public_infos ) {
+                switch ( $filters->show_public_infos ) {
+                case self::FILTER_W_PUBINFOS:
+                    $select->where('bool_display_info = true');
+                    break;
+                case self::FILTER_WO_PUBINFOS:
+                    $select->where('bool_display_info = false');
+                    break;
+                case self::FILTER_DC_PUBINFOS:
+                    //nothing to do here.
+                    break;
+                }
+            }
+
+            if ( $filters->status ) {
+                $select->where(
+                    'a.id_statut IN (' . implode(',', $filters->status) . ')'
+                );
+            }
+
+            if ( count($filters->free_search) > 0
+                && !isset($filters->free_search['empty'])
+            ) {
+                foreach ( $filters->free_search as $fs ) {
+                    $fs['search'] = mb_strtolower($fs['search']);
+                    $qop = null;
+                    switch ( $fs['qry_op'] ) {
+                    case AdvancedMembersList::OP_EQUALS:
+                        $qop = '=';
+                        break;
+                    case AdvancedMembersList::OP_CONTAINS:
+                        $qop = 'LIKE';
+                        $fs['search'] = '%' . $fs['search'] . '%';
+                        break;
+                    case AdvancedMembersList::OP_NOT_EQUALS:
+                        $qop = '!=';
+                        break;
+                    case AdvancedMembersList::OP_NOT_CONTAINS:
+                        $qop = 'NOT LIKE';
+                        $fs['search'] = '%' . $fs['search'] . '%';
+                        break;
+                    case AdvancedMembersList::OP_STARTS_WITH:
+                        $qop = 'LIKE';
+                        $fs['search'] = $fs['search'] . '%';
+                        break;
+                    case AdvancedMembersList::OP_ENDS_WITH:
+                        $qop = 'LIKE';
+                        $fs['search'] = '%' . $fs['search'];
+                        break;
+                    default:
+                        $log->log(
+                            'Unknown query operator: ' . $fs['qry_op'] .
+                            ' (will fallback to equals)',
+                            KLogger::WARN
+                        );
+                        $qop = '=';
+                        break;
+                    }
+
+                    $qry = '';
+                    $prefix = '';
+                    if ( strpos($fs['field'], 'dync_') === 0 ) {
+                        //dynamic choice spotted!
+                        $prefix = 'cdf.';
+                        $qry = 'df.field_form = \'adh\' AND df.field_id = ' .
+                            str_replace('dync_', '', $fs['field']) . ' AND ';
+                        $fs['field'] = 'val';
+                    } elseif ( strpos($fs['field'], 'dyn_') === 0 ) {
+                        //dynamic field spotted!
+                        $prefix = 'df.';
+                        $qry = 'df.field_form = \'adh\' AND df.field_id = ' .
+                            str_replace('dyn_', '', $fs['field']) . ' AND ';
+                        $fs['field'] = 'field_val';
+                    }
+
+                    $qry .= 'LOWER(' . $prefix . $fs['field'] . ') ' . $qop  . ' ?' ;
+                    if ( $fs['log_op'] === AdvancedMembersList::OP_AND ) {
+                        $select->where($qry, $fs['search']);
+                    } elseif ( $fs['log_op'] === AdvancedMembersList::OP_OR ) {
+                        $select->orWhere($qry, $fs['search']);
+                    }
+                }
+            }
         } catch (\Exception $e) {
             /** TODO */
             $log->log(
diff --git a/galette/templates/default/advanced_search.tpl b/galette/templates/default/advanced_search.tpl
new file mode 100644 (file)
index 0000000..32bf0e0
--- /dev/null
@@ -0,0 +1,193 @@
+        <form action="gestion_adherents.php" method="post" id="filtre">
+            <fieldset class="cssform large">
+                <legend class="ui-state-active ui-corner-top">{_T string="Simple search"}</legend>
+                <div>
+                    <p>
+                        <label class="bline" for="filter_str">{_T string="Search:"}</label>
+                        <input type="text" name="filter_str" id="filter_str" value="{$filters->filter_str}" type="search" placeholder="{_T string="Enter a value"}"/>&nbsp;
+                        {_T string="in:"}&nbsp;
+                        <select name="filter_field">
+                            {html_options options=$filter_field_options selected=$filters->field_filter}
+                        </select>
+                    </p>
+                    <p>
+                        <label class="bline" for="filter_membership">{_T string="Membership status"}</label>
+                        <select id="filter_membership" name="filter_membership">
+                            {html_options options=$filter_membership_options selected=$filters->membership_filter}
+                        </select>
+                    </p>
+                    <p>
+                        <label class="bline" for="filter_account">{_T string="Account activity"}</label>
+                        <select id="filter_account" name="filter_account">
+                            {html_options options=$filter_accounts_options selected=$filters->account_status_filter}
+                        </select>
+                    </p>
+                    <p>
+                        <label class="bline" for="group_filter">{_T string="Member of group"}</label>
+                        <select name="group_filter" onchange="form.submit()">
+                            <option value="0">{_T string="Select a group"}</option>
+{foreach from=$filter_groups_options item=group}
+                            <option value="{$group->getId()}"{if $filters->group_filter eq $group->getId()} selected="selected"{/if}>{$group->getName()}</option>
+{/foreach}
+                        </select>
+                    <p>
+                        <span class="bline">{_T string="With mail:"}</span>
+                        <input type="radio" name="email_filter" id="filter_dc_email" value="{php}echo Galette\Repository\Members::FILTER_DC_EMAIL;{/php}"{if $filters->email_filter eq constant('Galette\Repository\Members::FILTER_DC_EMAIL')} checked="checked"{/if}>
+                        <label for="filter_dc_email" >{_T string="Don't care"}</label>
+                        <input type="radio" name="email_filter" id="filter_with_email" value="{php}echo Galette\Repository\Members::FILTER_W_EMAIL;{/php}"{if $filters->email_filter eq constant('Galette\Repository\Members::FILTER_W_EMAIL')} checked="checked"{/if}>
+                        <label for="filter_with_email" >{_T string="With"}</label>
+                        <input type="radio" name="email_filter" id="filter_without_email" value="{php}echo Galette\Repository\Members::FILTER_WO_EMAIL;{/php}"{if $filters->email_filter eq constant('Galette\Repository\Members::FILTER_WO_EMAIL')} checked="checked"{/if}>
+                        <label for="filter_without_email" >{_T string="Without"}</label>
+                    </p>
+                </div>
+            </fieldset>
+            <fieldset class="cssform large">
+                <legend class="ui-state-active ui-corner-top">{_T string="Advanced search"}</legend>
+                <div>
+                    <p>
+                        <span class="bline">{_T string="Creation date"}</span>
+                        <label for="creation_date_begin">{_T string="beetween"}</label>
+                        <input id="creation_date_begin" name="creation_date_begin" type="text" class="modif_date" maxlength="10" size="10" value="{$filters->creation_date_begin}"/>
+                        <label for="creation_date_end">{_T string="and"}</label>
+                        <input id="creation_date_end" name="creation_date_end" type="text" class="modif_date" maxlength="10" size="10" value="{$filters->creation_date_end}"/>
+                    </p>
+                    <p>
+                        <span class="bline">{_T string="Modification date"}</span>
+                        <label for="modif_date_begin">{_T string="beetween"}</label>
+                        <input id="modif_date_begin" name="modif_date_begin" type="text" class="modif_date" maxlength="10" size="10" value="{$filters->modif_date_begin}"/>
+                        <label for="modif_date_end">{_T string="and"}</label>
+                        <input id="modif_date_end" name="modif_date_end" type="text" class="modif_date" maxlength="10" size="10" value="{$filters->modif_date_end}"/>
+                    </p>
+                    <p>
+                        <span class="bline">{_T string="Due date"}</span>
+                        <label for="due_date_begin">{_T string="beetween"}</label>
+                        <input id="due_date_begin" name="due_date_begin" type="text" class="due_date" maxlength="10" size="10" value="{$filters->due_date_begin}"/>
+                        <label for="due_date_end">{_T string="and"}</label>
+                        <input id="due_date_end" name="due_date_end" type="text" class="due_date" maxlength="10" size="10" value="{$filters->due_date_end}"/>
+                    </p>
+                    <p>
+                        <span class="bline">{_T string="Show public infos"}</span>
+                        <input type="radio" name="show_public_infos" id="show_public_infos_dc" value="{php}echo Galette\Repository\Members::FILTER_DC_PUBINFOS;{/php}"{if $filters->show_public_infos eq constant('Galette\Repository\Members::FILTER_DC_PUBINFOS')} checked="checked"{/if}>
+                        <label for="show_public_infos_dc" >{_T string="Don't care"}</label>
+                        <input type="radio" name="show_public_infos" id="show_public_infos_yes" value="{php}echo Galette\Repository\Members::FILTER_W_PUBINFOS;{/php}"{if $filters->show_public_infos eq constant('Galette\Repository\Members::FILTER_W_PUBINFOS')} checked="checked"{/if}>
+                        <label for="show_public_infos_yes" >{_T string="Yes"}</label>
+                        <input type="radio" name="show_public_infos" id="show_public_infos_no" value="{php}echo Galette\Repository\Members::FILTER_WO_PUBINFOS;{/php}"{if $filters->show_public_infos eq constant('Galette\Repository\Members::FILTER_WO_PUBINFOS')} checked="checked"{/if}>
+                        <label for="show_public_infos_no" >{_T string="No"}</label>
+                    </p>
+                    <p>
+                        <label class="bline" for="status">{_T string="Statuts"}</label>
+                        <select name="status[]" id="status" multiple="multiple">
+                            {html_options options=$statuts selected=$filters->status}
+                        </select>
+                    </p>
+                </div>
+            </fieldset>
+            <fieldset class="cssform large">
+                <legend class="ui-state-active ui-corner-top">{_T string="Free search"}<a class="clearfilter" href="#" title="{_T string="Add new free search criteria"}" id="btnadd_small">{_T string="Add"}</a></legend>
+                <ul id="fs_sortable" class="fields_list connectedSortable">
+{foreach from=$filters->free_search item=fs}
+                    <li>
+                        <select name="free_logical_operator[]">
+                            <option value="{php}echo Galette\Filters\AdvancedMembersList::OP_AND;{/php}"{if $fs.log_op eq constant('Galette\Filters\AdvancedMembersList::OP_AND')} selected="selected"{/if}>{_T string="and"}</option>
+                            <option value="{php}echo Galette\Filters\AdvancedMembersList::OP_OR;{/php}"{if $fs.log_op eq constant('Galette\Filters\AdvancedMembersList::OP_OR')} selected="selected"{/if}>{_T string="or"}</option>
+                        </select>
+                        <select name="free_field[]">
+                            <option value="">{_T string="Select a field"}</option>
+    {foreach $search_fields as $field}
+                            <option value="{$field@key}"{if $fs.field eq $field@key} selected="selected"{/if}>{$field.label}</option>
+    {/foreach}
+    {foreach $dynamic_fields as $field}
+                            <option value="dyn{if $field.field_type eq constant('Galette\Entity\DynamicFields::CHOICE')}c{/if}_{$field.field_id}"{if $fs.field eq $field.field_id} selected="selected"{/if}>{$field.field_name}</option>
+    {/foreach}
+                        </select>
+                        <select name="free_query_operator[]">
+                            <option value="{php}echo Galette\Filters\AdvancedMembersList::OP_EQUALS;{/php}"{if $fs.qry_op eq constant('Galette\Filters\AdvancedMembersList::OP_EQUALS')} selected="selected"{/if}>{_T string="is"}</option>
+                            <option value="{php}echo Galette\Filters\AdvancedMembersList::OP_CONTAINS;{/php}"{if $fs.qry_op eq constant('Galette\Filters\AdvancedMembersList::OP_CONTAINS')} selected="selected"{/if}>{_T string="contains"}</option>
+                            <option value="{php}echo Galette\Filters\AdvancedMembersList::OP_NOT_EQUALS;{/php}"{if $fs.qry_op eq constant('Galette\Filters\AdvancedMembersList::OP_NOT_EQUALS')} selected="selected"{/if}>{_T string="is not"}</option>
+                            <option value="{php}echo Galette\Filters\AdvancedMembersList::OP_NOT_CONTAINS;{/php}"{if $fs.qry_op eq constant('Galette\Filters\AdvancedMembersList::OP_NOT_CONTAINS')} selected="selected"{/if}>{_T string="do not contains"}</option>
+                            <option value="{php}echo Galette\Filters\AdvancedMembersList::OP_STARTS_WITH;{/php}"{if $fs.qry_op eq constant('Galette\Filters\AdvancedMembersList::OP_STARTS_WITH')} selected="selected"{/if}>{_T string="starts with"}</option>
+                            <option value="{php}echo Galette\Filters\AdvancedMembersList::OP_ENDS_WITH;{/php}"{if $fs.qry_op eq constant('Galette\Filters\AdvancedMembersList::OP_ENDS_WITH')} selected="selected"{/if}>{_T string="ends with"}</option>
+                        </select>
+                        <a class="fright clearfilter" href="#" title="{_T string="Remove criteria"}">{_T string="Remove criteria"}</a>
+                        <br/>
+                        <input type="text" name="free_text[]" class="large" value="{$fs.search}"/>
+                    </li>
+{/foreach}
+                </ul>
+            </fieldset>
+{* This one will be available later
+{if $login->isAdmin()}
+            <fieldset class="cssform large">
+                <legend class="ui-state-active ui-corner-top">{_T string="Expert search"}</legend>
+                <div>
+                    <p id="warningbox"><strong>{_T string="Be extremely careful when using this one!"}</strong><br/>{_T string="If the following is not empty, all others filters will be ignored."}</p>
+                    <p>
+                        <label class="bline" for="sql_where">{_T string="SQL query"}</label>
+                        <textarea name="sql" id="sql"></textarea><br/>
+                        <span class="exemple">{_T string="If your query does not begin with a 'SELECT' statement, it will automatically be added."}</span>
+                    </p>
+                </div>
+            </fieldset>
+{/if}*}
+            <div class="center">
+                <input type="hidden" name="advanced_filtering" value="true" />
+                <input type="submit" class="inline" value="{_T string="Filter"}"/>
+                <input type="submit" name="clear_filter" class="inline" value="{_T string="Clear filter"}"/>
+            </div>
+        </form>
+        <script type="text/javascript">
+            var _newFilter = function(elt) {
+                elt.find('input').val('');
+                elt.find('select').val('');
+            }
+            var _rmFilter = function(elt) {
+                if ( !elt ) {
+                    elt = $('li');
+                }
+                elt.find('.clearfilter').click(function(){
+                    var _this = $(this);
+                    if ( _this.parents('ul').find('li').length > 1 ) {
+                        _this.parent('li').remove();
+                    } else {
+                        _newFilter(_this.parent('li'));
+                    }
+                    return false;
+                });
+            }
+
+            $(function(){
+                _collapsibleFieldsets();
+                _initSortable();
+
+                $.datepicker.setDefaults($.datepicker.regional['{$galette_lang}']);
+                $('.modif_date').datepicker({
+                    changeMonth: true,
+                    changeYear: true,
+                    showOn: 'button',
+                    buttonImage: './templates/default/images/calendar.png',
+                    buttonImageOnly: true,
+                    maxDate: '-0d',
+                    yearRange: 'c-10'
+                });
+                $('.due_date').datepicker({
+                    changeMonth: true,
+                    changeYear: true,
+                    showOn: 'button',
+                    buttonImage: './templates/default/images/calendar.png',
+                    buttonImageOnly: true,
+                    yearRange: 'c-10:c+5'
+                });
+
+                $('#btnadd_small').click(function(){
+                    var _ul = $('#fs_sortable');
+                    var _new = _ul.find('li').last().clone();
+                    _newFilter(_new);
+                    _rmFilter(_new);
+                    _ul.append(_new);
+                    _fieldsInSortable();
+                    return false;
+                });
+
+                _rmFilter();
+            });
+        </script>
index 27a47a2bc26654cf6b3b3fd865f99244d7420aab..d64f6216c87d9c045a5f16c42bdf4883382bbc53 100644 (file)
@@ -597,7 +597,7 @@ h1 #sendmail .ui-button-text {
     background-image:url(images/icon-add.png), url("jquery-ui/images/ui-bg_glass_75_e6e6e6_1x400.png");
 }
 #btnadd.ui-state-hover, #btnadd_small.ui-state-hover{
-    background-image:url(images/icon-add.png), url("jquery-ui/images/ui-bg_glass_75_ffb619_1x400.png");
+   background-image:url(images/icon-add.png), url("jquery-ui/images/ui-bg_glass_75_ffb619_1x400.png");
 }
 
 #btnadd_small, #btnusers_small, #btnmanagers_small {
@@ -605,6 +605,9 @@ h1 #sendmail .ui-button-text {
     top: .5em;
     right: .5em;
 }
+legend #btnadd_small {
+    right: 2.5em;
+}
 
 #btncancel {
     background-image:url(images/icon-cancel.png), url("jquery-ui/images/ui-bg_glass_75_e6e6e6_1x400.png");
@@ -811,10 +814,11 @@ h1 #sendmail .ui-button-text {
     background-color: transparent;
 }
 
-#clearfilter {
+#clearfilter, .clearfilter {
     background: url(images/clearfilter.png) 0 50% no-repeat;
     display:inline-block;
     width:16px;
+    height:16px;
     overflow: hidden;
     text-indent: 20px;
     vertical-align: bottom;
@@ -1657,8 +1661,8 @@ th.bline, td.bline{
 .fleft{float:left;}
 .fright{float:right;}
 
-input.large{
-    width:90%;
+input.large, span.large {
+    width:90%!important;
 }
 
 .picker{
@@ -1823,6 +1827,7 @@ td.photo img{
     display:inline-block;
     width: 33%;
 }
+
 .fields_list span.yesno{
     margin-right:.2em;
     display:inline-block;
index f8e24ea8f7dfebb6e98b1c3442b653ca84d12086..a268f6d243810460803e1b46cfeb9174c9af09b5 100644 (file)
@@ -1,5 +1,6 @@
                <form action="gestion_adherents.php" method="get" id="filtre">
                <div id="listfilter">
+{if !$adv_filters}
                        <label for="filter_str">{_T string="Search:"}&nbsp;</label>
                        <input type="text" name="filter_str" id="filter_str" value="{$filters->filter_str}" type="search" placeholder="{_T string="Enter a value"}"/>&nbsp;
                        {_T string="in:"}&nbsp;
                 <input type="radio" name="email_filter" id="filter_without_email" value="{php}echo Galette\Repository\Members::FILTER_WO_EMAIL;{/php}"{if $filters->email_filter eq constant('Galette\Repository\Members::FILTER_WO_EMAIL')} checked="checked"{/if}>
                 <label for="filter_without_email" >{_T string="Without"}</label>
             </div>
+{else}
+            <p>
+                <strong>{_T string="Advanced search mode"}</strong>
+                <input type="submit" name="adv_criterias" class="inline" value="{_T string="Change search criterias"}"/>
+                <input type="submit" name="clear_filter" class="inline" value="{_T string="Clear filter"}"/>
+                <br/>
+                <a href="#" id="showhideqry">{_T string="Show/hide query"}</a>
+            </p>
+            <pre id="sql_qry" class="hidden">{$filters->query}</pre>
+{/if}
                </div>
                <table class="infoline">
                        <tr>
                     return true;
                 }
             });
+
+            if ( _shq = $('#showhideqry') ) {
+                _shq.click(function(){
+                    $('#sql_qry').toggleClass('hidden');
+                    return false;
+                });
+            }
         });
 
         var _attendance_sheet_details = function(){
index b5c02befcd297c0badc6c819a923599631c6e1da..e7403120cf38156727f43824ecdd33ae369f64a2 100644 (file)
                     <input type="hidden" name="login_adh" value="{$member->login}"/>
     {/if}
     {if !$self_adh}
-        {if $visibles.password_adh eq constant('Galette\Entity\FieldsConfig::VISIBLE') or ($visibles.password_adh eq constant('Galette\Entity\FieldsConfig::ADMIN') and ($login->isStaff() or $login->isAdmin() or $login->isSuperAdmin()))}
+        {if $visibles.mdp_adh eq constant('Galette\Entity\FieldsConfig::VISIBLE') or ($visibles.mdp_adh eq constant('Galette\Entity\FieldsConfig::ADMIN') and ($login->isStaff() or $login->isAdmin() or $login->isSuperAdmin()))}
                     <p>
                         <label for="mdp_adh" class="bline">{_T string="Password:"}</label>
                         <input type="password" name="mdp_adh" id="mdp_adh" value="" maxlength="20" autocomplete="off" {$disabled.mdp_adh}{if $required.mdp_adh eq 1} required{/if}/>
index 9641d3818fcd33a3afee4a3f9437e6bc2b370309..98e562985dc0ce542791b26d51a1d83c78055777 100644 (file)
@@ -102,6 +102,7 @@ We have to use a template file, so Smarty will do its work (like replacing varia
   {if $login->isAdmin() or $login->isStaff() or $login->isGroupManager()}
             <li{if $PAGENAME eq "desktop.php"} class="selected"{/if}><a href="{$galette_base_path}desktop.php" title="{_T string="Go to Galette's dashboard"}">{_T string="Dashboard"}</a></li>
                        <li{if $PAGENAME eq "gestion_adherents.php"} class="selected"{/if}><a href="{$galette_base_path}gestion_adherents.php" title="{_T string="View, search into and filter member's list"}">{_T string="List of members"}</a></li>
+                       <li{if $PAGENAME eq "advanced_search.php"} class="selected"{/if}><a href="{$galette_base_path}advanced_search.php" title="{_T string="Perform advanced search into members list"}">{_T string="Advanced search"}</a></li>
                        <li{if $PAGENAME eq "gestion_groupes.php"} class="selected"{/if}><a href="{$galette_base_path}gestion_groupes.php" title="{_T string="View and manage groups"}">{_T string="Manage groups"}</a></li>
   {/if}
   {if $login->isAdmin() or $login->isStaff()}