Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Added: View::startIfEmpty($name) #930

Merged
merged 3 commits into from

5 participants

@LiquidityC

Ticket: 3315

Added function View::startIfEmpty($name) that captures content to a block only if it has no existing content.

@LiquidityC

Removed the line from .gitignore

lib/Cake/View/ViewBlock.php
@@ -69,12 +78,38 @@ public function start($name) {
}
/**
+ * Start capturing output for a 'block' if it is empty
+ *
+ * Blocks allow you to create slots or blocks of dynamic content in the layout.
+ * view files can implement some or all of a layout's slots.
+ *
+ * You can end capturing blocks using View::end(). Blocks can be output
+ * using View::get();
+ *
+ * @param string $name The name of the block to capture for.
+ * @return void
+ * @see ViewBlock::startIfEmpty()
@ADmad Collaborator
ADmad added a note

This line needs to be removed. A @see to itself doesn't make sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@LiquidityC

I dropped that comment line now.

@bar
bar commented

Just to be able to track the whole PR flow, from: #925 and #929

@markstory
Owner

Anyone have objections to this? I think it provides a useful enhancement to the block system that better allows default content alongside the existing append behavior.

@lorenzo
Owner

I still don't find any good use for this, but I'm going with you guys :+1:

@ADmad
Collaborator

Yeah this new method doesn't make much sense to me either. Let hope someone doesn't call $this->startIfEmpty('foo'), echo some content and finally call $this->end() and then wonder why he/she got an empty block.

@markstory
Owner

@ADmad @lorenzo The primary use case would be when:

  • You have blocks in a layout that has a parent.
  • You want to define default content for blocks in the extended layout.
  • You want to be able to define content for those same blocks in a view, but not get the current appending behavior that blocks have.

In this situation, you could use startIfEmpty() to define the fallback content in the parent view or child layout. This allows your code to stay dry as you don't need to duplicate the block content through the various child views.

@lorenzo
Owner

Can you safely call end() after doing startIfEmpty() ? Will we need endIfStarted() ?

@LiquidityC
@ADmad
Collaborator
$this->startIfEmpty('test');
echo "Block content 1";
$this->end();
echo $this->fetch('test');

The test block fetched in this case would be empty isn't it?

@ADmad
Collaborator

Nvm, the block won't be empty in above code i showed, i misread.

@ADmad ADmad commented on the diff
lib/Cake/Test/Case/View/ViewTest.php
((4 lines not shown))
+ * Test block with startIfEmpty
+ *
+ * @return void
+ */
+ public function testBlockCaptureStartIfEmpty() {
+ $this->View->startIfEmpty('test');
+ echo "Block content 1";
+ $this->View->end();
+
+ $this->View->startIfEmpty('test');
+ echo "Block content 2";
+ $this->View->end();
+
+ $result = $this->View->fetch('test');
+ $this->assertEquals('Block content 1', $result);
+ }
@ADmad Collaborator
ADmad added a note

Perhaps you should add 1 more test where you first use start() for a new block and then startIfEmpty().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@LiquidityC

@ADmad I did as you suggested.

@lorenzo
Owner

Votes for/against this?

@lorenzo lorenzo merged commit 99e84b8 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 2, 2012
  1. @LiquidityC
  2. @LiquidityC

    Added test for View::startIfEmpty($name)

    LiquidityC authored LiquidityC committed
Commits on Nov 18, 2012
  1. @LiquidityC
This page is out of date. Refresh to see the latest.
View
36 lib/Cake/Test/Case/View/ViewTest.php
@@ -1217,6 +1217,42 @@ public function testBlockCapture() {
}
/**
+ * Test block with startIfEmpty
+ *
+ * @return void
+ */
+ public function testBlockCaptureStartIfEmpty() {
+ $this->View->startIfEmpty('test');
+ echo "Block content 1";
+ $this->View->end();
+
+ $this->View->startIfEmpty('test');
+ echo "Block content 2";
+ $this->View->end();
+
+ $result = $this->View->fetch('test');
+ $this->assertEquals('Block content 1', $result);
+ }
@ADmad Collaborator
ADmad added a note

Perhaps you should add 1 more test where you first use start() for a new block and then startIfEmpty().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+/**
+ * Test block with startIfEmpty
+ *
+ * @return void
+ */
+ public function testBlockCaptureStartStartIfEmpty() {
+ $this->View->start('test');
+ echo "Block content 1";
+ $this->View->end();
+
+ $this->View->startIfEmpty('test');
+ echo "Block content 2";
+ $this->View->end();
+
+ $result = $this->View->fetch('test');
+ $this->assertEquals('Block content 1', $result);
+ }
+
+/**
* Test appending to a block with capturing output.
*
* @return void
View
13 lib/Cake/View/View.php
@@ -599,7 +599,18 @@ public function start($name) {
}
/**
- * Append to an existing or new block. Appending to a new
+ * Start capturing output for a 'block' if it has no content
+ *
+ * @param string $name The name of the block to capture for.
+ * @return void
+ * @see ViewBlock::startIfEmpty()
+ */
+ public function startIfEmpty($name) {
+ return $this->Blocks->startIfEmpty($name);
+ }
+
+/**
+ * Append to an existing or new block. Appending to a new
* block will create the block.
*
* @param string $name Name of the block
View
34 lib/Cake/View/ViewBlock.php
@@ -52,6 +52,15 @@ class ViewBlock {
protected $_active = array();
/**
+ * Should the currently captured content be discarded on ViewBlock::end()
+ *
+ * @var boolean
+ * @see ViewBlock::end()
+ * @see ViewBlock::startIfEmpty()
+ */
+ protected $_discardActiveBufferOnEnd = false;
+
+/**
* Start capturing output for a 'block'
*
* Blocks allow you to create slots or blocks of dynamic content in the layout.
@@ -69,12 +78,37 @@ public function start($name) {
}
/**
+ * Start capturing output for a 'block' if it is empty
+ *
+ * Blocks allow you to create slots or blocks of dynamic content in the layout.
+ * view files can implement some or all of a layout's slots.
+ *
+ * You can end capturing blocks using View::end(). Blocks can be output
+ * using View::get();
+ *
+ * @param string $name The name of the block to capture for.
+ * @return void
+ */
+ public function startIfEmpty($name) {
+ if (empty($this->_blocks[$name])) {
+ return $this->start($name);
+ }
+ $this->_discardActiveBufferOnEnd = true;
+ ob_start();
+ }
+
+/**
* End a capturing block. The compliment to ViewBlock::start()
*
* @return void
* @see ViewBlock::start()
*/
public function end() {
+ if ($this->_discardActiveBufferOnEnd) {
+ $this->_discardActiveBufferOnEnd = false;
+ ob_end_clean();
+ return;
+ }
if (!empty($this->_active)) {
$active = end($this->_active);
$content = ob_get_clean();
Something went wrong with that request. Please try again.