certificate.module in Certificate 6
Same filename and directory in other branches
Certificate module.
File
certificate.moduleView source
<?php
/**
* Certificate module.
* @file
*/
/**
* Implementation of hook_node_info().
*/
function certificate_node_info() {
$items = array(
'certificate' => array(
'name' => t('Certificate'),
'module' => 'certificate',
'description' => t('A tokenized certificate template that will be converted to a PDF and displayed to users who complete accredited activities.'),
'has_title' => TRUE,
'title_label' => t('Title'),
'has_body' => TRUE,
'body_label' => t('Certificate Body'),
'min_word_count' => '0',
'help' => '',
'locked' => TRUE,
),
);
return $items;
}
/**
* Implementation of hook_access().
*/
function certificate_access($op, $node, $account) {
if ($op == 'create') {
return user_access('create certificate content', $account);
}
if ($op == 'update') {
if (user_access('edit any certificate content', $account) || user_access('edit own certificate content', $account) && $account->uid == $node->uid) {
return TRUE;
}
}
if ($op == 'delete') {
if (user_access('delete any certificate content', $account) || user_access('delete own certificate content', $account) && $account->uid == $node->uid) {
return TRUE;
}
}
}
function certificate_form(&$node, $form_state) {
// The site admin can decide if this node type has a title and body, and how
// the fields should be labeled. We need to load these settings so we can
// build the node form correctly.
$type = node_get_types('type', $node);
if ($type->has_title) {
$form['title'] = array(
'#type' => 'textfield',
'#title' => check_plain($type->title_label),
'#required' => TRUE,
'#default_value' => $node->title,
'#weight' => -5,
);
}
if ($type->has_body) {
// In Drupal 6, we use node_body_field() to get the body and filter
// elements. This replaces the old textarea + filter_form() method of
// setting this up. It will also ensure the teaser splitter gets set up
// properly.
$form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count);
}
// Now we define the form elements specific to our node type.
$form['certificate']['#tree'] = TRUE;
$form['certificate']['orientation'] = array(
'#type' => 'radios',
'#title' => t('Orientation'),
'#default_value' => isset($node->certificate['orientation']) ? $node->certificate['orientation'] : '',
'#options' => array(
'portrait' => t('Portrait'),
'landscape' => t('Landscape'),
),
'#required' => TRUE,
'#description' => 'The orientation of the generated certificate.',
);
$form['options']['status']['#default_value'] = 0;
$form['options']['promote']['#default_value'] = 0;
return $form;
}
/**
* Implementation of hook_help().
*/
function certificate_help($path, $arg) {
if ($path == 'admin/help#certificate') {
$txt = 'If you install the !advanced_help module, Views will provide more and better help.';
$link = l('Advanced help', 'http://drupal.org/project/advanced_help');
$replace = array(
'!advanced_help' => $link,
);
return '<p>' . t($txt, $replace) . '</p>';
}
}
/**
* Implementation of hook_menu().
*/
function certificate_menu() {
$items = array();
// Certificate types.
$items['admin/settings/certificate'] = array(
'title' => 'Certificates',
'access arguments' => array(
'administer certificates',
),
'file' => 'certificate.admin.inc',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'certificate_admin_settings_form',
),
);
$items['admin/settings/certificate/clear'] = array(
'title' => 'Clear',
'access arguments' => array(
'administer certificates',
),
'file' => 'certificate.admin.inc',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'certificate_admin_clear_form',
),
'type' => MENU_LOCAL_TASK,
);
$items['admin/settings/certificate/types'] = array(
'title' => 'Settings',
'description' => 'Select nodes which are certifiable.',
'access arguments' => array(
'administer certificates',
),
'file' => 'certificate.admin.inc',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -100,
);
$items['admin/settings/certificate/templates'] = array(
'title' => 'Templates',
'access arguments' => array(
'administer certificates',
),
'type' => MENU_LOCAL_TASK,
'file' => 'certificate.admin.inc',
'page callback' => 'certificate_templates_list',
'weight' => -90,
);
$items['admin/settings/certificate/sets'] = array(
'title' => 'Criteria sets',
'access arguments' => array(
'administer certificates',
),
'type' => MENU_LOCAL_TASK,
'page callback' => 'certificate_sets_page',
'file' => 'certificate.admin.inc',
'weight' => -80,
);
$items['admin/settings/certificate/sets/list'] = array(
'title' => 'Sets',
'description' => 'Set up certificate sets',
'page callback' => 'certificate_sets_page',
'access arguments' => array(
'administer certificates',
),
'file' => 'certificate.admin.inc',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/settings/certificate/sets/%certificate_set/criteria'] = array(
'title' => 'Criteria',
'description' => 'Edit certificate type criteria.',
'page callback' => 'certificate_sets_checks_page',
'page arguments' => array(
4,
),
'access arguments' => array(
'administer certificates',
),
'file' => 'certificate.admin.inc',
'type' => MENU_LOCAL_TASK,
);
// Edit/delete type.
$items['admin/settings/certificate/sets/%certificate_set/edit'] = array(
'title' => 'Edit certificate type',
'description' => 'Edit certificate type.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'certificate_sets_form',
4,
),
'access arguments' => array(
'administer certificates',
),
'file' => 'certificate.admin.inc',
);
$items['admin/settings/certificate/sets/%certificate_set/delete'] = array(
'title' => 'Edit certificate type',
'description' => 'Edit certificate type.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'certificate_set_delete_form',
4,
),
'access arguments' => array(
'administer certificates',
),
'file' => 'certificate.admin.inc',
);
// Delete criterion.
$items['admin/settings/certificate/criteria/%certificate_criterion/delete'] = array(
'title' => 'Delete Criterion',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'certificate_criterion_delete_form',
4,
),
'access arguments' => array(
'administer certificates',
),
'file' => 'certificate.admin.inc',
'type' => MENU_CALLBACK,
);
// Certificate templates.
$items['admin/settings/certificate/sets/add'] = array(
'title' => 'New set',
'description' => 'Add a new set of criteria',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'certificate_sets_form',
),
'access arguments' => array(
'administer certificates',
),
'file' => 'certificate.admin.inc',
'weight' => 1,
'type' => MENU_LOCAL_TASK,
);
$items['admin/settings/certificate/templates/add'] = array(
'title' => 'New template',
'description' => 'Add a new certificate template',
'page callback' => 'drupal_goto',
'page arguments' => array(
'node/add/certificate',
array(
'destination' => 'admin/settings/certificate/templates',
),
),
'access arguments' => array(
'administer certificates',
),
'type' => MENU_LOCAL_TASK,
'tab_parent' => 'admin/settings/certificate',
'tab_root' => 'admin/settings/certificate',
'file' => 'certificate.admin.inc',
'weight' => 100,
);
// Certificate template preview.
$items['admin/settings/certificate/templates/preview/%'] = array(
'title' => 'Certificate Preview',
'description' => 'Display earned certificate for this node',
'page callback' => 'certificate_preview',
'page arguments' => array(
5,
),
'access arguments' => array(
'administer certificates',
),
'file' => 'certificate.pages.inc',
'type' => MENU_LOCAL_TASK,
);
// Certificate tab on nodes.
$items['node/%node/certificate'] = array(
'title' => 'Certificate',
'description' => 'Display earned certificate for this node',
'page callback' => 'certificate_node_certificate',
'page arguments' => array(
1,
),
'access callback' => 'certificate_can_access_certificate',
'access arguments' => array(
1,
),
'file' => 'certificate.pages.inc',
'type' => MENU_LOCAL_TASK,
);
$items['admin/settings/certificate/mapping'] = array(
'title' => 'Mapping',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'certificate_settings_form',
),
'access arguments' => array(
'administer certificates',
),
'file' => 'certificate.admin.inc',
'type' => MENU_LOCAL_TASK,
);
$items['admin/settings/certificate/mapping/list'] = array(
'title' => 'Fields',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/settings/certificate/mapping/groups'] = array(
'title' => 'Field groups',
'description' => 'Set up certificate field groups',
'page callback' => 'certificate_field_grouping_page',
'access arguments' => array(
'administer certificates',
),
'file' => 'certificate.admin.inc',
'type' => MENU_LOCAL_TASK,
'weight' => -9,
);
$items['admin/settings/certificate/mapping/groups/add'] = array(
'title' => 'Add field group',
'description' => 'Add a field group',
'page callback' => 'certificate_field_grouping_add_page',
'access arguments' => array(
'administer certificates',
),
'file' => 'certificate.admin.inc',
'type' => MENU_LOCAL_TASK,
);
$items['admin/settings/certificate/mapping/groups/delete/%'] = array(
'title' => 'Delete field group',
'description' => 'Delete a field group',
'page callback' => 'certificate_field_grouping_delete_page',
'page arguments' => array(
6,
),
'access arguments' => array(
'administer certificates',
),
'file' => 'certificate.admin.inc',
'type' => MENU_LOCAL_TASK,
);
return $items;
}
/**
* Implementation of hook_perm().
*/
function certificate_perm() {
return array(
'access all certificates',
'administer certificates',
'create certificate content',
'delete own certificate content',
'delete any certificate content',
'edit own certificate content',
'edit any certificate content',
);
}
/**
* Implementation of hook_theme().
*
* Returns information about every themable function defined by the module.
*/
function certificate_theme() {
$items = array();
$items['certificate_history_form'] = array(
'arguments' => array(
'form' => array(),
),
'file' => 'certificate.admin.inc',
);
// Keep for now - we may want to theme the output specifically for Moodle.
$items['certificate_certificate'] = array(
'arguments' => array(
'certificate' => array(),
),
'file' => 'certificate.pages.inc',
);
$items['certificate_admin_clear_form'] = array(
'arguments' => array(
'form' => NULL,
),
'file' => 'certificate.admin.inc',
);
return $items;
}
/**
* Helper function to match template to certificate type.
*
* @return
* The content profile node object.
*
* @TODO: this currently assumes the content profile is of type 'profile'.
* We'll want to make that configurable (later).
*/
function _certificate_get_user_profile($account) {
$uid = $account->uid;
// Curently we're using only using content-profile for this feature.
if (module_exists('content_profile')) {
$profile = content_profile_load('profile', $uid);
return $profile;
}
return FALSE;
}
/**
* Define Fields.
*/
function certificate_fields() {
$field_options = array();
$field_options[] = 'no field';
foreach (content_fields() as $key => $field) {
// If field isn't a profile field with allowed values, do not allow it to be selectable. It wouldn't work anyways.
if ($field['type_name'] == 'profile' && ($field['allowed_values'] != '' || $field['allowed_values_php'] != '')) {
$field_options[$key] = $field['widget']['label'];
}
}
return $field_options;
}
/**
* Get certificate type field.
*
* @return the machine readable field name.
*/
function certificate_get_selected_type() {
// Get selected field.
return variable_get('certificate_field_certificate_type', 0);
}
/**
* Get certificate type field options.
*
* @return the selected field's options as an array.
*/
function certificate_get_selected_type_options() {
// Get selected field name.
$selected = certificate_get_selected_type();
// Add 'Default' to beginning of options array, whether or not an option field is selected.
$field_options = array(
'default' => t('Default'),
);
// Get selected field's options.
if ($selected == 'no field') {
return NULL;
}
else {
$field = content_fields($selected);
// Remove non-keyed values (for instance, if '|Please select' workaround is used).
$allowed_values = content_allowed_values($field);
$keys = $allowed_values ? array_keys($allowed_values) : array();
foreach ($keys as $key) {
if ($key != '') {
$allowed_values_keys[$key] = $allowed_values[$key];
}
}
// Merge allowed values with default option.
$field_options_array = $allowed_values_keys;
}
return $field_options_array;
}
/**
* Implementation of hook_function_load().
*
* Menu load handler for an certificate type.
*/
function certificate_set_load($id) {
$sql = "SELECT * FROM {certificate_types} ct\n left join {node} certificate on certificate.nid = ct.template_id\n WHERE type_id = %d";
$result = db_query($sql, $id);
if ($type = db_fetch_object($result)) {
return $type;
}
else {
return FALSE;
}
}
function certificate_criterion_load($id) {
$sql = "select * from {certificate_criteria} cc\n left join {certificate_types} ct on ct.type_id = cc.type_id\n where cc.check_id = %d";
$query = db_query($sql, $id);
if ($criterion = db_fetch_object($query)) {
$criterion->check_key = unserialize($criterion->check_key);
return $criterion;
}
else {
return FALSE;
}
}
/**
* Public loader function for the full collection of certificates.
*
* In situations where the module's data rarely changes, or is being used
* frequently (for example, loaded and processed on every page load), this
* is a prime candidate for caching. See The Beginner's Guide to Caching at
* http://www.lullabot.com/articles/a_beginners_guide_to_caching_data for more
* details.
*
* @return
* An array of all certificates, keyed by id.
*/
function certificate_certificate_load_all() {
$sql = "SELECT *,nid as cid FROM {node} node where type='certificate'";
$result = db_query($sql);
$certificates = array();
while ($certificate = db_fetch_array($result)) {
$certificates[$certificate['cid']] = $certificate;
}
drupal_alter('certificate_template_options', $certificates);
return $certificates;
}
/**
* Quick get per-node template settings.
*/
function certificate_course_node_template_settings($nid) {
$sql = "SELECT * FROM {certificate_node} WHERE nid = %d";
$result = db_query($sql, $nid);
$node_template_settings = array();
while ($node_template_setting = db_fetch_array($result)) {
$node_template_settings[$node_template_setting['type']] = $node_template_setting['template'];
}
return $node_template_settings;
}
/**
* Implements hook_form_alter for course nodes.
*/
function certificate_form_alter(&$form, &$form_state, $form_id) {
$type = basename($form_id, '_node_form');
if (certificate_node_is_certifiable($form['#node']) && strpos($form_id, '_node_form') !== FALSE) {
// Add per-node certificate settings.
module_load_include('inc', 'certificate', 'certificate.admin');
certificate_alter_node_form($form, $form_state);
}
}
function certificate_form_certificate_node_form_alter(&$form, &$form_state) {
if (module_exists('token')) {
// Embed token help.
$form['certificate_tokens'] = array(
'#title' => 'Certificate tokens',
'#type' => 'fieldset',
'#collapsible' => TRUE,
'#collapsed' => FALSE,
'#value' => theme('token_tree', array(
'global',
'node',
'user',
'certificate',
), FALSE),
);
}
// No preview - we want users to see it in PDF for accuracy.
$form['buttons']['preview'] = NULL;
}
/**
* Submit handler to update node template mappings.
*/
function certificate_update_node_mappings(&$node) {
$node_settings = $node->certificate['node_settings'];
if (is_array($node_settings)) {
db_query("DELETE FROM {certificate_node} WHERE nid = %d", $node->nid);
foreach ($node_settings as $type => $template) {
if ($template == 0) {
continue;
}
db_query("INSERT INTO {certificate_node} (nid, type, template) VALUES (%d, '%s', %d)", $node->nid, $type, $template);
}
}
}
/**
* Implements hook_nodeapi.
*/
function certificate_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
if (certificate_node_is_certifiable($node)) {
switch ($op) {
case 'insert':
case 'update':
if (certificate_node_is_certifiable($node)) {
certificate_update_node_mappings($node);
}
break;
case 'delete':
// Clean up the certificate template tables for the deleted node.
db_query("DELETE FROM {certificate_node} WHERE nid = %d", $node->nid);
db_query("DELETE FROM {certificate_snapshots} WHERE nid = %d", $node->nid);
break;
case 'load':
return array(
'certificate' => array(
'node_settings' => certificate_course_node_template_settings($node->nid),
),
);
break;
case 'view':
if (certificate_can_access_certificate($node)) {
$node->content['certificate']['#value'] = '<span class="certificate-link">' . l(t('Download certificate'), "node/{$node->nid}/certificate") . '</span>';
}
break;
}
}
if ($node->type == 'certificate') {
switch ($op) {
case 'insert':
case 'update':
$record = $node->certificate;
$record['nid'] = $node->nid;
if (db_result(db_query("select 1 from {certificate_node_settings} where nid = %d", $node->nid))) {
$keys = array(
'nid',
);
}
drupal_write_record('certificate_node_settings', $record, $keys);
break;
case 'load':
return array(
'certificate' => db_fetch_array(db_query("select * from {certificate_node_settings} where nid = %d", $node->nid)),
);
}
}
}
/**
* Implementation of hook_content_extra_fields().
* Allow the certificate download link to be sorted in the node edit forms.
*/
function certificate_content_extra_fields($type_name) {
$node->type = $type_name;
if (certificate_node_is_certifiable($node)) {
$extras['certificate'] = array(
'label' => t('Certificate'),
'description' => t('Certificate link.'),
'weight' => 10,
);
}
if ($type_name == 'certificate') {
$extras['certificate_tokens'] = array(
'label' => t('Certificate tokens'),
'description' => t('Tokens to insert into the certificate.'),
);
}
return $extras;
}
/**
* @todo make $types more generic.
*/
function certificate_node_is_certifiable(&$node) {
return variable_get("certificate_certifiable_{$node->type}", 0);
}
/**
* Quick certificates snapshot check.
*
* @param $account
* @param $node
*
* @return
* A single certificate snapshot in array format, or FALSE if none matched the incoming ID.
*/
function certificate_snapshot_load($account, $node) {
$sql = "SELECT * FROM {certificate_snapshots} WHERE uid = %d AND nid = %d";
$result = db_query($sql, $account->uid, $node->nid);
if ($snapshot = db_fetch_array($result)) {
return $snapshot;
}
else {
return FALSE;
}
}
/**
* Inserts a new snapshot, or updates an existing one.
*
* @param $certificate
* A certificate to be saved. If $certificate['cid'] is set, the certificate will be updated.
* Otherwise, a new certificate will be inserted into the database.
* @return
* The saved certificate, with its ID set.
*
* @see certificate_single()
*/
function certificate_snapshot_save($snapshot) {
if (isset($snapshot['csid'])) {
drupal_write_record('certificate_snapshots', $snapshot, 'csid');
}
else {
drupal_write_record('certificate_snapshots', $snapshot);
}
return $snapshot;
}
/**
* Remove snapshot.
*
* @param $account
* @param $node
*
* @return
* true
*/
function certificate_snapshot_delete($account, $node) {
$sql = "DELETE FROM {certificate_snapshots} WHERE uid = %d AND nid = %d";
db_query($sql, $account->uid, $node->nid);
return TRUE;
}
function certificate_snapshot_delete_by_node($node) {
$sql = "DELETE FROM {certificate_snapshots} WHERE nid = %d";
db_query($sql, $node->nid);
return TRUE;
}
/**
* Actions
*/
/**
* Implementation of hook_action_info().
*/
function certificate_action_info() {
$info['certificate_reset_certificates_action'] = array(
'type' => 'node',
'description' => t('Reset certificate snapshots for this event'),
'configurable' => FALSE,
'hooks' => array(
'nodeapi' => array(
'insert',
'update',
),
),
);
return $info;
}
function certificate_reset_certificates_action($object, $context) {
$node = $object;
if ($node->nid && is_numeric($node->nid)) {
certificate_snapshot_delete_by_node($node);
watchdog('action', 'Reset certificate snapshots for: %event.', array(
'%event' => $node->title,
));
}
else {
//print_r("No Node");
}
}
/**
* Check if a user can access a certificate for this node.
*
* This function:
* @return TRUE if certificate tab should show and be accessible.
* @return string (eval to true for Drupal's menu) if certificate tab should
* show but be denied with a message.
* @return FALSE if certificate tab should be hidden.
*/
function certificate_can_access_certificate($node, &$account = NULL) {
static $cert_access = array();
if (!$account) {
global $user;
$account = $user;
}
if (!$account->uid) {
return FALSE;
}
if (!isset($cert_access[$node->nid])) {
$access = module_invoke_all('access_certificate', $node, $account);
$cert_access[$node->nid] = $access;
}
else {
$access = $cert_access[$node->nid];
}
foreach ($access as $item) {
if ($item === TRUE) {
// Something said the leaner should access the certificate.
$found_true = TRUE;
}
if (is_string($item)) {
// Something returned a string, return it (will show the menu, but error)
return $item;
}
if ($item === FALSE) {
$found_false = TRUE;
}
}
if ($found_true) {
if ($found_false) {
// Found TRUE and FALSEs.
return FALSE;
}
// Only found TRUE.
return TRUE;
}
// All were false.
return FALSE;
}
function certificate_user($op, &$edit, &$account, $category = NULL) {
if ($op == 'delete') {
$sql = "delete from {certificate_snapshots} where uid = %d";
db_query($sql, $account->uid);
}
}
/**
* Return an array of certificate templates suitable for use in an options
* form element.
*/
function certificate_get_template_options() {
// Get existing templates.
$templates = certificate_certificate_load_all();
foreach ($templates as $key => $template) {
$template_options[$key] = $template['title'];
}
return $template_options;
}
Functions
Name | Description |
---|---|
certificate_access | Implementation of hook_access(). |
certificate_action_info | Implementation of hook_action_info(). |
certificate_can_access_certificate | Check if a user can access a certificate for this node. |
certificate_certificate_load_all | Public loader function for the full collection of certificates. |
certificate_content_extra_fields | Implementation of hook_content_extra_fields(). Allow the certificate download link to be sorted in the node edit forms. |
certificate_course_node_template_settings | Quick get per-node template settings. |
certificate_criterion_load | |
certificate_fields | Define Fields. |
certificate_form | |
certificate_form_alter | Implements hook_form_alter for course nodes. |
certificate_form_certificate_node_form_alter | |
certificate_get_selected_type | Get certificate type field. |
certificate_get_selected_type_options | Get certificate type field options. |
certificate_get_template_options | Return an array of certificate templates suitable for use in an options form element. |
certificate_help | Implementation of hook_help(). |
certificate_menu | Implementation of hook_menu(). |
certificate_nodeapi | Implements hook_nodeapi. |
certificate_node_info | Implementation of hook_node_info(). |
certificate_node_is_certifiable | @todo make $types more generic. |
certificate_perm | Implementation of hook_perm(). |
certificate_reset_certificates_action | |
certificate_set_load | Implementation of hook_function_load(). |
certificate_snapshot_delete | Remove snapshot. |
certificate_snapshot_delete_by_node | |
certificate_snapshot_load | Quick certificates snapshot check. |
certificate_snapshot_save | Inserts a new snapshot, or updates an existing one. |
certificate_theme | Implementation of hook_theme(). |
certificate_update_node_mappings | Submit handler to update node template mappings. |
certificate_user | |
_certificate_get_user_profile | Helper function to match template to certificate type. |