1
0
mirror of https://github.com/maximebf/php-debugbar.git synced 2025-05-04 13:57:55 +02:00

added stacked data

This commit is contained in:
maximebf 2013-09-15 12:56:08 -04:00
parent 90248ebb3c
commit db8bf5c6a1
9 changed files with 240 additions and 30 deletions

View File

@ -2,6 +2,9 @@
include __DIR__ . '/../tests/bootstrap.php';
// for stack data
session_start();
use DebugBar\StandardDebugBar;
$debugbar = new StandardDebugBar();

View File

@ -25,6 +25,10 @@ render_demo_page(function() {
<li><a href="ajax.php" class="ajax">load ajax content</a></li>
<li><a href="ajax_exception.php" class="ajax">load ajax content with exception</a></li>
</ul>
<h2>Stack</h2>
<ul>
<li><a href="stack.php">perform a redirect</a></li>
</ul>
<h2>PDO</h2>
<ul>
<li><a href="pdo.php">PDO demo</a></li>

6
demo/stack.php Normal file
View File

@ -0,0 +1,6 @@
<?php
include 'bootstrap.php';
$debugbar['messages']->addMessage('hello from redirect');
$debugbar->stackData();
header('Location: index.php');

View File

@ -1,24 +0,0 @@
# AJAX
As mentioned in the previous chapter, if you are performing AJAX requests
which return HTML content, you can use `JavascriptRenderer::render(false)`.
In the case you are sending back non-HTML data (eg: JSON), the DebugBar can
send data to the client using HTTP headers using the `sendDataInHeaders()` method
(no need to use the `JavascriptRenderer`):
$debugbar = new DebugBar();
// ...
$debugbar->sendDataInHeaders();
On the client side, an instance of `PhpDebugBar.AjaxHandler` will
parse the headers and add the dataset to the debugbar.
The AjaxHandler automatically binds to jQuery's *ajaxComplete* event
so if you are using jQuery, you have nothing to configure.
If you're not using jQuery, you can call `AjaxHandler.handle(xhr)`.
If you are using the `JavascriptRenderer` initialization, the instance
of `AjaxHandler` is stored in the `ajaxHandler` property of the `DebugBar` object.
debugbar.ajaxHandler.handle(xhr);

49
docs/ajax_and_stack.md Normal file
View File

@ -0,0 +1,49 @@
# AJAX and Stacked data
## AJAX
As mentioned in the previous chapter, if you are performing AJAX requests
which return HTML content, you can use `JavascriptRenderer::render(false)`.
In the case you are sending back non-HTML data (eg: JSON), the DebugBar can
send data to the client using HTTP headers using the `sendDataInHeaders()` method
(no need to use the `JavascriptRenderer`):
$debugbar = new DebugBar();
// ...
$debugbar->sendDataInHeaders();
On the client side, an instance of `PhpDebugBar.AjaxHandler` will
parse the headers and add the dataset to the debugbar.
The AjaxHandler automatically binds to jQuery's *ajaxComplete* event
so if you are using jQuery, you have nothing to configure.
If you're not using jQuery, you can call `AjaxHandler.handle(xhr)`.
If you are using the `JavascriptRenderer` initialization, the instance
of `AjaxHandler` is stored in the `ajaxHandler` property of the `DebugBar` object.
debugbar.ajaxHandler.handle(xhr);
## Stacked data
Some times you need to collect data about a request but the page won't actually
be displayed. The best example of that is during a redirect. You can use the
debug bar storage mechanism to store the data and re-open it later but it can
be cumbersome while testing a redirect page.
The solution is to use stacked data. The debug bar can temporarily store the
collected data in the session until the next time it will be displayed.
Simply call `DebugBar::stackData()` instead of rendering the debug bar.
PHP's session must be started before using this feature.
Note: The stacked data feature will use the storage mechanism of it's enabled
instead of storing the data in the session.
$debugbar = new DebugBar();
// ...
$debugbar->stackData();
Stacked data are rendered each time the debug bar is rendered using the
`JavascriptRenderer`.

View File

@ -6,7 +6,7 @@
"../README.md",
"data_collectors.md",
"rendering.md",
"ajax.md",
"ajax_and_stack.md",
"base_collectors.md",
"bridge_collectors.md",
"storage.md",

View File

@ -40,6 +40,10 @@ class DebugBar implements ArrayAccess
protected $storage;
protected $stackSessionNamespace = 'PHPDEBUGBAR_STACK_DATA';
protected $stackAlwaysUseSessionStorage = false;
/**
* Adds a data collector
*
@ -230,6 +234,120 @@ class DebugBar implements ArrayAccess
return $this;
}
/**
* Stacks the data in the session for later rendering
*/
public function stackData()
{
$this->initStackSession();
$data = null;
if (!$this->isDataPersisted() || $this->stackAlwaysUseSessionStorage) {
$data = $this->getData();
} else if ($this->data === null) {
$this->collect();
}
$_SESSION[$this->stackSessionNamespace][$this->getCurrentRequestId()] = $data;
return $this;
}
/**
* Checks if there is stacked data in the session
*
* @return boolean
*/
public function hasStackedData()
{
$this->initStackSession();
return count($_SESSION[$this->stackSessionNamespace]) > 0;
}
/**
* Returns the data stacked in the session
*
* @param boolean $delete Whether to delete the data in the session
* @return array
*/
public function getStackedData($delete = true)
{
$this->initStackSession();
$stackedData = $_SESSION[$this->stackSessionNamespace];
if ($delete) {
unset($_SESSION[$this->stackSessionNamespace]);
}
$datasets = array();
if ($this->isDataPersisted() && !$this->stackAlwaysUseSessionStorage) {
foreach ($stackedData as $id => $data) {
$datasets[$id] = $this->getStorage()->get($id);
}
} else {
$datasets = $stackedData;
}
return $datasets;
}
/**
* Sets the key to use in the $_SESSION array
*
* @param string $ns
*/
public function setStackDataSessionNamespace($ns)
{
$this->stackSessionNamespace = $ns;
return $this;
}
/**
* Returns the key used in the $_SESSION array
*
* @return string
*/
public function getStackDataSessionNamespace()
{
return $this->stackSessionNamespace;
}
/**
* Sets whether to only use the session to store stacked data even
* if a storage is enabled
*
* @param boolean $enabled
*/
public function setStackAlwaysUseSessionStorage($enabled = true)
{
$this->stackAlwaysUseSessionStorage = $enabled;
return $this;
}
/**
* Checks if the session is always used to store stacked data
* even if a storage is enabled
*
* @return boolean
*/
public function isStackAlwaysUseSessionStorage()
{
return $this->stackAlwaysUseSessionStorage;
}
/**
* Initializes the session for stacked data
*/
protected function initStackSession()
{
if ((function_exists('session_status') && session_status() == PHP_SESSION_NONE) || !isset($_SESSION)) {
throw new DebugBarException("Session must be started before using stack data in the debug bar");
}
$ns = $this->stackSessionNamespace;
if (!isset($_SESSION[$ns])) {
$_SESSION[$ns] = array();
}
}
/**
* Returns a JavascriptRenderer for this instance
*

View File

@ -614,18 +614,22 @@ class JavascriptRenderer
* @param boolean $initialize Whether to render the de bug bar initialization code
* @return string
*/
public function render($initialize = true)
public function render($initialize = true, $renderStackedData = true)
{
$js = '';
if ($initialize) {
$js = $this->getJsInitializationCode();
}
if ($renderStackedData && $this->debugBar->hasStackedData()) {
foreach ($this->debugBar->getStackedData() as $id => $data) {
$js .= $this->getAddDatasetCode($id, $data);
}
}
$js .= sprintf("%s.addDataSet(%s, \"%s\");\n",
$this->variableName,
json_encode($this->debugBar->getData()),
$this->debugBar->getCurrentRequestId());
$js .= $this->getAddDatasetCode($this->debugBar->getCurrentRequestId(), $this->debugBar->getData());
return "<script type=\"text/javascript\">\n$js\n</script>\n";
}
@ -728,4 +732,20 @@ class JavascriptRenderer
return $js;
}
/**
* Returns the js code needed to add a dataset
*
* @param string $requestId
* @param array $data
* @return string
*/
protected function getAddDatasetCode($requestId, $data)
{
$js = sprintf("%s.addDataSet(%s, \"%s\");\n",
$this->variableName,
json_encode($data),
$requestId);
return $js;
}
}

