-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconference.module
2863 lines (2569 loc) · 132 KB
/
conference.module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?php
// $Id: conference.module,v 1.5.2.6.2.10 2009/06/11 07:50:14 zyxware Exp $
$GLOBALS['debug']=0;
/* ----------------------------------------------------------------------
DRUPAL CONFERENCE MODULE - VERSION 3.0 for Drupal 6.x
**** Information regarding the current Fork for 6.x ****
Please read README.TXT for further informations.
** Customized for OR2013 Conference **
----------------------------------------------------------------------
Latest history (Oct.2008) :
version 3.0 - fork from 2.2 (Drupal 5.x), heavily rewritten for Drupal 6.x
Status from 5.x Version: still experimental. Thorough testing (& debugging?!) of node permission management needed.
(contributor's view/edit/modify/upload with/without timelimit and/or modification required;
reviewers access to node/uploaded file ; manager's and conf.administrator's access rights ?)
TODO: to find what's "TODO", scan for this keyword throughout the code below...
*/
// define these as constants to ensure they're identical everywhere
// (submitted and used as $op==...)
define( 'CONF_ASSIGN_DELETE', t('Delete this assignment'));
/**
* Implementation of hook_help().
*
* Display help and module information
*
* @param section which section of the site we're displaying help
* @return help text for section
*/
function conference_help($path, $arg) {
switch ($path) {
/*
case "admin/modules#description":
return t("Organise your conferences with drupal!");
* MFH: This was the only entry in the 4.x versions; it seems of no use
* in 5.x (superseeded by the "DESCRIPTION=" entry in conference.info ?)
* All of the following are new in v.2 / 5.x :
*/
case 'admin/help#conference':
/* This text is found on the page admin/help/conference, to which an entry labelled "Conference" points on admin/help.
* After this text, the help module displays a section "Conference administration pages" with 2 entires:
* "conference settings" => admin/settings/conference, and "configure permissions" => admin/user/permissions#module-conference
* and "conf.settings"
*/
return t("<p>The <em>conference</em> module is suited for organizing a conference. More precisely, its main function is to manage submission and reviewing process of contributed papers.</p>
<p>It provides a role 'administer conference', required to !edit_settings_link. These include the choice of a specific content type used for submitting papers and for writing reviews, respectively. Also, three roles must be chosen among the existing drupal roles: one for paper submission, one for reviewing papers, and one for '<a href='@manage'>conference management</a>' (see below) - for the latter, you will usually <a href='@add_role'>create a role</a> labelled 'conference chair' or similar. In the sequel, a user having one of these roles will be called 'author', 'reviewer' or 'manager', respectively.</p>
<h2>Content types</h2>
<h3>The 'paper' type</h3>
<p>A specific content type must be dedicated to paper submissions. All 'authors', i.e. potential contributors, must be granted permission (by a Drupal admin able to 'administer access control') to create and edit (their own) content of this type. All nodes of that type will be listed as 'submitted papers' on their author's '<a href='@papers'>My papers</a>' page and on the <a href='@manage'>conference management</a> pages. However, the content type is not required to have any specific fields. The conference module can provide a default content type with adequate description and instructions for authors. You may however want to <a href='@add_content_type'>create a specifically structured content type</a> using the <a href='@cck'>CCK module</a> or similar. (The paper itself will usually be submitted as an uploaded file (PDF,...) attached to the 'paper' node. All 'authors' must therefore have the permission to do such file uploads.)</p>
<p>The conference module also controls acces to nodes of that type, making them available only to the specific author, the assigned reviewer(s), and the conference managers. The managers can activate a 'time limit' after which new submissions are not possible any more. Moreover, if a paper is assigned to a reviewer, it cannot be edited any more by the author, unless a modification is requested.</p>
<h3>The 'review' type</h3>
<p>A second specific content type must be dedicated to writing reviews. All nodes of that type will be listed on their author's '<a href='@reviews'>My reviews</a>' page. All 'reviewers' must be able to create and edit (their own) content of that type. Nodes of that type can only be created (and edited) for a specific paper, by a reviewer assigned to that paper, by following a specific link on the <a href='@reviews'>My reviews</a> page or in the assignment notification e-mail. (Of course reviewers must therefore have read access to 'paper' nodes and to uploaded files.) However, the content type is not required to have any specific fields. The conference module can provide a default content type with adequate description and instructions for reviewers. You may however want to <a href='@add_content_type'>create a specifically structured content type</a> using the <a href='@cck'>CCK module</a> or similar, e.g. to add selection fields for rating the paper, etc... The 'manager'(s) can decide if the conference module should provide a field 'comment to the author' which will immediately be visible to the author on his 'My papers' page.</p>
<h3>The 'manager's task</h3>
<p>
The conference managers essentially assign submitted papers to reviewers and decide whether to accept or reject a paper or to request a modified version. The conference module tries to help them as much as possible to accomplish this task. It provides the possibility to send customizable e-mail reminders to reviewers, and notifications to authors. The manager can also activate a 'time limit', which disallows creation of new paper content; only if a modified version is requested for a paper, it can still be posted.
</p>
<h3>Author and reviewer roles</h3>
<p>The roles of 'author' and 'reviewer' mainly provide a link 'My papers' resp. 'My reviews' in the navigation menu. These roles must have permissions to create nodes of the respective content types, to edit those they created, and the reviewer's role must have permission to access 'paper' nodes. However, apart from the manager, only the author of a paper and the reviewer(s) assigned to that paper will be able to access it, and only the reviewer himself and conference manager(s) will be able to access a review. (A field 'comment to the author', which will automatically be shown to the author on his 'my papers' page, <b>may</b> be provided to the reviewer.) Once a reviewer is assigned to a paper, the author cannot modify it any more, unless a modification is required. The conference manager may also activate a <a href='!timelimit'>time limit</a> which disallows posting new papers.
</p>
<h2>Actions required by the drupal administrator</h2>
<p>In addition to installing the conference module, the following steps must be performed, which usually require administrative privileges on the drupal system:</p><ul>
<li>attibute the 'manage conference' permission to an adequate role,</li>
<li>create the Drupal roles for reviewers and contributors, unless one or both of them can be chosen to be 'authenticated user',</li>
<li>attribute these roles to the respective users (!) - which suggests to use - at least for the contributors - a role which is automatically attributed to accounts which can be created automatically on user request. The same could be done for reviewers; in that case the 'my reviews' link could or should be hidden until the user has been assigned to write a review. (TO DO - not yet implemented.)</li>
<li>make sure that they can create/access the respective content types, including file upload permission for the contributor (to attach his paper e.g. as PDF to the 'paper' node), and 'access uploaded files' permission to the reviewer. (TO DO: This could (and should) be checked automatically by the conference module when corresponding choices are made on the settings page, but this is not yet implemented.)</li>
</ul>
<p>For more information please read your local <a href='@readme'>conference readme file</a> or consult the <a href='@project'>conference project page</a> on drupal.org.</p>",
array( '!edit_settings_link' => l( t( 'edit several settings' ), 'admin/settings/conference'),
'@manage' => '?q=conference/manage', '@papers' => '?q=conference/papers',// TO DO: convert these (internal) links to the
'@add_content_type' => '?q=admin/content/types/add', '@add_role' => '?q=admin/user/roles',// same format than the first one
'@cck' => 'http://drupal.org/project/cck',
'@readme' => 'sites/all/modules/conference/readme.txt',
'@project' => 'http://drupal.org/projects/conference', // project page
'@handbook' => 'http://drupal.org/handbook/modules/conference' // handbook (not yet used/available)
));
case 'conference': // TO DO: check if a conference is ongoing and print out adequate messages according to user's permissions.
// (the ?conference page does not exist yet)
return "<p>". t("If you are a potential contributor, you should see a !My_papers_link item in the navigation menu and/or a link allowing you to !create_content_link corresponding to the submission of a paper.",
array( '!My_papers_link' => l( t( "'My papers'" ), 'conference/papers'),
'!create_content_link' => l( t( 'create content' ), 'node/add' ), // TO DO: determine paper_type and make specific link node/add/paper_type
))
."</p>\n<p>". t("If you are a potential reviewer, you should see a !My_reviews_link item in the navigation menu, and probably have received an e-mail about papers assigned to you for reviewing. You can create and edit a review only by following a specific link, which will exist on your !My_reviews_link page after you have been assigned to review a specific paper.",
array( '!My_reviews_link' => l( t( "'My reviews'" ), 'conference/reviews' )))
."</p>\n<p>". t("If you are a so-called 'manager' of the conference, you should see a !Manage_conference_link item in the navigation menu, and be able to administer review assignments and decisions concerning all submitted papers by following that link.",
array( '!Manage_conference_link' => l( t( 'Manage conference' ), 'conference/manage' )))
."</p>";
case 'admin/content/conference': // this text shows up in the page with this name, here WITH a link "more help" pointing to previous main help page
return '<p>'. t("The conference module offers a means to organize the reviewing process of papers submitted to a conference.") .'</p>';
case 'conference/manage': // this shows up on the "Manage conference" page at this path (here WITHOUT "more help" link)
return '<p>'. t("This screen allows you to view and edit assignments of reviewers to conference papers. <ul><li><a href='http://or2013.net/reviewer_loads'>Reviewer Loads</a></li><li><a href='http://or2013.net/proposal_overview/export'>Export list of papers to XLS</a></li></ul>") .'</p>';
case 'conference/manage/status/misc':
// Displayed on the "Misc settings" subtab of the "Manage conference" page at this path (here w/o "more help" link)
return '<p>'. t("This screen allows you to adjust miscallenous settings related to the conference management.") .'</p>';
}// end switch
}// end of conf_help - implicit return(NULL);
/**
* Implementation of hook_perm().
*
* Valid permissions for this module.
*
* @return array An array of valid permissions for this module.
*
* NOTE: one could imagine to add here : 'post papers', 'review papers', 'manage conference'...
* instead of using our own "conf_role_xxx" variables/system.
* However, the idea is to let the conference manager(s) manage as much as possible
* without necessarily requiring him to have permissions to attribute user rights.
* Also, it may be considered useless to have a drupal permission for these tasks which are each attributed
* to a single user role (while drupal permissions exist "in order to" be attributed to several roles.)
*/
function conference_perm() {
return array('administer conference', 'manage conference', 'author conference', 'review conference', 'create revisions'
// 'access conference papers and ratings' // not (yet) used !?
);
}
/**
* Implementation of hook_menu().
*
* see includes/menu.inc for details on the $items[] format
*/
function conference_menu() {
global $user;
// $no_may_cache = 1;
// the first two are used only once.
// if undefined, the default role -1 will never be matched, so nothing will be displayed
$access_paper = (int)isset( $user->roles[ variable_get('conference_role_paper', -1)]);
$access_review = (int)isset( $user->roles[ variable_get('conference_role_review', -1)]);
$access_management = (int)isset( $user->roles[ variable_get('conference_role_management', 1)]);
// and the menu items... see include/menu.inc for details
// if ($no_may_cache) { // modifications made here will be only visible e.g.
// after hitting "Update" on admin/settings/conference
// NB: the 'title' of MENU_NORMAL_ITEMs ((omitted) default 'type' if none is specified)
// is displayed in the menu and also as page title
$items['conference/papers'] = array(
'title' => "My papers",
'description' => 'Listing of the papers you have submitted.', // shown as popup
'page callback' => 'conference_papers',
'access callback' => 'user_access',
'access arguments' => array('author conference'),
);
$items['conference/reviews'] = array(
'title' => "My reviews",
'description' => 'Listing of the reviews that have been assigned to you.',
'page callback' => 'conference_reviews',
'access callback' => 'user_access',
'access arguments' => array('review conference'),
);
//timelimit:callback only // what's the title here for if it is overwritten/-ridden in the callback ?
$items['conference/timelimit'] = array(
'title' => 'Time limit for paper submission exceeded',
'page callback' => 'conference_timelimit',
'access callback' => 'user_access',
'access arguments' => array('manage conference'),
'type' => MENU_CALLBACK
);// just defines uri, callback & page title
//manage & assign
$items['conference/manage'] = array(
'title' => 'Manage conference',// displayed in navigation menu & as page title
'access callback' => 'user_access',
'page callback' => 'conference_manage_assignment',
'access arguments' => array('manage conference'),
);// was ...management_list in v1.2
// default local task (1st tab selected for main 'manage' page)
//$items['conference/manage/assignment'] = array(
//'title' => 'Assign reviews',
//'weight' => 1,
//'access callback' => 'user_access',
//'access arguments' => array($access_management),
// 'access arguments' => array('manage conference'),
// 'type' => MENU_LOCAL_TASK
// );
// callback only: create/edit/delete assignment (should be reached only via a link including &pnid=...)
$items['conference/manage/assignment/edit'] = array(
'title' => 'Edit assignment',
'page callback' => 'drupal_get_form',
'page arguments' => array('conference_manage_assignment_edit'),
'weight' => 2,
'access callback' => 'user_access',
//'access arguments' => array($access_management),
'access arguments' => array('manage conference'),
'type' => MENU_CALLBACK
);
//status & subtabs: remind, timelimit // (NB: MENU_LOCAL_TASK makes subtabs, )
$items['conference/manage/status'] = array(
'title' => 'Status',
'weight' => 1,
'page callback' => 'conference_manage_status',
'access callback' => 'user_access',
'access arguments' => array('manage conference'),
'type' => MENU_LOCAL_TASK
);
$items['conference/manage/status/remind'] = array(
'title' => 'Send reminder',
'description' => 'Send reminder to all or some of the "pending" reviewers',
'page callback' => 'drupal_get_form',
'page arguments' => array('conference_manage_status_remind'),
'weight' => 1,
'access callback' => 'user_access',
'access arguments' => array('manage conference'),
'type' => MENU_LOCAL_TASK
);
$items['conference/manage/status/exceed'] = array(
'title' => 'Time limit reached',
'description' => "Disable submission of new contributions.",
'page callback' => 'drupal_get_form',
'page arguments' => array('conference_manage_status_exceed'),
'weight' => 1,
'access callback' => 'user_access',
'access arguments' => array('manage conference'),
'type' => MENU_LOCAL_TASK
);
$items['conference/manage/status/misc'] = array(
'title' => 'Misc settings',
'description' => "Disable submission of new contributions.",
'page callback' => 'drupal_get_form',
'page arguments' => array('conference_manage_status_misc'),
'weight' => 2,
'access callback' => 'user_access',
//'access arguments' => array($access_management),
'access arguments' => array('manage conference'),
'type' => MENU_LOCAL_TASK
);
//TODO: change ".../exceed" into something better, e.g. .../{timelimit|deadline|...}
//decision // the following 2 are new in 1.3 and 2.1
$items['conference/manage/decision'] = array(
'title' => 'Decision',
'weight' => 2,
'page callback' => 'conference_manage_decision',
'access callback' => 'user_access',
//'access arguments' => array($access_management),
'access arguments' => array('manage conference'),
'type' => MENU_LOCAL_TASK
);
$items['conference/manage/decision/make'] = array(
'title' => 'Make a decision',
'page callback' => 'drupal_get_form',
'page arguments' => array('conference_manage_decision_make'), // 5.x version
'weight' => 2,
'access callback' => 'user_access',
//'access arguments' => array($access_management),
'access arguments' => array('manage conference'),
'type' => MENU_CALLBACK
);
// entry for admin/settings (Site configuration)
$items['admin/settings/conference'] = array(
'title' => 'Conference settings',
'page callback' => 'drupal_get_form',
'page arguments' => array('conference_admin_settings'),
'description' => "Set up content types, roles, messages etc. relevant to paper submission, review & decision.",
'access callback' => 'user_access',
'access arguments' => array('administer conference'),
'file' => 'conference.admin.inc',
);
// Revisions for the papers
$items['conference/manage/revisions'] = array(
'title' => 'Revisions',
'page callback' => 'conference_revisions',
'weight' => 2,
'description' => "View Revisions of existing papers that were requested",
'access callback' => 'user_access',
'access arguments' => array('manage conference'),
'type' => MENU_LOCAL_TASK
);
// Recreates the Conference_manage_assignment function with sub-tabs for tracks
$items['conference/manage/assign_reviewers'] = array(
'title' => 'Assign Reviewers',
'weight' => 1,
'page callback' => 'conference_manage_assignment',
'access callback' => 'user_access',
'access arguments' => array('manage conference'),
'type' => MENU_DEFAULT_LOCAL_TASK
);
$items['conference/manage/assign_reviewers/dspace'] = array(
'title' => 'DSpace',
'description' => 'Assign papers in the DSpace user track',
'page callback' => 'conference_manage_assignment_dspace',
'weight' => 2,
'access callback' => 'user_access',
'access arguments' => array('manage conference'),
'type' => MENU_LOCAL_TASK
);
$items['conference/manage/assign_reviewers/eprints'] = array(
'title' => 'EPrints',
'description' => 'Assign papers in the EPrints user track',
'page callback' => 'conference_manage_assignment_eprints',
'weight' => 2,
'access callback' => 'user_access',
'access arguments' => array('manage conference'),
'type' => MENU_LOCAL_TASK
);
$items['conference/manage/assign_reviewers/fedora'] = array(
'title' => 'Fedora',
'description' => 'Assign papers in the Fedora user track',
'page callback' => 'conference_manage_assignment_fedora',
'weight' => 2,
'access callback' => 'user_access',
'access arguments' => array('manage conference'),
'type' => MENU_LOCAL_TASK
);
//}
return $items;
};
/**
* Return the adequate form item
*
* This regroups form items which were duplicate in former versions of conference.module,
* so that changes are made in a coherent manner. Maybe it is also an issue for other items,
* but at present it is restricted to the e-mail notification message's "Subject" and "Body"
* which are editable on admin/settings/conference and also on the specific pages.
*
* The $what parameter is equal to the corresponding variable's name with the leading
* 'conference_email_' stripped, such that conference_email('xxx') produces the array
* containing '#default_value' => variable_get('conference_email_xxx', DEFAULT_VALUE)
*
* (The curly braces are a relict from an unreleased beta version where I had created a
* corresponding function on its own for each item: You can get back to that state
* by deleting what precedes the "function" keyword, and you can get back to the original
* version by replacing the function call with the array(...).)
*
*/
function conference_email( $what ) {
if ( !function_exists("conference_use_variables")) {
/**
* Intended to produces a "homogeneous" #description for variables that may be used.
*
* @param $vars : an array or comma separated string of available variables
* @param $desc : description to use if a default does not exist or should be superseeded.
* Note: the $vars 'author' and 'reviewer' are special cases for %username, see below.
* Any other "unknown" variable will just be listed without explanation.
* @return : a string t("You may use the variables: %var1% for xxx, ..., %varN% for zzz.").
*
* N.B.: Make sure that the blabla printed here corresponds to what conference_mail() really does!
*
* TODO: I think %var% would be preferrable to %var - but this would break backwards compatibilty
* with possibly already set (& stored) variables
* unless the database would be fixed by conference_update_N in conference.install ...
*/
function conference_use_variables( $vars, $desc = array()) {
if ( !is_array( $vars )) // comma separated string had been given
$vars = split( ',', $vars );
// remove useless whitespace and variable delimiters
$vars = array_map( 'trim', $vars , array_fill(0, count($vars), " \t\r\n\"!'@%" ));
$t = array();
foreach ( $vars as $var ) {
if (isset($desc[ $var ]))
$d = @$desc[ $var ];
else switch ( $var ) {
case 'conference':
$d = "the conference name";
break;
case 'decision':
$d = "the conference chair's decision";
break;
case 'download':
$d = "the download link(s)";
break;
case 'feedback':
$d = "the 'feedback' (explanation of the decision)";
break;
case 'papers':
$d = "the list of papers";
break;
case 'title':
$d = "the paper's title";
break;
case 'username':
$d = "the user's name";
break; // this is depreciated
case 'author': // here follows a hack: for these variables, the text depends on the
case 'reviewer': // variable name, while the latter is finally replaced by 'username'
case 'referee': // (see also conference_mail() !)
$d = "the $var's name"; $var = 'username';
break;
default:
$d = "the $var's name"; $var = 'username';
break;
}
$t[] = "<tt>%$var</tt>". ( $d ? " ". t("for ". $d) : "" );
}
return t( "You may use the variables " ) . join( ', ', $t) .".";
}
}// !function_exists("conference_use_variables")
switch ( $what ) {
case 'assignment_subject': // function conference_email_assignment_subject()
return array(
'#type' => 'textfield',
'#title' => t('Subject'),
'#default_value' => variable_get('conference_email_assignment_subject', '[%conference] Please review the paper "%title".'),
'#description' => conference_use_variables('conference,title'),
'#weight' => 2
);
case 'assignment_body': // function conference_email_assignment_body()
return array(
'#type' => 'textarea', '#title' => t('Content'),
'#description' => conference_use_variables('conference,reviewer,title,download'),//reviewer=>username
'#default_value' => variable_get('conference_email_assignment_body', "Dear %username,\nthe conference chair assigned you to review the following paper.Please provide a review in time using our website.\n\nPaper title: %title\nYou can use this link to download the paper:\n\n%download\n\nThank you for your assistance!\n\n--- %conference team\n"),
'#cols' => 30,
'#rows' => 5,
'#weight' => 3
);
// TODO: %username is replaced by the Drupal username, it would be nicer to use the "real life" full name
// of the person, if available (through user profile,...)
// For any such profile field available, there should be a %variable which represents that value.
// TODO: there is no t(...) around subject and body; would this be useful?
// or should the manager adopt this text to the majority of users?
// or should it be translated (by conference_mail()) according to each user's locale settings?
case'reminder_subject'://function conference_email_reminder_subject()
return array(
'#type' => 'textfield',
'#weight' => 2,
'#title' => t('Subject'),
'#default_value' => variable_get('conference_email_reminder_subject', '[%conference] Reminder'),
'#description' => conference_use_variables('conference')
);
case'reminder_body'://function conference_email_reminder_body()
return array(
'#type' => 'textarea',
'#title' => t('Content'),
'#default_value' => variable_get('conference_email_reminder_body', "Dear %username,\nthe conference chair assigned you to review the following papers:\n\n%papers\nAt least some of these papers have not been reviewed until now.Please don't forget to post your reviews in time. Thank you!\n--- %conference team\n"),
'#description' => conference_use_variables('conference,reviewer,papers'),//reviewer=>username
'#cols' => 30,
'#rows' => 5,
'#weight' => 3
);
//notification email to author
case'notify_subject':
return array(
'#type' => 'textfield',
'#weight' => 2,
'#title' => t('Subject'),
'#default_value' => variable_get('conference_email_notify_subject', '[%conference] New Paper Submission Notification'),
'#description' => conference_use_variables('conference,title,author,papers')
);
case'notify_body':
return array(
'#type' => 'textarea',
'#title' => t('Content'),
'#default_value' => variable_get('conference_email_notify_body', "Dear %username,\nYou have subimitted the Paper Titled:\n\n%title\n\nWe will be reviewing the paper and will get back to you regarding our decision.\n\nThank you!\n--- %conference team\n"),
'#description' => conference_use_variables('conference,title,author,papers'),//reviewer=>username
'#cols' => 30,
'#rows' => 5,
'#weight' => 3
);
//review complete email to manager
case'reviewed_subject':
return array(
'#type' => 'textfield',
'#weight' => 2,
'#title' => t('Subject'),
'#default_value' => variable_get('conference_email_reviewed_subject', '[%conference] Paper Review Created Notification'),
'#description' => conference_use_variables('conference,title,author,papers')
);
case'reviewed_body':
return array(
'#type' => 'textarea',
'#title' => t('Content'),
'#default_value' => variable_get('conference_email_reviewed_body', "Dear %username,\nThe requested review for the Paper Titled:\n\n%title\n\nHas been created please proceed to take a decision on this.\n\nThank you!\n--- %reviewer_name\n"),
'#description' => conference_use_variables('conference,title,author,papers'),//reviewer=>username
'#cols' => 30,
'#rows' => 5,
'#weight' => 3
);
//revision created email to manager
case'revision_subject':
return array(
'#type' => 'textfield',
'#weight' => 2,
'#title' => t('Subject'),
'#default_value' => variable_get('conference_email_revision_subject', '[%conference] Paper Revision Created Notification'),
'#description' => conference_use_variables('conference,title,author,papers')
);
case'revision_body':
return array(
'#type' => 'textarea',
'#title' => t('Content'),
'#default_value' => variable_get('conference_email_revision_body', "Dear %username,\nThe requested modification for the Paper Titled:\n\n%title\n\nHas been created and has been notified, we will proceed to take a decision on this.\n\nThank you!\n--- %conference team\n"),
'#description' => conference_use_variables('conference,title,author,papers'),//reviewer=>username
'#cols' => 30,
'#rows' => 5,
'#weight' => 3
);
case'decision_subject'://function conference_email_decision_subject()
return array(
'#type' => 'textfield',
'#weight' => 2,
'#title' => t('Subject'),
'#default_value' => variable_get('conference_email_decision_subject', '[%conference] Information about your paper.'),
'#description' => conference_use_variables('conference,decision,title,author'),
);
case'decision_body'://function conference_email_decision_body()
return array(
'#type' => 'textarea',
'#weight' => 3,
'#title' => t('Content'),
'#default_value' => variable_get('conference_email_decision_body', "Dear %username,\n\nThank you for submitting your paper \"%title\".\nThe conference chair made a decision concerning that paper:\n* %decision *\n\n%feedback\n\n--- %conference team"),
'#description' => conference_use_variables('conference,author,title,decision,feedback'),//author=>username
'#cols' => 30,
'#rows' => 5,
);
// the following 3 could also be integrated into conference_decision()
// return array suitable for forms like "email settings", "inform author",...
case 'decision_accept': // function conference_email_decision_accept()
$a = array(
'#weight' => 4,
'#title' => t('Information text for accepting a paper'),
'#default_value' => variable_get('conference_email_decision_accept', 'Your paper is accepted. Please upload the full paper in your submission')
);
break;
case 'decision_reject': // function conference_email_decision_reject()
$a = array(
'#weight' => 6,
'#title' => t('Information text for rejecting a paper'),
'#default_value' => variable_get('conference_email_decision_reject', 'Your paper is rejected.')
);
break;
case 'decision_modify': // function conference_email_decision_modify()
$a = array(
'#weight' => 5,
'#title' => t('Information text for requesting a modification'),
'#default_value' => variable_get('conference_email_decision_modify', 'Please modify your paper by creating a new revision of the current paper.')
);
break; // TODO: conference module should send notification to manager (and/or reviewer(s)) if modified version is uploaded
default:
return;//NULL
}// end switch $what.
// If we're here, it's after the "break" from one of the last 3 cases
$a['#type'] = 'textfield';
$a['#description'] = t( "The %decision variable will be replaced by this text if appropriate." );
return $a; // TODO: write the above line specifically to each case and put the return(...) into the switch{...}
}
/**
* Implementation of hook_node_grants
*
* TODO : document what's the point in having this code in addition to the node_access table updated above.
*/
function conference_node_grants($account, $op) {
if (!variable_get('conference_grants', 0))
return;
$grants = array();
$grants['all'] = array(-1); // disable default grants
// allow all users access to node types other than papers and reviews
$grants['conference_all'] = array(0);
// only creators can access papers and reviews
$grants['conference'] = array($account->uid);
// manager can access everything
$role_management= variable_get('conference_role_management', '-1');
if (array_key_exists($role_management, $account->roles))
$grants['conference_manage'] = array(1);
return $grants;
}
/**
* List all papers with the assigned reviewers.
*/
function conference_manage_assignment() { // was: function conference_management_list ()
if ( ! $ctype_paper = variable_get('conference_ctype_paper', '')
or ! $ctype_review= variable_get('conference_ctype_review', ''))
return conference_setup_required();
// table header
$header = array(
array(data => t('Track'), field => 'p.field_ptrack_value' ),
array(data => t('Title'), field => 'n.title' ),
array(data => t('User'), field => 'n.uid' ),
array(data => t('Date'), field => 'n.created', sort => 'desc'),
array(data => t('Reviewer'), field => 'c.rnid' ),
// del in 1.3
array (data => t('Revisions?') ),
array(data => t('Reviewed?') ),
array(data => t('Assignment') ),
);
$rows= array();
// get a paged list of all papers
// (TODO: we could avoid loading ALL data of the node here.)
$sql = "SELECT * FROM {node} n LEFT JOIN {conference} c ON n.nid = c.pnid LEFT JOIN {content_type_conference_paper} p ON n.nid = p.nid WHERE n.type='%s' AND (c.pvid = n.vid OR c.pvid is NULL OR c.pvid = (SELECT max(c.pvid) FROM {conference} c WHERE c.pnid = n.nid))";
$sql .= tablesort_sql($header);
$result = pager_query($sql, 25, 5, NULL, $ctype_paper);
while ( $item = db_fetch_array( $result )) {
// get user information
$p_user = user_load( array( 'uid' => $item['uid']));
if ($item['pvid'] == $item['vid']) {
$r_user = ($item['ruid'] ? user_load(array( 'uid' => $item['ruid'])) : NULL);
}
else {
$r_user = NULL;
}
// choose some operations to display
//added vid to keep track of revisions
$op = array();
if ($r_user) { //Fixed the fact that edit and create was being shown
$op[] = l( t( 'edit' ), 'conference/manage/assignment/edit',
array ( 'attributes' => array( 'title' => t("edit this assignment") ) ,
'query' => "pnid=$item[nid]&pvid=$item[vid]&ruid=$r_user->uid"
));
} else {
$op[]= l( t( 'create' ), 'conference/manage/assignment/edit',
array ( 'attributes' => array( 'title' => t("create a new assignment") ),
'query' => "pnid=$item[nid]&pvid=$item[vid]"
)); // added by MFH
}
//check for existance of reviews and display the content
$total_revisions = db_result( db_query("SELECT count(*) FROM {node_revisions} WHERE nid = %d", $item['nid']));
// build row
$rows[] = array(
$item['field_ptrack_value'],
l( $item['title'], 'node/'. $item['nid'] ),
l( $p_user->name, 'user/'. $p_user->uid),
format_date( $item['created']),
$r_user ? l( $r_user->name, 'user/'. $r_user->uid) : t('not assigned'),
$total_revisions == 1 ? t('No') : l('Yes', 'conference/manage/revisions/'.$item['nid']),
$item['rnid'] && $r_user ? l( t('yes: see review' ), "node/$item[rnid]" ) : t('no'),
implode( ', ', $op),
);
};
$content = theme('table', $header, $rows) . theme('pager', NULL, 25, 5);
print theme( 'page', $content );
};
/**
* List all papers with the assigned reviewers in the Eprints track.
*/
function conference_manage_assignment_eprints() {
if ( ! $ctype_paper = variable_get('conference_ctype_paper', '')
or ! $ctype_review= variable_get('conference_ctype_review', ''))
return conference_setup_required();
// table header
$header = array(
array(data => t('Title'), field => 'n.title' ),
array(data => t('User'), field => 'n.uid' ),
array(data => t('Date'), field => 'n.created', sort => 'desc'),
array(data => t('Reviewer'), field => 'c.rnid' ),
// del in 1.3
array (data => t('Revisions?') ),
array(data => t('Reviewed?') ),
array(data => t('Assignment') ),
);
$rows= array();
// get a paged list of all papers
// (TODO: we could avoid loading ALL data of the node here.)
$sql = "SELECT * FROM {node} n LEFT JOIN {conference} c ON n.nid = c.pnid LEFT JOIN {content_type_conference_paper} p ON n.nid = p.nid WHERE n.type='%s' AND (c.pvid = n.vid OR c.pvid is NULL OR c.pvid = (SELECT max(c.pvid) FROM {conference} c WHERE c.pnid = n.nid)) AND p.field_ptrack_value = 'eprints'";
$sql .= tablesort_sql($header);
$result = pager_query($sql, 25, 5, NULL, $ctype_paper);
while ( $item = db_fetch_array( $result )) {
// get user information
$p_user = user_load( array( 'uid' => $item['uid']));
if ($item['pvid'] == $item['vid']) {
$r_user = ($item['ruid'] ? user_load(array( 'uid' => $item['ruid'])) : NULL);
}
else {
$r_user = NULL;
}
// choose some operations to display
//added vid to keep track of revisions
$op = array();
if ($r_user) { //Fixed the fact that edit and create was being shown
$op[] = l( t( 'edit' ), 'conference/manage/assignment/edit',
array ( 'attributes' => array( 'title' => t("edit this assignment") ) ,
'query' => "pnid=$item[nid]&pvid=$item[vid]&ruid=$r_user->uid"
));
} else {
$op[]= l( t( 'create' ), 'conference/manage/assignment/edit',
array ( 'attributes' => array( 'title' => t("create a new assignment") ),
'query' => "pnid=$item[nid]&pvid=$item[vid]"
)); // added by MFH
}
//check for existance of reviews and display the content
$total_revisions = db_result( db_query("SELECT count(*) FROM {node_revisions} WHERE nid = %d", $item['nid']));
// build row
$rows[] = array(
l( $item['title'], 'node/'. $item['nid'] ),
l( $p_user->name, 'user/'. $p_user->uid),
format_date( $item['created']),
$r_user ? l( $r_user->name, 'user/'. $r_user->uid) : t('not assigned'),
$total_revisions == 1 ? t('No') : l('Yes', 'conference/manage/revisions/'.$item['nid']),
$item['rnid'] && $r_user ? l( t('yes: see review' ), "node/$item[rnid]" ) : t('no'),
implode( ', ', $op),
);
};
$content = theme('table', $header, $rows) . theme('pager', NULL, 25, 5);
print theme( 'page', $content );
};
/**
* List all papers with the assigned reviewers in the Fedora track.
*/
function conference_manage_assignment_fedora() {
if ( ! $ctype_paper = variable_get('conference_ctype_paper', '')
or ! $ctype_review= variable_get('conference_ctype_review', ''))
return conference_setup_required();
// table header
$header = array(
array(data => t('Title'), field => 'n.title' ),
array(data => t('User'), field => 'n.uid' ),
array(data => t('Date'), field => 'n.created', sort => 'desc'),
array(data => t('Reviewer'), field => 'c.rnid' ),
// del in 1.3
array (data => t('Revisions?') ),
array(data => t('Reviewed?') ),
array(data => t('Assignment') ),
);
$rows= array();
// get a paged list of all papers
// (TODO: we could avoid loading ALL data of the node here.)
$sql = "SELECT * FROM {node} n LEFT JOIN {conference} c ON n.nid = c.pnid LEFT JOIN {content_type_conference_paper} p ON n.nid = p.nid WHERE n.type='%s' AND (c.pvid = n.vid OR c.pvid is NULL OR c.pvid = (SELECT max(c.pvid) FROM {conference} c WHERE c.pnid = n.nid)) AND p.field_ptrack_value = 'fedora'";
$sql .= tablesort_sql($header);
$result = pager_query($sql, 25, 5, NULL, $ctype_paper);
while ( $item = db_fetch_array( $result )) {
// get user information
$p_user = user_load( array( 'uid' => $item['uid']));
if ($item['pvid'] == $item['vid']) {
$r_user = ($item['ruid'] ? user_load(array( 'uid' => $item['ruid'])) : NULL);
}
else {
$r_user = NULL;
}
// choose some operations to display
//added vid to keep track of revisions
$op = array();
if ($r_user) { //Fixed the fact that edit and create was being shown
$op[] = l( t( 'edit' ), 'conference/manage/assignment/edit',
array ( 'attributes' => array( 'title' => t("edit this assignment") ) ,
'query' => "pnid=$item[nid]&pvid=$item[vid]&ruid=$r_user->uid"
));
} else {
$op[]= l( t( 'create' ), 'conference/manage/assignment/edit',
array ( 'attributes' => array( 'title' => t("create a new assignment") ),
'query' => "pnid=$item[nid]&pvid=$item[vid]"
)); // added by MFH
}
//check for existance of reviews and display the content
$total_revisions = db_result( db_query("SELECT count(*) FROM {node_revisions} WHERE nid = %d", $item['nid']));
// build row
$rows[] = array(
l( $item['title'], 'node/'. $item['nid'] ),
l( $p_user->name, 'user/'. $p_user->uid),
format_date( $item['created']),
$r_user ? l( $r_user->name, 'user/'. $r_user->uid) : t('not assigned'),
$total_revisions == 1 ? t('No') : l('Yes', 'conference/manage/revisions/'.$item['nid']),
$item['rnid'] && $r_user ? l( t('yes: see review' ), "node/$item[rnid]" ) : t('no'),
implode( ', ', $op),
);
};
$content = theme('table', $header, $rows) . theme('pager', NULL, 25, 5);
print theme( 'page', $content );
};
/**
* List all papers with the assigned reviewers in the DSpace track.
*/
function conference_manage_assignment_dspace() {
if ( ! $ctype_paper = variable_get('conference_ctype_paper', '')
or ! $ctype_review= variable_get('conference_ctype_review', ''))
return conference_setup_required();
// table header
$header = array(
array(data => t('Title'), field => 'n.title' ),
array(data => t('User'), field => 'n.uid' ),
array(data => t('Date'), field => 'n.created', sort => 'desc'),
array(data => t('Reviewer'), field => 'c.rnid' ),
// del in 1.3
array (data => t('Revisions?') ),
array(data => t('Reviewed?') ),
array(data => t('Assignment') ),
);
$rows= array();
// get a paged list of all papers
// (TODO: we could avoid loading ALL data of the node here.)
$sql = "SELECT * FROM {node} n LEFT JOIN {conference} c ON n.nid = c.pnid LEFT JOIN {content_type_conference_paper} p ON n.nid = p.nid WHERE n.type='%s' AND (c.pvid = n.vid OR c.pvid is NULL OR c.pvid = (SELECT max(c.pvid) FROM {conference} c WHERE c.pnid = n.nid)) AND p.field_ptrack_value = 'dspace'";
$sql .= tablesort_sql($header);
$result = pager_query($sql, 25, 5, NULL, $ctype_paper);
while ( $item = db_fetch_array( $result )) {
// get user information
$p_user = user_load( array( 'uid' => $item['uid']));
if ($item['pvid'] == $item['vid']) {
$r_user = ($item['ruid'] ? user_load(array( 'uid' => $item['ruid'])) : NULL);
}
else {
$r_user = NULL;
}
// choose some operations to display
//added vid to keep track of revisions
$op = array();
if ($r_user) { //Fixed the fact that edit and create was being shown
$op[] = l( t( 'edit' ), 'conference/manage/assignment/edit',
array ( 'attributes' => array( 'title' => t("edit this assignment") ) ,
'query' => "pnid=$item[nid]&pvid=$item[vid]&ruid=$r_user->uid"
));
} else {
$op[]= l( t( 'create' ), 'conference/manage/assignment/edit',
array ( 'attributes' => array( 'title' => t("create a new assignment") ),
'query' => "pnid=$item[nid]&pvid=$item[vid]"
)); // added by MFH
}
//check for existance of reviews and display the content
$total_revisions = db_result( db_query("SELECT count(*) FROM {node_revisions} WHERE nid = %d", $item['nid']));
// build row
$rows[] = array(
l( $item['title'], 'node/'. $item['nid'] ),
l( $p_user->name, 'user/'. $p_user->uid),
format_date( $item['created']),
$r_user ? l( $r_user->name, 'user/'. $r_user->uid) : t('not assigned'),
$total_revisions == 1 ? t('No') : l('Yes', 'conference/manage/revisions/'.$item['nid']),
$item['rnid'] && $r_user ? l( t('yes: see review' ), "node/$item[rnid]" ) : t('no'),
implode( ', ', $op),
);
};
$content = theme('table', $header, $rows) . theme('pager', NULL, 25, 5);
print theme( 'page', $content );
};
/**
* Form to create and edit the assignment of a paper to a reviewer.
*
* In principle we could restrict this to require the pnid given through GET,
* and only the reviewer to be selected.
*/
function conference_manage_assignment_edit() { //was: function conference_manage_assign ()
// drupal_set_message( "conference_management_assign - REQUEST = ".var_export($_REQUEST,true) );
if ( ! $ctype_paper = variable_get('conference_ctype_paper', 0) // should be the type's name (a string)
or($role_review = variable_get('conference_role_review', '') ) === ''
) { // reviewer role could be 'anonymous user' : uid = 0 !
return conference_setup_required();
}
// get parameters: if present edit existing assignment, otherwise create new assignment.
$param_pnid = (int) @$_GET['pnid']; // $_GET, since here we test whether we followed a link
$param_ruid = (int) @$_GET['ruid']; // 'edit assignment' (both set) or 'create assignment' (only pnid)
// create an array with all selectable paper-nodes
// This is currently only useful for editing an existing assignment by
// changing the "reviewer's duty" (replace the assigned paper by another one)
// In previous version there was a "free assignment creation form"
// but now all should be done through the links on the "...manage..." page,
// i.e. (1) assign a (given) paper to a reviewer, (2) delete a given assignment.
// Thus, the paper selection should not be used.
$papers = array();
$rnid = 0;
// TO DO : for each of the parameters, make a list if it's not given, else don't.
if ($param_pnid AND $param_ruid) { // edit assignment // ...ON...WHERE ...
$result = db_query("SELECT * FROM {conference} c LEFT JOIN {node} n ON n.nid = c.pnid
WHERE c.pnid = $param_pnid AND c.ruid = $param_ruid" );
$item = db_fetch_object($result);
$papers[$item->nid] = $item->title;
$rnid = $item->rnid;
if ($GLOBAL['debug'])drupal_set_message( "Editing existing assignment for reviewer # $item[ruid], paper '$item[title]'" );
}
else {
//if($GLOBAL['debug']) drupal_set_message( "Create new assignment..." );
$result = db_query("SELECT * FROM {node} n LEFT JOIN {conference} c ON n.nid = c.pnid WHERE n.type='%s'", $ctype_paper );
while ( $item = db_fetch_array($result))
$papers[$item['nid']]= $item['title'];
if ( empty( $papers))
// not very elegant : treat this case separately and make a query for that singe item
if ($param_pnid && isset($papers[$param_pnid]))
$papers = array($param_pnid => $papers[$param_pnid]); // retain only that one
};
// form element: select paper
$form['pnid'] = array('#type' => 'select', '#title' => t('Paper'), '#options' => $papers, '#weight' => 0 );
if ( !$_POST['pnid'] && $param_pnid ) $form['pnid'][ '#default_value' ] = $param_pnid;
// create an array with all reviewer-users
$reviewer = //$param_ruid ? array( 0 => "nobody (drop this assignment)" ) :
array();
$puid = db_result(db_query("SELECT uid FROM node WHERE nid = %d", $param_pnid));
$result = db_query("SELECT * FROM {users_roles} r LEFT JOIN {users} u ON r.uid = u.uid WHERE r.rid = '%s' AND u.uid != '%s'", $role_review, $puid);
while ($item = db_fetch_array($result)) {
$reviewer[$item['uid']] = db_result(db_query("SELECT value FROM profile_values WHERE uid = %d AND fid = '1'", $item['uid'])) . " " . db_result(db_query("SELECT value FROM profile_values WHERE uid = %d AND fid = '4'", $item['uid'])) . " (" . $item['name'] . ")";
};
// form element: select reviewer
$form['ruid'] = array('#type' => 'select', '#title' => t('Reviewer'),
'#options' => $reviewer, '#weight' => 1, '#default_value' => @ $param_ruid,
);
// if( !$_POST['ruid'] && $param_ruid ) $form['ruid'][ '#default_value' ] = $param_ruid;
// MFH: check if this if(...) is still needed or should be preferred
// to the previous "#def..."=> $param_ruid (if the latter does )
// if there is a review-node (update existing assignment), ask what to do with it.
if ($rnid) {
$form['update_rnid'] = array('#type' => 'radios',
'#title' => t('The assigned reviewer already wrote a review for this paper. You can assign this to another reviewer if required'),
'#default_value' => $rnid,
'#options' => array( $rnid => t('keep this review'),
0 => t('loose this review (no way to assign it again!)')),
'#weight' => 2,
);
} else {
$form['assign_multiple_review'] = array (
'#type' => 'checkbox',
'#title' => t('Allow multiple reviewer assignment for this paper'),
'#description' => t('If you check this box and select a different reviwer, a new assignment will be created for the paper'),
'#default_value' => FALSE,
'#weight' => 2,
);
}
// new in 2.1 & 1.3 :
// form element: inform author by email?
$form['email']= array(
'#type' => 'fieldset',
'#weight' => 3,
'#title' => t('Inform reviewer by email')
);
$form['email']['send']= array(
'#type' => 'checkbox',
'#default_value' => 1,
'#weight' => 1,
'#title' => t('Send information email about this assignment to the reviewer'),
);
$form['email']['subject'] = conference_email('assignment_subject');
$form['email']['body'] = conference_email('assignment_body');
$form['email']['save'] = array(
'#type' => 'checkbox',
'#default_value' => 1,
'#weight' => 4,
'#title' => t('Save email content and subject as default'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
'#weight' => 9