| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640 | 
							- <?php
 
- /**
 
-  * @file
 
-  * Query By Form
 
-  *
 
-  * This module allows node modules to add a query by form tab for their node
 
-  * types to the default search form
 
-  *
 
-  * @copyright 2008 Ouest Systemes Informatiques (OSInet)
 
-  * @author Frederic G. MARAND
 
-  * @license CeCILL 2.0
 
-  * @package QBF
 
-  */
 
- // $Id: qbf.module,v 1.9.2.3 2008-10-03 17:40:40 marand Exp $
 
- /**
 
-  * Saved error reporting level.
 
-  *
 
-  * QBF module is supposed to pass parsing at E_ALL|E_STRICT, but other modules
 
-  * may not be so strict, so we save the level at the start of the module and
 
-  * restore it at the end of the module.
 
-  */
 
- global $_qbf_er;
 
- $_qbf_er = error_reporting(E_ALL | E_STRICT);
 
- /**
 
-  * Remove this element from the generated form
 
-  */
 
- define('QBF_LEVEL_REMOVE',           0);
 
- /**
 
-  * This element is only for display in the generated form: do not include it
 
-  * in the query vector.
 
-  */
 
- define('QBF_LEVEL_DISPLAY',          1);
 
- /**
 
-  * Include this element in the generated form and in the query vector, but do
 
-  * not mark it as required.
 
-  */
 
- define('QBF_LEVEL_OPTIONAL',         2);
 
- /**
 
-  * Include this element in the generated form and in the query vector, and
 
-  * mark it as required.
 
-  */
 
- define('QBF_LEVEL_REQUIRED',         3);
 
- /**
 
-  * The main QBF path.
 
-  *
 
-  * It MUST be a single component path, without a "/", otherwise qbf_menu() will
 
-  * need to be changed.
 
-  *
 
-  * @ingroup paths
 
-  * @see qbf_menu()
 
-  */
 
- define('QBF_PATH_MAIN',              'qbf');
 
- /**
 
-  * The QBF autocomplete path for search fields
 
-  * @ingroup paths
 
-  */
 
- define('QBF_PATH_AC',                'qbf/ac');
 
- /**
 
-  * Authorize use of QBF searches
 
-  */
 
- define('QBF_PERM_QUERY',             'use QBF search functions');
 
- /**
 
-  * Authorize QBF administration
 
-  */
 
- define('QBF_PERM_ADMIN',             'administer QBF');
 
- /**
 
-  * The name of the table used to store queries
 
-  */
 
- define('QBF_TABLE_NAME',             'qbf_queries');
 
- /**
 
-  * Notify owner about saved query deletions, variable name.
 
-  */
 
- define('QBF_VAR_NOTIFY_DELETE',      'qbf_notify_delete');
 
- /**
 
-  * Notify owner about saved query deletions, default value.
 
-  */
 
- define('QBF_DEF_NOTIFY_DELETE',      FALSE);
 
- /**
 
-  * Transform a form array for QBF.
 
-  *
 
-  * This function obtains the form array using Forms API, and transforms it by
 
-  * modifying widgets to other types where needed.
 
-  *
 
-  * Any additional parameter passed to the function is transmitted to the form
 
-  * generating function.
 
-  *
 
-  * @ingroup forms
 
-  * @param string $form_id
 
-  * @return array
 
-  */
 
- function qbf_transform_form($form_id) {
 
-   $arArgs = func_get_args();
 
- //dsm(array('qtf' => $arArgs));
 
-   // Fetch the basic form and rename it, passing it the caller's arguments
 
-   $form = call_user_func_array('drupal_retrieve_form', $arArgs);
 
-   $newFormId = "qbf_$form_id";
 
-   // Only keep the children of the form and QBF properties on the form itself
 
-   $elements = array();
 
-   $newForm = array();
 
-   $newForm['#qbf_source_form_id'] = $form_id;
 
-   if (in_array('#qbf', element_properties($form)))
 
-     {
 
-     $newForm += $form['#qbf'];
 
-     }
 
-   foreach (element_children($form) as $key)
 
-     {
 
-     // dsm("Transforming $key, type " . $form[$key]['#type']);
 
-     $newElement = _qbf_transform_element($key, $form[$key]);
 
-     if (!is_null($newElement))
 
-       {
 
-       $newForm[$key] = $newElement;
 
-       }
 
-     }
 
-   $newForm['#id'] = $newFormId;
 
-   $newForm['#multistep'] = TRUE;
 
-   // Do not set #redirect, even to FALSE (submit handlers)
 
-   // $newForm['#redirect']  = FALSE;
 
-   $newForm['#after_build'][] = 'qbf_after_build';
 
-   $newForm['#submit'] = array('qbf_submit' => array());
 
- // dsm($newForm);
 
-   return $newForm;
 
- }
 
