You are here

pm.module in Drupal PM (Project Management) 7.2

Same filename and directory in other branches
  1. 8 pm.module
  2. 7.3 pm.module
  3. 7 pm.module
  4. 4.x pm.module

Main module file for the Project Management module.

File

pm.module
View source
<?php

/**
 * @file
 * Main module file for the Project Management module.
 */
define('PM_ICON_SET_DEFAULT_BEHAVIOUR', 'default');
define('PM_ICON_SET_FONTAWESOME', 'fontawesome');
define('PM_ICON_SET_STORM', 'storm');
define('PM_ICON_SET_NO_ICON', 'none');

/**
 * Implements hook_help().
 */
function pm_help($path, $arg) {
  $output = '';
  switch ($path) {
    case "admin/help#pm":
      $output = '<p>' . t("Provides a complete project management environment") . '</p>';
      break;
  }
  return $output;
}

/**
 * Implements hook_permission().
 */
function pm_permission() {
  return array(
    'Project Management: access dashboard' => array(
      'title' => t('Access Dashboard'),
      'description' => t('Allows the user to access the Project Management dashboard. The items included on the dashboard are set through permissions on the individual modules that provide those links.'),
    ),
    'Project Management: access administration pages' => array(
      'title' => t('Administer Project Management'),
      'description' => t('Allow the user to perform administrative tasks on Project Management modules, such as altering configuration.'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function pm_menu() {
  $items = array();
  $dashboard_types = module_invoke_all('pm_dashboard_types');
  foreach ($dashboard_types as $type => $type_info) {
    if (isset($type_info['url'])) {
      $title = isset($type_info['title']) ? $type_info['title'] : 'Project Management Dashboard';
      $items[$type_info['url']] = array(
        'title' => $title,
        'description' => $title,
        'page callback' => 'pm_dashboard',
        'page arguments' => array(
          $type,
        ),
        'access arguments' => array(
          'Project Management: access dashboard',
        ),
        'parent' => '',
        'type' => MENU_NORMAL_ITEM,
      );
      if (isset($type_info['menu_options'])) {
        $items[$type_info['url']] = array_merge($items[$type_info['url']], $type_info['menu_options']);
      }
    }
  }
  $items['admin/config/pm'] = array(
    'title' => 'Project Management',
    'description' => 'Project Management settings',
    'page callback' => 'system_admin_menu_block_page',
    'access arguments' => array(
      'Project Management: access administration pages',
    ),
    'file' => 'system.admin.inc',
    'file path' => drupal_get_path('module', 'system'),
  );
  $items['admin/config/pm/pm'] = array(
    'title' => 'Project Management',
    'description' => 'Project Management settings including display and taxation.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'pm_admin_settings',
    ),
    'access arguments' => array(
      'Project Management: access administration pages',
    ),
    'weight' => -100,
  );
  return $items;
}

/**
 * Implements hook_theme().
 */
function pm_theme() {
  return array(
    'pm_dashboard' => array(
      'file' => 'pm.theme.inc',
      'arguments' => array(
        'links' => array(),
      ),
    ),
    'pm_dashboard_block' => array(
      'file' => 'pm.theme.inc',
      'arguments' => array(
        'links' => array(),
      ),
    ),
    'pm_dashboard_link' => array(
      'file' => 'pm.theme.inc',
      'arguments' => array(
        'link_blocks' => array(),
      ),
    ),
    'pm_list_default' => array(
      'template' => 'pm-list-default',
      'variables' => array(
        'value' => NULL,
        'key' => NULL,
        'field_name' => NULL,
      ),
    ),
  );
}

/**
 * Function to create a dashboard (call to theme function).
 *
 * @param string $type
 *   Dashboard type, used for pm_get_dashboard_links.
 *
 * @return string
 *   Themed string.
 */
function pm_dashboard($type = 'page') {
  $types = module_invoke_all('pm_dashboard_types');

  // Only set Page Title if it has a url, so there is a menu entry for that.
  // The block type has no url and shouldn't change the title!
  if (isset($types[$type]['url']) && isset($types[$type]['title'])) {
    drupal_set_title($types[$type]['title']);
  }
  drupal_add_css(drupal_get_path('module', 'pm') . '/pm-dashboard.css');
  $link_blocks = pm_dashboard_get_links(TRUE, $type);
  if (!empty($link_blocks)) {

    // Divide links into two blocks.
    $count = ceil(count($link_blocks) / 2);
    $link_blocks = array_chunk($link_blocks, $count);
  }
  $theme = isset($types[$type]['theme']) ? $types[$type]['theme'] : 'pm_dashboard';
  $content = theme($theme, $link_blocks);
  return $content;
}

/**
 * Return links array for the pm dashboard.
 *
 * @param bool $check_active
 *   When FALSE, returns all links whether active or not (for admin settings).
 * @param string $type
 *   Dashboard type.
 *
 * @return array
 *   Dashboard links.
 */
function pm_dashboard_get_links($check_active = TRUE, $type = 'page') {
  $links = module_invoke_all('pm_dashboard_links', $type);
  if (!empty($links)) {
    $default_dashboard_settings = variable_get('pm_' . $type . 'dashboard_settings', array());
    $weight = 0;
    foreach ($links as $key => &$link_array) {

      // Active check.
      if ($check_active && isset($default_dashboard_settings[$link_array['path']]['active']) && $default_dashboard_settings[$link_array['path']]['active'] == FALSE) {
        unset($links[$key]);
        continue;
      }

      // Module exist check.
      if (isset($link_array['destination_module']) && !module_exists($link_array['destination_module'])) {
        unset($links[$key]);
        continue;
      }

      // Access check.
      if (!drupal_valid_path($link_array['path'])) {
        unset($links[$key]);
      }
      if (isset($default_dashboard_settings[$link_array['path']]['weight'])) {
        $link_array['weight'] = $default_dashboard_settings[$link_array['path']]['weight'];
      }
      elseif (!isset($link_array['weight'])) {
        $link_array['weight'] = $weight;
        $weight++;
      }
    }

    // Hook for altering links.
    drupal_alter('pm_dashboard_links', $links, $type);

    // Sort links by weight.
    uasort($links, '_pm_dashboard_sort_links');
  }
  return $links;
}

/**
 * Orders dashboard links by weight. Helper for pm_dashboard_get_links().
 *
 * @param array $a
 *   Dashboard link array.
 * @param array $b
 *   Dashboard link array.
 *
 * @return int
 *   Relative weight of $a and $b.
 *
 * @see uasort()
 */
function _pm_dashboard_sort_links(array $a, array $b) {
  if (intval($a['weight']) == intval($b['weight'])) {
    return 0;
  }
  elseif (intval($a['weight']) < intval($b['weight'])) {
    return -1;
  }
  else {
    return 1;
  }
}

/**
 * Implements hook_pm_dashboard_links().
 */
function pm_pm_dashboard_links($type) {
  $links = array();
  if ($type == 'page' || $type == 'block') {
    $links[] = array(
      'title' => t('Configuration'),
      'icon' => 'pmconfiguration',
      'path' => 'admin/config/pm',
      'params' => array(),
      'node_type' => '',
      'add_type' => '',
      'map' => array(),
      'weight' => 15,
    );
  }
  return $links;
}

/**
 * Implements hook_pm_dashboard_types().
 */
function pm_pm_dashboard_types() {
  return array(
    'page' => array(
      // URL: menu path which should be used, if omitted no menu item will be
      // created.
      'url' => 'pm',
      // Title: Required. Title of menu item, page title and title for the pm
      // settings.
      'title' => t('Project Management'),
      // Description: Required. Description for the fieldset in the pm
      // settings.
      'description' => t('You can disable or reorder the links from the !dashboard here', array(
        '!dashboard' => l(t('dashboard'), 'pm'),
      )),
      // Theme: theme which should be used to display this dashboard.
      // If omitted uses standard theme pm_dashboard.
      'theme' => 'pm_dashboard',
      // Menu_options: This array will be merged into the default menu item
      // array. If the menu should have special access arguments, title, it can
      // be set here.
      // Page callback and page argument shouldn't been overwritten.
      'menu_options' => array(
        'title' => t('Project Management'),
        'description' => t('Project Management dashboard'),
      ),
    ),
    'block' => array(
      'title' => t('Dashboard block'),
      'description' => t('You can disable or reorder the links from the dashboard !block here', array(
        '!block' => l(t('block'), 'admin/build/block'),
      )),
      'theme' => 'pm_dashboard_block',
    ),
  );
}

/**
 * Implements hook_block_info().
 */
function pm_block_info() {

  // Register Project Management menu block.
  $blocks['pm_menu'] = array(
    'info' => t('Project Management Menu'),
  );
  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function pm_block_view($delta = '') {

  // Define Project Management menu block.
  $block = array();
  switch ($delta) {
    case 'pm_menu':
      $block = array(
        'subject' => 'Project Management',
        'content' => pm_dashboard('block'),
      );
      break;
  }
  return $block;
}

/**
 * Defines the administration settings form for the Project Management module.
 */
function pm_admin_settings() {
  $form = array();
  $w = -10;
  $form['icons'] = array(
    '#type' => 'fieldset',
    '#title' => t('Icons'),
    '#collapsed' => TRUE,
    '#collapsible' => TRUE,
    '#weight' => $w++,
  );
  $icon_options = array(
    PM_ICON_SET_DEFAULT_BEHAVIOUR => t('<strong>Default Behaviour</strong> : Uses PM Legacy icons if fontawesome is not installed.'),
    PM_ICON_SET_FONTAWESOME => t('<strong>fontawesome</strong> : Requires fontawesome module and libraries to be installed.)'),
    PM_ICON_SET_STORM => t('<strong>PM legacy icons</strong> : Deprecated - this option will be removed in a future release)'),
    PM_ICON_SET_NO_ICON => t('<strong>No icons</strong> : The icons that ship with Project Management may not fit well with some themes. If this option is selected, icons will be hidden.'),
  );
  $form['icons']['pm_icon'] = array(
    '#type' => 'radios',
    '#multiple' => FALSE,
    '#title' => t('Project Management icons'),
    '#options' => $icon_options,
    '#default_value' => variable_get('pm_icon', PM_ICON_SET_DEFAULT_BEHAVIOUR),
    '#weight' => $w++,
  );

  // Dashboard settings.
  $form['pm_dashboard_settings'] = array(
    '#type' => 'fieldset',
    '#title' => t('Dashboard settings'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $types = module_invoke_all('pm_dashboard_types');
  foreach ($types as $type => $type_data) {
    $all_links_options = array();
    $all_links = pm_dashboard_get_links(FALSE, $type);
    foreach ($all_links as $link) {
      $all_links_options[$link['path']] = l($link['title'], $link['path']);
    }
    $default_dashboard_settings = variable_get('pm_' . $type . 'dashboard_settings', array());
    $form['pm_dashboard_settings'][$type] = array(
      '#type' => 'fieldset',
      '#title' => $type_data['title'],
      '#description' => $type_data['description'],
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    $form['pm_dashboard_settings'][$type]['dashboard_links'] = array(
      '#infix' => $type,
    );
    $weight = 0;
    foreach ($all_links_options as $path => $title) {
      $form['pm_dashboard_settings'][$type]['dashboard_links'][$path][$type . '_pm_dashboard_link_active_' . $path] = array(
        '#type' => 'checkbox',
        '#title' => $title,
        '#default_value' => isset($default_dashboard_settings[$path]['active']) ? $default_dashboard_settings[$path]['active'] : TRUE,
      );
      $form['pm_dashboard_settings'][$type]['dashboard_links'][$path][$type . '_pm_dashboard_link_weight_' . $path] = array(
        '#type' => 'weight',
        '#default_value' => isset($default_dashboard_settings[$path]['weight']) ? $default_dashboard_settings[$path]['weight'] : $weight,
        '#delta' => 30,
      );
      $form['pm_dashboard_settings'][$type]['dashboard_links'][$path]['#value'] = $title;
      $weight++;
    }
  }
  if (empty($form['#submit'])) {
    $form['#submit'] = array();
  }
  $form['#submit'] = array(
    'pm_admin_settings_form_submit',
  );
  return system_settings_form($form);
}

/**
 * Submit function for admin settings form.
 */
function pm_admin_settings_form_submit($form, $form_state) {
  $op = isset($form_state['values']['op']) ? $form_state['values']['op'] : '';

  // Reset.
  if ($op == t('Reset to defaults')) {
    $types = module_invoke_all('pm_dashboard_types');
    foreach ($types as $type => $type_data) {
      variable_del('pm_' . $type . 'dashboard_settings');
    }
    return;
  }

  // Get options.
  $types = module_invoke_all('pm_dashboard_types');
  foreach ($types as $type => $type_data) {
    $all_links = pm_dashboard_get_links(FALSE, $type);
    $settings = array();
    foreach ($all_links as $link) {
      $path = $link['path'];
      $settings[$path]['active'] = $form_state['values'][$type . '_pm_dashboard_link_active_' . $path];
      $settings[$path]['weight'] = $form_state['values'][$type . '_pm_dashboard_link_weight_' . $path];
    }
    variable_set('pm_' . $type . 'dashboard_settings', $settings);
  }
}

/**
 * Provides an add icon for Project Management nodes.
 */
function pm_icon_add_node($node, $params = array()) {
  return pm_icon_add('node/add/' . $node->type, $params);
}

/**
 * Provides an edit icon for Project Management nodes.
 */
function pm_icon_edit_node($node, $params = array()) {
  return pm_icon_edit('node/' . $node->nid . '/edit', $params);
}

/**
 * Provides a delete icon for Project Management nodes.
 */
function pm_icon_delete_node($node, $params = array()) {
  return pm_icon_delete('node/' . $node->nid . '/delete', $params);
}

/**
 * Provides a Project Management add icon.
 */
function pm_icon_add($path, $params = array()) {
  $attributes = array(
    'class' => array(
      'popups-form',
    ),
  );
  return pm_icon_l('application_add', $path, t('Add'), $params, $attributes);
}

/**
 * Provides a Project Management edit icon.
 */
function pm_icon_edit($path, $params = array()) {
  $attributes = array(
    'class' => array(
      'popups-form',
    ),
  );
  return pm_icon_l('application_edit', $path, t('Edit'), $params, $attributes);
}

/**
 * Provides a Project Management delete icon.
 */
function pm_icon_delete($path, $params = array()) {
  $attributes = array(
    'class' => array(
      'popups-form',
    ),
  );
  return pm_icon_l('application_delete', $path, t('Delete'), $params, $attributes);
}

/**
 * Provides an icon link.
 */
function pm_icon_l($icon, $path, $title, $params = array(), $attributes = array()) {
  if (!drupal_valid_path($path)) {
    return '';
  }
  $icon = pm_icon($icon, $title);
  $attributes['title'] = $title;
  $query = '';
  if (array_key_exists('q', $params)) {
    $destination = $params['q'];
    unset($params['q']);
    $c = 0;
    if (array_key_exists('page', $params)) {
      $destination .= '?page=' . $params['page'];
      unset($params['page']);
      $c++;
    }
    if (array_key_exists('sort', $params)) {
      if ($c) {
        $destination .= '&';
      }
      else {
        $destination .= '?';
      }
      $destination .= 'sort=' . $params['sort'];
      unset($params['sort']);
      $c++;
    }
    if (array_key_exists('order', $params)) {
      if ($c) {
        $destination .= '&';
      }
      else {
        $destination .= '?';
      }
      $destination .= 'order=' . $params['order'];
      unset($params['order']);
      $c++;
    }
    $query .= 'destination=' . urlencode($destination);
    unset($params['destination']);
  }
  return l($icon, $path, array(
    'attributes' => $attributes,
    'html' => TRUE,
    'query' => _pm_icon_urlencode_helper($params),
  ));
}

/**
 * Encodes URL for icon links.
 */
function _pm_icon_urlencode_helper($params, $org_key = "") {
  $new_params = array();
  foreach ($params as $key => $value) {
    if (!empty($org_key)) {
      $new_key = $org_key . "[" . $key . "]";
    }
    else {
      $new_key = $key;
    }
    if (is_array($value)) {
      $new_params = array_merge(_pm_icon_urlencode_helper($value, $new_key), $new_params);
    }
    else {
      $new_params[$new_key] = urlencode($value);
    }
  }
  return $new_params;
}

/**
 * Provides a Project Management icon.
 */
function pm_icon($icon, $title) {

  // Running check_plain() on these variables means that we can call pm_icon()
  // without further sanitising.
  $icon = check_plain($icon);
  $title = check_plain($title);
  $icon = str_replace(' ', '_', $icon);
  if (variable_get('pm_icon', PM_ICON_SET_DEFAULT_BEHAVIOUR) !== PM_ICON_SET_NO_ICON) {
    $fa_icon = pm_helper_get_fa_icon($icon, '');

    // @todo: Should we force default? what if other module handles the icon?
    if (empty($fa_icon)) {
      return pm_icon_default($icon, $title);
    }
    else {
      return $fa_icon;
    }
  }
  else {

    // Icons set to not display.
    return '<span class="pm-no-icon">' . $title . '</span>';
  }
}

/**
 * Forces a recache of Project Management icons.
 */
function pm_icon_recache() {
  $available = array();
  $dir = variable_get('pm_icons_path', drupal_get_path('module', 'pm') . '/icons');
  $files = scandir($dir);
  foreach ($files as $file) {
    $available[] = $file;
  }
  cache_set('pm:icons', $available, 'cache', CACHE_TEMPORARY);
  $available = cache_get('pm:icons');
  return $available;
}

/**
 * Provides a default icon to avoid missing icons.
 */
function pm_icon_default($icon, $title) {

  // For now, just return $title.
  // A future extension could be more intelligent using $icon.
  return $title;
}

/**
 * Set body class to use pm default icons if required.
 */
function pm_preprocess_html(&$vars) {
  $pm_icon = variable_get('pm_icon', PM_ICON_SET_DEFAULT_BEHAVIOUR);
  $font_awesome_enabled = module_exists('fontawesome');
  switch ($pm_icon) {
    case PM_ICON_SET_DEFAULT_BEHAVIOUR:
      $vars['classes_array'][] = $font_awesome_enabled ? "pm-use-fa-icons" : "pm-use-storm-icons";
      break;
    case PM_ICON_SET_FONTAWESOME:
      $vars['classes_array'][] = "pm-use-fa-icons";
      break;
    case PM_ICON_SET_STORM:
      $vars['classes_array'][] = "pm-use-storm-icons";
      break;
  }
}

/**
 * Helper to attach fontawesome icons.
 */
function pm_helper_get_fa_icon($key, $default_class = 'fa_wrench') {
  if (variable_get('pm_icon', PM_ICON_SET_DEFAULT_BEHAVIOUR) == PM_ICON_SET_NO_ICON) {
    return '';
  }
  $key = str_replace(' ', '_', $key);
  $key = str_replace('-', '_', $key);
  switch ($key) {
    case 'pmconfiguration':
      $class = 'fa-gear';
      break;
    case 'pmexpenses':
      $class = 'fa-money';
      break;
    case 'pmnotes':
      $class = 'fa-file-o';
      break;
    case 'pmtimetrackings':
      $class = 'fa-clock-o';
      break;
    case 'pmtickets':
      $class = 'fa-ticket';
      break;
    case 'pmtasks':
      $class = 'fa-tasks';
      break;
    case 'pmprojects':
      $class = 'fa-cubes';
      break;
    case 'pmteams':
      $class = 'fa-users';
      break;
    case 'pmorganizations':
      $class = 'fa-institution';
      break;
    case 'pmissues':
      $class = 'fa-cube';
      break;
    case 'application_add':
      $class = 'fa-plus';
      break;
    case 'application_delete':
      $class = 'fa-remove pm-status-danger-onfocus';
      break;
    case 'application_edit':
      $class = 'fa-edit';
      break;

    // Issue type.
    case 'bug':
      $class = 'fa-bug';
      break;
    case 'task':
      $class = 'fa-tasks';
      break;
    case 'feature_request':
      $class = 'fa-ticket';
      break;
    case 'support':
      $class = 'fa-phone';
      break;

    // Project type.
    case 'development':
      $class = 'fa-flask';
      break;

    // Progress.
    case 'in_progress':
      $class = 'fa-play pm-status-info';
      break;
    case 'completed':
      $class = 'fa-check pm-status-success';
      break;
    case 'on_hold':
      $class = 'fa-pause pm-status-warning';
      break;
    case 'inserted':
      $class = 'fa-square pm-status-normal';
      break;

    // Priority.
    case '1_low':
      $class = 'fa-circle pm-status-info';
      break;
    case '2_normal':
      $class = 'fa-circle pm-status-success';
      break;
    case '3_high':
      $class = 'fa-circle pm-status-warning';
      break;
    case '4_urgent':
      $class = 'fa-circle pm-status-danger';
      break;
    case 'default':
      $class = '';
      break;
    default:

      // @todo: Discuss how to handle other keys.
      return '';
  }
  return "<i class='fa pm-icon {$class} fa-fw'></i>";
}

/**
 * Helper function to return nid of particular bundle in hierarchy.
 *
 * @param object $node
 *   The node whose parent's should be hunted for.
 * @param string $type
 *   The parent node type that is being hunted for.
 * @param int $iteration
 *   Number of maximum iterations to try for.
 *
 * @return int
 *   Node id of the required parent.
 */
function pm_get_parent($node, $type = 'pmorganization', $iteration = 10) {
  try {
    $wrapper = entity_metadata_wrapper('node', $node);
    while ($iteration) {
      $iteration--;
      $bundle = $wrapper
        ->getBundle();
      if ($bundle == $type) {
        return $wrapper
          ->getIdentifier();
      }
      if ($wrapper
        ->__isset($bundle . '_parent')) {
        $parent_field = $bundle . '_parent';
      }
      elseif ($wrapper
        ->__isset('field_' . $bundle . '_parent')) {
        $parent_field = 'field_' . $bundle . '_parent';
      }
      else {
        return FALSE;
      }
      $wrapper = $wrapper->{$parent_field};
    }
  } catch (EntityMetadataWrapperException $exc) {
    watchdog('pm', 'See ' . __FUNCTION__ . '() <pre>' . $exc
      ->getTraceAsString() . '</pre>', NULL, WATCHDOG_ERROR);
  }
}

/**
 * Implements hook_views_api().
 */
function pm_views_api() {
  return array(
    'api' => 3.0,
    'path' => drupal_get_path('module', 'pm') . '/includes/views',
  );
}

/**
 * Implements hook_field_formatter_info().
 */
function pm_field_formatter_info() {
  return array(
    'pm_list_default' => array(
      'label' => t('Project Management Icons'),
      'field types' => array(
        'list_integer',
        'list_float',
        'list_text',
        'list_boolean',
      ),
    ),
  );
}

/**
 * Implements hook_field_formatter_view().
 */
function pm_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array();
  switch ($display['type']) {
    case 'pm_list_default':
      $allowed_values = list_allowed_values($field, $instance, $entity_type, $entity);
      foreach ($items as $delta => $item) {
        $value = '';
        if (isset($allowed_values[$item['value']])) {
          $value = field_filter_xss($allowed_values[$item['value']]);
        }
        else {

          // If no match was found in allowed values, fall back to the key.
          $value = field_filter_xss($item['value']);
        }
        $key = $item['value'];
        $output = theme('pm_list_default', array(
          'value' => $value,
          'key' => $key,
          'field_name' => $instance['field_name'],
        ));
        $element[$delta] = array(
          '#markup' => $output,
        );
      }
      break;
  }
  return $element;
}

Functions

Namesort descending Description
pm_admin_settings Defines the administration settings form for the Project Management module.
pm_admin_settings_form_submit Submit function for admin settings form.
pm_block_info Implements hook_block_info().
pm_block_view Implements hook_block_view().
pm_dashboard Function to create a dashboard (call to theme function).
pm_dashboard_get_links Return links array for the pm dashboard.
pm_field_formatter_info Implements hook_field_formatter_info().
pm_field_formatter_view Implements hook_field_formatter_view().
pm_get_parent Helper function to return nid of particular bundle in hierarchy.
pm_help Implements hook_help().
pm_helper_get_fa_icon Helper to attach fontawesome icons.
pm_icon Provides a Project Management icon.
pm_icon_add Provides a Project Management add icon.
pm_icon_add_node Provides an add icon for Project Management nodes.
pm_icon_default Provides a default icon to avoid missing icons.
pm_icon_delete Provides a Project Management delete icon.
pm_icon_delete_node Provides a delete icon for Project Management nodes.
pm_icon_edit Provides a Project Management edit icon.
pm_icon_edit_node Provides an edit icon for Project Management nodes.
pm_icon_l Provides an icon link.
pm_icon_recache Forces a recache of Project Management icons.
pm_menu Implements hook_menu().
pm_permission Implements hook_permission().
pm_pm_dashboard_links Implements hook_pm_dashboard_links().
pm_pm_dashboard_types Implements hook_pm_dashboard_types().
pm_preprocess_html Set body class to use pm default icons if required.
pm_theme Implements hook_theme().
pm_views_api Implements hook_views_api().
_pm_dashboard_sort_links Orders dashboard links by weight. Helper for pm_dashboard_get_links().
_pm_icon_urlencode_helper Encodes URL for icon links.

Constants

Namesort descending Description
PM_ICON_SET_DEFAULT_BEHAVIOUR @file Main module file for the Project Management module.
PM_ICON_SET_FONTAWESOME
PM_ICON_SET_NO_ICON
PM_ICON_SET_STORM