CVS edit link for duozersk

I want to contribute one module I already developed to the stage others might find useful. I'm also doing some other stuff based on Drupal, but it is more specific and/or not ready to be shown in public.

So the module - it is called Node Feedback. Basically, it allows to place a fieldset under the node content with a set of questions. When I searched for the similar functionality in the contrib I came across the pollfield module - but it was designed to provide another set of functionality. It is based of CCK and allows the custom poll to be set up for every node. It was overkilling to use it to ask the set of the same questions on all the nodes of specific node type + it places the submit button under each and every question and altogether it looks just weird + in order to modify the questions set you would need to update each and every node.
I have also seen the need for this kind of the module in the community as found several blog/forum posts discussing the ways to gather users feedback on the nodes besides the voting widgets Fivestar and other modules provide.

Currently only radios and textarea questions are supported. It stores the radios answers in the great VotingAPI database (it is dependent on VotingAPI - here comes all the goodies as Views integration; anonymous voting handling; etc.) and the text answers go to the nodefeedback database table (doesn't have any Views integration, so the reporting sucks in this case - needs some love from the community :)).

To see this module in the work go to http://kb.acronis.com and open any content.

It uses the FormAPI to build the form and render it; so it does integrate just fine with others that are using the form_alter and other similar techniques. On the abovementioned site it works hand-to-hand with the hashcash module to prevent spam submissions. I believe there should be no issues to work with CAPTCHA or Mollom or any other module that hooks into Form rendering process.

It has the basic configuration page (available for users with the 'administer site configuration' permission) where you can choose the node types to add the Feedback form to and modify some texts. The questions currently need to be set inside the code - it has the function that returns the questions array. It needs to be written so that the questions configuration is available in the GUI. Another enhancement might be to have different set of questions for different content types (per content type) - might be rather easy to do, just didn't have a use-case for it to make time to implement :)

Currently it provides two permissions:
'provide node feedback' - this one controls who can see the nodefeedback form
'see nodefeedback results' - this one adds the number of answers for each option in the radios question type

I tried to follow all the guidelines to write the good and secure code. I believe I used the t() function for all the strings (where applicable), did the check_plain on the user entered text, and the theme function is not needed as I don't generate any HTML code but rather just use the built-in Form processing to do the job for me. I also tried to leave sensible comments in the code and describe the functions. It will definitely need some love in the areas identified above and some others - so this is the right time to share it with the community to get it rocking!

Comments

duozersk’s picture

Status: Postponed (maintainer needs more info) » Needs review

Here is the code.

duozersk’s picture

StatusFileSize
new4.56 KB

Hm... didn't attach the first time? Trying again.

avpaderno’s picture

Issue tags: +Module review
duozersk’s picture

StatusFileSize
new3.84 KB

Looked through other CVS accounts applications and fixed 2 very popular issues with the t() function:

- Menu system '#title's and '#description's shouldn't be passed through the t() function as it is done by the Drupal menu system
- The empty strings '' shouldn't be passed through the t() function as the translation of an empty string is an empty string in any language

New version attached.

avpaderno’s picture

Status: Needs review » Needs work
  $form['types'] = array(
    '#type'        => 'fieldset',
    '#title'       => t('Enabled content types'),
    '#description' => t('Check the content types you want the feedback form to appear on.'),
    '#collapsible' => TRUE,
    '#collapsed'   => TRUE,
  );

That options would be better placed in the content type edit form, inside the fieldset Workflow.

function nodefeedback_settings_submit($form, &$form_state) {
  variable_set('nodefeedback:enabled_types', $form_state['values']['enabled'], array());
  variable_set('nodefeedback:form_title', $form_state['values']['form_title'], t('Provide feedback on this information'));
  variable_set('nodefeedback:confirmation_message', $form_state['values']['confirmation_message'], t('Thank you! Your feedback is used to help us improve our content.'));
  variable_set('nodefeedback:button_text', $form_state['values']['button_text'], t('Send'));
}

Check the argument accepted by variable_set().

function nodefeedback_nodeapi(&$node, $op, $teaser, $page) {
  switch ($op) {
    case 'view':
      $exclude_modes = array(
        NODE_BUILD_PREVIEW,
        NODE_BUILD_SEARCH_INDEX,
        NODE_BUILD_SEARCH_RESULT,
        NODE_BUILD_RSS,
      );
      $enabled_types = variable_get('nodefeedback:enabled_types', array());
      if (!$teaser && !in_array($node->build_mode, $exclude_modes) && $enabled_types[$node->type] && user_access('provide node feedback')) {
        $node->content['nodefeedback'] = array(
          '#value'  => drupal_get_form('nodefeedback_form', $node->nid),
          '#weight' => 50,
        );
      }
      break;
  }
}

Why isn't the code not using hook_form_alter()?

      $results[substr($value['function'], -1)] = $value['value'];

The code should use the Drupal Unicode functions.

  // removes all variables that start with "nodefeedback:"
  $result = db_query("SELECT name FROM {variable} WHERE name LIKE 'nodefeedback:%%'");
  while ($row = db_fetch_object($result)) {
    variable_del($row->name);
  }
}

