home forums resources search newsjoinmembers: 6370
Hiveminds Network PHP Flash Java Ruby Windows Linux
Hiveminds | Wed, 2006-05-10 20:07  tags: , ,

PHP developer

If you are high on the new Drupal 4.7 then you may want to take your grain of salt now. The latest release is filled with complications brought on by the new Forms API . Not complicated for the user and not complicated for the originating developers but if you are a PHPer jsut diving into the Drupal code version 4.7 suddenly makes phpNuke code look pleasant. The idea was good, the implementation within the core is badly coded and needs a re-work.

This is where Drupal is going to have to break down and start confessing that there is better code and better ways. Those better ways are OOP in nature and design.

In the case of a Forms API they should have used Smarty or quickHTML forms (PEAR) or any number of Forms Class files out there. But instead they went with their own and here is the result. Incomprehensible complexity and convoluted procedural coding.

This fairly easy to understand code in Drupal 4.6:

<?php

function user_admin_perm($edit = array()) {
  if (
$edit) {
    
// Save permissions:
    
$result db_query('SELECT * FROM {role} ');
    while (
$role db_fetch_object($result)) {
      
// Delete, so if we clear every checkbox we reset that role;
      // otherwise permissions are active and denied everywhere.
      
db_query('DELETE FROM {permission} WHERE rid = %d'$role->rid);
      foreach (
$edit[$role->rid] as $key => $value) {
        if (!
$value) {
          unset(
$edit[$role->rid][$key]);
        }
      }
      if (
count($edit[$role->rid])) {
        
db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')"$role->ridimplode(', 'array_keys($edit[$role->rid])));
      }
    }
    
// Clear the cache, as we might have changed the anonymous user's
    // permissions.
    
cache_clear_all();
    
menu_rebuild();
    
drupal_goto($_GET['q']);
  }
  
// Compile role array:
  
$result db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid ORDER BY name');
  
$roles = array();
  while (
$role db_fetch_object($result)) {
    
$role_perms[$role->rid] = $role->perm;
  }
  
$result db_query('SELECT rid, name FROM {role} ORDER BY name');
  
$role_names = array();
  while (
$role db_fetch_object($result)) {
    
$role_names[$role->rid] = $role->name;
  }
  
// Render role/permission overview:
  
$header = array(t('Permissions'),t('Roles'));
  foreach (
module_list() as $module) {
    if (
$perms module_invoke($module'perm')) {
      
$rows[] = array(array('data' => t('%module module', array('%module' => $module)), 'class' => 'module''colspan' => count($role_names) + 1));
      
asort($perms);
      foreach (
$perms as $perm) {
        
$row[] = array('data' => t($perm), 'class' => 'permission');
        
$output '<div style="height:160px;width:200px;overflow:auto;">';
        foreach (
$role_names as $rid => $name) {
          
$output .= form_checkbox($name"$rid][$perm"1strstr($role_perms[$rid], $perm)).'';
        }
        
$output .= '</div>';
        
$row[] = $output;
        
$rows[] = $row;
        unset(
$row);
      }
    }
  }
  
$output theme('table'$header$rows, array('id' => 'permissions'));
  
$output .= form_submit(t('Save permissions'));
  return 
form($output);
}
?>

Now look like this:

<?php

/**
 * Menu callback: administer permissions.
 */