- /**
 
-  * Transform a form element for QBF.
 
-  *
 
-  * QBF-specific properties are:
 
-  * - #qbf : array of properties
 
-  * - #level: only within #qbf
 
-  *
 
-  * See QBF_* constants
 
-  *
 
-  * @ingroup forms
 
-  * @param string $key
 
-  * @param array $element
 
-  * @return void
 
-  */
 
- function _qbf_transform_element($key, $element) {
 
-   // dsm(array('key' => $key, 'element' => $element));
 
-   /**
 
-    * List default type transformations applied to widget by FAPI.
 
-    *
 
-    * Types without a default transformation are not transformed
 
-    */
 
-   static $arDefaultTypeTransformations = array
 
-     (
 
-     'button'         => NULL,
 
-     'file'           => NULL,
 
-     // 'hidden'         => NULL,
 
-     'markup'         => NULL,
 
-     'password'       => NULL,
 
-     'radio'          => NULL,
 
-     'submit'         => NULL,
 
-     'textarea'       => 'textfield',
 
-     // 'value'          => 'value',
 
-     );
 
-   /**
 
-    * List default property transformations applied to widget by FAPI property.
 
-    *
 
-    * Properties without a default transformation are not transformed
 
-    */
 
-   static $arDefaultPropertyTransformations = array
 
-     (
 
-     // Standard properties
 
-     '#action'        => NULL,
 
-     '#after_build'   => NULL,
 
-     '#base'          => NULL,
 
-     '#button_type'   => NULL,
 
-     '#built'         => NULL,
 
-     '#description'   => NULL,
 
-     '#method'        => NULL,
 
-     '#parents'       => NULL,
 
-     '#redirect'      => NULL,
 
-     '#ref'           => NULL,
 
-     '#required'      => NULL,
 
-     '#rows'          => NULL,
 
-     '#submit'        => NULL,
 
-     '#tree'          => NULL,
 
-     '#validate'      => NULL,
 
-     );
 
-   /**
 
-    * List properties causing causing element removal.
 
-    *
 
-    * The key is the property name, the value is the one causing removal.
 
-    */
 
-   static $arKillerProperties = array
 
-     (
 
-     '#disabled'      => TRUE,
 
-     );
 
-   // Transform type
 
-   $sourceType = $element['#type'];
 
-   // .. Default transformation
 
-   $destType = array_key_exists($sourceType, $arDefaultTypeTransformations)
 
-     ? $arDefaultTypeTransformations[$sourceType]
 
-     : $sourceType;
 
-   // .. Apply form-defined type override
 
-   if (isset($element['#qbf']['#type']))
 
-     {
 
-     $destType = $element['#qbf']['#type'];
 
-     }
 
-   if (is_null($destType))
 
-     {
 
-     $ret = NULL;
 
-     }
 
-   else
 
-     {
 
-     $ret = $element;
 
-     $ret['#type'] = $destType;
 
-     if (!array_key_exists('#qbf', $element) || $element['#qbf']['#level'] == QBF_LEVEL_REMOVE)
 
-       {
 
-       $ret = NULL;
 
-       }
 
-     else
 
-       {
 
-       foreach (element_properties($element) as $propertyName)
 
-         {
 
-         // Apply killer properties first to avoid useless work
 
-         if (array_key_exists($propertyName, $arKillerProperties)
 
-           && ($element[$propertyName] = $arKillerProperties[$propertyName]))
 
-           {
 
-           $ret = NULL;
 
-           break;
 
-           }
 
-         // Now transform or copy remaining properties
 
-         if (array_key_exists($propertyName, $arDefaultPropertyTransformations))
 
-           {
 
-           $ret[$propertyName] = $arDefaultPropertyTransformations[$propertyName];
 
-           }
 
-         else
 
-           {
 
-           $ret[$propertyName] = $element[$propertyName];
 
-           }
 
-         // And apply form-defined property overrides
 
-         if ($propertyName == '#qbf')
 
-           {
 
-           foreach ($element[$propertyName] as $overrideName => $overrideValue)
 
-             {
 
-             $ret[$overrideName] = $overrideValue;
 
-             }
 
-           }
 
-         }
 
-       // Recursively transform children
 
-       foreach (element_children($element) as $childName)
 
-         {
 
-         $child = _qbf_transform_element($childName, $element[$childName]);
 
-         if (is_null($child))
 
-           {
 
-           unset($ret[$childName]);
 
-           }
 
-         else
 
-           {
 
-           $ret[$childName] = $child;
 
-           }
 
-         }
 
-       }
 
-     }
 
-   //dsm(array('key' => $key, 'transformed element' => $ret));
 
-   return $ret;
 
- }
 
