CVS edit link for tutumlum

I am a school administrator, and developing school database for 6 years along with teaching chemistry :) at the same school. I have been writing school database with php-mysql. I decided to write whole system as a group of CMS modules, and I decided for Drupal for many and strong reasons that are needless to mention here. I'm re-writing whole system as D7 modules for 4 months as School Administration package.
Developed modules till now are:
school_administration (main module) (~2200 lines),
classes_and_lessons (~1200 lines)
class_lists (~300 lines)
pdf_documentation (based on FPDF) (~400 lines)
working-on module:
grading
student_marks
in-plan modules:
grade_book
term_comments
accounting_student_payment
accounting_staff_salary
accounting_statistics
exam_stats
school_transcript
attendance
school_id_card
sitting_plans
discipline
medical_records
clubs
auto_sms_mesaging

All modules mentioned above are in use now as a single hard-coded system. I will convert all of them to D7 modules and we will continue to use same functionalities with the power of Drupal core and its modules. I want to contribute them for "Drupal in Education"

I need advice about my current modules to integrate with D7 seamlessly, I need advices about the way to write in-plan modules for best integration.
I know power of open source, I know power of sharing, I know power of Drupal, I saw power of Drupal community :)

Best Regards,
Murat Tutumlu
[Edit: information removed at request of poster]

Comments

tutumlum’s picture

Status: Postponed (maintainer needs more info) » Needs review
StatusFileSize
new10.1 KB
new638.06 KB
dave reid’s picture

Status: Needs review » Needs work

Just on an initial quick review, the profile_role.module has this in it:

/**
 * @file
 * Define profile categories by role.
 *
 * Copyright 2008 by Jimmy Berry ("boombatower", http://drupal.org/user/214218)
 */

So this isn't even your module? Turns out it's an existing project http://drupal.org/project/profile_role so I don't know what you're hoping to accomplish by submitting an already existing project with your CVS application. The only thing I can think of is to make yourself look better and hope we don't notice?

tutumlum’s picture

Status: Needs work » Needs review

No, I didn't submit it as my module, I convert it to D7 because it is required module. After I receive CVS account I will...

tutumlum’s picture

By the way, If try to trick you, be sure that I should erase copy-right data, change module name, and use it as mine. I just convert and use original module to D7, and I sent it to you, If you want to try, you will need it. Thank you for your blaming :(

dave reid’s picture

You do not need a CVS account to help port a module to D7. All you need to do is post patches to the module's issue queue. Boombatower is quite active and isn't exactly abandoning his modules. I'm sure he would accept your porting patches. I am sorry I blamed you, but nothing in your application said "I wrote these modules, but I also helped port some existing D6 modules to D7."

avpaderno’s picture

Status: Needs review » Needs work

No, I didn't submit it as my module, I convert it to D7 because it is required module.

Still, it doesn't make sense.
You are supposed to report here your code, not the code developed from somebody else that you converted to a newer version of Drupal. If your module depends on a module that has not been converted to the Drupal version used by your module, you simply report your code adding a note that it depends on a module that needs to be ported.

tutumlum’s picture

Status: Needs work » Needs review

In info file of school_administration it is mentioned that it depends on profile_role module. And in profile module it IS mentioned that it is belong to its owner. See copyright notice :)

tutumlum’s picture

And I am mentioning here that FPDF is also not belong to me. Do not think same thing for it when you see it in pdf_documentation module. You can see copyright info in it too..

avpaderno’s picture