function user_admin_perm($str_rids NULL) {
  if (
preg_match('/^([0-9]+[+ ])*[0-9]+$/'$str_rids)) {
    
// The '+' character in a query string may be parsed as ' '.
    
$rids preg_split('/[+ ]/'$str_rids);
  }
  if(
$rids) {
    
$breadcrumbs drupal_get_breadcrumb();
    
$breadcrumbs[] = l(t('all roles'), 'admin/access');
    
drupal_set_breadcrumb($breadcrumbs);
    
$result db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid WHERE r.rid IN (%s) ORDER BY name'implode(', '$rids));
  }
  else {
    
$result db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid ORDER BY name');
  }
  
// Compile role array:
  
$roles = array();
  while (
$role db_fetch_object($result)) {
    
$role_permissions[$role->rid] = $role->perm;
  }
  if(
$rids) {
    
$result db_query('SELECT rid, name FROM {role} r WHERE r.rid IN (%s) ORDER BY name'implode(', '$rids));
  }
  else {
    
$result db_query('SELECT rid, name FROM {role} ORDER BY name');
  }
  
$role_names = array();
  while (
$role db_fetch_object($result)) {
    
$role_names[$role->rid] = $role->name;
  }
  
// Render role/permission overview:
  
$options = array();
  foreach (
module_list(FALSEFALSETRUE) as $module) {
    if (
$permissions module_invoke($module'perm')) {
      
$form['permission'][] = array('#type' => 'markup''#value' => t('%module module', array('%module' => $module)));
      
asort($permissions);
      foreach (
$permissions as $perm) {
        
$options[$perm] = '';
        
$form['permission'][$perm] = array('#type' => 'markup''#value' => t($perm));
        foreach (
$role_names as $rid => $name) {
          
// Builds arrays for checked boxes for each role
          
if (strstr($role_permissions[$rid], $perm)) {
            
$status[$rid][] = $perm;
          }
        }
      }
    }
  }
  
// Have to build checkboxes here after checkbox arrays are built
  
foreach ($role_names as $rid => $name) {
    
$form['checkboxes'][$rid] = array('#type' => 'checkboxes''#options' => $options'#default_value' => $status[$rid]);
    
$form['role_names'][$rid] = array('#type' => 'markup''#value' => l($name'admin/access/'$rid), '#tree' => TRUE);
  }
  
$form['submit'] = array('#type' => 'submit''#value' => t('Save permissions'));
  return 
drupal_get_form('user_admin_perm'$form);
}
function 
theme_user_admin_perm($form) {
  foreach (
element_children($form['permission']) as $key) {
    
// Don't take form control structures
    
if (is_array($form['permission'][$key])) {
      
$row = array();
      
// Module name
      
if (is_numeric($key)) {
        
$row[] = array('data' => form_render($form['permission'][$key]), 'class' => 'module''colspan' => count($form['role_names']) + 1);
      
// Permissions
      
}
      else {
        
$row[] = array('data' => form_render($form['permission'][$key]), 'class' => 'permission');
        foreach (
element_children($form['checkboxes']) as $rid) {
          if (
is_array($form['checkboxes'][$rid])) {
            
$row[] = array('data' => form_render($form['checkboxes'][$rid][$key]), 'align' => 'center''title' => t($key));
          }
        }
      }
      
$rows[] = $row;
    }
  }
  
$header[] = (t('Permission'));
  foreach (
element_children($form['role_names']) as $rid) {
    if (
is_array($form['role_names'][$rid])) {
      
$header[] = form_render($form['role_names'][$rid]);
    }
  }
  
$output theme('table'$header$rows, array('id' => 'permissions'));
  
$output .= form_render($form);
  return 
$output;
}
?>

Who can make heads or tails out of this? I love arrays. I deal a lot in them as my first PHP coding involved using no databases just flat files and arrays. You learn two things when using arrays on a daily basis. First arrays are wonderful in when coded right but if coded wrong like trying to reassemble spagetti after a handgrenade hits an italian restaurant.

No, you won't be seeing any 4.7 code from me. I think that Drupal should just junk this API and rollback to 4.6. I seriously doubt that this API will get any better to work with even with perfect documentation. There is just too much memory travel involved. Most people can remember seven pieces of information short term. This API requires that you remember at least 15 maybe 50 to start! Plus whatever code you have in front of you and if you don't have an IDE throwing hints at you then you are lost. One of the biggest points that irritate me is the use of #, don't ask me why but I think it just sucks. It's like a certain aquaintence of mine that hates PHP becuase it uses $ on variables. But I guess since the code is already complicated and looks like the ugliest of Perl code, why not just dot the i with #?

Another thing and something I see as a flaw in the design is the use of #prefix and #suffix. These should not be needed. The theming functions should handle any use of HTML. But this goes back a long way. Drupal has always carried the baggage of having too much HTML in its' core PHP. The is one good thing about the Forms API. It will keep developers from plugging in HTML where it should not be. This is because they will not know where to place it.

Hiveminds's picture
This article brought to you by the Hiveminds Magazine - Staff. Contact us if you want to post an article or announcement anonymously
 
Bitrix Site manager - fast to create, easy to manage CMS Comparison Matrix
Put Your Site Here Developer Links
Web Developers Drupal Content Management Systems Wordpress Wordpress Content Management Systems
 

Newsletter

Get updates on Hiveminds services, articles and downloads by signing up for the newsletter.

Editor's choice

Some of the better articles, stories and tutorials found at Hiveminds.

Find more

Find more of Hiveminds articles, stories, tutorials and user comments by searching.




Picked links

Hand picked websites and articles from around the web that provide quality reading.