View File

@ -53,4 +53,38 @@ class DebugBarTest extends DebugBarTestCase
$data = $this->debugbar->collect();
$this->assertEquals($s->data[$this->debugbar->getCurrentRequestId()], $data);
}
public function testStackedData()
{
$_SESSION = array();
$this->debugbar->addCollector($c = new MockCollector(array('foo')));
$this->debugbar->stackData();
$this->assertArrayHasKey($ns = $this->debugbar->getStackDataSessionNamespace(), $_SESSION);
$this->assertArrayHasKey($id = $this->debugbar->getCurrentRequestId(), $_SESSION[$ns]);
$this->assertArrayHasKey('mock', $_SESSION[$ns][$id]);
$this->assertEquals($c->collect(), $_SESSION[$ns][$id]['mock']);
$this->assertTrue($this->debugbar->hasStackedData());
$data = $this->debugbar->getStackedData();
$this->assertArrayNotHasKey($ns, $_SESSION);
$this->assertArrayHasKey($id, $data);
$this->assertEquals(1, count($data));
$this->assertArrayHasKey('mock', $data[$id]);
$this->assertEquals($c->collect(), $data[$id]['mock']);
}
public function testStackedDataWithStorage()
{
$s = new MockStorage();
$this->debugbar->setStorage($s);
$this->debugbar->addCollector($c = new MockCollector(array('foo')));
$this->debugbar->stackData();
$id = $this->debugbar->getCurrentRequestId();
$this->assertNull($_SESSION[$this->debugbar->getStackDataSessionNamespace()][$id]);
$data = $this->debugbar->getStackedData();
$this->assertEquals($c->collect(), $data[$id]['mock']);
}
}