- /**
 
-  * Implement hook_perm().
 
-  *
 
-  * @ingroup hooks
 
-  * @return array
 
-  */
 
- function qbf_perm() {
 
-   $ret = array
 
-     (
 
-     QBF_PERM_QUERY,
 
-     );
 
-   return $ret;
 
- }
 
- /**
 
-  * Implement hook_forms().
 
-  *
 
-  * @ingroup forms
 
-  * @ingroup hooks
 
-  * @return array
 
-  */
 
- function qbf_forms() {
 
-   $hookName = 'qbf_register';
 
-   foreach (module_implements($hookName) as $module)
 
-     {
 
-     foreach (module_invoke($module, $hookName) as $formName)
 
-       {
 
-       $forms["qbf_$formName"] = array
 
-         (
 
-         'callback'           => 'qbf_transform_form',
 
-         'callback arguments' => array($formName),
 
-         );
 
-       }
 
-     }
 
-   return $forms;
 
- }
 
- /**
 
-  * Insert the query results at the bottom of the query form.
 
-  *
 
-  * @ingroup forms
 
-  * @param array $form
 
-  * @param array $form_values
 
-  * @return array
 
-  */
 
- function qbf_after_build($form, $form_values) {
 
-   if (empty($form['#post']))
 
-     {
 
-     return $form;
 
-     }
 
-   // If #post is not emtpy, we are indeed querying
 
-   $arQuery = _qbf_extract_query($form, $form_values);
 
-   /* This function is called at the end of the form building process, which
 
-    * means that child properties of #qbf have already been upgraded to element
 
-    * properties. So we look for $form['#callback'] and not
 
-    * $form['#qbf']['#callback']
 
-    */
 
-   if (isset($form['#callback']) && function_exists($function = $form['#callback']))
 
-     {
 
-     $results = $function($arQuery);
 
-     }
 
-   else
 
-     {
 
-     drupal_set_message(t('QBF: incorrect callback function for search'), 'error');
 
-     }
 
-   $form['qbf_query_results'] = array
 
-     (
 
-     '#type'    => 'markup',
 
-     '#value'   => $results,
 
-     '#weight'  => 10,
 
-     );
 
-   return $form;
 
- }
 
- /**
 
-  * Recursively build a query array from the form and its values
 
-  *
 
-  * In the current version, element names are supposed to be unique, even at
 
-  * different levels in the tree.
 
-  *
 
-  * @ingroup forms
 
-  * @param array $form
 
-  * @param array $form_values
 
-  */
 
- function _qbf_extract_query($form, $form_values) {
 
-   $name = $form['#parents'][0];
 
-   // Elements which are removed or display-only have no place in the query
 
-   if (array_key_exists('#qbf', $form) && array_key_exists('#level', $form['#qbf'])
 
-     && $form['#qbf']['#level'] >= QBF_LEVEL_OPTIONAL)
 
-     {
 
-     $ret = array($name => $form_values[$name]);
 
-     }
 
-   else
 
-     {
 
-     $ret = array();
 
-     }
 
-   // QBF level is not inherited, so this loop is outside the "if" above
 
-   foreach (element_children($form) as $childName)
 
-     {
 
-     $ret += _qbf_extract_query($form[$childName], $form_values);
 
-     }
 
-   return $ret;
 
- }
 
