6 * Partner management module for Drupal Tábor 2010.
10 * Implementation of hook_perm().
12 function partner_perm() {
14 'access partner list',
22 * Implementation of hook_menu().
24 function partner_menu() {
25 $items['partner'] = array(
26 'title' => 'List partners',
27 'page callback' => 'partner_page',
28 'access arguments' => array('access partner list'),
29 'type' => MENU_NORMAL_ITEM,
31 $items['partner/list'] = array(
33 'page callback' => 'partner_page',
34 'access arguments' => array('access partner list'),
35 'type' => MENU_DEFAULT_LOCAL_TASK,
37 $items['partner/add'] = array(
39 'page callback' => 'drupal_get_form',
40 'page arguments' => array('partner_form_edit'),
41 'access arguments' => array('create partner'),
42 'type' => MENU_LOCAL_TASK,
45 $items['partner/%partner_entry'] = array(
47 'page callback' => 'drupal_get_form',
48 'page arguments' => array('partner_form_edit', 1),
49 'access arguments' => array('edit partner'),
50 'type' => MENU_CALLBACK,
52 $items['partner/%partner_entry/delete'] = array(
54 'page callback' => 'drupal_get_form',
55 'page arguments' => array('partner_form_delete', 1),
56 'access arguments' => array('delete partner'),
57 'type' => MENU_CALLBACK,
66 * ID of the partner to be loaded.
68 * Partner object (with all of its addresses), or FALSE if not found.
70 function partner_entry_load($pid) {
71 if ($partner = db_fetch_object(db_query('SELECT * FROM {partner} WHERE pid = %d', $pid))) {
72 $partner->addresses = array();
73 $result = db_query('SELECT * FROM {address} WHERE pid = %d ORDER BY weight', $pid);
74 while ($address = db_fetch_object($result)) {
75 $partner->addresses[] = $address;
82 * Implementation of hook_theme().
84 function partner_theme($existing, $type, $theme, $path) {
86 'partner_form_filter' => array(
87 'arguments' => array('form' => NULL),
89 'partner_form_edit' => array(
90 'arguments' => array('form' => NULL),
96 * Lists the available partners.
98 function partner_page() {
100 $filter = partner_page_build_filter_query();
101 $output = drupal_get_form('partner_form_filter');
103 array('data' => t('Name'), 'field' => 'name'),
104 array('data' => t('Favourite beer'), 'field' => 'favourite'),
107 $can_edit = user_access('edit partner');
108 $can_delete = user_access('delete partner');
109 if ($can_edit || $can_delete) {
110 $header[] = array('data' => t('Operations'), 'colspan' => '2');
112 $sql = 'SELECT pid, name, favourite, COUNT(aid) AS addresses FROM {partner} LEFT JOIN {address} USING (pid)';
113 $group_by = ' GROUP BY pid';
114 $tablesort = tablesort_sql($header);
115 $result = pager_query($sql . $tablesort, $pagelen);
116 if (!empty($filter['where'])) {
117 $result = pager_query($sql .' WHERE '. $filter['where'] . $group_by . $tablesort, $pagelen, 0, NULL, $filter['args']);
120 $result = pager_query($sql . $group_by . $tablesort, $pagelen);
123 while ($entry = db_fetch_object($result)) {
125 check_plain($entry->name),
126 check_plain($entry->favourite),
130 $row[] = l(t('Edit'), 'partner/'. $entry->pid);
133 $row[] = l(t('Delete'), 'partner/'. $entry->pid .'/delete');
138 $output .= t('There is no partner (that meets the filter).');
141 $output .= theme('table', $header, $rows);
142 $output .= theme('pager', NULL, $pagelen, 0);
148 * Adds a non-existing partner.
150 * @param $partner = NULL
151 * The partner object (if any) to be edited.
154 * @see partner_form_add_validate()
155 * @see partner_form_add_submit()
157 function partner_form_edit($form_state, $partner = NULL) {
158 $form['pid'] = array(
160 // -1 stands for 'new'.
161 '#value' => empty($partner->pid) ? -1 : $partner->pid,
163 $form['name'] = array(
164 '#type' => 'textfield',
165 '#title' => t('Name'),
168 '#description' => t('Must be unique.'),
169 '#default_value' => empty($partner->name) ? '' : $partner->name,
171 $form['favourite'] = array(
172 '#type' => 'textfield',
173 '#title' => t('Favourite beer'),
176 '#default_value' => empty($partner->favourite) ? '' : $partner->favourite,
178 // There should be at least one empty line for a new address.
179 $form['addresses']['emptyrows'] = array(
181 '#value' => empty($form_state['values']['addresses']['emptyrows']) ? 1 : $form_state['values']['addresses']['emptyrows'],
183 // Create the new address rows as needed.
184 for ($i = 1; $i <= $form['addresses']['emptyrows']['#value']; $i++) {
185 $partner->addresses[] = (object) array(
186 // Negative value stands for 'new'.
188 // If the form has been rebuilt (eg. because the 'Add address' button
189 // has been pressed), then dig up the defaults.
190 'zipcode' => empty($form_state['values']['addresses'][-$i]['zipcode']) ? '' : $form_state['values']['addresses'][-$i]['zipcode'],
191 'city' => empty($form_state['values']['addresses'][-$i]['city']) ? '' : $form_state['values']['addresses'][-$i]['city'],
192 'street' => empty($form_state['values']['addresses'][-$i]['street']) ? '' : $form_state['values']['addresses'][-$i]['street'],
193 'weight' => empty($form_state['values']['addresses'][-$i]['weight']) ? 0 : $form_state['values']['addresses'][-$i]['weight'],
196 foreach ($partner->addresses as $address) {
197 $form['addresses'][$address->aid]['aid'] = array(
199 '#value' => $address->aid,
201 $form['addresses'][$address->aid]['zipcode'] = array(
202 '#type' => 'textfield',
203 '#title' => t('Zip code'),
206 '#default_value' => empty($address->zipcode) ? '' : $address->zipcode,
208 $form['addresses'][$address->aid]['city'] = array(
209 '#type' => 'textfield',
210 '#title' => t('City'),
212 '#default_value' => empty($address->city) ? '' : $address->city,
214 $form['addresses'][$address->aid]['street'] = array(
215 '#type' => 'textfield',
216 '#title' => t('Street address'),
218 '#default_value' => empty($address->street) ? '' : $address->street,
220 $form['addresses'][$address->aid]['weight'] = array(
222 '#title' => t('Weight'),
223 '#default_value' => empty($address->weight) ? 0 : $address->weight,
225 $form['addresses'][$address->aid]['remove'] = array(
226 '#type' => 'checkbox',
227 '#title' => t('Remove'),
228 '#default_value' => empty($form_state['values']['addresses'][$address->aid]['remove']) ? FALSE : $form_state['values']['addresses'][$address->aid]['remove'],
231 $form['addresses']['addaddress'] = array(
233 '#value' => t('Add address'),
235 $form['addresses']['#tree'] = TRUE;
236 $form['buttons']['submit'] = array(
238 '#value' => t('Save'),
240 if ($partner && $partner->pid) {
241 drupal_set_title(t('Edit %name', array('%name' => $partner->name)));
247 * Verify that a (new) partner is valid.
249 * @see partner_form_edit()
250 * @see partner_form_edit_submit()
252 function partner_form_edit_validate($form, &$form_state) {
253 $old_pid = db_result(db_query("SELECT pid FROM {partner} WHERE name = '%s' AND (NOT (pid = %d))", $form_state['values']['name'], $form_state['values']['pid']));
255 form_set_error('name', t('This partner name already exists.'));
257 if ($form_state['clicked_button']['#value'] == t('Add address')) {
258 $form_state['values']['addresses']['emptyrows']++;
259 $form_state['rebuild'] = TRUE;
264 * Save a (new) partner to the database.
266 * @see partner_form_edit()
267 * @see partner_form_edit_validate()
269 function partner_form_edit_submit($form, &$form_state) {
271 // If the partner ID is positive, then we UPDATE that partner.
272 if ($form_state['values']['pid'] != -1) {
275 // $form_state['values']['pid'] will hold the partner ID, whether it's a new
277 $saved = drupal_write_record('partner', $form_state['values'], $key);
280 watchdog('partner', '%name has been added to the partners.', array('%name' => $form_state['values']['name']), WATCHDOG_NOTICE, l(t('edit'), 'partner/'. $form_state['values']['pid']));
281 drupal_set_message(t('%name has been added to the partners.', array('%name' => $form_state['values']['name'])));
284 watchdog('partner', '%name has been updated.', array('%name' => $form_state['values']['name']), WATCHDOG_NOTICE, l(t('edit'), 'partner/'. $form_state['values']['pid']));
285 drupal_set_message(t('%name has been updated.', array('%name' => $form_state['values']['name'])));
288 drupal_set_message(t('%name could not be saved (name is not unique, probably).', array('%name' => $form_state['values']['name'])), 'warning');
291 // Do not waste time with storing addresses if the partner could not be
294 foreach ($form_state['values']['addresses'] as $address) {
295 // Skip the button(s).
296 if (!is_array($address)) {
299 // Easy removing: if all fields of an already-existing address are
300 // empty, DELETE that address.
301 if (empty($address['zipcode']) && empty($address['city']) && empty($address['street']) && ($address['aid'] > 0)) {
302 db_query('DELETE FROM {address} WHERE aid = %d', $address['aid']);
304 // Easier removing: if the checkbox of an already-existing address is
305 // ticked, DELETE that address.
306 elseif ($address['remove'] && ($address['aid'] > 0)) {
307 db_query('DELETE FROM {address} WHERE aid = %d', $address['aid']);
310 // Copy the partner ID from the partner record already stored by
311 // drupal_write_record('partner', ...).
312 $address['pid'] = $form_state['values']['pid'];
313 // If the address ID is positive, then we UPDATE that address.
314 if ($address['aid'] > 0) {
315 drupal_write_record('address', $address, 'aid');
317 // Only INSERT the new address if at least one of its (text)fields is
319 elseif (!(empty($address['zipcode']) && empty($address['city']) && empty($address['street']))) {
320 drupal_write_record('address', $address);
325 $form_state['redirect'] = 'partner';
329 * Confirms deleting a partner.
331 * @see partner_form_delete_submit()
333 function partner_form_delete($form_state, $partner) {
334 // This data is needed in the submit callback.
335 $form['pid'] = array(
337 '#value' => $partner->pid,
339 $form['name'] = array(
341 '#value' => $partner->name,
345 t('Are you sure you want to delete %name?', array('%name' => $partner->name)),
347 t('This action cannot be undone.'),
354 * Execute partner deletion.
356 * @see partner_form_delete()
358 function partner_form_delete_submit($form, &$form_state) {
359 db_query("DELETE FROM {partner} WHERE pid = %d", $form_state['values']['pid']);
360 db_query("DELETE FROM {address} WHERE pid = %d", $form_state['values']['pid']);
361 watchdog('partner', '%name has been deleted.', array('%name' => $form_state['values']['name']));
362 drupal_set_message(t('%name has been deleted.', array('%name' => $form_state['values']['name'])));
363 $form_state['redirect'] = 'partner';
367 * Adds filter capability to partner_page().
370 * @see partner_form_filter_validate
371 * @see partner_form_filter_submit
373 function partner_form_filter() {
374 $session = &$_SESSION['partner_page_filter'];
375 $session = is_array($session) ? $session : array();
376 $filters = partner_page_filters();
377 $form['filters'] = array(
378 '#type' => 'fieldset',
379 '#title' => t('Filter partners'),
380 '#theme' => 'partner_form_filter',
381 '#collapsible' => TRUE,
382 '#collapsed' => empty($session),
384 foreach($filters as $key => $filter) {
385 $form['filters']['status'][$key] = array(
386 '#title' => $filter['title'],
387 '#type' => $filter['type'],
389 foreach(array('options', 'maxlength', 'size', 'autocomplete_path', 'description') as $arg) {
390 if(isset($filter[$arg])) {
391 $form['filters']['status'][$key]["#$arg"] = $filter[$arg];
394 if(!empty($session[$key])) {
395 $form['filters']['status'][$key]['#default_value'] = $session[$key];
398 $form['filters']['buttons']['submit'] = array(
400 '#value' => t('Filter'),
402 if(!empty($session)) {
403 $form['filters']['buttons']['reset'] = array(
405 '#value' => t('Reset')
412 * Validates filtering form for partner_page().
414 function partner_form_filter_validate($form, &$form_state) {
415 if ($form_state['values']['op'] == t('Filter') && empty($form_state['values']['name']) && empty($form_state['values']['favourite'])) {
416 form_set_error('name', t('You must select something to filter by.'));
421 * Stores the filtering options for partner_page() into session variables.
423 function partner_form_filter_submit($form, &$form_state) {
424 $op = $form_state['values']['op'];
425 $filters = partner_page_filters();
428 foreach($filters as $name => $filter) {
429 if (isset($form_state['values'][$name])) {
430 $_SESSION['partner_page_filter'][$name] = $form_state['values'][$name];
435 $_SESSION['partner_page_filter'] = array();
438 // Redirect to the list.
439 $form_state['redirect'] = 'partner';
443 * Returns the available filtering options for both partner_page() and
444 * partner_page_build_filter_query().
446 function partner_page_filters() {
448 $filters['name'] = array(
449 'type' => 'textfield',
450 'title' => t('Name'),
451 'where' => "name LIKE '%%%s%%'",
452 'description' => t('Name should contain this.'),
455 $filters['favourite'] = array(
456 'type' => 'textfield',
457 'title' => t('Favourite beer'),
458 'where' => "favourite = '%s'",
461 'description' => t('His/her favourite beer.'),
467 * Returns a pair of filter/args array for partner_page(), filled with
468 * values based on session variables, if any.
470 function partner_page_build_filter_query() {
471 if (empty($_SESSION['partner_page_filter'])) {
474 $filters = partner_page_filters();
475 $where = $args = array();
476 foreach ($_SESSION['partner_page_filter'] as $key => $filter) {
477 $filter_where = array();
478 if (is_array($filter)) {
479 foreach($filter as $value) {
481 $filter_where[] = $filters[$key]['where'];
486 elseif (!empty($filter)) {
487 $filter_where[] = $filters[$key]['where'];
490 if (!empty($filter_where)) {
491 $where[] = '('. implode(' OR ', $filter_where) .')';
494 $where = !empty($where) ? implode(' AND ', $where) : '';
502 * Default theme function for partner_form_filter().
504 function theme_partner_form_filter($form = NULL) {
505 drupal_add_css(drupal_get_path('module', 'partner') .'/partner.css');
506 $buttons = drupal_render($form['buttons']);
507 return drupal_render($form) .'<div class="partner-page-filter-buttons">'. $buttons .'</div>';
511 * Default theme function for partner_form_edit().
513 function theme_partner_form_edit($form = NULL) {
514 $buttons = drupal_render($form['buttons']);
523 foreach (element_children($form['addresses']) as $aid) {
524 // Skip the button(s).
525 if (!is_numeric($aid)) {
528 unset($form['addresses'][$aid]['zipcode']['#title']);
529 unset($form['addresses'][$aid]['city']['#title']);
530 unset($form['addresses'][$aid]['street']['#title']);
531 unset($form['addresses'][$aid]['weight']['#title']);
532 unset($form['addresses'][$aid]['remove']['#title']);
533 $form['addresses'][$aid]['city']['#size'] = 30;
534 $form['addresses'][$aid]['street']['#size'] = 30;
536 drupal_render($form['addresses'][$aid]['zipcode']),
537 drupal_render($form['addresses'][$aid]['city']),
538 drupal_render($form['addresses'][$aid]['street']),
539 drupal_render($form['addresses'][$aid]['weight']),
540 drupal_render($form['addresses'][$aid]['remove']),
546 'data' => drupal_render($form['addresses']['addaddress']),
549 $addresses = theme('table', $header, $rows) . drupal_render($form['addresses']);
550 $output = drupal_render($form);
551 $output .= '<div class="partner-page-edit-addresses">'. $addresses .'</div>';
552 $output .= '<div class="partner-page-edit-buttons">'. $buttons .'</div>';