PageRenderTime 46ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/sites/all/modules/contrib/drupalforfirebug/drupalforfirebug.module

https://bitbucket.org/antisocnet/drupal
Unknown | 657 lines | 612 code | 45 blank | 0 comment | 0 complexity | 88985cb6aaeed8aee496c45364fb90c5 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0, LGPL-2.1
  1. <?php
  2. /**
  3. * Implementation of hook_init()
  4. */
  5. function drupalforfirebug_init() {
  6. // Do nothing
  7. }
  8. /**
  9. * Implementation of hook_example()
  10. */
  11. function drupalforfirebug_exit() {
  12. $dff = TRUE;
  13. // Try not to break non html pages. [from new devel.module]
  14. if (function_exists('drupal_get_http_header')) {
  15. $header = drupal_get_http_header('content-type');
  16. if ($header) {
  17. $formats = array('xml', 'javascript', 'json', 'plain', 'image', 'application', 'csv', 'x-comma-separated-values');
  18. foreach ($formats as $format) {
  19. if (strstr($header, $format)) {
  20. $dff = FALSE;
  21. }
  22. }
  23. }
  24. }
  25. // Exclude AJAX Functionality from Ctools
  26. if (arg(1) == 'ajax' || arg(3) == 'ajax') {
  27. $dff = FALSE;
  28. }
  29. // Try not to break non html pages. [from new devel.module]
  30. if (function_exists('drupal_get_http_header')) {
  31. $header = drupal_get_http_header('content-type');
  32. if ($header) {
  33. $formats = array('xml', 'javascript', 'json', 'plain', 'image', 'application', 'csv', 'x-comma-separated-values');
  34. foreach ($formats as $format) {
  35. if (strstr($header, $format)) {
  36. $dff = FALSE;
  37. }
  38. }
  39. }
  40. }
  41. // Check with Devel if Installed
  42. if (module_exists('devel')) {
  43. if (drupal_is_cli()) {
  44. $dff = FALSE;
  45. }
  46. }
  47. global $_drupalforfirebug_enable_output;
  48. if($_drupalforfirebug_enable_output !== TRUE) {
  49. $dff = FALSE;
  50. }
  51. if ($dff) {
  52. // Load Relevant Files and Register Shutdown
  53. drupal_load('module', 'user');
  54. register_shutdown_function('drupalforfirebug_shutdown');
  55. // Load the SQL Query Information
  56. global $queries;
  57. $queries = Database::getLog('devel', 'default');
  58. }
  59. }
  60. /**
  61. * Implementation of hook_menu()
  62. */
  63. function drupalforfirebug_menu() {
  64. $items['admin/firebug/exec'] = array(
  65. 'page callback' => 'drupalforfirebug_get_exec_php_callback',
  66. 'access arguments' => array('access content'),
  67. 'type' => MENU_CALLBACK,
  68. );
  69. return $items;
  70. }
  71. /**
  72. * Implementation of hook_nodes()
  73. * TODO - are there other hooks we want to track?
  74. */
  75. function drupalforfirebug_node_delete($node) {
  76. drupalforfirebug_node_process($node, 'delete');
  77. }
  78. function drupalforfirebug_node_insert($node) {
  79. drupalforfirebug_node_process($node, 'insert');
  80. }
  81. function drupalforfirebug_node_load($nodes, $types) {
  82. foreach($nodes as $node) {
  83. // TOOD - make this work
  84. drupalforfirebug_node_process($node, 'load');
  85. }
  86. }
  87. function drupalforfirebug_node_update($node) {
  88. drupalforfirebug_node_process($node, 'update');
  89. }
  90. function drupalforfirebug_node_validate($node) {
  91. drupalforfirebug_node_process($node, 'validate');
  92. }
  93. function drupalforfirebug_node_view($node) {
  94. drupalforfirebug_node_process($node, 'view');
  95. }
  96. /**
  97. * Processing function for Node API
  98. */
  99. function drupalforfirebug_node_process(&$node, $op) {
  100. global $dfp_runtime;
  101. if (!user_access('Access Firebug Debug')) {
  102. return;
  103. }
  104. $nid = (isset($node->nid)) ? $node->nid : '*'. t('NEW') . '*';
  105. $data = drupalforfirebug_array_compare((array) $dfp_runtime['drupalforfirebug_nodes']['original'][$node->type][$nid], (array) $node);
  106. $output = drupalforfirebug_field_object('node', $nid, $op, $data);
  107. drupalforfirebug_log($output, 'hook_nodeapi');
  108. }
  109. /**
  110. * Implementation of hook_views_pre_view();
  111. */
  112. function drupalforfirebug_views_pre_view(&$view, &$display_id) {
  113. global $dfp_runtime;
  114. if (!user_access('Access Firebug Debug')) {
  115. return;
  116. }
  117. $data = drupalforfirebug_array_compare((array) $dfp_runtime['drupalforfirebug_views']['original'][$view->name], (array) $view);
  118. $output = drupalforfirebug_field_object('view', $view->name, NULL, $data);
  119. drupalforfirebug_log($output, 'hook_views');
  120. }
  121. /**
  122. * Implementation of hook_page_alter()
  123. */
  124. function drupalforfirebug_page_alter(&$page) {
  125. global $dfp_runtime;
  126. global $_drupalforfirebug_enable_output;
  127. $_drupalforfirebug_enable_output = TRUE;
  128. // TODO - make this work without recursion problems
  129. // $data = drupalforfirebug_array_compare((array) $dfp_runtime['drupalforfirebug_page']['original']['page'], (array) $page);
  130. // $output = drupalforfirebug_field_object('page', 'page', NULL, $data);
  131. $output = t('Page Alter Support is Not Yet Implemented');
  132. drupalforfirebug_log($output, 'hook_page_alter');
  133. }
  134. /**
  135. * Implementation of hook_form_alter()
  136. */
  137. function drupalforfirebug_form_alter(&$form, &$form_state, $form_id) {
  138. global $dfp_runtime;
  139. if (!user_access('Access Firebug Debug')) {
  140. return;
  141. }
  142. if ($form_id != 'drupalforfirebug_execute_form') {
  143. $form_modified = (array) $form;
  144. $data = drupalforfirebug_array_compare($dfp_runtime['drupalforfirebug_forms']['original'][$form_id], $form_modified);
  145. $output = drupalforfirebug_field_object('form', $form_id, NULL, $data);
  146. drupalforfirebug_log($output, 'hook_form_alter');
  147. }
  148. }
  149. /**
  150. * Implementation of hook_users()
  151. */
  152. function drupalforfirebug_user_insert(&$edit, $account, $category) {
  153. drupalforfirebug_user_processing('insert', $account);
  154. }
  155. function drupalforfirebug_user_load($users) {
  156. foreach($users as $account) {
  157. drupalforfirebug_user_processing('insert', $account);
  158. }
  159. }
  160. // TODO - more user hook stuff
  161. /**
  162. * Processor for Hook Usering
  163. */
  164. function drupalforfirebug_user_processing($op, &$account) {
  165. global $dfp_runtime;
  166. if (!user_access('Access Firebug Debug')) {
  167. return;
  168. }
  169. if (isset($account->uid)) {
  170. $uid = $account->uid;
  171. $name = $account->name;
  172. } else {
  173. $uid = '*' . t('NEW') . '*';
  174. $name = '*' . t('NEW') . '*';
  175. }
  176. if (is_object($account)) {
  177. $account_clone = clone($account);
  178. $account_clone->pass = '**' . t('Not shown for security reasons') . '**';
  179. $data = drupalforfirebug_array_compare((array) $account_clone, (array) $account_clone);
  180. $output = drupalforfirebug_field_object('user', $uid, $op, $data);
  181. drupalforfirebug_log($output, 'hook_user');
  182. }
  183. }
  184. /**
  185. * API Function to Record a Message to the Drupal Firebug Log
  186. */
  187. function drupalforfirebug_log($message, $type = 'general') {
  188. global $dfp_runtime;
  189. $dfp_runtime['firebug_messages'][$type][] = $message;
  190. }
  191. /**
  192. * Command Function to Record a Data Element to the Drupal Firebug Log
  193. */
  194. function firep($element, $title = NULL) {
  195. if ($title) {
  196. drupalforfirebug_log('<strong>'.$title.':</strong>');
  197. }
  198. drupalforfirebug_log('<PRE>'. print_r($element, true) . '<br><br></PRE>', 'general');
  199. }
  200. /**
  201. * Output Function to Return the Results of the Log
  202. */
  203. function drupalforfirebug_get($panetype) {
  204. global $dfp_runtime;
  205. $output = '';
  206. if (isset($dfp_runtime['firebug_messages'][$panetype])) {
  207. foreach($dfp_runtime['firebug_messages'][$panetype] as $message) {
  208. $output .= '<div>' . $message .'</div>';
  209. }
  210. unset($dfp_runtime['firebug_messages'][$panetype]);
  211. return $output;
  212. }
  213. }
  214. /**
  215. * Output Function to Return the Results of the SQL Log
  216. */
  217. function drupalforfirebug_get_sql_log() {
  218. $output = '<fieldset>';
  219. if (!module_exists('devel')) {
  220. $output .= '<legend>' . t('Devel Module is Not Installed') . '</legend>';
  221. $output .= t('Please install and enable the Devel Module to display the SQL queries.');
  222. } elseif (!variable_get('devel_query_display', 0)) {
  223. $output .= '<legend>' . t('Query Logging is Not Enabled') . '</legend>';
  224. $output .= t('Please enable "Display query info" in the Devel Module Settings (devel/settings) to use this feature.');
  225. } else {
  226. if (function_exists('theme_get_registry') && theme_get_registry()) {
  227. global $queries;
  228. list($counts, $query_summary) = devel_query_summary($queries);
  229. $output .= '<legend>' . t('SQL Query Log') . '</legend>';
  230. $output .= $query_summary;
  231. $output .= drupalforfirebug_devel_query_table($queries, $counts);
  232. }
  233. }
  234. $output .= '</fieldset>';
  235. return $output;
  236. }
  237. /**
  238. * Generates an Execute PHP Drupal For Firebug Form
  239. **/
  240. function drupalforfirebug_execute_form() {
  241. $form['code'] = array(
  242. '#type' => 'textarea',
  243. '#rows' => 2,
  244. '#description' => t('Enter PHP code for execution. Do not use <code>&lt;?php ?&gt;</code> tags.')
  245. );
  246. $form['token'] = array(
  247. '#type' => 'hidden',
  248. '#value' => drupal_get_token(),
  249. );
  250. $form['op'] = array('#type' => 'submit', '#value' => t('Execute'));
  251. $form['#redirect'] = FALSE;
  252. $form['#action'] = url('admin/firebug/exec', array('absolute' => TRUE));
  253. $form['#skip_duplicate_check'] = TRUE;
  254. return $form;
  255. }
  256. function drupalforfirebug_get_php_exec_area() {
  257. $output = '<object style="width:100%;frameborder:0;height:100%;margin-bottom:-3px;" type="text/html" data="' . url('admin/firebug/exec', array('absolute' => TRUE)) . '"></object>';
  258. return $output;
  259. }
  260. function drupalforfirebug_get_php_exec($code = NULL, $token = NULL) {
  261. $output = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
  262. $output .= '<html><head><title>Execute PHP Code</title>';
  263. $output .= drupal_get_js();
  264. $output .= '</head><body>';
  265. $output .= '<fieldset>';
  266. if (!user_access('Execute Firebug PHP') || (!is_null($code) && !drupal_valid_token($token))) {
  267. $output .= '<legend>' . t('Execute Firebug PHP') . '</legend>';
  268. $output .= t('You do not have the proper permissions to use this functionality.');
  269. $output .= '</fieldset></body></html>';
  270. print $output;
  271. exit();
  272. } else {
  273. if (!$code) {
  274. $output .= '<legend>' . t('Execute Firebug PHP') . '</legend>';
  275. $dff_exec_form = drupal_get_form('drupalforfirebug_execute_form');
  276. $output .= drupal_render($dff_exec_form);
  277. $output .= '</fieldset></body></html>';
  278. print $output;
  279. exit();
  280. } else {
  281. $output = '<legend>' . t('PHP Code Execution Results') . '</legend>';
  282. // Run the PHP command, get output in variable
  283. ob_start();
  284. eval($code);
  285. $eval_result = ob_get_contents();
  286. ob_end_clean();
  287. $output .= '<PRE>' . $eval_result . '</PRE>';
  288. $output .= '</fieldset></body></html>';
  289. print $output;
  290. exit();
  291. }
  292. }
  293. }
  294. /**
  295. * Outputs a Execute PHP Form
  296. */
  297. function drupalforfirebug_get_exec_php_callback() {
  298. $code = (isset($_POST['code'])) ? $_POST['code'] : NULL;
  299. $token = (isset($_POST['token'])) ? $_POST['token'] : NULL;
  300. return drupalforfirebug_get_php_exec($code, $token);
  301. }
  302. /**
  303. * Output Function to Return Hidden Div Containers in Footer
  304. */
  305. function drupalforfirebug_shutdown() {
  306. if (!user_access('Access Firebug Debug')) {
  307. return;
  308. }
  309. $output = '<div style="display: none" id="drupalforfirebug_general">';
  310. $output .= '<fieldset>';
  311. $output .= '<legend>' . t('Drupal for Firebug General Messages') . '</legend>';
  312. $general_messages = drupalforfirebug_get('general');
  313. $output .= $general_messages;
  314. if (!$general_messages) {
  315. $output .= t('There were no messages sent to the general log. Please use "firep($item, $optional_title)" to output messages to this console.');
  316. }
  317. $output .= '</div>';
  318. $output .= '<div style="display: none" id="drupalforfirebug_sql">';
  319. $output .= drupalforfirebug_get_sql_log();
  320. $output .= '</div>';
  321. $output .= '<div style="display: none" id="drupalforfirebug_hook_form_alter">';
  322. $output .= $form_alter_output = drupalforfirebug_get('hook_form_alter');
  323. if (!$form_alter_output) { $output .= t('There was no form altering.'); }
  324. $output .= '</div>';
  325. $output .= '<div style="display: none" id="drupalforfirebug_hook_user">';
  326. $output .= $user_output = drupalforfirebug_get('hook_user');
  327. if (!$user_output) { $output .= t('There was no user processing.'); }
  328. $output .= '</div>';
  329. $output .= '<div style="display: none" id="drupalforfirebug_hook_nodeapi">';
  330. $output .= $node_api_output = drupalforfirebug_get('hook_nodeapi');
  331. if (!$node_api_output) { $output .= t('There was no node processing.'); }
  332. $output .= '</div>';
  333. $output .= '<div style="display: none" id="drupalforfirebug_hook_views">';
  334. if (module_exists('views')) {
  335. $output .= $views_output = drupalforfirebug_get('hook_views');
  336. if (!$views_output) { $output .= t('There was no views processing.'); }
  337. } else {
  338. $output .= t('The views module is not installed.');
  339. }
  340. $output .= '</div>';
  341. $output .= '<div style="display: none" id="drupalforfirebug_hook_page_alter">';
  342. $output .= $page_output = drupalforfirebug_get('hook_page_alter');
  343. if (!$page_output) { $output .= t('There was no page processing.'); }
  344. $output .= '</div>';
  345. $output .= '<div style="display: none" id="drupalforfirebug_php">';
  346. $output .= drupalforfirebug_get_php_exec_area();
  347. $output .= '</div>';
  348. print $output;
  349. unset($GLOBALS['dfp_runtime']);
  350. }
  351. /**
  352. * Implementation of hook_permission()
  353. */
  354. function drupalforfirebug_permission() {
  355. return array(
  356. 'Access Firebug Debug' => array(
  357. 'title' => t('Access Firebug Debug'),
  358. ),
  359. 'Execute Firebug PHP' => array(
  360. 'title' => t('Execute Firebug PHP'),
  361. ),
  362. );
  363. }
  364. /**
  365. * Generalized Array Comparision Function
  366. */
  367. function drupalforfirebug_array_compare($a, $b) {
  368. $data = drupalforfirebug_array_compare_code($a, $b);
  369. $style = drupalforfirebug_array_highlight_code($data);
  370. return $style;
  371. }
  372. /**
  373. * Specialized Function to Return an Array Row
  374. */
  375. function drupalforfirebug_array_row_build($key, $value, $style, $depth) {
  376. $spacing = '';
  377. for ($x = 0; $x <= $depth; $x++) {
  378. $spacing .= '&nbsp;&nbsp;&nbsp;&nbsp;';
  379. }
  380. switch ($style) {
  381. case 'ADDED':
  382. $color = '<span style="color: green;">';
  383. $colorend = '</span>';
  384. break;
  385. case 'REMOVED':
  386. $color = '<span style="color: red;">';
  387. $colorend = '</span>';
  388. break;
  389. case 'SAME':
  390. $color = '<span style="color: black;">';
  391. $colorend = '</span>';
  392. break;
  393. case 'DIFFERENT':
  394. $color = '<span style="color: orange;">';
  395. $colorend = '</span>';
  396. break;
  397. default: // suppose to be for objects
  398. $color = '<span style="color: grey;">'.$style;
  399. $colorend = '</span>';
  400. break;
  401. }
  402. $output = '';
  403. if (is_array($value) || is_object($value)) {
  404. if ($style == 'DIFFERENT') { // do not highlight if contained item is just changed.
  405. $color = '';
  406. $colorend = '';
  407. }
  408. if (is_array($value)) {
  409. $output .= "<div>$spacing $color [$key] => array ( $colorend </div>";
  410. } else {
  411. $output .= '<div>$spacing <span style="color: grey;"> [' . $key .'] => stdClass (' . $colorend .'</div>';
  412. }
  413. $output .= drupalforfirebug_array_highlight_code($value, $depth + 1);
  414. $output .= "<div>$spacing $color ) $colorend </div>";
  415. } else {
  416. if (isset($key) || isset($value)) {
  417. if (is_resource($value)) {
  418. $output .= "<div>$spacing $color [$key] => RESOURCE $colorend </div>";
  419. } else {
  420. $output .= "<div>$spacing $color [$key] => [" . check_plain($value) . "] $colorend </div>";
  421. }
  422. }
  423. }
  424. return $output;
  425. }
  426. /**
  427. * Specialized Array Data Style Function
  428. */
  429. function drupalforfirebug_array_highlight_code($data, $depth = 0) {
  430. // Smartly Handling Recursion for Objects
  431. if (is_object($data)) {
  432. $data = (array) $data;
  433. static $refChain = array();
  434. foreach ($refChain as $refVal) {
  435. if ($refVal === $data) {
  436. $data = array('**' . t('Recursion Detected') . '**');
  437. }
  438. }
  439. array_push($refChain, $data);
  440. }
  441. $output = '';
  442. foreach($data as $key => $value) {
  443. if ((string) $key != '#firebug_style') {
  444. if (isset($data['#firebug_style']) && isset($data['#firebug_style'][$key])) {
  445. $output .= drupalforfirebug_array_row_build($key, $value, $data['#firebug_style'][$key], $depth);
  446. }
  447. }
  448. }
  449. return $output;
  450. }
  451. /**
  452. * Specialized Array Data Comparision Code
  453. */
  454. function drupalforfirebug_array_compare_code($a, $b, $c = array(), $history = array()) {
  455. // Create the Compared Data Object
  456. $maxcount = count($a) > count($b) ? count($a) : count($b);
  457. $akeys = is_array($a) ? array_keys($a) : array();
  458. $bkeys = is_array($b) ? array_keys($b) : array();
  459. for ($x = 0; $x < $maxcount; $x++) {
  460. // Set the Proper Styling
  461. if (isset($akeys[$x]) && array_key_exists($akeys[$x], array_flip($bkeys))) { // is it in B array?
  462. if ($a[$akeys[$x]] === $b[$akeys[$x]]) {
  463. $c['#firebug_style'][$akeys[$x]] = 'SAME';
  464. } else {
  465. $c['#firebug_style'][$akeys[$x]] = 'DIFFERENT';
  466. }
  467. } else { // not in B array, must be removed
  468. if (isset($akeys[$x])) {
  469. $c['#firebug_style'][$akeys[$x]] = 'REMOVED';
  470. }
  471. }
  472. // Set the Proper Element
  473. if (isset($akeys[$x]) && is_array($a[$akeys[$x]]) && $bkeys) { // is b a valid array
  474. if (isset($c[$akeys[$x]])) {
  475. $aval = &$a[$akeys[$x]];
  476. $bval = &$b[$akeys[$x]];
  477. $cval = &$c[$akeys[$x]];
  478. $c[$akeys[$x]] = drupalforfirebug_array_compare_code($aval, $bval, $cval);
  479. } else {
  480. $aval = &$a[$akeys[$x]];
  481. $bval = &$b[$akeys[$x]];
  482. $c[$akeys[$x]] = drupalforfirebug_array_compare_code($aval, $bval, array());
  483. }
  484. } else {
  485. if (isset($akeys[$x]) && array_key_exists($akeys[$x], array_flip($bkeys))) { // is it in B array?
  486. if ($a[$akeys[$x]] === $b[$akeys[$x]]) {
  487. $c[$akeys[$x]] = $a[$akeys[$x]];
  488. } else {
  489. $c[$akeys[$x]] = $b[$akeys[$x]];
  490. }
  491. } else { // not in B array, must be removed
  492. if (isset($akeys[$x])) {
  493. $c[$akeys[$x]] = $a[$akeys[$x]];
  494. }
  495. }
  496. }
  497. if (isset($bkeys[$x]) && isset($b[$bkeys[$x]])) { // does b have a valid argument
  498. // Set the Proper Styling
  499. if (array_key_exists($bkeys[$x], array_flip($akeys))) { // is it in A array?
  500. // exists in the A array, already processed
  501. } else {
  502. $c[$bkeys[$x]] = $b[$bkeys[$x]];
  503. $c['#firebug_style'][$bkeys[$x]] = 'ADDED';
  504. }
  505. // Set the Proper Element
  506. $aval = &$a[$bkeys[$x]];
  507. $bval = &$b[$bkeys[$x]];
  508. $cval = &$c[$bkeys[$x]];
  509. if (isset($bval) && is_array($bval) && isset($aval) && isset($cval)) { // is b a valid array
  510. $c[$bkeys[$x]] = drupalforfirebug_array_compare_code($aval, $bval, $cval);
  511. }
  512. }
  513. }
  514. return $c;
  515. }
  516. // Array Handling Helper Function
  517. function do_offset($level) {
  518. $offset = ""; // offset for subarry
  519. for ($i=1; $i<$level;$i++) {
  520. $offset = $offset . "<td></td>";
  521. }
  522. return $offset;
  523. }
  524. // Array Handling Helper Function
  525. function drupalforfirebug_show_array($array, $level, $sub){
  526. $output = '';
  527. if (is_array($array) == 1){ // check if input is an array
  528. foreach($array as $key_val => $value) {
  529. $offset = "";
  530. if (is_array($value) == 1){ // array is multidimensional
  531. $output .= "<tr>";
  532. $offset = do_offset($level);
  533. $output .= $offset . "<td>" . $key_val . "</td>";
  534. $output .= drupalforfirebug_show_array($value, $level+1, 1);
  535. }
  536. else{ // (sub)array is not multidim
  537. if ($sub != 1){ // first entry for subarray
  538. $output .= "<tr nosub>";
  539. $offset = do_offset($level);
  540. }
  541. $sub = 0;
  542. $output .= $offset . "<td main ".$sub." width=\"120\">" . $key_val .
  543. "</td><td width=\"120\">" . $value . "</td>";
  544. $output .= "</tr>\n";
  545. }
  546. } //foreach $array
  547. }
  548. return $output;
  549. }
  550. // Function to Show an Array
  551. function html_drupalforfirebug_show_array($array){
  552. $output = "<table cellspacing=\"0\" border=\"2\">\n";
  553. $output .= drupalforfirebug_show_array($array, 1, 0);
  554. $output .= "</table>\n";
  555. return $output;
  556. }
  557. /**
  558. * Function for fieldsets that wrap object dumps
  559. *
  560. * For efficiency and consistent behavior in firebug window
  561. * Use to be a theme function, but that broke things
  562. */
  563. function drupalforfirebug_field_object($marker, $id, $op = NULL, $data) {
  564. $output = '<fieldset class="toggler">';
  565. $output .= '<legend><strong><a href="#"><em>' . $op . '</em> $'. $marker .'->'. $id . '</a></strong></legend>';
  566. $output .= '<div class="content" style="display: none;">';
  567. $output .= '<div>' . '&nbsp;$'. $marker .' = (' . '</div>';
  568. $output .= $data;
  569. $output .= '<div>' . '&nbsp;);</div>';
  570. $output .= '</div>';
  571. $output .= '</fieldset>';
  572. return $output;
  573. }
  574. /**
  575. * Replication of Devel Query Display (but as a table instead of CSS styled div structure)
  576. * This is done to work with the Firefox extension which has a harder time loading CSS
  577. */
  578. function drupalforfirebug_devel_query_table($queries, $counts) {
  579. $version = devel_get_core_version(VERSION);
  580. $header = array ('ms', '#', 'where', 'query');
  581. $i = 0;
  582. $api = variable_get('devel_api_url', 'api.drupal.org');
  583. foreach ($queries as $query) {
  584. $function = !empty($query['caller']['class']) ? $query['caller']['class'] . '::' : '';
  585. $function .= $query['caller']['function'];
  586. $count = isset($counts[$query['query']]) ? $counts[$query['query']] : 0;
  587. $diff = round($query['time'] * 1000, 2);
  588. if ($diff > variable_get('devel_execution', 5)) {
  589. $cell[$i][] = array ('data' => $diff, 'class' => 'marker');
  590. }
  591. else {
  592. $cell[$i][] = $diff;
  593. }
  594. $cell[$i][] = $count;
  595. $cell[$i][] = l($function, "http://$api/api/function/$function/$version");
  596. // EXPLAIN only valid for select queries.
  597. // 3 divs for each variation of the query. Last 2 are hidden by default.
  598. $placeholders = '<div class="dev-placeholders">' . check_plain($query['query']) . "</div>\n";
  599. $args = '<div class="dev-arguments" style="display: none;"></div>' . "\n";
  600. $explain = '<div class="dev-explain" style="display: none;"></div>' . "\n";
  601. $cell[$i][] = array(
  602. 'id' => "devel-query-$i",
  603. 'data' => $placeholders . $args . $explain,
  604. );
  605. $i++;
  606. unset($diff, $count, $ops);
  607. }
  608. if (variable_get('devel_query_sort', DEVEL_QUERY_SORT_BY_SOURCE)) {
  609. usort($cell, '_devel_table_sort');
  610. }
  611. return theme('table', array('header' => $header, 'rows' => $cell));
  612. }