View source
<?php
function bootstrap_tour_run_tour($name, $force = FALSE) {
$tour = bootstrap_tour_load($name);
if (empty($tour) || !empty($tour->disabled)) {
return;
}
if (!empty($tour->roles)) {
global $user;
$tour_roles = explode(',', $tour->roles);
$user_roles = array_keys($user->roles);
$compare = array_intersect($tour_roles, $user_roles);
if ($user->uid != 1 && empty($compare)) {
return;
}
}
if (!empty($tour->steps) && !is_array($tour->steps)) {
$tour->steps = unserialize($tour->steps);
}
if (count($tour->steps) > 1) {
$_SESSION['tour'] = $name;
}
$first_path = $tour->steps[0]['path'];
if ($first_path == current_path() || $first_path == request_path() || $first_path == '<front>' && request_path() == '') {
if (empty($_GET['step']) || $_GET['step'] == 0) {
if (!empty($_SESSION['nexttour'])) {
unset($_SESSION['nexttour']);
}
}
}
drupal_alter('bootstrap_tour', $tour);
$step_path = '';
foreach ($tour->steps as $key => &$step) {
if ($step['path']) {
$step_path = $step['path'];
}
else {
$step['path'] = $step_path;
}
if ($key == 0 && ($step['path'] == current_path() || $step['path'] == request_path() || $step['path'] == '<front>' && request_path() == '')) {
if (!empty($_GET['tour']) && (empty($_GET['step']) || $_GET['step'] == 0)) {
$tour->isFirstStep = TRUE;
}
}
$step['title'] = check_plain($step['title']);
$step['content'] = check_markup($step['content'], $step['format']);
}
$tour->force = $force;
$tour->cleanUrls = variable_get('clean_url', 0);
drupal_add_js(array(
'bootstrapTour' => array(
'tour' => $tour,
),
), 'setting');
if (module_exists('libraries') && ($library = libraries_detect('bootstrap_tour')) && !empty($library['installed'])) {
libraries_load('bootstrap_tour');
}
else {
global $base_url;
$base = parse_url($base_url);
drupal_add_css($base['scheme'] . '://cdnjs.cloudflare.com/ajax/libs/bootstrap-tour/0.6.1/css/bootstrap-tour.min.css', 'external');
drupal_add_js($base['scheme'] . '://cdnjs.cloudflare.com/ajax/libs/bootstrap-tour/0.6.1/js/bootstrap-tour.min.js', 'external');
}
drupal_add_js(drupal_get_path('module', 'bootstrap_tour') . '/js/bootstrap-tour.js');
drupal_add_css(drupal_get_path('module', 'bootstrap_tour') . '/css/bootstrap-tour.css');
}
function bootstrap_tour_end_current_tour() {
unset($_SESSION['tour']);
}
function bootstrap_tour_page_build(&$page) {
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
return;
}
$tours = bootstrap_tour_load_all();
$current_name = !empty($_SESSION['tour']) ? $_SESSION['tour'] : NULL;
if (!empty($_GET['tour']) && ($_GET['tour'] == $current_name || empty($_GET['step']))) {
$current_name = $_GET['tour'];
}
if (!empty($current_name)) {
foreach ($tours as $tour) {
if ($tour->name == $current_name) {
bootstrap_tour_run_tour($tour->name, TRUE);
return;
}
}
}
if (!empty($_SESSION['nexttour'])) {
foreach ($tours as $tour) {
if ($_SESSION['nexttour'] == $tour->name) {
bootstrap_tour_run_tour($tour->name, TRUE);
return;
}
}
}
foreach ($tours as $tour) {
if (!empty($tour->steps) && $tour->autorun) {
if (!is_array($tour->steps)) {
$tour->steps = unserialize($tour->steps);
}
$path = $tour->steps[0]['path'];
if ($path == current_path() || $path == request_path() || $path == '<front>' && request_path() == '') {
bootstrap_tour_run_tour($tour->name);
}
}
}
}
function bootstrap_tour_menu() {
$items = array();
$items['admin/structure/tours'] = array(
'title' => 'Site Tours',
'description' => 'Create, edit and delete guided site tours',
'page callback' => 'bootstrap_tour_list',
'access arguments' => array(
'administer bootstrap tours',
),
);
$items['admin/structure/tours/list'] = array(
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/structure/tours/add'] = array(
'title' => 'Add site tour',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'bootstrap_tour_form',
),
'access arguments' => array(
'administer bootstrap tours',
),
'type' => MENU_LOCAL_ACTION,
);
$items['admin/structure/tours/manage/%bootstrap_tour'] = array(
'title' => 'Edit site tour',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'bootstrap_tour_form',
4,
),
'access arguments' => array(
'administer bootstrap tours',
),
);
$items['admin/structure/tours/manage/%bootstrap_tour/edit'] = array(
'title' => 'Edit site tour',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/structure/tours/manage/%bootstrap_tour/delete'] = array(
'title' => 'Delete site tour',
'page arguments' => array(
'bootstrap_tour_delete_confirm',
4,
),
'page callback' => 'drupal_get_form',
'access arguments' => array(
'administer bootstrap tours',
),
'type' => MENU_LOCAL_TASK,
);
$items['admin/structure/tours/manage/%bootstrap_tour/toggle'] = array(
'title' => 'Toggle tour status',
'page arguments' => array(
4,
),
'page callback' => 'bootstrap_tour_toggle_status',
'access arguments' => array(
'administer bootstrap tours',
),
'type' => MENU_LOCAL_TASK,
);
$items['bootstrap_tour/ajax/end_current_tour'] = array(
'title' => 'AJAX callback to end current tour',
'page callback' => 'bootstrap_tour_end_current_tour',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
return $items;
}
function bootstrap_tour_permission() {
return array(
'administer bootstrap tours' => array(
'title' => t('Administer bootstrap tours'),
'description' => t('Create and edit Bootstrap Tours'),
),
);
}
function bootstrap_tour_delete_confirm($form, &$form_state, $tour = '') {
if (empty($tour)) {
drupal_goto('admin/structure/tours');
}
$form['tour'] = array(
'#type' => 'value',
'#value' => $tour->name,
);
return confirm_form($form, t('Are you sure you want to delete %title?', array(
'%title' => $tour->title,
)), 'admin/structure/tours', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
}
function bootstrap_tour_toggle_status($tour) {
if (empty($tour->disabled)) {
drupal_set_message(t('The ') . $tour->title . t(' tour has been disabled.'));
$disable = TRUE;
}
else {
drupal_set_message(t('The ') . $tour->title . t(' tour has been enabled.'));
$disable = FALSE;
}
ctools_export_crud_set_status('bootstrap_tour', $tour, $disable);
drupal_goto('admin/structure/tours');
}
function bootstrap_tour_delete_confirm_submit($form, &$form_state) {
if ($form_state['values']['confirm']) {
$tour = $form_state['values']['tour'];
$result = db_delete('bootstrap_tour')
->condition('name', $tour)
->execute();
drupal_set_message(t('Tour has been deleted.'));
}
$form_state['redirect'] = 'admin/structure/tours';
}
function bootstrap_tour_form($form, &$form_state, $tour = '') {
if (!empty($tour)) {
if (!empty($tour->steps) && !is_array($tour->steps)) {
$tour->steps = unserialize($tour->steps);
}
}
else {
$tour = new stdClass();
}
$form['title'] = array(
'#type' => 'textfield',
'#title' => t('Name'),
'#description' => t('A human readable name for this site tour.'),
'#required' => TRUE,
'#default_value' => !empty($tour->title) ? $tour->title : '',
);
$form['name'] = array(
'#type' => 'value',
'#value' => !empty($tour->name) ? $tour->name : '',
);
$form['description'] = array(
'#type' => 'textfield',
'#title' => t('Description'),
'#description' => t('Used for administrative purposes only.'),
'#default_value' => !empty($tour->description) ? $tour->description : '',
);
$form['roles'] = array(
'#type' => 'select',
'#title' => t('Roles'),
'#description' => t('Which roles can access this tour? Leave blank for all.'),
'#multiple' => TRUE,
'#options' => user_roles(),
'#default_value' => !empty($tour->roles) ? explode(',', $tour->roles) : '',
);
$form['autorun'] = array(
'#type' => 'checkbox',
'#title' => t('Automatically run'),
'#description' => t('Should this tour start automatically the first time a user visits the path of the first step? If this is checked, the first step must have the "Path" field filled out.'),
'#default_value' => !empty($tour->autorun) ? $tour->autorun : '',
'#weight' => 5,
);
$form['steps_fieldset'] = array(
'#type' => 'fieldset',
'#title' => t('Tour steps'),
'#prefix' => '<div id="steps-fieldset-wrapper">',
'#suffix' => '</div>',
'#weight' => 10,
);
if (empty($form_state['num_steps'])) {
if (empty($tour->steps)) {
$form_state['num_steps'] = 1;
}
else {
$form_state['num_steps'] = count($tour->steps);
}
}
for ($i = 0; $i < $form_state['num_steps']; $i++) {
$form['steps_fieldset'][$i . '_path'] = array(
'#type' => 'textfield',
'#title' => t('Path'),
'#required' => $i == 0,
'#description' => t('Which path should this step be displayed on? This is required on the first step, but if subsequent steps will use the same path as the previous step(s) you can leave this blank. Enter <front> for the front page.'),
'#default_value' => !empty($tour->steps[$i]['path']) ? $tour->steps[$i]['path'] : '',
);
$form['steps_fieldset'][$i . '_selector'] = array(
'#type' => 'textfield',
'#title' => t('CSS Selector'),
'#description' => t('Leave this blank if you want this popup to show up centered on the page and not attached to a specific element.'),
'#default_value' => !empty($tour->steps[$i]['selector']) ? $tour->steps[$i]['selector'] : '',
);
$form['steps_fieldset'][$i . '_placement'] = array(
'#type' => 'select',
'#title' => t('Placement'),
'#options' => array(
'top' => t('Top'),
'bottom' => t('Bottom'),
'left' => t('Left'),
'right' => t('Right'),
),
'#default_value' => !empty($tour->steps[$i]['placement']) ? $tour->steps[$i]['placement'] : '',
);
$form['steps_fieldset'][$i . '_title'] = array(
'#type' => 'textfield',
'#title' => t('Popup Title'),
'#required' => TRUE,
'#default_value' => !empty($tour->steps[$i]['title']) ? $tour->steps[$i]['title'] : '',
);
$form['steps_fieldset'][$i . '_content'] = array(
'#type' => 'text_format',
'#base_type' => 'textarea',
'#suffix' => '<hr />',
'#title' => t('Popup Content'),
'#default_value' => !empty($tour->steps[$i]['content']) ? $tour->steps[$i]['content'] : '',
);
}
$form['add_step'] = array(
'#type' => 'submit',
'#value' => t('Add another step'),
'#submit' => array(
'bootstrap_tour_form_add_one',
),
'#ajax' => array(
'callback' => 'bootstrap_tour_form_add_one_callback',
'wrapper' => 'steps-fieldset-wrapper',
),
'#suffix' => ' ',
'#weight' => 20,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
'#weight' => 20,
);
return $form;
}
function bootstrap_tour_form_add_one($form, &$form_state) {
$form_state['num_steps']++;
$form_state['rebuild'] = TRUE;
}
function bootstrap_tour_form_add_one_callback($form, $form_state) {
return $form['steps_fieldset'];
}
function bootstrap_tour_form_submit($form, &$form_state) {
$vals = $form_state['values'];
$tour = new stdClass();
$tour->description = $vals['description'];
$tour->title = $vals['title'];
$tour->is_new = empty($vals['name']) || bootstrap_tour_is_default($vals['name']);
$tour->name = !empty($vals['name']) ? $vals['name'] : bootstrap_tour_generate_machine_name($vals['title']);
$tour->autorun = $vals['autorun'];
$tour->roles = implode(',', $vals['roles']);
$i = 0;
while (!empty($vals[$i . '_title'])) {
$tour->steps[] = array(
'selector' => $vals[$i . '_selector'],
'path' => $vals[$i . '_path'],
'placement' => $vals[$i . '_placement'],
'title' => $vals[$i . '_title'],
'content' => $vals[$i . '_content']['value'],
'format' => $vals[$i . '_content']['format'],
);
$i++;
}
drupal_alter('bootstrap_tour_presave', $tour, $vals);
if ($tour->is_new) {
drupal_write_record('bootstrap_tour', $tour);
}
else {
drupal_write_record('bootstrap_tour', $tour, array(
'name',
));
}
drupal_set_message('Tour successfully saved.');
$form_state['redirect'] = 'admin/structure/tours';
}
function bootstrap_tour_list() {
$names = bootstrap_tour_load_all(TRUE);
$header = array(
t('Name'),
array(
'data' => t('Operations'),
'colspan' => '2',
),
);
$rows = array();
foreach ($names as $name => $tour) {
$row = array();
$row[] = array(
'data' => check_plain($tour->title),
);
$row[] = array(
'data' => l(t('edit'), 'admin/structure/tours/manage/' . $name),
);
if (!bootstrap_tour_is_default($tour->name)) {
$row[] = array(
'data' => l(t('delete'), 'admin/structure/tours/manage/' . $name . '/delete'),
);
}
else {
if (empty($tour->disabled)) {
$row[] = array(
'data' => l(t('disable'), 'admin/structure/tours/manage/' . $name . '/toggle'),
);
}
else {
$row[] = array(
'data' => l(t('enable'), 'admin/structure/tours/manage/' . $name . '/toggle'),
);
}
}
$rows[] = $row;
}
$build['tours_table'] = array(
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
'#empty' => t('No site tours available. <a href="@link">Add a site tour</a>.', array(
'@link' => url('admin/structure/tours/add'),
)),
);
return $build;
}
function bootstrap_tour_libraries_info() {
$libraries['bootstrap_tour'] = array(
'name' => 'Bootstrap Tour',
'vendor url' => 'http://bootstraptour.com',
'download url' => 'https://github.com/sorich87/bootstrap-tour/releases',
'path' => 'build',
'version' => '0.5.0',
'files' => array(
'js' => array(
'js/bootstrap-tour.min.js',
),
'css' => array(
'css/bootstrap-tour.min.css',
),
),
'variants' => array(
'minified' => array(
'files' => array(
'js' => array(
'js/bootstrap-tour.min.js',
),
'css' => array(
'css/bootstrap-tour.min.css',
),
),
),
'source' => array(
'files' => array(
'js' => array(
'js/bootstrap-tour.js',
),
'css' => array(
'css/bootstrap-tour.css',
),
),
),
),
);
return $libraries;
}
function bootstrap_tour_load_all($include_disabled = FALSE) {
ctools_include('export');
$tours = ctools_export_crud_load_all('bootstrap_tour');
if (!$include_disabled) {
$tours = array_filter($tours, 'bootstrap_tour_is_enabled');
}
return $tours;
}
function bootstrap_tour_load($name) {
ctools_include('export');
return ctools_export_crud_load('bootstrap_tour', $name);
}
function bootstrap_tour_is_default($name) {
$tour = bootstrap_tour_load($name);
return !empty($tour->in_code_only);
}
function bootstrap_tour_is_enabled($tour) {
return empty($tour->disabled);
}
function bootstrap_tour_generate_machine_name($text) {
$text = preg_replace('/[^A-Za-z0-9_]+/', '_', $text);
return strtolower($text);
}