In school_administration.forms.php (the extension should be ".inc"):

  1. There are many functions that are marked as implementations of hook_form() when they are not (the correct definition of such hook is hook_form($node, $form_state), and it's implemented by modules that handle nodes).
  2. Also there is some code that is outside a function.
    $job_types = array(
    t('Organization'),
    t('Company'),
    t('Government'));
    $jobs = array(
    "--",
    t("Assistant Teacher"),
    t("Canteen"),
    t("Cashier"),
    t("Cleaner"),
    t("Club Teacher"),
    t("Cook"),
    t("Cook Assistant"),
    t("Counselor"),
    t("Director"),
    t("Driver"),
    t("Full Time Teacher"),
    t("Guard"),
    t("IT Designer"),
    t("Librarian"),
    t("MPA Guard"),
    t("Nurse"),
    t("Part Time Teacher"),
    t("Receptionist"),
    t("Secretary"),
    t("Security"),
    t("Supervisor"),
    t("Teacher"));
    $relations = array(
    "--",
    t("Aunt"),
    t("Brother"),
    t("Brother in Law"),
    t("Father"),
    t("Grandfather"),
    t("Grandmother"),
    t("Husband"),
    t("Mother"),
    t("Own"),
    t("Sister"),
    t("Sister in Law"),
    t("Step Brother"),
    t("Step Father"),
    t("Step Mother"),
    t("Step Sister"),
    t("Uncle"),
    t("Wife"));
    $withdraw_reasons = array(
    "--",
    t("Academic difficulty"),
    t("Change in career plans"),
    t("Death"),
    t("Discipline problems"),
    t("Dissatisfied with school"),
    t("Employment"),
    t("Family problems"),
    t("Financial problems"),
    t("Goals undefined"),
    t("Graduation"),
    t("Health problems"),
    t("Housing problems"),
    t("Marriage"),
    t("Moving"),
    t("No reason specified"),
    t("Personal problems"),t("Temporary travel"),
    t("Transfer to another school"),
    t("Transportation Problems"),
    t("With family wish"));
    $gender = array(
    1 => t('Male'),
    2 => t('Female'));
    

In school_administration.install:

  1. There are some functions that are not prefixed by the name of the module; in the specific case, all the function names must start with school_administration_.
  2. The indentation used is not two spaces as suggested by the Drupal coding standards.
  3. It seems there is code that has been copied from another module, and pasted in the proposed module (see the comment that says "insert filed roles (profile_role module)"); it has not been even modified to change the function names, and the proposed module is likely to create a conflict with the module from which it took the code.
  4. insert_field_roles() contains the following code (which should not even exist):
      echo 'field roles are recorded<br/>';
    
tutumlum’s picture

number 1:

There are many functions that are marked as implementations of hook_form()...

I will maintain it. But I am not still not so clear. Ok I will try to figure it out.

number 2, 5, and 6:

Also there is some code that is outside a function...

It seems there is code that has been copied from...

insert_field_roles() contains the following...

That lines are used to insert data from my in-use project to new modules to try it. Do you know, for 4 modules, I wrote "query_migrate_to_drupal.php" (~900 lines) (~30Kb), it deploys more than 100,000 rows to drupal db. I sent my on-working copy directly. I put them there, because I wrote them for an installation profile, but I noticed that installation profile system of D7 is still changing, and I put it there. The reason is, I don't want to write same thing with "mysql_query()" again.
Ok, I understood that is a mistake. I will put initial data to somewhere else.

number 3:

There are some functions that are not prefixed by the name of the module;...

I will change it.
number 4:

The indentation used is not two spaces...

I changed my editor's configuration for drupal's indentation, tabbing, line ending etc. I don't know where it is you talked about...

Thank you for suggestions and for your time..

tutumlum’s picture

What do I need to do after changing? Attach again? if yes whole module system or just changed ones?

tutumlum’s picture

I started to change function names, but couldn't answer a question: What if I use those functions in other module like an API? I don't know may be it is a stupid question, but I want to clarify it.

avpaderno’s picture

If you call functions that are present in other modules, then the name of the function is as defined in that module. If with "using those functions in other modules" you mean that you copy the file containing the function definitions in your module, then that is not allowed.
A module uses the functions given from third-party modules, but it doesn't incorporate them inside itself. If you need some functions present in a module, then your module must declare its dependency from the other module.

tutumlum’s picture

I mean with use function as call function. Sorry.. Of course, copy-the function rename it and use is not allowed, and not a good way, because updating and security issues cannot be tracked..
So I am renaming all functions which module names are not mentioned in function name...

AjK’s picture

Status: Needs review » Needs work

Waiting for new upload of corrected code.

tutumlum’s picture

Status: Needs work » Needs review
StatusFileSize
new637.59 KB
tutumlum’s picture

StatusFileSize
new637.55 KB

I forgot to test re-installing modules. Here is the error-free installable ones.

avpaderno’s picture

What I was referring is this code (school_admin.install):

/** 
 * Implementation of hook_schema()
 */
function school_administration_schema() {
  $cyear = variable_get("c_year", '');
  foreach(array($cyear . '_', ($cyear + 1) . '_') AS $tbl_pf) {
    $schema['2009_student_parents'] = array(
        'description' => 'Stores parents and elder realtives of students.',
        'fields' => array(
             'id' => array('type' => 'serial', 'not null' => TRUE, 'disp-width' => '11'),
             'school_no' => array('type' => 'int', 'not null' => TRUE, 'disp-width' => '11'),
             'relation' => array('type' => 'varchar', 'length' => '32', 'not null' => TRUE),
             'uid' => array('type' => 'int', 'not null' => TRUE, 'disp-width' => '11'),
             'guardian' => array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 0, 'disp-width' => '1')),
        'primary key' => array('id'),
    );
  }

The indentation passes from 4 characters to 8, and from 8 to 13; it is supposed to pass from 4 to 6, and from 6 to 8 characters.

AjK’s picture

Status: Needs review » Needs work

@KiamLaLuno, if you are wanting the applicant to make changes please set the status to "needs work". Thanks :)