As the code is using variable_de(), then it would be better to explicitly delete the Drupal variables used.

  $schema['nodefeedback'] = array(
    'fields' => array(
      'nodefeedback_id' => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),
      'content_type' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => 'node'),
      'content_id' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
      'value' => array('type' => 'text', 'size' => 'big', 'not null' => TRUE, 'default' => ''),
      'tag' => array('type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => 'vote'),
      'uid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
      'timestamp' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
      'vote_source' => array('type' => 'varchar', 'length' => 255),
    ),
    'primary key' => array('nodefeedback_id'),
    'indexes' => array(
      'content_uid' => array('content_type', 'content_id', 'uid'),
      'content_uid_2' => array('content_type', 'uid'),
      'content_source' => array('content_type', 'content_id', 'vote_source'),
    ),
  );

It would be better if the code would be formatted differently, and it would add a description for each field.

duozersk’s picture

Status: Needs work » Needs review
StatusFileSize
new4 KB

Thank you for the valuable review!

1. That options would be better placed in the content type edit form, inside the fieldset "Workflow".
It would require some serious rewrite and has questionable usability aspect - from my side it is much more usable to manage all the content types Nodefeedback form is enabled on in one place. Plus this Workflow settings are really about the Node Edit form, not about the node view.
Do you think it is critical to have this option on the content type edit page? We might move it there (add it there additionally to the current implementation) if there would be strong feeling that this is right, now I don't feel like this is the right thing to do - but I do accept patches ;)

2. Check the argument accepted by variable_set().
Fixed, thanks.

3. Why isn't the code not using hook_form_alter()?
Well... I believe there is no form to alter in this case. The Nodefeedback form is attached to the node when it is being viewed - so there is no form to alter, correct?

4. The code should use the Drupal Unicode functions.
OK, fixed ;)

5. As the code is using variable_del(), then it would be better to explicitly delete the Drupal variables used.
Probably yes, however, I didn't really get the reasoning for this...
I used this approach to clean up all the variables that follow the module variables naming convention so if I add new variable in a module - I don't need to modify the uninstall function. I found this approach in the LuceneAPI module uninstall function.
Can you please advise on the reasoning and if it is critical to get it fixed to contribute this module?

6. It would be better if the code would be formatted differently, and it would add a description for each field.
Probably, but this formatting change makes the schema description really long. Formatted it and added fields descriptions.
I got this formatting from the VotingAPI module and thought that it is fine to keep with it.

Thanks again for your time you put into reviewing this module code. Hope to get it approved soon.

avpaderno’s picture

Plus this Workflow settings are really about the Node Edit form

That is not exact.
The fieldset Workflow settings is used when a module doesn't have enough options to justify a new fieldset. In the content type form there are all the settings that depends from the content type; it is where you find the settings for the content type comments, which include the setting for how the comments are displayed in the node view, which doesn't interest the node edit form.

Probably yes, however, I didn't really get the reasoning for this...
I used this approach to clean up all the variables that follow the module variables naming convention so if I add new variable in a module - I don't need to modify the uninstall function. I found this approach in the LuceneAPI module uninstall function.
Can you please advise on the reasoning and if it is critical to get it fixed to contribute this module?

The code should be deleting its own Drupal variables, not the ones used by other modules. As you checked what another module did, and you did the same, somebody could create a module that extends the module you created, and use variables with names starting with nodefeedback: simply because you used the same schema.

Probably, but this formatting change makes the schema description really long. Formatted it and added fields descriptions.
I got this formatting from the VotingAPI module and thought that it is fine to keep with it.

