' . t('Welcome to !suitedesk, my own web based app for planning, knowledge sharing, clients support, collaboration and personal productivity, with both powerful and simplicity in mind.', array('!suitedesk' => 'SuiteDesk')) . '
'; $output .= '' . t('As a customer, you will have direct access to !suitedesk on any device to keep track your project(s), view online documentation, report project issues or access billing information.', array('!suitedesk' => 'SuiteDesk')) . '
' . t('Keep track of everything, with visual indicators and Gantt charts to monitorize tasks and subtasks in order to stay up to date with milestones, track of time, workflows and all that requires your attention.') . '
'; $output .= '' . t('Documents are "web documents", availables wherever you are. Use the book project to keep project requeriments, attached files, install and user guides, or meeting minutes at your fingertips.') . '
'; $output .= '' . t('You can report and interact on every issue that arise in your project and easily track it and get all needed information until get fixed and tested.') . '
'; $output .= '' . t('!suitedesk is optimized to look great on mobile devices thanks to its !rwd. All pages adapt automatically to the screen size on a mobile phone, tablet or desktop computer.', array('!suitedesk' => 'SuiteDesk', '!rwd' => '' . t('responsive design') . '')) . '
'; $output .= '' . t("Provides a complete project management environment") . '
'; break; case "admin/help#stormattribute": $output = '' . t("Provides attributes support for SuiteDesk") . '
'; $output .= '' . t("Price Modes - Price modes are used calculate the price of the SuiteDesk node when added to an invoice. A price mode can be added to any SuiteDesk node type and any type can be added to an invoice. When a node is added to an invoice it looks for a price mode in the following order:") . '
'; $output .= '' . t("Ticket, Task, Project, Organization.") . '
'; $output .= '' . t("It will take the price mode for it's current node or the first valid node type above in it's tree. e.g. For a task node type, if that node doesn't have a price mode it will look at the project and then the organization and take the first one it finds. This means you can define a price mode for the organization and it will be used for all nodes under that organization unless it's given a different one.") . '
'; $output .= '' . t("The following price modes keys are defined:") . '
';
$output .= '
' . t('The following table shows all users that have SuiteDesk notifications enabled.') . '
'); $form['users'] = array(); $result = db_query('SELECT u.uid, u.name, u.mail, n.* FROM {users} u LEFT JOIN {notify} n ON u.uid = n.uid WHERE n.status = 1 AND u.status = 1 ORDER BY u.name'); while ($notify = db_fetch_object($result)) { $form['users'][$notify->uid] = array(); $form['users'][$notify->uid]['name'] = array('#type' => 'markup', '#value' => theme('username', $notify)); $form['users'][$notify->uid]['mail'] = array('#type' => 'markup', '#value' => $notify->mail); $form['users'][$notify->uid]['node'] = array('#type' => 'checkbox', '#default_value' => $notify->node); $form['users'][$notify->uid]['comment'] = array('#type' => 'checkbox', '#default_value' => $notify->comment); $form['users'][$notify->uid]['attempts'] = array('#type' => 'textfield', '#size' => 2, '#default_value' => $notify->attempts ? intval($notify->attempts) : 0); } $form['submit'] = array('#type' => 'submit', '#value' => t('Save settings')); return $form; } function storm_notify_user_settings_form(&$form_state, $arg) { global $user; if ($user->uid != $arg->uid && !$_SESSION['deskmenu'][1]) { drupal_access_denied(); return; } $account = user_load(array('uid' => $arg->uid)); if (!is_object($account)) { drupal_not_found(); return; } drupal_set_title(check_plain($account->name)); $result = db_query('SELECT u.uid, u.name, u.mail, n.status, n.node, n.comment FROM {users} u LEFT JOIN {notify} n ON u.uid = n.uid WHERE u.uid = %d AND u.status = 1', $account->uid); $notify = db_fetch_object($result); $form = array(); if (!$notify->mail) { drupal_set_message(t('Your e-mail address must be specified on your my account page.', array('@url' => url('user/'. $account->uid .'/edit'))), 'error'); } $form['notify_page_master'] = array('#type' => 'fieldset', '#title' => t('SuiteDesk notifications')); $form['notify_page_master']['status'] = array('#type' => 'radios', '#title' => t('Notify status'), '#default_value' => $notify->status, '#options' => array(t('Disabled'), t('Enabled')), '#description' => t('Do you wish to receive periodic e-mails when new content is posted?'), ); $form['notify_page_master']['node'] = array('#type' => 'radios', '#title' => t('Notify new content'), '#default_value' => $notify->node, '#options' => array(t('Disabled'), t('Enabled')), '#description' => t('Include new posts in the notification mail.'), ); $form['notify_page_master']['comment'] = array('#type' => 'radios', '#title' => t('Notify new comments'), '#default_value' => $notify->comment, '#options' => array(t('Disabled'), t('Enabled')), '#description' => t('Include new comments in the notification mail.'), ); $form['uid'] = array('#type' => 'value', '#value' => $account->uid); $form['submit'] = array('#type' => 'submit', '#value' => t('Save settings')); return $form; } function storm_notify_user_settings_form_submit($form, &$form_state) { unset($form); db_query('DELETE FROM {notify} WHERE uid = %d', $form_state['values']['uid']); db_query('INSERT INTO {notify} (uid, status, node, comment) VALUES (%d, %d, %d, %d)', $form_state['values']['uid'], $form_state['values']['status'], $form_state['values']['node'], $form_state['values']['comment']); drupal_set_message(t('Notify settings saved.')); } function storm_notify_admin_users_submit($form, &$form_state) { unset($form); if ($form_state['values']['users']) { foreach ($form_state['values']['users'] as $uid => $settings) { db_query('UPDATE {notify} SET node = %d, comment = %d, attempts = %d WHERE uid = %d', $settings['node'], $settings['comment'], $settings['attempts'], $uid); } } drupal_set_message(t('Notify settings saved.')); } /* function _storm_chamilo_settings() { return drupal_get_form('_storm_chamilo_settings_form'); } function _storm_chamilo_settings_form() { $form['chamilo_sso_protocol'] = array( '#type' => 'radios', '#title' => t('SSO Server Protocol'), '#options' => array('http://', 'https://'), '#default_value' => variable_get('chamilo_sso_protocol', 0), ); $form['chamilo_server'] = array( '#type' => 'textfield', '#title' => t('Application URL and Path'), '#description' => t('NOTICE: Do NOT use trailing slash nor http://. i.e: yourchamilosite.com'), '#default_value' => variable_get('chamilo_server', ''), ); return system_settings_form($form); } */ function storm_theme() { return array( 'storm_form_group' => array( 'file' => 'storm.theme.inc', 'arguments' => array('header', 'form'), ), 'datetime' => array( 'file' => 'storm.theme.inc', 'arguments' => array('element'), ), 'dateext' => array( 'file' => 'storm.theme.inc', 'arguments' => array('element'), ), 'storm_link' => array( 'file' => 'storm.theme.inc', 'arguments' => array('source_module', 'destination_module', 'node_nid', 'weight'), ), 'storm_list_report' => array( 'file' => 'storm.theme.inc', 'arguments' => array('header', 'rows', 'title', 'footer', 'headtitle'), ), 'storm_report' => array( 'file' => 'storm.theme.inc', 'arguments' => array('header', 'content', 'title', 'footer'), ), 'storm_view_item' => array( 'file' => 'storm.theme.inc', 'arguments' => array('label', 'value'), ), 'storm_dashboard' => array( 'file' => 'storm.theme.inc', 'arguments' => array('links' => array()), ), 'storm_dashboard_block' => array( 'file' => 'storm.theme.inc', 'arguments' => array('links' => array()), ), 'storm_dashboard_link' => array( 'file' => 'storm.theme.inc', 'arguments' => array('link_blocks' => array()), ), 'storm_dashboard_links_weight_table' => array( 'file' => 'storm.theme.inc', 'arguments' => array('form' => array()), ), 'storm_number_items' => array( 'file' => 'storm.theme.inc', 'arguments' => array('number' => ''), ), 'storm_attribute_list' => array( 'file' => 'storm.theme.inc', 'arguments' => array('form'), ), 'storm_notify_admin_users' => array( 'file' => 'storm.theme.inc', 'arguments' => array('form' => NULL) ), ); } /** * Register a node form field for alteration by modules implementing the * hook_form_field_alter() hook. * * The mother of the lamb :) * * See https://drupal.org/node/823858 */ function storm_form_field_alter_register(&$fields, $name) { foreach (element_children($fields) as $key) { if (isset($fields[$key]) && ($fields[$key]['#name'] == $name || $fields[$key]['#field_name'] == $name || $fields[$key]['#group_name'] == $name)) { foreach (module_implements('form_field_alter') as $module) { call_user_func_array($module . '_form_field_alter', array($name, &$fields[$key])); } } else { storm_form_field_alter_register($fields[$key], $name, $callback); } } } /** * Function to create a dashboard (call to theme function) * * @param string $type dashboard type, used for storm_get_dashboard_links * @param null|string $theme Theme function to use, if omitted it uses storm_dashboard * @return string themed string */ function storm_dashboard($type = 'page') { $types = module_invoke_all('storm_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', 'storm') .'/storm-dashboard.css'); $link_blocks = storm_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'] : 'storm_dashboard'; $content = theme($theme, $link_blocks); return $content; } /** * Return links array for the storm dashboard. * * @param bool $check_active when FALSE, returns all links, no matter if activated or not (needed for admin settings) * @param string $type * @return array dashboard links */ function storm_dashboard_get_links($check_active = TRUE, $type = 'page') { $links = module_invoke_all('storm_dashboard_links', $type); if (!empty($links)) { $default_dashboard_settings = variable_get('storm_'. $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 (!empty($link_array['access_callback'])) { if (function_exists($link_array['access_callback'])) { if (!isset($link_array['access_arguments'])) { $link_array['access_arguments'] = ""; } // USE THE ACCESS CHECK OF THE MENU API _menu_check_access($link_array, $link_array['map']); } } elseif (isset($link_array['access_arguments'])) { $link_array['access'] = user_access($link_array['access_arguments']); } else { $link_array['access'] = TRUE; } if (!$link_array['access']) { 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('storm_dashboard_links', $links, $type); // SORT LINKS BY WEIGHT uasort($links, '_storm_dashboard_sort_links'); } return $links; } /** * Helper function for storm_dashboard_get_links(). * Order dashboard links by their weight. * This is a uasort callback function. * * @see uasort() * @param array $a dashboard link array * @param array $b dashboard link array * @return int */ function _storm_dashboard_sort_links($a, $b) { if (intval($a['weight']) == intval($b['weight'])) { return 0; } elseif (intval($a['weight']) < intval($b['weight'])) { return -1; } else { return 1; } } function storm_storm_dashboard_links($type) { $links = array(); if ($type == 'page' || $type == 'block') { $links[] = array( 'theme' => 'storm_dashboard_link', 'title' => t('Desktop'), 'icon' => 'stormoptions', 'path' => '/', 'access_arguments' => 'access content', 'weight' => -10, ); /* if (module_exists('storm_dashboard')) { $links[] = array( 'theme' => 'storm_dashboard_link', 'title' => t('Desktop'), 'icon' => 'stormknowledgebase', 'path' => 'stormdashboard', 'access_arguments' => 'create stormdoc content', 'weight' => -9, ); } if ($_GET['q'] == 'admin/settings/storm' || !empty($_SESSION['SuiteCRM_Session_ID'])) { $links[] = array( 'theme' => 'storm_dashboard_link', 'title' => 'SuiteCRM', 'icon' => 'stormknowledgebase', 'path' => 'crm', 'weight' => -8, ); } */ $links[] = array( 'theme' => 'storm_dashboard_link', 'title' => t('Tasks Kanban'), 'icon' => 'stormkanban', 'path' => 'tasks/kanban', 'access_arguments' => 'Storm task: access', 'weight' => 5, ); $links[] = array( 'theme' => 'storm_dashboard_link', 'title' => t('Attributes'), 'icon' => 'stormattributes', 'path' => 'attributes', 'params' => array(), 'access_arguments' => 'Storm: access administration pages', 'map' => array(), 'weight' => 14, ); $links[] = array( 'title' => t('Configuration'), 'icon' => 'stormconfiguration', 'path' => 'admin/settings/storm', 'params' => array(), 'access_arguments' => 'Storm: access administration pages', 'node_type' => '', 'add_type' => '', 'map' => array(), 'weight' => 15, ); /* $links[] = array( 'theme' => 'storm_dashboard_link', 'title' => t('My calendar'), 'icon' => 'stormevent', 'path' => 'calendar', 'params' => array(), 'access_arguments' => 'create stormevent content', 'node_type' => 'stormevent', 'add_type' => 'stormevent', 'map' => array(), 'weight' => 21, ); */ $links[] = array( 'theme' => 'storm_dashboard_link', 'title' => t('Glossary'), 'icon' => 'stormglossary', 'path' => 'lexicon', 'access_arguments' => 'access lexicon', 'weight' => 22, ); $links[] = array( 'theme' => 'storm_dashboard_link', 'title' => t('FAQ'), 'icon' => 'stormfaq', 'path' => 'faq', 'access_arguments' => 'view faq page', 'weight' => 23, ); $links[] = array( 'theme' => 'storm_dashboard_link', 'title' => t('Watcher'), 'icon' => 'stormwatcher', 'path' => 'user/watcher', 'access_arguments' => 'use watcher', 'weight' => 24, ); $links[] = array( 'theme' => 'storm_dashboard_link', 'title' => t('Trash'), 'icon' => 'stormtrash', 'path' => 'trash', 'access_arguments' => 'Storm: access trash', 'weight' => 25, ); } return $links; } /** * Implementation of hook_storm_dashboard_types(). * Defines dashboard types page and block. * This can be used as an example for other types * @return array */ function storm_storm_dashboard_types() { return array( /* 'page' => array( // URL: menu path which should be used, if omitted no menu item will be created 'url' => 'dashboard', // title: Required. Title of menu item, page title and title for the storm settings 'title' => t('SuiteDesk'), // description: Required. Description for the fieldset in the storm settings 'description' => t('You can disable or reorder the links from the !dashboard here', array('!dashboard' => l(t('dashboard'), 'dashboard'))), // theme: theme which should be used to display this dashboard. If omitted uses standard theme storm_dashboard 'theme' => 'storm_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('SuiteDesk'), 'description' => t('SuiteDesk dashboard'), ), ), */ 'block' => array( 'title' => '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' => 'storm_dashboard_block', ), ); } /** * Implements hook_filter(). */ function storm_filter($op, $delta = 0, $format = -1, $text = '', $cache_id = 0) { if ($op == 'list') { return array(0 => t('Empty paragraph killer')); } elseif ($delta == 0) { switch ($op) { case 'description': return t('Content editors/creators sometimes hit the carriage return twice at the end of a paragraph. This may not be in keeping with the look and feel of your site. When entering more than one carriage return, this filter will ensure that only the first will be honored.'); case 'no cache': // This case can be removed for most filters, // but returning TRUE is useful for development. return TRUE; case 'prepare': return $text; case 'process': // Empty paragraph killer filter. $text = preg_replace('#]*>(\s| ?)*
#', '', $text); return $text; } } } /** * Implements hook_form_alter(). */ function storm_form_alter(&$form, $form_state, $form_id) { if (stristr($form_id, 'node_form')) { $node = $form['#node']; $types = node_get_types(); if (empty($node->nid)) { drupal_set_title(t('Create ' . $types[$node->type]->name)); } if (!empty($form['title']['#title'])) { $form['title']['#title'] = t($form['title']['#title']); } if (!empty($form['body_field']['body']['#title'])) { $form['body_field']['body']['#title'] = t($form['body_field']['body']['#title']); } // Hide body field show summary: if (isset($form['body_field']['teaser_include'])) { unset($form['body_field']['teaser_include']); } } if ($form_id == 'node_type_form' && isset($form['identity']['type'])) { // Allow SuiteDesk node edition in a block per content type: $form['stormblock'] = array( '#type' => 'fieldset', '#title' => t('SuiteDesk Block'), '#collapsible' => TRUE, '#collapsed' => TRUE, ); $form['stormblock']['stormblock_expose'] = array( '#type' => 'checkbox', '#title' => t('Enable data entry from a block'), '#default_value' => variable_get('stormblock_expose_'. $form['#node_type']->type, 0), '#description' => t('Enable this option to make the entry form for this content type available as a block.'), ); $form['stormblock']['stormblock_show_help'] = array( '#type' => 'checkbox', '#title' => t('Show submission guidelines'), '#default_value' => variable_get('stormblock_show_help_'. $form['#node_type']->type, 0), '#options' => $options, '#description' => t('Enable this option to show the submission guidelines in the block above the form.'), '#process' => array('stormblock_dependent_process'), '#dependency' => array('edit-stormblock-expose' => array('1')), ); // Node type edit form, add checkbox to activate trash: $form['workflow']['trash_settings'] = array( '#type' => 'checkboxes', '#title' => t('Trash'), '#description' => t('If the trash is enabled for this node type, nodes will be moved to trash instead of being deleted. To permanently delete them you need to delete them from the !trash.', array('!trash' => l(t('trash'), 'trash'))), '#options' => array( 'enabled' => t('Enable trash'), ), '#weight' => 5, '#default_value' => variable_get('trash_settings_' . $form['#node_type']->type, array()), ); } if (isset($form['type']) && $form_id == $form['type']['#value'] . '_node_form') { // Node editing form. Add classes to node form: $class = isset($form['#attributes']['class']) ? $form['#attributes']['class'] . ' ' : NULL; $class .= $form_id; $form['#attributes']['class'] = $class; foreach ($form as $key => $elem) { if (is_array($elem) && (isset($elem['#type']) ? $elem['#type'] : NULL) == 'fieldset') { $class = (isset($elem['#attributes']['class'])) ? $elem['#attributes']['class'] . ' ' : NULL; $class .= $key; $form[$key]['#attributes']['class'] = $class; } } // Check if node is edited and it is an affected type for trash nodes: if ($form['nid']['#value'] && _storm_trash_enabled($form['type']['#value'])) { $form['buttons']['delete']['#value'] = t('Move to trash'); } // Disable fields for tickets and tasks comments: if ($form['nid']['#value'] && in_array($form['type']['#value'], array('stormticketc', 'stormtaskc'))) { $form['#after_build'][] = 'storm_node_form_after_build'; } } } function storm_node_form_after_build($form, &$form_state) { $v = 'value'; $a = '#attributes'; $g = 'group_' . $form['type']['#value'] . '_data'; // https://www.silviogutierrez.com/blog/making-cck-fields-read-only-drupal-6: switch ($form['type']['#value']) { case 'stormticketc': # Title: $form[$g]['field_stormticketc_title'][0][$v][$a]['readonly'] = 'readonly'; $form[$g]['field_stormticketc_title'][0][$v][$a]['onclick'] = 'blur();'; $form[$g]['field_stormticketc_title'][0][$v][$a]['style'] = 'cursor: not-allowed;'; # Category: $form[$g]['field_stormticketc_category'][$v][$a]['disabled'] = 'disabled'; # Status: $form[$g]['field_stormticketc_status'][$v][$a]['disabled'] = 'disabled'; # Priority: $form[$g]['field_stormticketc_priority'][$v][$a]['disabled'] = 'disabled'; # Assigned: $form[$g]['field_stormticketc_assigned'][$v][$a]['readonly'] = 'readonly'; $form[$g]['field_stormticketc_assigned'][$v][$a]['onclick'] = 'return false;'; $form[$g]['field_stormticketc_assigned'][$v][$a]['style'] = 'cursor: not-allowed;'; break; case 'stormtaskc': # Title: $form[$g]['field_stormtaskc_title'][0][$v][$a]['readonly'] = 'readonly'; $form[$g]['field_stormtaskc_title'][0][$v][$a]['onclick'] = 'blur();'; $form[$g]['field_stormtaskc_title'][0][$v][$a]['style'] = 'cursor: not-allowed;'; # Category: $form[$g]['field_stormtaskc_category'][$v][$a]['disabled'] = 'disabled'; # Status: $form[$g]['field_stormtaskc_status'][$v][$a]['disabled'] = 'disabled'; # Priority: $form[$g]['field_stormtaskc_priority'][$v][$a]['disabled'] = 'disabled'; } return $form; } /** * Implements hook_form_FORM_ID_alter(). * Alter form id node_delete_confirm at node.pages.inc * URL: node/%/delete */ function storm_form_node_delete_confirm_alter(&$form, &$form_state) { $node = node_load($form['nid']['#value']); if ($node->status == STATUS_TRASH) { drupal_set_title(t('Trash: @title', array('@title' => $node->title))); if (user_access('Storm: access trash')) { $deleted = '' . t('This content has been moved to the !trash.', array('!trash' => l(t('trash'), 'trash'))) . '
'; } else { $deleted = '' . t('This content has been moved to the trash.') . '
'; } if (node_access('delete', $node)) { $deleted .= '' . t('You can !restore the !lastest.', array('!restore' => l(t('restore'), 'trash/' . $node->nid . '/restore'), '!lastest' => l(t('lastest version'), 'node/' . $node->nid))) . '
'; $deleted .= '' . t('You can permanently !delete this content.', array('!delete' => l(t('delete'), 'trash/' . $node->nid . '/delete'))) . '
'; } unset($form['description']); unset($form['actions']); $form['node_trash_deleted'] = array( '#value' => $deleted ); } else { if (_storm_trash_enabled($node->type)) { drupal_set_title(t('Are you sure you want to move %title to the trash?', array('%title' => $node->title))); $form['log'] = array( '#type' => 'textfield', '#title' => t('Log message'), '#default_value' => t('Moved to trash'), '#weight' => -1, ); $form['description']['#value'] = t('The node will be moved to the !trash where it can be restored or permanently deleted.', array('!trash' => l(t('trash'), 'trash'))); $form['actions']['submit']['#value'] = t('Move to trash'); } $form['actions']['submit']['#submit'][] = 'storm_form_node_delete_confirm_submit'; } } function storm_form_node_delete_confirm_submit(&$form, &$form_state) { if ($form_state['values']['confirm']) { $delete = TRUE; $redirect = '' . l(t('Empty trash'), "trash/empty") . '
'; } } else { $output .= '' . t('The trash is empty.') . '
'; } return $output; } /** * Empty trash confirmation form. */ function storm_empty_trash_confirm(&$form_state) { return confirm_form($form, t('Are you sure you want to empty the trash?', array('%title' => $node->title)), isset($_GET['destination']) ? $_GET['destination'] : 'trash', t('This action cannot be undone. Only contents with delete permission will be deleted.'), t('Empty trash'), t('Cancel')); } /** * Empty trash confirmation form submit handler. */ function storm_empty_trash_confirm_submit($form, &$form_state) { if ($form_state['values']['confirm']) { $result = db_query("SELECT n.nid FROM {node} n WHERE n.status = %d", STATUS_TRASH); while ($node = db_fetch_object($result)) { node_delete($node->nid); } } $form_state['redirect'] = 'trash'; } /** * Implementation of hook_block(). */ function storm_block($op = 'list', $delta = 0) { switch ($op) { // Declare the list of blocks to create: case 'list' : $blocks = array(); $blocks['storm_dashboard_block']['info'] = t('SuiteDesk dashboard block'); if (module_exists('recently_read')) { $blocks['storm_recent_nodes']['info'] = t('Recent SuiteDesk nodes'); } foreach (node_get_types('names') as $type => $name) { if (variable_get('stormblock_expose_'. $type, 0)) { $blocks[$type] = array( 'info' => t('@name form block', array('@name' => $name)), 'cache' => BLOCK_NO_CACHE, ); } } return $blocks; // Assign the content for the listed block: case 'view': switch ($delta) { case 'storm_dashboard_block': $block = array( 'subject' => t('Shortcuts'), 'content' => storm_dashboard('block'), ); return $block; case 'storm_recent_nodes': $block = array( 'subject' => t('Recent hits on nodes'), 'content' => storm_block_recent_nodes(), ); return $block; default: return storm_get_block($delta); } return NULL; } } /** * Generate a block containing a node entry form. */ function storm_get_block($type) { if (node_access('create', $type) && variable_get('stormblock_expose_'. $type, 0)) { // Include page handler for node_add() module_load_include('inc', 'node', 'node.pages'); // Note title before rendering of form. $title = drupal_get_title(); $form = node_add($type); // Restore title, which will have been overridden. drupal_set_title($title); $node_type = node_get_types('type', $type); $help = ''; if (variable_get('stormblock_show_help_'. $type, 0)) { $help = (!empty($node_type->help) ? ''. filter_xss_admin($node_type->help) .'
' : ''); } return array( 'subject' => t('@type form', array('@type' => $node_type->name)), 'content' => $help . $form, ); } } /** * Process callback to add dependency to form items. */ /* function storm_dependent_process($element, $edit, &$form_state, &$form) { if (isset($element['#dependency'])) { if (!isset($element['#dependency_count'])) { $element['#dependency_count'] = 1; } if (!isset($element['#dependency_type'])) { $element['#dependency_type'] = 'hide'; } $js = array( 'values' => $element['#dependency'], 'num' => $element['#dependency_count'], 'type' => $element['#dependency_type'], ); if (!empty($form_state['ajax'])) { $form_state['js settings']['stormblock']['dependent'][$element['#id']] = $js; } else { $path = drupal_get_path('module', 'storm'); drupal_add_js($path .'/storm.js', 'module', 'header'); $options['stormblock']['dependent'][$element['#id']] = $js; drupal_add_js($options, 'setting'); } } return $element; } */ function storm_block_recent_nodes() { global $user; $content = ''; $count_items_1 = 0; $count_items_2 = 0; if (module_exists('recently_read')) { // Disable page caching if this block is displayed: recently_read_disable_page_cache(); $items = recently_read_get_read_items(array( 'stormorganization', 'stormperson', 'stormproject', 'stormtask', 'stormticket', 'stormtimetracking', 'stormexpense', 'storminvoice', 'stormevent'), $user->uid, 14); $count_items_1 = count($items); if ($count_items_1) { $content .= theme('recently_read_item_list', $items); } $items = recently_read_get_read_items(array('stormdok', 'stormnote'), $user->uid, 14); $count_items_2 = count($items); if ($count_items_2) { $content .= theme('recently_read_item_list', $items); } } if ($count_items_1 + $count_items_2 == 0) { $content = '' . t('Nothing has been read yet.') . '
'; } return $content; } /** * @function * Defines the administration settings form for the SuiteDesk module */ function storm_admin_settings() { $form = array(); $w = -10; $form['icons'] = array( '#type' => 'fieldset', '#title' => t('Icons'), '#collapsed' => TRUE, '#collapsible' => TRUE, '#weight' => $w++, ); $form['icons']['storm_icons_display'] = array( '#type' => 'checkbox', '#title' => t('Display SuiteDesk icons'), '#default_value' => variable_get('storm_icons_display', TRUE), '#description' => t('The icons that ship with SuiteDesk may not fit well with some themes. If this box is unchecked, icons will be hidden.'), '#weight' => $w++, ); $form['icons']['storm_icons_path'] = array( '#type' => 'textfield', '#title' => t('Icons directory'), '#default_value' => variable_get('storm_icons_path', drupal_get_path('module', 'storm') .'/icons'), '#description' => t("The directory that contains SuiteDesk's icons."), '#weight' => $w++, '#element_validate' => array('storm_admin_settings_icons_path_validate'), ); $form['lists'] = array( '#type' => 'fieldset', '#title' => t('Lists'), '#collapsed' => TRUE, '#collapsible' => TRUE, '#weight' => $w++, ); $form['lists']['storm_default_items_per_page'] = array( '#type' => 'textfield', '#title' => t('Default Items per Page'), '#default_value' => variable_get('storm_default_items_per_page', 10), '#description' => t('Default items per page when viewing lists'), '#size' => 5, '#weight' => $w++ ); $form['reports'] = array( '#type' => 'fieldset', '#title' => t('Reports'), '#collapsed' => TRUE, '#collapsible' => TRUE, '#weight' => $w++, ); $form['reports']['storm_report_header'] = array( '#type' => 'textarea', '#title' => t('Report header'), '#default_value' => variable_get('storm_report_header', ''), '#description' => t('The header that will appear on SuiteDesk reports'), '#weight' => $w++, ); $form['yearsrange'] = array( '#type' => 'fieldset', '#title' => t('Years range in dates'), '#collapsed' => TRUE, '#collapsible' => TRUE, '#weight' => $w++, ); $form['yearsrange']['group0'] = array( '#type' => 'markup', '#theme' => 'storm_form_group', '#weight' => $w++, ); $form['yearsrange']['group0']['storm_yearsrangebegin'] = array( '#type' => 'select', '#title' => t('Begin'), '#options' => drupal_map_assoc(range(1970, 2037)), '#default_value' => variable_get('storm_yearsrangebegin', 2001), ); $form['yearsrange']['group0']['storm_yearsrangeend'] = array( '#type' => 'select', '#title' => t('End'), '#options' => drupal_map_assoc(range(1970, 2037)), '#default_value' => variable_get('storm_yearsrangeend', 2015), ); $form['taxation'] = array( '#type' => 'fieldset', '#title' => t('Taxation defaults'), '#collapsed' => TRUE, '#collapsible' => TRUE, '#weight' => $w++, ); $form['taxation']['storm_tax1_app'] = array( '#type' => 'select', '#title' => t('Tax 1: Application'), '#default_value' => variable_get('storm_tax1_app', 1), '#description' => t('The method of application to use for Tax 1'), '#options' => array( 1 => t('Apply to item amount'), 0 => t('Do not apply tax'), ), '#weight' => $w++, ); $form['taxation']['group0'] = array( '#type' => 'markup', '#theme' => 'storm_form_group', '#weight' => $w++, ); $form['taxation']['group0']['storm_tax1_name'] = array( '#type' => 'textfield', '#title' => t('Tax 1: Name'), '#default_value' => variable_get('storm_tax1_name', 'VAT'), '#description' => t('The name to use for Tax 1'), '#weight' => $w++, ); $form['taxation']['group0']['storm_tax1_percent'] = array( '#type' => 'textfield', '#title' => t('Tax 1: Default percentage'), '#default_value' => variable_get('storm_tax1_percent', 20), '#description' => t('Default percentage for Tax 1'), '#size' => 20, '#weight' => $w++ ); $form['taxation']['storm_tax2_app'] = array( '#type' => 'select', '#title' => t('Tax 2: Application'), '#default_value' => variable_get('storm_tax2_app', 0), '#description' => t('The method of application to use for Tax 2'), '#options' => array( 2 => t('Apply to total of item amount plus previous tax'), 1 => t('Apply to item amount'), 0 => t('Do not apply tax'), ), '#weight' => $w++, ); $form['taxation']['group1'] = array( '#type' => 'markup', '#theme' => 'storm_form_group', '#weight' => $w++, ); $form['taxation']['group1']['storm_tax2_name'] = array( '#type' => 'textfield', '#title' => t('Tax 2: Name'), '#default_value' => variable_get('storm_tax2_name', 'Tax 2 Name'), '#description' => t('The name to use for Tax 2'), '#weight' => $w++, ); $form['taxation']['group1']['storm_tax2_percent'] = array( '#type' => 'textfield', '#title' => t('Tax 2: Default percentage'), '#default_value' => variable_get('storm_tax2_percent', 20), '#description' => t('Default percentage for Tax 2'), '#size' => 20, '#weight' => $w++, ); $form['taxation']['storm_tax_display'] = array( '#type' => 'checkbox', '#title' => t('Display tax edit fields'), '#default_value' => variable_get('storm_tax_display', TRUE), '#description' => t('If disabled, all tax fields will use the default values and you will not be able to override them for any nodes until this setting is enabled again.'), '#weight' => $w++, ); $form['taxation']['storm_tax2_display'] = array( '#type' => 'checkbox', '#title' => t('Display tax 2 edit fields'), '#default_value' => variable_get('storm_tax2_display', TRUE), '#description' => t('If disabled, tax 2 fields will use the default values and you will not be able to override them for any nodes until this setting is enabled again. This setting will be ignored unless the general "Display tax edit fields" setting is enabled above.'), '#weight' => $w++, ); // DASHBOARD SETTINGS $form['storm_dashboard_settings'] = array( '#type' => 'fieldset', '#title' => t('Dashboard settings'), '#collapsible' => TRUE, '#collapsed' => TRUE, ); $types = module_invoke_all('storm_dashboard_types'); foreach ($types as $type => $type_data) { $all_links_options = array(); $all_links = storm_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('storm_'. $type .'dashboard_settings', array()); $form['storm_dashboard_settings'][$type] = array( '#type' => 'fieldset', '#title' => t($type_data['title']), '#description' => $type_data['description'], '#collapsible' => TRUE, '#collapsed' => TRUE, ); $form['storm_dashboard_settings'][$type]['dashboard_links'] = array( '#theme' => 'storm_dashboard_links_weight_table', '#infix' => $type, ); $weight = 0; foreach ($all_links_options as $path => $title) { $form['storm_dashboard_settings'][$type]['dashboard_links'][$path][$type .'_storm_dashboard_link_active_'. $path] = array( '#type' => 'checkbox', '#default_value' => isset($default_dashboard_settings[$path]['active']) ? $default_dashboard_settings[$path]['active'] : TRUE, ); $form['storm_dashboard_settings'][$type]['dashboard_links'][$path][$type .'_storm_dashboard_link_weight_'. $path] = array( '#type' => 'weight', '#default_value' => isset($default_dashboard_settings[$path]['weight']) ? $default_dashboard_settings[$path]['weight'] : $weight, '#delta' => 30, ); $form['storm_dashboard_settings'][$type]['dashboard_links'][$path]['#value'] = $title; $weight++; } } if (empty($form['#submit'])) { $form['#submit'] = array(); } $form['#submit'] = array('storm_admin_settings_form_submit'); return system_settings_form($form); } /** * Validate Icon Path form element. * * @param $form * @param $form_values */ function storm_admin_settings_icons_path_validate($form, $form_values) { $icon_path_old = variable_get('storm_icons_path', drupal_get_path('module', 'storm') .'/icons'); $icon_path = $form_values['values']['storm_icons_path']; // check if directory exists if (!is_dir($icon_path)) { form_set_error('storm_icons_path', t('Icon path %path does not exist', array('%path' => $icon_path))); } // if it exists and changed, delete cache, so there are no old values in the cache elseif ($icon_path != $icon_path_old) { cache_clear_all('storm:icons', 'cache', FALSE); } } function storm_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('storm_dashboard_types'); foreach ($types as $type => $type_data) { variable_del('storm_'. $type .'dashboard_settings'); }; return; } // GET OPTIONS $types = module_invoke_all('storm_dashboard_types'); foreach ($types as $type => $type_data) { $all_links = storm_dashboard_get_links(FALSE, $type); $settings = array(); foreach ($all_links as $link) { $path = $link['path']; $settings[$path]['active'] = $form_state['values'][$type .'_storm_dashboard_link_active_'. $path]; $settings[$path]['weight'] = $form_state['values'][$type .'_storm_dashboard_link_weight_'. $path]; } variable_set('storm_'. $type .'dashboard_settings', $settings); } } // DATE / TIME MANIPULATION function storm_elements() { $type['datetime'] = array( '#input' => TRUE, '#process' => array('storm_datetime_expand'), '#element_validate' => array('storm_datetime_validate'), '#default_value' => array( 'day' => format_date(time(), 'custom', 'j'), 'month' => format_date(time(), 'custom', 'n'), 'year' => format_date(time(), 'custom', 'Y'), 'hour' => format_date(time(), 'custom', 'H'), 'minute' => format_date(time(), 'custom', 'i'), ), ); $type['dateext'] = array( '#input' => TRUE, '#process' => array('storm_dateext_expand'), '#element_validate' => array('storm_dateext_validate'), '#default_value' => time(), '#withnull' => FALSE, '#disable_date_popup' => FALSE, ); return $type; } function storm_datetime_expand($element) { if (empty($element['#value'])) { $element['#value'] = array( 'day' => format_date(time(), 'custom', 'j'), 'month' => format_date(time(), 'custom', 'n'), 'year' => format_date(time(), 'custom', 'Y'), 'hour' => format_date(time(), 'custom', 'H'), 'minute' => format_date(time(), 'custom', 'i'), ); } $element['#tree'] = TRUE; // Determine the order of day, month, year in the site's chosen date format. $format = variable_get('date_format_short', 'm/d/Y - H:i'); $sort = array(); $sort['day'] = max(strpos($format, 'd'), strpos($format, 'j')); $sort['month'] = max(strpos($format, 'm'), strpos($format, 'M')); $sort['year'] = strpos($format, 'Y'); $sort['hour'] = strpos($format, 'H'); $sort['minute'] = strpos($format, 'i'); asort($sort); $order = array_keys($sort); // Output multi-selector for date. foreach ($order as $type) { switch ($type) { case 'year': $options = drupal_map_assoc(range(variable_get('storm_yearsrangebegin', 2001), variable_get('storm_yearsrangeend', 2012))); break; case 'month': $options = drupal_map_assoc(range(1, 12), 'map_month'); break; case 'day': $options = drupal_map_assoc(range(1, 31)); break; case 'hour': $options = drupal_map_assoc(range(0, 23)); break; case 'minute': $options = drupal_map_assoc(range(0, 59)); break; } $parents = $element['#parents']; $parents[] = $type; $element[$type] = array( '#type' => 'select', '#value' => $element['#value'][$type], '#attributes' => $element['#attributes'], '#options' => $options, ); } return $element; } function storm_datetime_validate($form) { if (!checkdate($form['#value']['month'], $form['#value']['day'], $form['#value']['year'])) { form_error($form, t('The specified date is invalid.')); } } function storm_dateext_expand($element, $edit, $form_state, $form) { if (empty($element['#value'])) { if (!$element['#withnull']) { $element['#value'] = array( 'day' => format_date(time(), 'custom', 'j'), 'month' => format_date(time(), 'custom', 'n'), 'year' => format_date(time(), 'custom', 'Y'), ); } else { $element['#value'] = array('day' => -1, 'month' => -1, 'year' => -1); } } $element['#tree'] = TRUE; // If date popup exists, we should use date popup, // but you can force to disable it by set disable_date_popup to true if (module_exists('date_popup') && (!isset($element['disable_date_popup']) || !$element['disable_date_popup'])) { // value is timestamp if (is_numeric($element['#value']) && $element['#value'] != 0) { $element['#value'] = array('popup' => format_date($element['#value'], 'custom', 'Y-m-d')); } // value is date array elseif (is_array($element['#value']) && !isset($element['#value']['popup']) && $element['#value']['day'] != -1) { $element['#value'] = array('popup' => sprintf("%04d-%02d-%02d", $element['#value']['year'], $element['#value']['month'], $element['#value']['day'])); } elseif (is_numeric($element['#value']) || !isset($element['#value']['popup']) || (isset($element['#value']['day']) && $element['#value']['day'] == -1)) { $element['#value'] = array('popup' => ''); } if (is_array($element['#value']['popup']) && isset($element['#value']['popup']['date'])) { $value = $element['#value']['popup']['date']; } else { $value = $element['#value']['popup']; } $current_year = date('Y'); $begin = variable_get('storm_yearsrangebegin', 2001) - $current_year; if ($begin > 0) { $begin = '+'. $begin; } $end = variable_get('storm_yearsrangeend', 2015) - $current_year; if ($end > 0) { $end = '+'. $end; } $parents = $element['#parents']; $parents[] = 'popup'; $element['popup'] = array( '#type' => 'date_popup', '#date_timezone' => date_default_timezone_name(), '#date_format' => "Y-m-d", '#date_year_range' => $begin .':'. $end, '#default_value' => $value, '#attributes' => $element['#attributes'], '#withnull' => $element['#withnull'], ); } // fallback - use select boxes to choose the date else { // its a timestamp, convert it to a date format if (is_numeric($element['#value']) && $element['#value'] != 0) { $element['#value'] = _storm_gmtimestamp_to_date($element['#value']); } // Determine the order of day, month, year in the site's chosen date format. $format = variable_get('date_format_short', 'm/d/Y - H:i'); $sort = array(); $sort['day'] = max(strpos($format, 'd'), strpos($format, 'j')); $sort['month'] = max(strpos($format, 'm'), strpos($format, 'M')); $sort['year'] = strpos($format, 'Y'); asort($sort); $order = array_keys($sort); // Output multi-selector for date. foreach ($order as $type) { switch ($type) { case 'year': $options = drupal_map_assoc(range(variable_get('storm_yearsrangebegin', 2001), variable_get('storm_yearsrangeend', 2012))); break; case 'month': $options = drupal_map_assoc(range(1, 12), 'map_month'); break; case 'day': $options = drupal_map_assoc(range(1, 31)); break; } if ($element['#withnull']) { $options = array('-1' => '-') + $options; } if (empty($element['#attributes'])) { $element['#attributes'] = array(); } $parents = $element['#parents']; $parents[] = $type; $element[$type] = array( '#type' => 'select', '#value' => isset($element['#value'][$type]) ? $element['#value'][$type] : NULL, '#options' => $options, '#attributes' => array_merge(array('onchange' => "storm_datext_tonull(this, '". $element['#id'] ."')"), $element['#attributes']), ); } } return $element; } function storm_dateext_validate($element, &$form_state) { // value is a string, convert it back to array if (is_array($element['#value']) && isset($element['#value']['popup'])) { if (!$element['#withnull'] && empty($element['#value']['popup']['date'])) { form_set_error($element, t('Field %field is required.', array('%field' => !empty($element['#title']) ? $element['#title'] : ''))); } # if (preg_match('/(\d{4})-(\d{2})-(\d{2})/', $element['#value']['popup']['date'], $matches)) { if (isset($element['#value']['popup']['date']) && preg_match('/(\d{4})-(\d{2})-(\d{2})/', $element['#value']['popup']['date'], $matches)) { $element['#value'] = array(); $element['#value']['day'] = (int) $matches[3]; $element['#value']['month'] = (int) $matches[2]; $element['#value']['year'] = (int) $matches[1]; } else { if (!$element['#withnull'] && !empty($element['#value']['popup']['date'])) { form_set_error($element, t('Wrong Format for Field %field. Format should be YYYY-MM-DD.', array('%field' => !empty($element['#title']) ? $element['#title'] : ''))); } $element['#value'] = array('day' => -1, 'month' => -1, 'year' => -1); } form_set_value($element, $element['#value'], $form_state); } if ($element['#value']['day'] == -1 && !$element['#withnull']) { form_set_error($element, t('Field %field is required.', array('%field' => !empty($element['#title']) ? $element['#title'] : ''))); } if ($element['#value']['day'] != -1 && !checkdate($element['#value']['month'], $element['#value']['day'], $element['#value']['year'])) { form_error($element, t('The specified date is invalid.')); } return $element; } function storm_dependent_select_process($form, $edit, $form_state, $complete_form) { unset($form['#needs_validation']); return $form; } function _timestamp_to_gm($timestamp, $timezone=NULL) { if (!isset($timezone)) { global $user; if (variable_get('configurable_timezones', 1) && $user->uid && drupal_strlen($user->timezone)) { $timezone = $user->timezone; } else { $timezone = variable_get('date_default_timezone', 0); } } $timestamp -= $timezone; return $timestamp; } function _storm_date_to_gmtimestamp($date, $timezone=NULL) { if ($date['month'] == -1 || $date['year'] == -1 || $date['day'] == -1) { return NULL; } else { $gmttimestamp = gmmktime(0, 0, 0, intval($date['month']), intval($date['day']), intval($date['year'])); return _timestamp_to_gm($gmttimestamp, $timezone); } } function _storm_datetime_to_gmtimestamp($datetime, $timezone=NULL) { $gmttimestamp = gmmktime(intval($datetime['hour']), intval($datetime['minute']), 0, intval($datetime['month']), intval($datetime['day']), intval($datetime['year'])); return _timestamp_to_gm($gmttimestamp, $timezone); } function _storm_gmtimestamp_to_datetime($timestamp, $timezone=NULL) { $datetime = array( 'day' => format_date($timestamp, 'custom', 'j', $timezone), 'month' => format_date($timestamp, 'custom', 'n', $timezone), 'year' => format_date($timestamp, 'custom', 'Y', $timezone), 'hour' => (int)format_date($timestamp, 'custom', 'H', $timezone), 'minute' => (int)format_date($timestamp, 'custom', 'i', $timezone), ); return $datetime; } function _storm_gmtimestamp_to_date($timestamp, $timezone=NULL) { if ($timestamp) { $date = array( 'day' => format_date($timestamp, 'custom', 'j', $timezone), 'month' => format_date($timestamp, 'custom', 'n', $timezone), 'year' => format_date($timestamp, 'custom', 'Y', $timezone), ); } else { $date = array( 'day' => -1, 'month' => -1, 'year' => -1, ); } return $date; } function _storm_gmtimestamp_without_time($timestamp, $timezone=NULL) { $date = _storm_gmtimestamp_to_date($timestamp, $timezone); $gmttimestamp = gmmktime(0, 0, 0, $date['month'], $date['day'], $date['year']); return _timestamp_to_gm($gmttimestamp, $timezone); } function _storm_strtotime($timestr='') { $timestr = drupal_substr($timestr, 0, 5); $time = array(); $time['hour'] = 0; $time['minute'] = 0; $ar = explode(':', $timestr); if (is_array($ar)) { if (array_key_exists(0, $ar)) $time['hour'] = $ar[0]; if (array_key_exists(1, $ar)) $time['minute'] = $ar[1]; } return $time; } function _timetostr($time=array()) { $timestr = str_pad($time['hour'], 2, "0", STR_PAD_LEFT) .':'. str_pad($time['minute'], 2, "0", STR_PAD_RIGHT); return $timestr; } /** * @function * Calculates taxation for SuiteDesk nodes */ function storm_taxation(&$node) { // If values are not set, then use default values if (!isset($node->tax1app)) { $node->tax1app = variable_get('storm_tax1_app', 'none'); } if (!isset($node->tax1percent)) { $node->tax1percent = variable_get('storm_tax1_percent', '20'); } if (!isset($node->tax2app)) { $node->tax2app = variable_get('storm_tax2_app', 'none'); } if (!isset($node->tax2percent)) { $node->tax2percent = variable_get('storm_tax2_percent', '20'); } switch ($node->tax1app) { case 0: $node->tax1 = 0; break; case 1: $node->tax1 = $node->amount * $node->tax1percent / 100; break; default: // ERROR drupal_set_message(t('Error during tax calculations (SuiteDesk module)'), 'error'); } $node->subtotal = $node->amount + $node->tax1; switch ($node->tax2app) { case 0: $node->tax2 = 0; break; case 1: $node->tax2 = $node->amount * $node->tax2percent / 100; break; case 2: $node->tax2 = $node->subtotal * $node->tax2percent / 100; break; default: // ERROR drupal_set_message(t('Error during tax calculations (SuiteDesk module)'), 'error'); } $node->total = $node->subtotal + $node->tax2; } // STORM ICON ADD / EDIT / LINK FUNCTIONS function storm_icon_add_node($node, $params=array()) { return storm_icon_add('node/add/'. $node->type, $node, $params); } function storm_icon_edit_node($node, $params=array()) { return storm_icon_edit('node/'. $node->nid .'/edit', $node, $params); } function storm_icon_comment_node($node, $params=array()) { return storm_icon_comment('node/add/'. $node->type .'c/'. $node->nid, $node, $params); } function storm_icon_delete_node($node, $params=array()) { return storm_icon_delete('node/'. $node->nid .'/delete', $node, $params); } function storm_icon_restore_node($node, $params=array()) { $params['q'] = drupal_get_path_alias('node/' . $node->nid); return storm_icon_restore('trash/'. $node->nid .'/restore', $node, $params); } function storm_icon_delete_perm_node($node, $params=array()) { return storm_icon_delete_perm('trash/'. $node->nid .'/delete', $node, $params); } function storm_icon_gantt_project($project, $params=array()) { return storm_icon_gantt('node/'. $project->nid .'/tasks', $project, $params); } function storm_icon_gantt_task($task, $params=array()) { return storm_icon_gantt('node/'. $task->project_nid .'/tasks', $task, $params); } function storm_icon_add($path, $item, $params=array()) { global $user; if (!node_access('create', $item, $user)) return ''; $attributes = array('class' => 'popups-form'); return storm_icon_l('application_add', $path, t('Add'), '', $params, $attributes); } function storm_icon_edit($path, $item, $params=array()) { global $user; if (!node_access('update', $item, $user)) return ''; $attributes = array('class' => 'popups-form'); return storm_icon_l('application_edit', $path, t('Edit'), '', $params, $attributes); } function storm_icon_comment($path, $item, $params=array()) { global $user; if (!user_access('create '. $item->type .'c content')) return ''; $attributes = array('class' => 'popups-form'); return storm_icon_l('application_comment', $path, t('Add comment'), '', $params, $attributes); } function storm_icon_delete($path, $item, $params=array()) { global $user; if (!node_access('delete', $item, $user)) return ''; $attributes = array('class' => 'popups-form'); return storm_icon_l('application_delete', $path, t('Delete'), '', $params, $attributes); } function storm_icon_restore($path, $item, $params=array()) { global $user; if (!node_access('delete', $item, $user)) return ''; $attributes = array('class' => 'popups-form'); return storm_icon_l('application_restore', $path, t('Restore'), '', $params, $attributes); } function storm_icon_delete_perm($path, $item, $params=array()) { global $user; if (!node_access('delete', $item, $user)) return ''; $attributes = array('class' => 'popups-form'); return storm_icon_l('application_delete', $path, t('Delete permanently'), '', $params, $attributes); } function storm_icon_gantt($path, $item, $params=array()) { global $user; if (!user_access('Storm project: access')) return ''; $attributes = array('class' => 'popups-form'); // Disabling URL destination in Gantt links: unset($params['q']); return storm_icon_l('application_gantt', $path, t('Project tasks'), '', $params, $attributes); } function storm_icon_l($icon, $path, $title, $permission='', $params=array(), $attributes=array()) { if ($permission && !user_access($permission)) return ''; $icon = storm_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']); } $params = _storm_icon_urlencode_helper($params); foreach ($params as $key => $value) { if ($query) $query .= '&'; $query .= $key .'='. urlencode($value); } $o = l($icon, $path, array('attributes' => $attributes, 'query' => $query, 'html' => TRUE)); return $o; } function _storm_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(_storm_icon_urlencode_helper($value, $new_key), $new_params); } else { $new_params[$new_key] = $value; } } return $new_params; } function storm_icon($icon, $title) { global $base_path; // Running checkplain on these variables means that we can call storm_icon without further sanitising $icon = check_plain($icon); $title = check_plain($title); $icon = str_replace(' ', '_', $icon); if (variable_get('storm_icons_display', TRUE) == TRUE) { $available = cache_get('storm:icons'); if (!is_object($available)) { // Cache miss $available = storm_icon_recache(); } if (in_array($icon .'.png', $available->data)) { // Standard route - display normal image $img_src = $base_path . variable_get('storm_icons_path', drupal_get_path('module', 'storm') .'/icons') .'/'. $icon .'.png'; $o = '' . t('Recent content - !count', array('!count' => format_plural($node_count, '1 new post', '@count new posts'))) . ':
' . '' . t('!count attached to !type posted by !author: !title', array('!count' => format_plural(count($comment), '1 new comment', '@count new comments'), '!title' => $nodes[$nid]->title, '!type' => node_get_types('name', $nodes[$nid]), '!author' => $nodes[$nid]->name ? $nodes[$nid]->name : variable_get('anonymous', 'Anonymous'))) . '
' . '' . t('Recent comments - !count', array('!count' => format_plural($total_comment_count, '1 new comment', '@count new comments'))) . '
' . $comment_body; } } $body = $node_body . $comment_body; // If there was anything new, send mail: if ($body) { // Set up initial values for e-mail: $headers = array(); if (!drupal_mail('storm', 'send', $user->mail, user_preferred_language($user), array('content' => $body), NULL, TRUE)) { $num_failed++; db_query('UPDATE {notify} SET attempts = attempts + 1 WHERE uid = %d', $user->uid); watchdog('notify', 'User %name (%mail) could not be notified. Mail error.', array('%name' => $user->name, '%mail' => $user->mail), WATCHDOG_ERROR); } else { $num_sent++; watchdog('notify', 'User %name (%mail) notified successfully.', array('%name' => $user->name, '%mail' => $user->mail), WATCHDOG_INFO); } } } } // Restore user: _storm_switch_user(); return array($num_sent, $num_failed); } function storm_mail($key, &$message, $params) { global $user, $base_url; $sitename = '' . variable_get('site_name', 'Drupal') . ''; $url_preferences = str_replace('http://', 'https://', url("user/$user->uid/notify", array('absolute' => TRUE))); $headers = array( 'MIME-Version' => '1.0', 'Content-Type' => 'text/html; charset=UTF-8; format=flowed', 'Content-Transfer-Encoding' => '8Bit', 'X-Mailer' => 'Drupal', ); foreach ($headers as $key => $value) { $message['headers'][$key] = $value; } $message['subject'] = t('!sitename notification for !username', array('!sitename' => variable_get('site_name', 'Drupal'), '!username' => $user->name)); $message['body'] = '' . t('Hi !username!', array('!username' => '' . $user->name . '')) . '
' . '' .
t('This is an automatic e-mail from !sitename.', array('!sitename' => $sitename)) . '
' .
t('To stop receiving these e-mails, change your !preferences.', array('!preferences' => '' . t('notification preferences') . '')) .
'
' . t('!suitedesk is a web based software for project management, planning, personal productivity, communication between project stakeholders, collaboration, customers support, documentation, cost control and change management.', array('!suitedesk' => 'SuiteDesk', '!sitename' => $sitename)) . '
' . 'Manuel Cillero 【ツ】
' . 'manuel@cillero.es
' .
'https://manuel.cillero.es
' .
'https://twitter.com/manuelcillero
' .
'https://facebook.com/manuelcillero