- /**
 
-  * Provide an optional automatic mapping mechanism for query building.
 
-  *
 
-  * This function takes a partly built query map $arQueryMap, and a defaults
 
-  * array to complete it in $arDefaults, and returns a fully built query array
 
-  * ready to be used for querying.
 
-  *
 
-  * @param array $arQuery
 
-  * @param array $arDefaults
 
-  * @return array
 
-  */
 
- function qbf_query_mapper($arQueryMap = array(), $arDefaults = array()) {
 
-   $ret = array();
 
-   foreach ($arQueryMap as $name => $value)
 
-     {
 
-     if (!is_array($value)) // accept NULL, empty strings...
 
-       {
 
-       $value = array();
 
-       }
 
-     $item = $value;
 
-     foreach ($arDefaults as $defaultKey => $defaultValue)
 
-       {
 
-       if (!array_key_exists($defaultKey, $item))
 
-         {
 
-         $item[$defaultKey] = is_null($defaultValue)
 
-           ? $name
 
-           : $defaultValue;
 
-         }
 
-       // else if is already in $item, so we don't touch it
 
-       }
 
-     $ret[$name] = $item;
 
-     }
 
-   return $ret;
 
- }
 
- /**
 
-  * Load a form_values array into a form used by QBF.
 
-  *
 
-  * This is typically useful when loading saved queries using qbf_load().
 
-  * For other cases, the mechanisms built within FAPI should be used instead.
 
-  *
 
-  * @see qbf_load()
 
-  *
 
-  * @ingroup forms
 
-  * @param array $form
 
-  * @param array $form_values
 
-  * @return array The modified form
 
-  */
 
- function qbf_import_values($element, $form_values) {
 
-   foreach (element_children($element) as $childName)
 
-     {
 
-     if (!empty($form_values[$childName]))
 
-       {
 
-       $element[$childName]['#qbf']['#default_value'] = $form_values[$childName];
 
-       }
 
-     $element[$childName] = qbf_import_values($element[$childName], $form_values);
 
-     }
 
-   return $element;
 
- }
 
- /**
 
-  * Load a saved QBF query.
 
-  *
 
-  * @see qbf_import_values()
 
-  *
 
-  * @param int $qid
 
-  * @return array A form_values array usable by qbf_import_values
 
-  */
 
- function qbf_load($qid) {
 
-   $sq = 'SELECT qq.qid, qq.uid, qq.query, qq.name '
 
-       . 'FROM {%s} qq '
 
-       . 'WHERE qq.qid = %d ';
 
-   // db_rewrite_sql does not apply here until we add more advanced support for access control
 
-   $q = db_query($sq, QBF_TABLE_NAME, $qid);
 
-   $ret = db_fetch_object($q); // 0 or 1 row: we are querying on the primary key
 
-   if ($ret === NULL) // FALSE does not happen
 
-     {
 
-     $ret = NULL;
 
-     }
 
-   else
 
-     {
 
-     $ret->query = unserialize($ret->query);
 
-     }
 
-   return $ret;
 
- }
 
- /**
 
-  * Submit handler for query save form.
 
-  *
 
-  * @ingroup forms
 
-  * @param $form_id string
 
-  * @param $form_values array
 
-  * @return string
 
-  */
 
- function qbf_submit($form_id, $form_values) {
 
-   switch ($form_values['op'])
 
-     {
 
-     case t('Search'):
 
-       $ret = FALSE;
 
-       break;
 
-     case t('Save query'):
 
-       _qbf_save($form_id, $form_values);
 
-       drupal_set_message(t('Your query was saved as "@name".',
 
-         array('@name' => $form_values['save-name'])));
 
-       global $user;
 
-       $ret = "user/$user->uid/edit/job";;
 
-       break;
 
-     }
 
-   //dsm(array('QS' => $form_values));
 
-   return $ret;
 
- }
 
- /**
 
-  * List queries owned by a given user.
 
-  *
 
-  * @param int $uid > 0
 
-  * @return array
 
-  */
 
- function qbf_get_queries_by_user($uid = NULL) {
 
-   if (is_null($uid))
 
-     {
 
-     global $user;
 
-     $uid = $user->uid;
 
-     }
 
-   $sq = 'SELECT qq.qid, qq.uid, qq.name, qq.query '
 
-       . 'FROM {%s} qq '
 
-       . 'WHERE qq.uid = %d '
 
-       . 'ORDER BY qq.name ';
 
-   $q = db_query($sq, QBF_TABLE_NAME, $uid);
 
-   $ret = array();
 
-   while ($o = db_fetch_object($q))
 
-     {
 
-     $ret[$o->qid] = $o; // qid is the PK, so it is present and unique
 
-     }
 
-   return $ret;
 
- }
 