The database schema as it is now it is not readable; the coding standards report how the code should be formatted to make it more readable. If we would only be worried about the code length, why would the coding standards reports to write if ($test) {? That means to add at least 2 characters more for each if statement. Why aren't we allowed to write if($test){? We would save 2 characters for each if statement, and we would save a lot of characters if we would not indent each code line; if then we write all the code inline, we would have a shorter code.

duozersk’s picture

StatusFileSize
new4.15 KB

Thanks, Alberto!

That is not exact.
The fieldset "Workflow settings" is used when a module doesn't have enough options to justify a new fieldset. In the content type form there are all the settings that depends from the content type; it is where you find the settings for the content type comments, which include the setting for how the comments are displayed in the node view, which doesn't interest the node edit form.

OK, I got some time and placed the checkbox to enable the Node Feedback form into the Node Type settings form. It is in sync with the main Node Feedback settings page and has a link to it in the description (to modify other Node Feedback options that are not node type specific). Hope this is what we wanted ;)

The code should be deleting its own Drupal variables, not the ones used by other modules. As you checked what another module did, and you did the same, somebody could create a module that extends the module you created, and use variables with names starting with "nodefeedback:" simply because you used the same schema.

Agreed, changed. Thank you.

The database schema as it is now it is not readable; the coding standards report how the code should be formatted to make it more readable. If we would only be worried about the code length, why would the coding standards reports to write if ($test) {? That means to add at least 2 characters more for each if statement. Why aren't we allowed to write if($test){? We would save 2 characters for each if statement, and we would save a lot of characters if we would not indent each code line; if then we write all the code inline, we would have a shorter code.

I do understand this and already changed the schema definition in the comment #6. I wasn't arguing, just referenced the initial code I got it from - probably, we should open the issue for the VotingAPI module then and help them to fix it too by submitting a patch ;)

Here goes the updated module code. Hopefully this will get committed to the CVS soon ;)

Thank you.

avpaderno’s picture

Status: Needs review » Needs work
  1. /**
     * Submit handler for the nodefeedback settings form.
     */
    function nodefeedback_settings_submit($form, &$form_state) {
      variable_set('nodefeedback:enabled_types', $form_state['values']['enabled']);
      variable_set('nodefeedback:form_title', $form_state['values']['form_title']);
      variable_set('nodefeedback:confirmation_message', $form_state['values']['confirmation_message']);
      variable_set('nodefeedback:button_text', $form_state['values']['button_text']);
    }
    

    That code should not be required if the module would use system_settings_form(), and would use the proper names for the form fields.

  2. The Drupal variable name doesn't follow the schema normally used, which should be <module_name>_<variable_name>.
  3. /**
     * Implementation of hook_form_alter().
     */
    function nodefeedback_form_node_type_form_alter(&$form, &$form_state) {
      $enabled_types = variable_get('nodefeedback:enabled_types', array());
      $form['workflow']['nodefeedback'] = array(
        '#type'          => 'checkboxes',
        '#title'         => t('Node Feedback form settings'),
        '#description'   => t('Enable the Node Feedback form for this content type. For other settings check the <a href="@nodefeedback-settings-page">Node Feedback settings page</a>.', array('@nodefeedback-settings-page' => url('admin/settings/nodefeedback'))),
        '#options'       => array($form['#node_type']->type => t('Enable Node Feedback form')),
        '#default_value' => array($form['#node_type']->type => $enabled_types[$form['#node_type']->type]),
        '#access'        => user_access('administer site configuration'),
      );
      $form['#submit'][] = 'nodefeedback_node_type_form_submit';
    }
    

    The code duplicates a setting already present in the module settings page; the code is then not correct because, if you would visit the content type form of two different content types, it would allow to see node feedback form fields only in the last content type.

    The code should be similar to this one, to be correct.

      if (isset($form['#node_type'])) {
    
        // …
    
        $form['nodewords']['nodewords_edit_metatags'] = array(
          '#type' => 'checkbox',
          '#title' => t('Allow editing of meta tags'),
          '#description' => t('If selected, the node edit form will allow the users with the right permissions to edit the meta tags associated with nodes of this content type.'),
          '#default_value' => variable_get('nodewords_edit_metatags_' . $form['#node_type']->type, TRUE),
        );
    
        // …
      }
    

    See the name of the Drupal variable used.

duozersk’s picture

Status: Needs review » Needs work
StatusFileSize
new4.13 KB