tutumlum’s picture

Status: Needs work » Needs review
StatusFileSize
new633.57 KB

Here it is. After some more cleaning with your suggestion..

dave reid’s picture

  1. In your module's .info files, do not specify the version line. That is supposed to be added by the drupal.org packaging script. See http://drupal.org/node/152819 and http://drupal.org/node/231036.
  2. Arrays need to have commas after their last element. See http://drupal.org/coding-standards#array.
    Your code:
      $gender = array(
        1 => t('Male'),
        2 => t('Female')
      );
    

    Should be:

      $gender = array(
        1 => t('Male'),
        2 => t('Female'), <--- added comma is here
      );
    
  3. It appears that you are creating/using several variables that could potentially cause conflicts with other modules since your variables are not prefixed with your module's name.
    function school_administration_uninstall() {
      drupal_uninstall_schema('school_administration');
      variable_del('c_year');
      variable_del('std_id_len');
      variable_del('num_range');
      variable_del('register_to');
      variable_del('password_inc');
      variable_del('st_id_conf');
      variable_del('school_admin_mod_relations');
      variable_del('school_admin_mod_jobs');
      variable_del('school_admin_mod_withd');
      variable_del('s_year');
    }
    

    If I were to create a password.module and use my own password_inc variable and someone uninstalls your module, it will unexpectedly mess up with an unrelated module. Likewise, your table names should also be prefixed with your module's name as to avoid collision. For instance, you have a table named 'withdrawal'. [Warning: silly example ahead] What if someone wanted to create an ATM module that allowed people to withdraw things? We always need to be sure that we take care with our module's functions, variables, and table names to use the module's namespace and avoid these potential conflicts.

  4. In school_administration_add_roles_and_permissions() you are creating roles based on the assumption that the next rid starts with 3. What if another module has been installed before yours and the next available rid is 10? This is going to fail. You should run db_insert() on the role table, which should return the rid that was inserted. Then use that value to insert into the role_permission table.
      //add roles and role permissions
      $rid = 3;
      if (db_query("SELECT COUNT(*) FROM {role}")->fetchField() <= $rid) {
        $query1 = db_insert('role')->fields(array('rid', 'name'));
        $query2 = db_insert('role_permission')->fields(array('rid', 'permission'));
        foreach ($role_permissions AS $role => $permissions) {
          $rid++;
          $query1->values(array($rid, $role));
          foreach ($permissions AS $perm) {
            $query2->values(array($rid, $perm));
          }
        }
        $query1->execute();
        $query2->execute();
        drupal_set_message('new roles are recorded');
      }
    
  5. The array definitions that are longer than 80 characters, specifically in school_administration_schema(), should use the format detailed in the coding standards. See http://drupal.org/coding-standards#array.

That was without going through the .module file. While it's clear you have a starting grasp of how to write modules, it's clear to me that there is still a lot of work to be done.

