'icon'); } return $hooks; } /** * Implements hook_library(). */ function icon_library() { $libaries_path = drupal_get_path('module', 'icon') . '/libraries'; $libraries['icon_selector'] = array( 'title' => 'Icon Selector', 'website' => 'http://drupal.org/project/icon', 'version' => '1.0.0', 'css' => array( $libaries_path . '/icon_selector/css/icon_selector.css' => array(), ), 'js' => array( $libaries_path . '/icon_selector/js/icon_selector.js' => array(), 0 => array( 'type' => 'setting', 'data' => array( 'icon_selector' => array( 'bundles' => array_keys(icon_bundles()), ), ), ), ), ); return $libraries; } /** * Implements hook_menu(). */ function icon_menu() { $module_path = drupal_get_path('module', 'icon'); $items = array(); $items[ICON_ADMIN_PATH] = array( 'title' => 'Icons', 'description' => 'Overview of all available icons.', 'page callback' => 'drupal_get_form', 'page arguments' => array('icon_bundle_overview_form'), 'access arguments' => array('administer icons'), 'file' => 'admin.inc', 'file path' => $module_path . '/includes', ); $items[ICON_ADMIN_PATH . '/overview'] = array( 'type' => MENU_DEFAULT_LOCAL_TASK, 'title' => 'Bundles', 'description' => 'Overview of all available icon bundles.', 'weight' => -10, ); $import_providers = icon_providers_support_import(); if (!empty($import_providers)) { $items[ICON_ADMIN_PATH . '/import'] = array( 'type' => MENU_LOCAL_TASK, 'title' => 'Import', 'description' => 'Import a bundle from a provider.', 'page callback' => 'drupal_get_form', 'page arguments' => array('icon_provider_import_form'), 'access arguments' => array('administer icons'), 'file' => 'import.inc', 'file path' => $module_path . '/includes', ); } $items[ICON_ADMIN_PATH . '/bundle/%icon_bundle'] = array( 'title callback' => 'icon_bundle_get_title', 'title arguments' => array(5), 'description' => 'An icon bundle.', 'page callback' => 'icon_bundle_list', 'page arguments' => array(5), 'access arguments' => array('administer icons'), 'theme callback' => 'icon_bundle_get_theme', 'theme arguments' => array(5), 'file' => 'admin.inc', 'file path' => $module_path . '/includes', ); $items[ICON_ADMIN_PATH . '/bundle/%icon_bundle/icons'] = array( 'type' => MENU_DEFAULT_LOCAL_TASK, 'title' => 'Icons', 'description' => 'Provide an overview of all available icon bundles.', 'weight' => -10, ); $items[ICON_ADMIN_PATH . '/bundle/%icon_bundle/configure'] = array( 'type' => MENU_LOCAL_TASK, 'title' => 'Configure', 'description' => 'Form callback for configuring an icon bundle.', 'page callback' => 'drupal_get_form', 'page arguments' => array('icon_bundle_configure_form', 5), 'access arguments' => array('administer icons'), 'file' => 'admin.inc', 'file path' => $module_path . '/includes', ); $items[ICON_ADMIN_PATH . '/bundle/%icon_bundle/delete'] = array( 'title' => 'Delete', 'description' => 'Confirmation page for deleting an icon bundle from the database.', 'page callback' => 'drupal_get_form', 'page arguments' => array('icon_bundle_delete_form', 5), 'type' => MENU_CALLBACK, 'access arguments' => array('administer icons'), 'file' => 'admin.inc', 'file path' => $module_path . '/includes', ); $items[ICON_ADMIN_PATH . '/bundle/%icon_bundle/reset'] = array( 'title' => 'Reset', 'description' => 'Confirmation page for resetting a module or theme provided bundle that has been overridden in the database.', 'page callback' => 'drupal_get_form', 'page arguments' => array('icon_bundle_reset_form', 5), 'type' => MENU_CALLBACK, 'access arguments' => array('administer icons'), 'file' => 'admin.inc', 'file path' => $module_path . '/includes', ); // The actual path will be set in hook_menu_alter() but we want the item to be // defined here to let the menu system fill-in defaults. To ensure we do not // have path collisions, we just temporarily a child of our admin path. $view_path_alias = ICON_ADMIN_PATH . '/tmp'; $items[$view_path_alias] = $items[ICON_ADMIN_PATH]; $items[$view_path_alias]['access arguments'] = array('view icons'); $items[$view_path_alias . '/%icon_bundle'] = $items[ICON_ADMIN_PATH . '/bundle/%icon_bundle']; $items[$view_path_alias . '/%icon_bundle']['access arguments'] = array('view icons'); $items[$view_path_alias . '/%icon_bundle']['title arguments'] = array(1); $items[$view_path_alias . '/%icon_bundle']['page arguments'] = array(1); $items[$view_path_alias . '/%icon_bundle']['theme arguments'] = array(1); return $items; } /** * Implements hook_menu_alter(). */ function icon_menu_alter(&$items) { // Create a path alias for users with the "view icons" permission. $view_path_alias = variable_get('icon_api_view_path_alias'); // If variable is not set and path is not taken, set it. if ($view_path_alias === NULL && empty($items['icons'])) { $view_path_alias = 'icons'; variable_set('icon_api_view_path_alias', $view_path_alias); } $tmp_path = ICON_ADMIN_PATH . '/tmp'; if (!empty($view_path_alias)) { $items[$view_path_alias] = $items[$tmp_path]; $items[$view_path_alias . '/%icon_bundle'] = $items[$tmp_path . '/%icon_bundle']; } unset($items[$tmp_path]); unset($items[$tmp_path . '/%icon_bundle']); } /** * Implements hook_permission(). * * Invokes hook_icon_permission() so sub-modules can be grouped together with * the Icon API module on the permissions table. */ function icon_permission() { return array_merge_recursive(array( 'administer icons' => array( 'title' => t('Administer Icons'), 'description' => t('Grants selected roles full administrative permissions for all aspects of the Icon API. It supersedes all permissions below.'), 'restrict access' => TRUE, ), 'view icons' => array( 'title' => t('View Icons'), 'description' => t('Grants selected roles permission to view all icons in enabled bundles.'), ), ), module_invoke_all('icon_permission')); } /** * Returns information about icons render hooks. * * @param string $hook * (optional) The name of the render hook to return information for. If * omitted, render hook information provided by all modules and themes will * be returned. * @param bool $reset * Boolean to force reset of the cached data. Default: FALSE. * * @return array|false * An associative array containing render hook information from all modules * and themes, the information for the render hook specified by $hook, or * FALSE if the render hook $name is not registered. * * @see hook_icon_render_hooks() */ function &icon_render_hooks($hook = NULL, $reset = FALSE) { $hooks = & drupal_static(__FUNCTION__); if (!isset($hooks) || $reset) { if (!$reset && ($cache = cache_get('icon_render_hooks')) && !empty($cache->data)) { $hooks = $cache->data; } else { $hooks = array(); // Gather information from extensions that implement // hook_icon_render_hooks(). foreach (icon_extension_implements('icon_render_hooks') as $extension => $type) { $extension_hooks = (array) icon_extension_invoke($type, $extension, 'icon_render_hooks'); foreach ($extension_hooks as $render_hook => $data) { if (!is_string($render_hook) && is_string($data)) { $render_hook = $data; $data = array(); } $data['name'] = $render_hook; $data['type'] = $type; $data[$type] = $extension; if (!isset($data['file'])) { $data['file'] = 'module' === $type ? $extension . '.module' : 'template.php'; } if (!isset($data['path'])) { $data['path'] = drupal_get_path($type, $extension); } $hooks[$render_hook] = $data; } } // Allow extensions to alter render hook information. drupal_alter('icon_render_hooks', $hooks); // Cache the render hook information. cache_set('icon_render_hooks', $hooks); } } if (isset($hook)) { if (!empty($hooks[$hook])) { return $hooks[$hook]; } else { $false = FALSE; return $false; } } return $hooks; } /** * Default properties for a bundle definition. * * @param array $bundle * An associative array of bundle information, passed by reference. * @param string $name * The machine name of the bundle. */ function icon_bundle_defaults(&$bundle = array(), $name = '') { $bundle += array( 'icons' => array(), 'name' => $name, 'provider' => '', 'settings' => array(), 'status' => 1, 'title' => $name, 'version' => '', '#attached' => array(), ); return $bundle; } /** * Returns information about all icon bundles. * * @param string $name * The name of the bundle to load. * @param bool $reset * Boolean to force reset of the cached data. Default: FALSE. * * @return array|false * An associative array containing information for all bundles. * * @see hook_icon_info() */ function icon_bundles($name = NULL, $reset = FALSE) { $bundles = & drupal_static(__FUNCTION__); if (!isset($bundles) || $reset) { if (!$reset && ($cache = cache_get('icon_bundles')) && !empty($cache->data)) { $bundles = $cache->data; } else { $bundles = array(); // Gather information from extensions that implement hook_icon_bundles(). foreach (icon_extension_implements('icon_bundles') as $extension => $type) { $extension_bundles = (array) icon_extension_invoke($type, $extension, 'icon_bundles'); foreach ($extension_bundles as $bundle_name => $bundle) { icon_bundle_defaults($bundle, $bundle_name); if (empty($bundle['provider'])) { $bundle['provider'] = $extension; } // Alphabetically sort the icons. if (!empty($bundle['icons'])) { ksort($bundle['icons']); } // In cases where themes may provide sprite icons (such as Bootstrap), // we need to specify the theme to use for this bundle. These types // of bundles do not attach a separate CSS file with the bundle and // the sprite classes are instead, generated with the theme's CSS. // @see icon_bundle_get_theme() // @see icon_menu(). if ($type === 'theme' && $bundle['render'] === 'sprite' && empty($bundle['#attached']['css'])) { $bundle['theme'] = $extension; } $bundles[$bundle_name] = $bundle; } } // Gather database bundles (which overrides any module implementations). $database_bundles = db_select('icon_bundle', 'b') ->fields('b') ->execute(); foreach ($database_bundles as $database_bundle) { $bundle = unserialize($database_bundle->bundle); if ($bundle === FALSE) { $bundle = array(); } else { icon_bundle_defaults($bundle, $bundle['name']); if (!empty($bundles[$database_bundle->name])) { $bundle['overridden'] = TRUE; } } $bundle['database'] = TRUE; $bundle['status'] = (int) $database_bundle->status; if (isset($bundles[$database_bundle->name])) { $bundle = array_merge($bundles[$database_bundle->name], $bundle); } $bundles[$database_bundle->name] = $bundle; } // Allow extensions to alter the bundles. drupal_alter('icon_bundles', $bundles); // Cache the info. cache_set('icon_bundles', $bundles); } } if (isset($name)) { if (!empty($bundles[$name])) { return $bundles[$name]; } else { $false = FALSE; return $false; } } return $bundles; } /** * Delete the icon bundle that matches {icon_bundle}.name in the database. * * @param array $bundle * The icon bundle array. * * @return bool * TRUE if successful, FALSE if bundle does not exist or on failure. */ function icon_bundle_delete(array $bundle = array()) { if (empty($bundle['name']) || !icon_bundle_load($bundle['name'])) { return FALSE; } // Execute the query. try { // Execute query and remove database entries. db_delete('icon_bundle')->condition('name', $bundle['name'])->execute(); // Delete files if not in code and path starts in public folder and exists. if (empty($bundle['overridden']) && strpos($bundle['path'], 'public://') === 0 && file_exists($bundle['path'])) { file_unmanaged_delete_recursive($bundle['path']); } // Determine which hook to invoke. $hook = 'icon_bundle_' . (!empty($bundle['overridden']) ? t('reset') : t('delete')); // Invoke hook_icon_bundle_reset() or hook_icon_bundle_delete() accordingly. foreach (icon_extension_implements($hook) as $extension => $type) { icon_extension_invoke($type, $extension, $hook, $bundle); } icon_clear_all_caches(); drupal_set_message(t('The icon bundle %bundle has been successfully !action.', array( '!action' => (!empty($bundle['overridden']) ? t('reset') : t('deleted')), '%bundle' => $bundle['title'], ) )); return TRUE; } catch (Exception $e) { drupal_set_message(t('An error occurred while attempting to !action the icon bundle "%bundle":
@message', array( '!action' => (!empty($bundle['overridden']) ? t('reset') : t('delete')), '%bundle' => $bundle['title'], '@message' => $e->getMessage(), )), 'error'); } return FALSE; } /** * Disable the icon bundle that matches {icon_bundle}.name in the database. * * @param array $bundle * The icon bundle array. * * @return bool * TRUE if successful, FALSE if the bundle is already disabled or on failure. */ function icon_bundle_disable(array $bundle = array()) { $bundle['status'] = 0; if (icon_bundle_save($bundle)) { drupal_set_message(t('The icon bundle %bundle has been disabled.', array('%bundle' => $bundle['title']))); icon_clear_all_caches(); return TRUE; } drupal_set_message(t('An error occurred while attemping to disable the icon bundle: %bundle.', array('%bundle' => $bundle['title'])), 'error'); return FALSE; } /** * Enable the icon bundle that matches {icon_bundle}.name in the database. * * @param array $bundle * The icon bundle array. * * @return bool * TRUE if successful, FALSE if the bundle is already enabled or on failure. */ function icon_bundle_enable(array $bundle = array()) { $bundle['status'] = 1; if (icon_bundle_save($bundle)) { drupal_set_message(t('The icon bundle %bundle has been enabled.', array('%bundle' => $bundle['title']))); icon_clear_all_caches(); return TRUE; } drupal_set_message(t('An error occurred while attemping to enable the icon bundle: %bundle.', array('%bundle' => $bundle['title'])), 'error'); return FALSE; } /** * Helper function to return the proper theme. * * Necessary for displaying a list of icons of a specific bundle. */ function icon_bundle_get_theme($bundle, $global = FALSE) { global $theme; return !empty($bundle['theme']) && !$global ? $bundle['theme'] : $theme; } /** * Helper function to return the page title for bundles. */ function icon_bundle_get_title($bundle) { return !empty($bundle['title']) ? $bundle['title'] : t('Bundle'); } /** * Load a specific bundle. * * @param string $name * The name of the bundle to load. * * @return array * An associative array of bundle information as returned from * icon_bundles(). */ function icon_bundle_load($name) { $loaded = & drupal_static(__FUNCTION__, array()); if (empty($loaded[$name])) { $loaded[$name] = icon_bundles($name); } return $loaded[$name]; } /** * Save an icon bundle in the {icon_bundle} table. * * @param array $bundle * The icon bundle array. * * @return int|false * If the save failed, returns FALSE. If successful, returns SAVED_NEW or * SAVED_UPDATED, depending on the drupal_write_record() operation * that was performed. */ function icon_bundle_save(array $bundle = array()) { if (empty($bundle['name'])) { return FALSE; } // Allow extensions to alter the bundle before it's saved. drupal_alter('icon_bundle_save', $bundle); $primary_keys = array(); $record = array( 'name' => $bundle['name'], ); $existing_bundle = icon_bundle_load($bundle['name']); if (!$existing_bundle) { $existing_bundle = array(); } // If the existing bundle is from the database, update the record. if (!empty($existing_bundle['database'])) { $primary_keys[] = 'name'; } // Determine if there are differences between an existing bundle and this one. $diff = icon_array_diff_recursive($existing_bundle, $bundle); // If the status has changed, update the status field. if (isset($diff['status'])) { $record['status'] = (int) $bundle['status']; // Remove status from $diff to determine if anything else needs to be saved. unset($diff['status']); } // If there are still differences, replace the entire {icon_bundle}.bundle // field with the updated bundle array. if (!empty($diff)) { $record['bundle'] = $bundle; } // Only write to the database if necessary. if (isset($record['status']) || isset($record['bundle'])) { if ($status = drupal_write_record('icon_bundle', $record, $primary_keys)) { icon_clear_all_caches(); return $status; } } return FALSE; } /** * Default properties for a provider definition. * * @param array $provider * An associative array of provider information, passed by reference. * @param string $name * The machine name of the provider. */ function icon_provider_defaults(&$provider = array(), $name = '') { $provider += array( 'default bundle' => array(), 'name' => $name, 'title' => $name, 'url' => '', ); return $provider; } /** * Returns information about all icon providers. * * @param string $name * The name of the provider to load. * @param bool $reset * Boolean to force reset of the cached data. Default: FALSE. * * @return array|false * An associative array containing information for all providers. * * @see hook_icon_info() */ function icon_providers($name = NULL, $reset = FALSE) { $providers = & drupal_static(__FUNCTION__); if (!isset($providers) || $reset) { if (!$reset && ($cache = cache_get('icon_providers')) && !empty($cache->data)) { $providers = $cache->data; } else { $providers = array(); // Invoke hook_icon_providers(). foreach (icon_extension_implements('icon_providers') as $extension => $type) { $extension_providers = (array) icon_extension_invoke($type, $extension, 'icon_providers'); foreach ($extension_providers as $provider_name => $provider) { if ($provider_name === 'automatic') { drupal_set_message(t('The !type %extension tried to specify a provider with the name: %name. This is a reserved name and cannot be used, please rename your provider.', array( '!type' => $type, '%extension' => $extension, '%name' => $provider_name, )), 'warning'); continue; } icon_provider_defaults($provider, $provider_name); $provider['name'] = $provider_name; $provider['type'] = $type; $provider[$type] = $extension; $providers[$provider_name] = $provider; } } // Allow extensions to alter the providers. drupal_alter('icon_providers', $providers); // Cache the info. cache_set('icon_providers', $providers); } } if (!empty($name)) { if (!empty($providers[$name])) { return $providers[$name]; } return FALSE; } return $providers; } /** * Returns information about whether a provider supports importing. * * @todo make this "JSON importing"? * * @param string $name * The name of the provider to load. * * @return array|false * Returns an array of providers that support importing or just $name if it * was provided. Returns FALSE if there are no providers or specific $name * does not exist. */ function icon_providers_support_import($name = NULL) { $providers = & drupal_static(__FUNCTION__); if (!isset($providers)) { $providers = array(); foreach (icon_providers() as $provider) { if (icon_extension_hook($provider['type'], $provider[$provider['type']], 'icon_' . $provider['name'] . '_import_validate') && icon_extension_hook($provider['type'], $provider[$provider['type']], 'icon_' . $provider['name'] . '_import_process') ) { $providers[$provider['name']] = $provider; } } } if (!empty($name)) { if (!empty($providers[$name])) { return $providers[$name]; } return FALSE; } return $providers; } /** * Load a specific provider. * * @param string $name * The name of the provider to load. * * @return array * An associative array of provider information as returned from * icon_providers(). */ function icon_provider_load($name) { $loaded = & drupal_static(__FUNCTION__, array()); if (empty($loaded[$name])) { if (($cache = cache_get($name, 'cache_icon_providers')) && !empty($cache->data)) { $loaded[$name] = $cache->data; } else { $provider = icon_providers($name); cache_set($name, $provider, 'cache_icon_providers'); $loaded[$name] = $provider; } } return $loaded[$name]; } /** * Provides the list of permitted wrapper options. * * @return array * An associative array of key/value pairs, where the wrapper HTML element is * the key and an human readable label is the value. */ function icon_wrapper_options() { // Use the advanced drupal_static() pattern, since this is called very often. static $drupal_static_fast; if (!isset($drupal_static_fast)) { $drupal_static_fast['options'] = &drupal_static(__FUNCTION__); } $options = &$drupal_static_fast['options']; if (!isset($options)) { $options = array( '' => t('None'), 'div' => 'Div', 'span' => 'Span', 'h2' => 'H2', 'h3' => 'H3', 'h4' => 'H4', 'h5' => 'H5', 'h6' => 'H6', 'p' => 'P', 'em' => 'Em', 'strong' => 'Strong', ); drupal_alter(__FUNCTION__, $options); } return $options; }