WOW, another valuable review! Thank you, Alberto!

That code should not be required if the module would use system_settings_form(), and would use the proper names for the form fields.

Cool, thanks, now it is using the system_settings_form().

The Drupal variable name doesn't follow the schema normally used, which should be <module_name>_<variable_name>.

OK, changed it.

The code duplicates a setting already present in the module settings page; the code is then not correct because, if you would visit the content type form of two different content types, it would allow to see node feedback form fields only in the last content type.

Didn't get this one :(
Actually, yes, it is a kind of duplication. I initially implemented node type checkboxes only on the Node Feedback module settings page, but then you asked to make it available in the Node Type edit pages. I replied that there is a usability concern to have all the node type checkboxes in one place (on the module settings page) and that I can add the checkbox on the Node Type edit pages later.
Then I went ahead and added them (while leaving the Node Feedback settings page as it was). The settings on these two kind of pages are in sync as they both are using the nodefeedback_enabled_types variable which is an associative array (keys are node types).
The Node Feedback settings page uses the whole array, while the Node Type edit pages uses only one element of this array corresponding to the node type.

While I love working on enhancing this module - can we please accept it as it follows the Coding Standards and provides not duplicate functionality?

Thanks
AndyB

duozersk’s picture

Status: Needs work » Needs review

Marking as Needs Review.

duozersk’s picture

Question - some mechanism now creates the nodefeedback_<node_type> variables on submitting the Node Type edit forms. I believe it is related to the last comment in the #9.

Any advice on how to change/manage/disable these variables creation would help.

Thanks
AndyB

avpaderno’s picture

Status: Needs work » Needs review
function nodefeedback_node_type($op, $info) {
  if ($op == 'delete') {
    variable_del('nodefeedback_' . $info->type);
  }
}

The code doesn't need to do anything when a content type is renamed, because that is done automatically by Drupal, if you use nodefeedback_form_node_type_form_alter(). The settings page you created would lose the setting for a content type if the content type would be renamed; that is a reason more to use nodefeedback_form_node_type_form_alter() to handle settings that depend from a content type.
If the settings that depend on the content type are already added by nodefeedback_form_node_type_form_alter(), then they should be removed in other settings pages.

If you need the code to delete the Drupal variables used for a content type, then use the following one, which should be placed in nodefeedback_uninstall():

  foreach (array_keys(node_get_types('names')) as $node_type) {
    variable_del('nodefeedback_' . $node_type);
  }
duozersk’s picture

StatusFileSize
new4.24 KB

OK, finally I believe I got it implemented correctly :)

Changed to use only the nodefeedback_<node_type> variables.

Please review the attached version.

Thanks
AndyB

duozersk’s picture

StatusFileSize
new5.33 KB

One more step forward:

- Added per content type settings for the Node Feedback form
- Questions array is now configured through the GUI and passed to the eval() function - do you know any better way for it?
- Implemented default Node Feedback from settings - if you opt-out to use the default, then the custom settings are ignored
- Moved the administration form (default Node Feedback form settings) to the nodefeedback.admin.inc file

Next focus would be the Views integration for the Nodefeedback storage-type questions.

Thanks
AndyB

dave reid’s picture

Status: Needs review » Needs work

The one big thing pointing out is you're allowing PHP input with the 'Node Feedback questions array config' field, even though you've added warnings. The security would most likely recommend (since we just dealt with this same problem with Views and Node Import) is new permissions, 'administer node feedback' as the base access for the admin/settings/nodefeedback callback, and 'use PHP for node feedback options' to make it *explicitly* clear that PHP could be used to own your site.

Other than that, I don't see anything else holding this up!

duozersk’s picture

Status: Needs work » Needs review
StatusFileSize
new5.4 KB

Thanks a lot, Dave! I knew you would not leave this issue without any response ;)

I have added the 2 permissions:
- administer nodefeedback - controls access to the nodefeedback administering options (page and fieldset on the node type edit page)
- use PHP input for nodefeedback options - controls access to the text areas for the PHP input

Hope the attached version will finally make it in.

AndyB

dave reid’s picture

Also wondering if I entered in JavaScript it looks like it wouldn't be filtered out. Kinda a moot point since you've added the special PHP permission, but the security team would probably still like to see use of filter_xss_admin or filter_xss.