dave reid’s picture

Status: Needs review » Needs work
tutumlum’s picture

Status: Needs work » Needs review
StatusFileSize
new633.34 KB

I am here to work with :)
after module names issues and some making up here it is...

avpaderno’s picture

Status: Needs review » Needs work

school_administration.module:

  1. If you don't you the second argument of t(), it's perfectly useless you pass it.
        $replace = array();
        return '<p>' . t($txt, $replace) . '</p>';
    
  2. The indentation is still wrong; this happens in more than one part.
  3. school_administration_access() should always return a value, not just when it is TRUE.
  4.   $items['school_administration/browse/%/%/%'] = array(
        'title' => 'Browse Persons',
        'description' => 'Add Portrait Photo',
        'page callback' => 'school_administration_identity',
        'page arguments' => array(4),
        'access callback' => 'school_administration_access',
        'access arguments' => array(1),
        'weight' => 0,
        'type' => MENU_CALLBACK,
      );
    

    The menu uses three '%', but only one of those values are not used; in that case, the menu should be $items['school_administration/browse/%'], and the rest of the definition changed. I am not sure if 'access arguments' => array(1) is correct, or you meant 'access arguments' => array(2).

  5.       $cyear = SCHOOL_ADMINISTRATION_C_YEAR;
          $result = t("@acd ACADEMIC YEAR", array('@acd' => ($cyear - 1) . '-' . $cyear));
    

    There is not need to use a variable that you don't change to contain the value of a constant.

  6. substr(), and strlen() should be replaced by Drupal functions.
  7. 'school_administration/browse/' . $group . '/' . $sub_group . '/' . $member can be rewritten "school_administration/browse/$group/$sub_group/$member" (and so do similar strings).
  8. Use a placeholder in the SQL queries every time the parameter is not a constant.
  9. The functions that the comment says to be implementations of hook_validate() are really not; the same is true for the functions the comment says to be implementations of hook_submit().
  10. t() doesn't understand placeholders that doesn't start with !, @, %.
  11. There are many callbacks that return complex HTML output; it would be better to rewrite them to use theme functions.
tutumlum’s picture

Status: Needs work » Needs review
StatusFileSize
new633.79 KB

all okay as much as I figured out except last suggestion which is about HTML output. I suspected from school_administration_next_year_link() function and I simplified it.
I corrected school_administration.module and I am sending review, I will continue correcting the other files..

tutumlum’s picture

By the way I didn't know that these posts are in public. Could you remove my personal information from my first post?

avpaderno’s picture

Status: Needs review » Needs work
  1. There are some constants that are not prefixed by the module name.
  2. Some of the SQL queries are built concatenating not constant strings; even in the case you use the constant SCHOOL_ADMINISTRATION_C_YEAR (which is not truly a constant, as its value is created by the result of a call to variable_get()) it should be better to use a placeholder (as you already do in other cases).
  3. The callbacks I was referring to are the menu callbacks, or the page callbacks; many of them output complex HTML text, and it would be better to rewrite them using theme functions.
tutumlum’s picture

Status: Needs work » Needs review
StatusFileSize
new632.89 KB

First 2 isses: done
Last issue: I checked all page callback functions but I cannot figure it out. Could you be more specific please...

tutumlum’s picture

StatusFileSize
new632.9 KB

some typo correction..

avpaderno’s picture

