'CDN integration', 'description' => 'Configure various settings for CDN integration.', 'access arguments' => array('administer site configuration'), 'page callback' => 'drupal_get_form', 'page arguments' => array('cdn_admin_settings_form'), 'type' => MENU_NORMAL_ITEM, 'file' => 'cdn.admin.inc', ); $items['admin/settings/cdn/settings'] = array( 'title' => 'Settings', 'access arguments' => array('administer site configuration'), 'weight' => -10, 'type' => MENU_DEFAULT_LOCAL_TASK, 'file' => 'cdn.admin.inc', ); $items['admin/settings/cdn/basic'] = array( 'title' => 'Basic mode', 'description' => 'Basic mode settings.', 'access arguments' => array('administer site configuration'), 'page callback' => 'drupal_get_form', 'page arguments' => array('cdn_admin_basic_settings_form'), 'weight' => -8, 'type' => MENU_LOCAL_TASK, 'file' => 'cdn.admin.inc', ); $items['admin/settings/cdn/advanced'] = array( 'title' => 'Advanced mode', 'description' => 'Advanced mode settings.', 'access arguments' => array('administer site configuration'), 'page callback' => 'drupal_get_form', 'page arguments' => array('cdn_admin_advanced_settings_form'), 'weight' => -6, 'type' => MENU_LOCAL_TASK, 'file' => 'cdn.admin.inc', ); $items['admin/settings/cdn/other'] = array( 'title' => 'Other', 'description' => 'Other settings.', 'access arguments' => array('administer site configuration'), 'page callback' => 'drupal_get_form', 'page arguments' => array('cdn_admin_other_settings_form'), 'weight' => -4, 'type' => MENU_LOCAL_TASK, 'file' => 'cdn.admin.inc', ); return $items; } /** * Implementation of hook_perm(). */ function cdn_perm() { return array(CDN_PERM_ACCESS_STATS, CDN_PERM_ACCESS_DEBUG); } /** * Implementation of hook_theme(). */ function cdn_theme() { return array( 'cdn_page_stats' => array( 'file' => 'theme.inc', 'arguments' => array( $file_count => NULL, $cdn_file_count => NULL, $synced_files_per_server_count => NULL, $total_time => NULL, $synced_files => NULL, $unsynced_files => NULL, ), ), ); } /** * Implementation of hook_exit(). */ function cdn_exit($destination = NULL) { require_once(drupal_get_path('module', 'cdn') . '/cdn.stats.inc'); // Try not to break non-HTML pages. if (function_exists('drupal_get_headers')) { $headers = drupal_get_headers(); $formats = array('xml', 'javascript', 'json', 'plain', 'image', 'application', 'csv', 'x-comma-separated-values'); foreach ($formats as $format) { if (strstr($headers, $format)) { return; } } } if (!$destination && variable_get(CDN_STATUS_VARIABLE, CDN_DISABLED) != CDN_DISABLED && variable_get(CDN_STATS_VARIABLE, FALSE) && user_access(CDN_PERM_ACCESS_STATS)) { list( $file_count, $cdn_file_count, $synced_files_per_server_count, $total_time, $synced_files, $unsynced_files, ) = _cdn_devel_page_stats(); print theme('cdn_page_stats', $file_count, $cdn_file_count, $synced_files_per_server_count, $total_time, $synced_files, $unsynced_files ); } } /** * Implementation of hook_requirements(). */ function cdn_requirements($phase) { $requirements = array(); $t = get_t(); switch ($phase) { case 'install' : case 'runtime' : $status = variable_get(CDN_STATUS_VARIABLE, CDN_DISABLED); $mode = variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC); $requirements['cdn']['title'] = $t('CDN integration'); // Set the basic info: disabled/debug/enabled. if ($status == CDN_DISABLED) { $requirements['cdn'] += array( 'description' => $t('CDN integration is disabled for all users.'), 'severity' => REQUIREMENT_WARNING, 'value' => $t('Disabled'), ); } elseif ($status == CDN_DEBUG) { $requirements['cdn'] += array( 'description' => $t('CDN integration is only enabled for users with the %cdn-debug-mode-permission permission', array('%cdn-debug-mode-permission' => CDN_PERM_ACCESS_DEBUG) ), 'severity' => REQUIREMENT_WARNING, 'value' => $t('In debug mode'), ); } else { $requirements['cdn'] += array( 'description' => $t('CDN integration is enabled for all users.'), 'severity' => REQUIREMENT_OK, 'value' => $t('Enabled'), ); } // When CDN integration is enabled, add on more information. if ($status != CDN_DISABLED) { if ($mode == CDN_MODE_BASIC) { $requirements['cdn']['value'] .= ' – '. t('basic mode'); } else { $requirements['cdn']['value'] .= ' – '. t('advanced mode'); $items = array(); $synced_files_db = variable_get(CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE, FALSE); if ($synced_files_db !== FALSE) { $daemon_pid_file = str_replace(CDN_DAEMON_SYNCED_FILES_DB, CDN_DAEMON_PID_FILE, $synced_files_db); $persistent_data_db = str_replace(CDN_DAEMON_SYNCED_FILES_DB, CDN_DAEMON_PERSISTENT_DATA_DB, $synced_files_db); $drupal_root_path = variable_get(CDN_DRUPAL_ROOT_VARIABLE, realpath('.')); $synced_files_db_exists = file_exists($synced_files_db); $synced_files_db_readable = @fopen($synced_files_db, 'r'); $persistent_data_db_exists = file_exists($persistent_data_db); $persistent_data_db_readable = @fopen($persistent_data_db, 'r'); $daemon_pid_file_exists = file_exists($daemon_pid_file); $db = _cdn_advanced_get_db_connection(); if ($db !== FALSE) { $input_file_mask = $drupal_root_path .'%'; $sql = "SELECT COUNT(*) AS count, server FROM synced_files WHERE input_file LIKE :input_file GROUP BY server"; $stmt = $db->prepare($sql); $stmt->bindParam(':input_file', $input_file_mask, PDO::PARAM_STR); $stmt->execute(); $result = $stmt->fetchAll(); $synced_file_stats = $result; } if ($persistent_data_db_exists && $persistent_data_db_readable) { try { $db = new PDO('sqlite:' . $persistent_data_db); } catch(PDOException $e) { $items[] = t("Could not connect to persistent data database."); } if ($db !== FALSE) { $sql = "SELECT COUNT(*) FROM pipeline_queue"; $stmt = $db->prepare($sql); $stmt->execute(); $result = $stmt->fetchAll(); $pipeline_queue_count = $result[0][0]; $sql = "SELECT COUNT(*) FROM pipeline_list"; $stmt = $db->prepare($sql); $stmt->execute(); $result = $stmt->fetchAll(); $pipeline_list_count = $result[0][0]; } } $items[] = ($synced_files_db_exists) ? t('The synced files database exists.') : t("The synced files database doesn't exist."); $items[] = ($synced_files_db_readable) ? t('The synced files database is readable.') : t("The synced files database isn't readable."); if ($synced_files_db_readable) { foreach ($synced_file_stats as $row) { $items[] = t('!synced-file-count files have been synced to the %server server.', array('!synced-file-count' => $row['count'], '%server' => $row['server'])); } } else { $items[] = t("Number of synced files is unknown."); } $items[] = ($daemon_pid_file_exists) ? t('The daemon is currently running.') : '' . t('The daemon is currently not running.') . ''; if (isset($pipeline_queue_count)) { $items[] = t("!pipeline-queue-count files are waiting to be synced.", array('!pipeline-queue-count' => $pipeline_queue_count)); $items[] = t("!pipeline-list-count files are currently being synced.", array('!pipeline-list-count' => $pipeline_list_count)); } // If either of these 3 checks failed, mark this requirement's // severity as being an error. if (!($synced_files_db_exists && $synced_files_db_readable && $daemon_pid_file_exists)) { $requirements['cdn']['severity'] = REQUIREMENT_ERROR; } } else { $items[] = t('The synced files database setting has not yet been configured.'); $requirements['cdn']['severity'] = REQUIREMENT_ERROR; } $requirements['cdn']['description'] .= '
' . theme('item_list', $items); } } } return $requirements; } //---------------------------------------------------------------------------- // Public functions. /** * Gets the URL for a file when the basic mode is enabled. * * @param $path * The path to get the URL for. */ function cdn_basic_get_url($path) { // Ensure the configuration is correct. if (variable_get(CDN_BASIC_URL_VARIABLE, FALSE) === FALSE) { return FALSE; } $extensions = str_replace(array(' ', '.'), array('|', '\.'), variable_get(CDN_BASIC_EXTENSIONS_VARIABLE, CDN_BASIC_EXTENSIONS_DEFAULT)); if (preg_match("/($extensions)$/", $path)) { $base_path = base_path(); $cdn_url = variable_get(CDN_BASIC_URL_VARIABLE, 'http://yourcdn.com'); return $cdn_url . $base_path . $path; } else { return FALSE; } } /** * Gets the URL for a file when the basic mode is enabled. * * @param $path * The path to get the URL for. */ function cdn_advanced_get_url($path) { $db = _cdn_advanced_get_db_connection(); // In case no connection to the database could be made, pretend the file was // not found in the synced files database. if (!$db) { return array(FALSE, FALSE); } // Get the real path to the file (resolves symbolic links). $input_file = realpath('./' . $path); // Retrieve the URLs of the file on the CDN. $sql = "SELECT url, server FROM synced_files WHERE input_file = :input_file"; $stmt = $db->prepare($sql); $stmt->bindParam(':input_file', $input_file, PDO::PARAM_STR); $stmt->execute(); $servers = $stmt->fetchAll(PDO::FETCH_ASSOC); // The file is not available from any server. if (count($servers) == 0) { $url = FALSE; $server = FALSE; } // If the file is available from multiple servers, then allow a special // function to pic the desired server. The decision can be made on any // desired criteria: user's location, user's role, current date … else if (count($servers) > 1 && function_exists('cdn_advanced_pick_server')) { $picked_server = cdn_advanced_pick_server($servers); $url = $picked_server['url']; $server = $picked_server['server']; } // The file is available from at least one server, simply pick the first. else { $url = $servers[0]['url']; $server = $servers[0]['server']; } return array($url, $server); } /** * Implementation of cdn_advanced_pick_server(). */ function cdn_advanced_pick_server($servers_for_file) { static $server_name; if (!isset($server_name)) { $server_name = 'ftp push cdn'; } // Try to pick the desired server - if the file being served is available on // our the desired server. foreach ($servers_for_file as $server_for_file) { if ($server_for_file['server'] == $server_name) { return $server_for_file; } } // In case our desired server does not have the file, pick the first server // that does have it. return $servers_for_file[0]; } //---------------------------------------------------------------------------- // Private functions. /** * Get a connection to the database. The resulting PDO object is statically * cached. * * @return * A database connection (through PDO), or FALSE in case of failure. */ function _cdn_advanced_get_db_connection() { static $db; $synced_files_db = variable_get(CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE, FALSE); if ($synced_files_db === FALSE || !file_exists($synced_files_db) || filesize($synced_files_db) == 0) { $db = FALSE; } elseif (!isset($db)) { try { $db = new PDO('sqlite:' . variable_get(CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE, '')); } catch(PDOException $e) { watchdog('cdn', t("Could not open synced files DB: %error.", array('%error' => $e))); $db = FALSE; } } return $db; }