Something like:

  0 => array(
    'tag'            => 'resolution',
    'title'          => '<script>alert('XSS!');</script>,
    'type'           => 'radios',
    'description'    => '',
    'required'       => FALSE,
    'storage'        => 'votingapi',
    'answer_options' => array(
      0 => "Yes",
      1 => "No",
      2 => "I don't know",
    ),
   ),
duozersk’s picture

Dave,

I would love to improve the security every way possible (keeping in mind that the "architecture" would still be the same (not require many lines of code) - meaning that the real GUI for questions management is the whole another story, not in this version).

As I don't directly call the variable_set() anywhere in the module code - can you please advise on what would be the best way to add the filter_xss check on the input? Use of some validate function?

Thanks in advance.
AndyB

dave reid’s picture

The extra stuff would be put on display of the form from the auto-PHP-array. It's this part that's the problem:

function nodefeedback_form(&$form_state, $node_type, $nid) {
  ...
  foreach ($nodefeedback_questions as $key => $question) {
    $form['nodefeedback'][$question['tag']] = array(
      '#title'         => $question['title'], <-- XSS potential here
      '#type'          => $question['type'],
      '#description'   => $question['description'], <-- XSS potential here
      '#required'      => $question['required'],
    );
    if ($question['type'] == 'radios') {
      $form['nodefeedback'][$question['tag']]['#options'] = nodefeedback_answer_options_array($question, $node_type, $nid);  <-- XSS potential here (kinda)
      $form['nodefeedback'][$question['tag']]['#default_value'] = 'NULL'; //we need default value so it doesn't vote to the option "0" when the answer is not chosen
    }
    if ($question['type'] == 'textarea') {
      $form['nodefeedback'][$question['tag']]['#cols'] = 65;
      $form['nodefeedback'][$question['tag']]['#rows'] = 5;
      $form['nodefeedback'][$question['tag']]['#resizable'] = FALSE;
    }
  }
duozersk’s picture

StatusFileSize
new5.43 KB

Ok, got you - added the filter_xss() on the #title and #description + in the nodefeedback_answer_options_array() function. Thank you, Dave.

As a bonus track - fixed one typo in the texts and added some more comments.

The latest version attached.

AndyB

duozersk’s picture

Still can't get all this process around getting access to the CVS... it is open for 2 months and a half, isn't it crazy?

Ravish’s picture

I agree, it is...

Perhaps this is the reason why many developers are unable to contribute to Drupal.org. While I agree that security and coding standards are important, CVS application issue queue is not the best way to deal with it. I can see many CVS applications in the queue waiting because of negligible reasons like 'provide more motivation' or 'there is an extra space in xyz.php file' etc.

Developers applying for CVS account are new at contributing to Drupal.org and may not be well acquainted with the coding practices followed at Drupal.org. There is no reason to expect that every module or theme being submitted to be flawless, nothing can be flawless.

Project tools like issue queue, version control and patches are for improving and maintaining modules and themes. Perhaps 'Project' is the best place to tackle these issues rather than holding up the CVS applications queue.

Coming from Wordpress development to Drupal.org, it feels like CVS application process is more of a hurdle than a helpful tool. I strongly believe the CVS application process must be simplified and barriers to entry must be lowered.

duozersk’s picture

There are always at least two sides of the coin... For instance, I saw the issues with patches on the Drupal.org projects aimed to fix the coding standards in the module that the maintainers marked as "won't fix" (providing reasons like "I'm writing it like I want it to be written"). I bet Dave Reid has a handful of these examples.

Anyway, I don't consider myself being that kind of a "bad guy":
- I followed all the standards I could find and read of
- I wrote the comprehensive description (see the first posting)
- I implemented all the suggestions raised in this issue, etc...
- I do strongly believe that the standard (be it a coding/commenting style or security rules) is a way to go when collaborating in the community of thousands of developers
- I'm ready to thankfully accept patches ;)
- I want Drupal to flourish :)

And now I feel all the pain loops associated with waiting and waiting and waiting... and waiting. I even twitted Dries asking him if "is it really that hard to contribute to Drupal?" and asked Dave Reid for the help (thank you, Dave!).

Maybe next week? :)

avpaderno’s picture

@Ravish: There is a place to discuss of how CVS applications should be make better; that place is not this queue, though.

avpaderno’s picture

Status: Needs review » Fixed

Status: Fixed » Closed (fixed)
Issue tags: -Module review

Automatically closed -- issue fixed for 2 weeks with no activity.