- /**
 
-  * Save a query and return its qid.
 
-  *
 
-  * @ingroup forms
 
-  * @param $form_id string
 
-  * @param $form_values array
 
-  * @return int
 
-  */
 
- function _qbf_save($form_id, $form_values) {
 
-   global $user;
 
-   if ($user->uid == 0)
 
-     {
 
-     $warning = t('Attempt by anonymous user to save a QBF query. Should not happen.');
 
-     drupal_set_message($warning, 'error');
 
-     watchdog('qbf', $warning, WATCHDOG_WARNING);
 
-     $ret = 0;
 
-     }
 
-   else
 
-     {
 
-     $sq = 'INSERT INTO {%s} (qid, uid, name, query) '
 
-          ."VALUES           (%d,  %d,  '%s', '%s' ) ";
 
-     $ret = db_next_id('qbf_qid');
 
-     $q = db_query($sq, QBF_TABLE_NAME, $ret, $user->uid, $form_values['save-name'], serialize($form_values));
 
-     }
 
-   return $ret;
 
- }
 
- /**
 
-  * Implement hook_menu().
 
-  *
 
-  * @param $may_cache boolean
 
-  * @return array
 
-  */
 
- function qbf_menu($may_cache) {
 
-   $items = array();
 
-   if ($may_cache)
 
-     {
 
-     }
 
-   else
 
-     {
 
-     if ((arg(0) == QBF_PATH_MAIN) && is_numeric(arg(1)) && arg(1) > 0 && arg(2) == 'delete')
 
-       {
 
-       $qid = arg(1);
 
-       $querorAccess = user_access(QBF_PERM_QUERY);
 
-       $items[] = array
 
-         (
 
-         'path'     => QBF_PATH_MAIN . '/' . $qid . '/delete',
 
-         'type'     => MENU_CALLBACK,
 
-         'access'   => $querorAccess,
 
-         'callback' => '_qbf_query_delete',
 
-         'callback arguments' => array($qid),
 
-         );
 
-       }
 
-     }
 
-   return $items;
 
- }
 
- /**
 
-  * Delete a query by qid
 
-  *
 
-  * $qid has been tested in qbf_menu() to be a positive integer, so it is a safe
 
-  * number, but we still need to know more about it.
 
-  *
 
-  * @param $qid integer
 
-  */
 
- function _qbf_query_delete($qid) {
 
-   global $user;
 
-   $query = qbf_load($qid);
 
-   $notify = variable_get(QBF_VAR_NOTIFY_DELETE, QBF_DEF_NOTIFY_DELETE);
 
-   $link = l($qid, QBF_PATH_MAIN . '/' . $qid . '/delete');
 
-   // @todo Check safety, this seem dangerous
 
-   $usArgs = func_get_args();
 
-   $path = implode('/', array_slice($usArgs, 1));
 
-   // only valid if valid query, and owner or admin
 
-   if (isset($query->uid) && (($query->uid == $user->uid) || user_access(QBF_PERM_ADMIN)))
 
-     {
 
-     $sq = 'DELETE FROM %s WHERE qid = %d ';
 
-     $q = db_query($sq, QBF_TABLE_NAME, $qid);
 
-     $message = t('Query @id "@name" has been deleted.', array
 
-       (
 
-       '@id'    => $qid,
 
-       '@name' => $query->name,
 
-       ));
 
-     drupal_set_message($message, 'status');
 
-     watchdog('qbf', $message, WATCHDOG_NOTICE, $link);
 
-     }
 
-   else
 
-     {
 
-     $message = t('Failed attempt to delete query @qid. Administrators has been alerted.', array
 
-       (
 
-       '@qid' => $qid,
 
-       ));
 
-     drupal_set_message($message, 'error');
 
-     watchdog('qbf', $message, WATCHDOG_ERROR, $link);
 
-     }
 
-   drupal_goto($path);
 
- }
 
- error_reporting($_qbf_er);
 
 
  |