Status: Needs review » Needs work
  1. include_once('school_administration.forms.inc') is not necessary in Drupal 7 because, giving the right information in the .info file, Drupal will include the necessary files; that is also true for Drupal core files, and functions defined in those files.
  2. t($txt) should be avoided because it is not possible to extract the string that needs to be translated; it's better to use t('Sentence to translate, which will be catched').
  3.   $items['photo/%'] = array(
        'title' => 'photo',
        'description' => 'Administer Your School',
        'page callback' => 'school_administration_portrait_photo',
        'page arguments' => array(1),
        'access callback' => 'school_administration_access',
        'weight' => -2,
      );
    

    The menu relative URL doesn't contain a string that is specific for your module, and it could cause a conflict with another module. It is still possible for somebody else to create a module named photo.module, and your module would not allow to use it; who creates a module is not forced to check all the menu callbacks defined by third-party modules, and see if they are defined as they are supposed to be.

  4. Check that the functions you are using inside SQL queries are not specific for a database engine; CONCAT_WS() is one of them.
  5. Some of the code that you placed in a submit function should be placed in a validation function. This is valid for the code that verify if the user given the right name of a directory (and if it's really a directory).
  6. Always use a function Drupal makes available; using a different function just causes a duplication of code which should be avoided.
  7. There are still functions that are declared as hooks, which are not hooks.
tutumlum’s picture

Status: Needs work » Needs review
StatusFileSize
new632.89 KB

issue 1, 2, 3: done
issue 4: done. I couldn't find how to handle mysql HEX() function (line:1083), I just comment it for future search. If you have any idea and tell me, I will be appreciated.
issue 5: okay I moved directory validation to validate function. I'm not moving the ones "continue"s the loop...
issue 6: I modified 2 links done by <a>, Is there more? or can you be more specific?
issue 7: done, is there hook_user_view in D7? I read before that hook_user($op will be divided to separate functions. It works, but cannot see in API documentation.

avpaderno’s picture

Status: Needs review » Needs work

I already signaled a problem, but the code still have that problem.

Rather than rushing to change the problems reported in the exact code reported, it would be better to check all the code and see if a similar problem exists in other parts of the modules. Just to make an example, the problem of the namespace not being respected has been reported by Dave, but then I reported the same problem twice; the code was different all the times, but when you are said that every Drupal variable names, and all the function names must be prefixed with the module name, you should check that every functions respect that.

You could wait to attach a new copy of the files, and check the code to see if it still needs to be modified as suggested here.

tutumlum’s picture

Status: Needs work » Needs review
StatusFileSize
new28 KB

Just to make an example, the problem of the namespace not being respected has been reported...

I strictly checked school_administration module and I couldn't find namespace problem. I thought that you are reviewing only school_administration module. I think you are talking about all modules I submit. Ok let's make it more convenient. I am submitting only first two modules to review. (Maybe it is better if I submit only one?)

I will "of course" obey all of Drupal rules for all future modules as I figured out during these submissions, I am here to do it, but maintaining 6 modules together not easy.
If I am missing something please tell me..
P.S: By the way, I start to comment all functions..

avpaderno’s picture

Status: Needs review » Needs work
  1.   drupal_set_header("Content-type:", "image/pjpeg");
    

    The content type is not the one usually used for JPEG pictures.

  2. The code initializes a variable with a constant, but then the variable is not changed at all; in other words, the variable is used as a constant. In that case, why does not the code use the constant directly, then?
  3. There are again SQL queries that don't use a placeholder when they should (especially because the value they use is not a constant value). There isn't a rush to attach here a new version of the code; check the code trice, wait 6 hours, re-check it, and then attach the new version.
    We are reviewing the code, but that doesn't mean we are going to do the work for you. ;-)
  4. /**
     * To limit access to menu callbacks
     */
    function classes_and_lessons_access($op = 'view') {
      return true;
      GLOBAL $user;
      switch ($op) {
        case 'view':
          if (isset($user->access) && $user->access && $user->status && (
            user_access('access user profiles') || 
            school_administration_student($user->uid) || 
            school_administration_student_parent($user->uid) || 
            school_administration_school_admin($user->uid) ||
            classes_and_lessons_teaching($user->uid) || 
            classes_and_lessons_supervisor($user->uid) ||
            classes_and_lessons_hr_teacher($user->uid)
          ))
          return TRUE;
        default:
          return FALSE;
        //false returns access denied
      }
    }
    

    This function will always return TRUE. Without any comment present, I guess that is not what it is supposed to do.

  5. function classes_and_lessons_delete_class_form($form_state) {
      $form['name'] = array(
        '#title' => 'Class',
      );
      return $form;
    }
    

    The form doesn't define any visible element; what is its purpose?

  6. function classes_and_lessons_student_list_for_parent($parent_id) {
      //used only in student_marks_student.inc on line 25 
      //check that it might be neddless
      $students = array();
      // ...
      foreach ($queryst AS $st) {
       $students[$st->school_no] = l("$st->school_no $st->name", "student_marks/student//$st->school_no/view");
      }
      return $students;
    }
    

    "student_marks/student//$st->school_no/view" should maybe be "student_marks/student/$st->school_no/view".

tutumlum’s picture

Status: Needs work » Needs review
StatusFileSize
new29.09 KB

done,
I hope :)

avpaderno’s picture

Status: Needs review » Needs work
  1.       switch ($group) {
            // ...
            case 'students' || 'parents' :
              $list = (module_exists('classes_and_lessons')) ? array()
              : school_administration_student_list($sub_group);
              break;
    
            default :
              $list = array();
          }
    

    I am not sure it works as you thought. Trying to execute the following code

    $a = 'test';
    
    switch ($a) {
      case 'a' || 'b' :
        print "AAA";
        break;
      case 'test' || 'tset' :
        print "BBB";
        break;
    }
    

    will print "AAA", differently from what you would suppose.

  2. The code uses PHP string functions when there are Drupal functions for that purpose; the reason the Drupal equivalent functions are preferable is because they can handle UTF8 characters even when the multi byte functions are not available.
  3. Some SQL queries are not using placeholders, and the code is creating the query by concatenating strings.
dave reid’s picture

Re #36:
1. Should be

case 'students':
case 'parents':
  // do stuff here
tutumlum’s picture

#36:
2. what about ucwords? there is no drupal_ucwords(). Do we have to do explode, ucfirst, implode?

tutumlum’s picture

Status: Needs work » Needs review
StatusFileSize
new29.32 KB
new29.32 KB
tutumlum’s picture

So, what is wrong? Why don't you review?

AjK’s picture

Status: Needs review » Needs work
  1.     return t('<p>First step of administrating a school is '
          . 'administering registration of students, teachers and non-academic staff. '
          . 'This module is a base module of school administration system, and it is '
          . 'responsible from keeping data of people.</p>');
    

    When suppyling a fixed string to t() you should not concat it like this. The correct method is:-

        return t('<p>First step of administrating a school is administering registration of students, teachers and non-academic staff. This module is a base module of school administration system, and it is responsible from keeping data of people.</p>');
    

    Yes, I know your code looks a lot more readable and neat but the reason is the extractor.php program translators use doesn't execute the code, it uses PHP's token_get_all(). The outcome of this is errors are thrown and translators cannot extract the fixed string correctly.

  2. function school_administration_access($op = 'main') {
      GLOBAL $user;
      if (school_administration_school_admin($user->uid) || user_access('access administration pages')) :
          return TRUE;
      elseif (school_administration_school_admin($user->uid) || user_access('access administration pages')) :
          return TRUE;
      endif;
      return FALSE;
    }
    

    What is the elseif doing? It looks the same as the if. Also, I may be wrong but the if() : ... endif; format is used by themes. I thought module coding standards were to use curly braces? See http://drupal.org/coding-standards#controlstruct

avpaderno’s picture

Some queries are still built concatenating strings.

  switch ($op) {
    case 'new' :
      $condition = "school_no > " . (SCHOOL_ADMINISTRATION_C_YEAR - 2001)*1000;
      break;

    case 'old' :
      $condition = "school_no < " . (SCHOOL_ADMINISTRATION_C_YEAR - 2001)*1000;
      break;
tutumlum’s picture

Status: Needs work » Needs review
StatusFileSize
new29.33 KB

During my summer vacation I just found a chance to work with the project. :) Please review...

avpaderno’s picture

Issue tags: +Module review, +Drupal 7.x
tutumlum’s picture

I am waiting for your review.. Please review...

avpaderno’s picture

Status: Needs review » Fixed

Status: Fixed » Closed (fixed)
Issue tags: -Module review, -Drupal 7.x

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

Anonymous’s picture

Issue summary: View changes

Removing private information

avpaderno’s picture

Component: Miscellaneous » new project application
Assigned: Unassigned » avpaderno
Status: Closed (fixed) » Fixed
Issue tags: -Drupal 7.x

Status: Fixed » Closed (fixed)

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