- #47510: Show JavaScript alert when PHP errors occur
							parent
							
								
									afde65151c
								
							
						
					
					
						commit
						d38429248e
					
				| 
						 | 
				
			
			@ -1171,6 +1171,8 @@ function drupal_call_js($function) {
 | 
			
		|||
 | 
			
		||||
/**
 | 
			
		||||
 * Converts a PHP variable into its Javascript equivalent.
 | 
			
		||||
 *
 | 
			
		||||
 * We use HTML-safe strings, i.e. with <, > and & escaped.
 | 
			
		||||
 */
 | 
			
		||||
function drupal_to_js($var) {
 | 
			
		||||
  switch (gettype($var)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1180,8 +1182,18 @@ function drupal_to_js($var) {
 | 
			
		|||
      return $var;
 | 
			
		||||
    case 'resource':
 | 
			
		||||
    case 'string':
 | 
			
		||||
      return '"'. str_replace(array("\r", "\n"), array('\r', '\n'), addslashes($var)) .'"';
 | 
			
		||||
      return '"'. str_replace(array("\r", "\n", "<", ">", "&"),
 | 
			
		||||
                              array('\r', '\n', '\x3c', '\x3e', '\x26'),
 | 
			
		||||
                              addslashes($var)) .'"';
 | 
			
		||||
    case 'array':
 | 
			
		||||
      if (array_keys($var) === range(0, sizeof($var) - 1)) {
 | 
			
		||||
        $output = array();
 | 
			
		||||
        foreach($var as $v) {
 | 
			
		||||
          $output[] = drupal_to_js($v);
 | 
			
		||||
        }
 | 
			
		||||
        return '[ '. implode(', ', $output) .' ]';
 | 
			
		||||
      }
 | 
			
		||||
      // Fall through  
 | 
			
		||||
    case 'object':
 | 
			
		||||
      $output = array();
 | 
			
		||||
      foreach ($var as $k => $v) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -113,24 +113,8 @@ function HTTPPost(uri, callbackFunction, callbackParameter, object) {
 | 
			
		|||
 * window.parent.iframeHandler() after submission.
 | 
			
		||||
 */
 | 
			
		||||
function redirectFormButton(uri, button, handler) {
 | 
			
		||||
  // Insert the iframe
 | 
			
		||||
  // Note: some browsers require the literal name/id attributes on the tag,
 | 
			
		||||
  // some want them set through JS. We do both.
 | 
			
		||||
  var div = document.createElement('div');
 | 
			
		||||
  div.innerHTML = '<iframe name="redirect-target" id="redirect-target" class="redirect"></iframe>';
 | 
			
		||||
  var iframe = div.firstChild;
 | 
			
		||||
  with (iframe) {
 | 
			
		||||
    name = 'redirect-target';
 | 
			
		||||
    setAttribute('name', 'redirect-target');
 | 
			
		||||
    id = 'redirect-target';
 | 
			
		||||
  }
 | 
			
		||||
  with (iframe.style) {
 | 
			
		||||
    position = 'absolute';
 | 
			
		||||
    height = '1px';
 | 
			
		||||
    width = '1px';
 | 
			
		||||
    visibility = 'hidden';
 | 
			
		||||
  }
 | 
			
		||||
  document.body.appendChild(iframe);
 | 
			
		||||
  // Make sure we have an iframe to target
 | 
			
		||||
  createIframe();
 | 
			
		||||
 | 
			
		||||
  // Trap the button
 | 
			
		||||
  button.onmouseover = button.onfocus = function() {
 | 
			
		||||
| 
						 | 
				
			
			@ -147,11 +131,34 @@ function redirectFormButton(uri, button, handler) {
 | 
			
		|||
      handler.onsubmit();
 | 
			
		||||
 | 
			
		||||
      // Set iframe handler for later
 | 
			
		||||
      window.iframeHandler = function (data) {
 | 
			
		||||
      window.iframeHandler = function () {
 | 
			
		||||
        var iframe = $('redirect-target');
 | 
			
		||||
        // Restore form submission
 | 
			
		||||
        button.form.action = action;
 | 
			
		||||
        button.form.target = target;
 | 
			
		||||
        handler.oncomplete(data);
 | 
			
		||||
 | 
			
		||||
        // Get response from iframe body
 | 
			
		||||
        try {
 | 
			
		||||
          response = (iframe.contentWindow || iframe.contentDocument || iframe).document.body.innerHTML;
 | 
			
		||||
          if (window.opera) {
 | 
			
		||||
            // Opera-hack: it returns innerHTML sanitized.
 | 
			
		||||
            response = response.replace(/"/g, '"');
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        catch (e) {
 | 
			
		||||
          response = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Recreate the iframe: re-using an old iframe can sometimes cause browser bugs.
 | 
			
		||||
        createIframe();
 | 
			
		||||
 | 
			
		||||
        response = parseJson(response);
 | 
			
		||||
        // Check response code
 | 
			
		||||
        if (response.status == 0) {
 | 
			
		||||
          handler.onerror(response.data);
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        handler.oncomplete(response.data);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -300,6 +307,55 @@ function stopEvent(event) {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Parse a JSON response.
 | 
			
		||||
 *
 | 
			
		||||
 * The result is either the JSON object, or an object with 'status' 0 and 'data' an error message.
 | 
			
		||||
 */
 | 
			
		||||
function parseJson(data) {
 | 
			
		||||
  if (data.substring(0,1) != '{') {
 | 
			
		||||
    return { status: 0, data: data.length ? data : 'Unspecified error' };
 | 
			
		||||
  }
 | 
			
		||||
  return eval('(' + data + ');');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create an invisible iframe for form submissions.
 | 
			
		||||
 */
 | 
			
		||||
function createIframe() {
 | 
			
		||||
  // Delete any previous iframe
 | 
			
		||||
  deleteIframe();
 | 
			
		||||
  // Note: some browsers require the literal name/id attributes on the tag,
 | 
			
		||||
  // some want them set through JS. We do both.
 | 
			
		||||
  window.iframeHandler = function () {};
 | 
			
		||||
  var div = document.createElement('div');
 | 
			
		||||
  div.id = 'redirect-holder';
 | 
			
		||||
  div.innerHTML = '<iframe name="redirect-target" id="redirect-target" class="redirect" onload="window.iframeHandler();"></iframe>';
 | 
			
		||||
  var iframe = div.firstChild;
 | 
			
		||||
  with (iframe) {
 | 
			
		||||
    name = 'redirect-target';
 | 
			
		||||
    setAttribute('name', 'redirect-target');
 | 
			
		||||
    id = 'redirect-target';
 | 
			
		||||
  }
 | 
			
		||||
  with (iframe.style) {
 | 
			
		||||
    position = 'absolute';
 | 
			
		||||
    height = '1px';
 | 
			
		||||
    width = '1px';
 | 
			
		||||
    visibility = 'hidden';
 | 
			
		||||
  }
 | 
			
		||||
  document.body.appendChild(div);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Delete the invisible iframe for form submissions.
 | 
			
		||||
 */
 | 
			
		||||
function deleteIframe() {
 | 
			
		||||
  var holder = $('redirect-holder');
 | 
			
		||||
  if (typeof holder != 'undefined') {
 | 
			
		||||
    removeNode(holder);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Wrapper around document.getElementById().
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
 * the DOM afterwards through progressBar.element.
 | 
			
		||||
 *
 | 
			
		||||
 * method is the function which will perform the HTTP request to get the
 | 
			
		||||
 * progress bar status. Either HTTPGet or HTTPPost.
 | 
			
		||||
 * progress bar state. Either HTTPGet or HTTPPost.
 | 
			
		||||
 *
 | 
			
		||||
 * e.g. pb = new progressBar('myProgressBar');
 | 
			
		||||
 *      some_element.appendChild(pb.element);
 | 
			
		||||
| 
						 | 
				
			
			@ -18,14 +18,14 @@ function progressBar(id, callback, method) {
 | 
			
		|||
  this.element.id = id;
 | 
			
		||||
  this.element.className = 'progress';
 | 
			
		||||
  this.element.innerHTML = '<div class="percentage"></div>'+
 | 
			
		||||
                           '<div class="status"> </div>'+
 | 
			
		||||
                           '<div class="message"> </div>'+
 | 
			
		||||
                           '<div class="bar"><div class="filled"></div></div>';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Set the percentage and status message for the progressbar.
 | 
			
		||||
 */
 | 
			
		||||
progressBar.prototype.setProgress = function (percentage, status) {
 | 
			
		||||
progressBar.prototype.setProgress = function (percentage, message) {
 | 
			
		||||
  var divs = this.element.getElementsByTagName('div');
 | 
			
		||||
  var div;
 | 
			
		||||
  for (var i = 0; div = divs[i]; ++i) {
 | 
			
		||||
| 
						 | 
				
			
			@ -37,12 +37,12 @@ progressBar.prototype.setProgress = function (percentage, status) {
 | 
			
		|||
        divs[i].innerHTML = percentage + '%';
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (hasClass(divs[i], 'status')) {
 | 
			
		||||
      divs[i].innerHTML = status;
 | 
			
		||||
    if (hasClass(divs[i], 'message')) {
 | 
			
		||||
      divs[i].innerHTML = message;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (this.callback) {
 | 
			
		||||
    this.callback(percentage, status, this);
 | 
			
		||||
    this.callback(percentage, message, this);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -84,12 +84,16 @@ progressBar.prototype.receivePing = function (string, xmlhttp, pb) {
 | 
			
		|||
  if (xmlhttp.status != 200) {
 | 
			
		||||
    return alert('An HTTP error '+ xmlhttp.status +' occured.\n'+ pb.uri);
 | 
			
		||||
  }
 | 
			
		||||
  // Split into values
 | 
			
		||||
  var matches = string.length > 0 ? string.split('|') : [];
 | 
			
		||||
  // Update progress
 | 
			
		||||
  if (matches.length >= 2) {
 | 
			
		||||
    pb.setProgress(matches[0], matches[1]);
 | 
			
		||||
  // Parse response
 | 
			
		||||
  var progress = parseJson(string);
 | 
			
		||||
  // Display errors
 | 
			
		||||
  if (progress.status == 0) {
 | 
			
		||||
    alert(progress.data);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Update display
 | 
			
		||||
  pb.setProgress(progress.percentage, progress.message);
 | 
			
		||||
  // Schedule next timer
 | 
			
		||||
  pb.timer = setTimeout(function() { pb.sendPing(); }, pb.delay);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ if (isJsEnabled()) {
 | 
			
		|||
      }
 | 
			
		||||
 | 
			
		||||
      var progress = new progressBar('updateprogress', updateCallback, HTTPPost);
 | 
			
		||||
      progress.setProgress(-1, 'Starting updates...');
 | 
			
		||||
      progress.setProgress(-1, 'Starting updates');
 | 
			
		||||
      $('progress').appendChild(progress.element);
 | 
			
		||||
      progress.startMonitoring('update.php?op=do_update', 0);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,9 +54,22 @@ jsUpload.prototype.onsubmit = function () {
 | 
			
		|||
 */
 | 
			
		||||
jsUpload.prototype.oncomplete = function (data) {
 | 
			
		||||
  // Remove progressbar
 | 
			
		||||
  removeNode(this.progress);
 | 
			
		||||
  removeNode(this.progress.element);
 | 
			
		||||
  this.progress = null;
 | 
			
		||||
  // Replace form and re-attach behaviour
 | 
			
		||||
  $(this.wrapper).innerHTML = data;
 | 
			
		||||
  uploadAutoAttach();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handler for the form redirection error.
 | 
			
		||||
 */
 | 
			
		||||
jsUpload.prototype.onerror = function (error) {
 | 
			
		||||
  alert('An error occurred:\n\n'+ error);
 | 
			
		||||
  // Remove progressbar
 | 
			
		||||
  removeNode(this.progress.element);
 | 
			
		||||
  this.progress = null;
 | 
			
		||||
  // Undo hide
 | 
			
		||||
  $(this.hide).style.position = 'static';
 | 
			
		||||
  $(this.hide).style.left = '0px';
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -543,6 +543,6 @@ function upload_js() {
 | 
			
		|||
  $output = theme('status_messages') . form_render($form);
 | 
			
		||||
 | 
			
		||||
  // We send the updated file attachments form.
 | 
			
		||||
  print drupal_call_js('window.parent.iframeHandler', $output);
 | 
			
		||||
  print drupal_to_js(array('status' => TRUE, 'data' => $output));
 | 
			
		||||
  exit;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -543,6 +543,6 @@ function upload_js() {
 | 
			
		|||
  $output = theme('status_messages') . form_render($form);
 | 
			
		||||
 | 
			
		||||
  // We send the updated file attachments form.
 | 
			
		||||
  print drupal_call_js('window.parent.iframeHandler', $output);
 | 
			
		||||
  print drupal_to_js(array('status' => TRUE, 'data' => $output));
 | 
			
		||||
  exit;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										19
									
								
								update.php
								
								
								
								
							
							
						
						
									
										19
									
								
								update.php
								
								
								
								
							| 
						 | 
				
			
			@ -396,7 +396,7 @@ function update_progress_page() {
 | 
			
		|||
 *
 | 
			
		||||
 * @return
 | 
			
		||||
 *   An array indicating the status after doing updates. The first element is
 | 
			
		||||
 *   the overall percent finished. The second element is a status message.
 | 
			
		||||
 *   the overall percentage finished. The second element is a status message.
 | 
			
		||||
 */
 | 
			
		||||
function update_do_updates() {
 | 
			
		||||
  while (($update = reset($_SESSION['update_remaining']))) {
 | 
			
		||||
| 
						 | 
				
			
			@ -412,12 +412,12 @@ function update_do_updates() {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  if ($_SESSION['update_total']) {
 | 
			
		||||
    $percent = floor(($_SESSION['update_total'] - count($_SESSION['update_remaining']) + $update_finished) / $_SESSION['update_total'] * 100);
 | 
			
		||||
    $percentage = floor(($_SESSION['update_total'] - count($_SESSION['update_remaining']) + $update_finished) / $_SESSION['update_total'] * 100);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    $percent = 100;
 | 
			
		||||
    $percentage = 100;
 | 
			
		||||
  }
 | 
			
		||||
  return array($percent, isset($update['module']) ? 'Updating '. $update['module'] .' module' : 'Updating complete');
 | 
			
		||||
  return array($percentage, isset($update['module']) ? 'Updating '. $update['module'] .' module' : 'Updating complete');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function update_do_update_page() {
 | 
			
		||||
| 
						 | 
				
			
			@ -437,26 +437,27 @@ function update_do_update_page() {
 | 
			
		|||
  }
 | 
			
		||||
  ini_set('display_errors', FALSE);
 | 
			
		||||
 | 
			
		||||
  print implode('|', update_do_updates());
 | 
			
		||||
  list($percentage, $message) = update_do_updates();
 | 
			
		||||
  print drupal_to_js(array('status' => TRUE, 'percentage' => $percentage, 'message' => $message));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function update_progress_page_nojs() {
 | 
			
		||||
  $new_op = 'do_update_nojs';
 | 
			
		||||
  if ($_SERVER['REQUEST_METHOD'] == 'GET') {
 | 
			
		||||
    list($percent, $message) = update_do_updates();
 | 
			
		||||
    if ($percent == 100) {
 | 
			
		||||
    list($percentage, $message) = update_do_updates();
 | 
			
		||||
    if ($percentage == 100) {
 | 
			
		||||
      $new_op = 'finished';
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    // This is the first page so return some output immediately.
 | 
			
		||||
    $percent = 0;
 | 
			
		||||
    $percentage = 0;
 | 
			
		||||
    $message = 'Starting updates';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  drupal_set_html_head('<meta http-equiv="Refresh" content="0; URL=update.php?op='. $new_op .'">');
 | 
			
		||||
  drupal_set_title('Updating');
 | 
			
		||||
  $output = theme('progress_bar', $percent, $message);
 | 
			
		||||
  $output = theme('progress_bar', $percentage, $message);
 | 
			
		||||
  $output .= '<p>Updating your site will take a few seconds.</p>';
 | 
			
		||||
 | 
			
		||||
  return $output;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue