/**
 * Renders an edit form for a slot
 * 
 * @param sfSympalContent $content The content on which the slot should be rendered
 * @param sfSympalContentSlot $slot The slot to render in a form
 * @param array $options An options array. Available options include:
 *   * edit_mode
 * 
 */
function get_sympal_content_slot_editor($content, $slot, $options = array())
{
    $slot->setContentRenderedFor($content);
    // merge in some global default slot options
    $options = array_merge(array('edit_mode' => sfSympalConfig::get('inline_editing', 'default_edit_mode'), 'view_url' => url_for('sympal_content_slot_view', array('id' => $slot->id, 'content_id' => $slot->getContentRenderedFor()->id))), $options);
    // merge the default config for this slot into the given config
    $slotOptions = sfSympalConfig::get($slot->getContentRenderedFor()->Type->slug, 'content_slots', array());
    if (isset($slotOptions[$slot->name])) {
        $options = array_merge($slotOptions[$slot->name], $options);
    }
    /*
     * Finally, override the "type" option, it should be set to whatever's
     * in the database, regardless of what the original slot options were
     */
    $options['type'] = $slot->type;
    /*
     * Give the slot a default value if it's blank.
     * 
     * @todo Move this somewhere where it can be specified on a type-by-type
     * basis (e.g., if we had an "image" content slot, it might say
     * "Click to choose image"
     */
    $renderedValue = $slot->render();
    if (!$renderedValue) {
        $renderedValue = __('[Hover over and click edit to change.]');
    }
    $inlineContent = sprintf('<a href="%s" class="sympal_slot_button">' . __('Edit') . '</a>', url_for('sympal_content_slot_form', array('id' => $slot->id, 'content_id' => $slot->getContentRenderedFor()->id)));
    $inlineContent .= sprintf('<span class="sympal_slot_content">%s</span>', $renderedValue);
    return sprintf('<span class="sympal_slot_wrapper %s" id="sympal_slot_wrapper_%s">%s</span>', htmlentities(json_encode($options)), $slot->id, $inlineContent);
}
function get_sympal_content_slot_editor(sfSympalContent $content, sfSympalContentSlot $slot, $options = array())
{
    $content->setEditableSlotsExistOnPage(true);
    $slot->setContentRenderedFor($content);
    $name = $slot->getName();
    $isColumn = $slot->getIsColumn();
    $form = $slot->getEditForm();
    $renderedValue = $slot->render();
    if (!$renderedValue && sfSympalContext::getInstance()->shouldLoadFrontendEditor()) {
        $renderedValue = __('[Double click to enable inline edit mode.]');
    }
    return '
<span title="' . __('[Double click to enable inline edit mode.]') . '" id="sympal_content_slot_' . $slot->getId() . '" class="sympal_content_slot">
  <input type="hidden" class="content_slot_id" value="' . $slot->getId() . '" />
  <input type="hidden" class="content_id" value="' . $slot->getContentRenderedFor()->getId() . '" />
  <span class="editor">' . get_partial('sympal_edit_slot/slot_editor', array('form' => $form, 'contentSlot' => $slot)) . '</span>
  <span class="value toggle_edit_mode">' . $renderedValue . '</span>
</span>';
}
 /**
  * Change the content slot form value widget
  *
  * @param string $type The type of the widget
  * @param sfForm $form The form whose slot will be modified
  * @param string $fieldName The name of the "slot" field on the form
  * @return void
  */
 public static function changeContentSlotValueWidget(sfSympalContentSlot $slot, sfForm $form)
 {
     // in case the type is blank
     $type = $slot->type ? $slot->type : 'Text';
     $widgetSchema = $form->getWidgetSchema();
     $validatorSchema = $form->getValidatorSchema();
     $contentSlotTypes = sfSympalConfig::get('content_slot_types', null, array());
     $options = isset($contentSlotTypes[$type]) ? $contentSlotTypes[$type] : array();
     $widgetClass = isset($options['widget_class']) ? $options['widget_class'] : 'sfWidgetFormSympal' . $type;
     $widgetOptions = isset($options['widget_options']) ? $options['widget_options'] : array();
     $validatorClass = isset($options['validator_class']) ? $options['validator_class'] : 'sfValidatorFormSympal' . $type;
     $validatorOptions = isset($options['validator_options']) ? $options['validator_options'] : array();
     $validatorOptions['required'] = false;
     /*
      * Setup the widget and validator: 3 cases:
      *   1) widget_class & is validator_class are not false, so we setup widget/validator using those
      *   2) widget_class & validator_class ARE false, the slot is a column - get the widget/validator from the content form
      *   3) All else fails, leave widget & validator alone
      */
     if ($widgetClass && $validatorClass) {
         $widgetSchema['value'] = new $widgetClass($widgetOptions, array('class' => 'slot_' . strtolower($type)));
         $validatorSchema['value'] = new $validatorClass($validatorOptions);
     } elseif ($slot->is_column) {
         $contentForm = $slot->getContentSlotColumnForm();
         $contentWidgetSchema = $contentForm->getWidgetSchema();
         $contentValidatorSchema = $contentForm->getValidatorSchema();
         $widgetSchema['value'] = $contentForm->getWidgetSchema()->offsetGet($slot->name);
         $validatorSchema['value'] = $contentForm->getValidatorSchema()->offsetGet($slot->name);
     }
 }
/**
 * Renders the actual form that edits a content slot
 * 
 * @param sfSympalContent $content The content record being modified
 * @param sfSympalContentSlot $slot The content slot to edit
 * 
 * @return string
 */
function get_sympal_content_slot_form($content, $slot)
{
    $slot->setContentRenderedFor($content);
    $form = $slot->getEditForm();
    return get_partial('sympal_edit_slot/slot_editor', array('form' => $form, 'contentSlot' => $slot));
}
 /**
  * Retrieves or creates an sfSympalContentSlot object with the given
  * name for this sfSympalContent object
  * 
  * @return sfSympalContentSlot
  */
 public function getOrCreateSlot($name, $options = array())
 {
     if (!($hasSlot = $this->hasSlot($name))) {
         $isColumn = $this->hasField($name) ? true : false;
         // if type isn't specified, give it a type of Column or Text
         if (isset($options['type'])) {
             $type = $options['type'];
         } else {
             $type = $isColumn ? 'Column' : 'Text';
         }
         if (!$isColumn && $type == 'Column') {
             throw new sfException('Cannot set a non-column slot to type "Column"');
         }
         $slot = new sfSympalContentSlot();
         $slot->setContentRenderedFor($this);
         $slot->is_column = $isColumn;
         $slot->name = $name;
         $slot->type = $type;
         if (isset($options['default_value'])) {
             $slot->value = $options['default_value'];
         }
         $slot->save();
         $this->addSlot($slot);
     } else {
         $slot = $this->getSlot($name);
     }
     $slot->setContentRenderedFor($this);
     return $slot;
 }
 public function getOrCreateSlot($name, $type = null, $renderFunction = null, $options = array())
 {
     if (!($hasSlot = $this->hasSlot($name))) {
         $isColumn = $this->hasField($name) ? true : false;
         $type = $type ? $type : 'Text';
         $slot = new sfSympalContentSlot();
         $slot->is_column = $isColumn;
         if ($slot->is_column && is_null($renderFunction)) {
             $renderFunction = 'get_sympal_content_property';
         }
         $slot->render_function = $renderFunction;
         $slot->name = $name;
         $slot->type = $type;
         if (isset($options['default_value'])) {
             $slot->value = $options['default_value'];
         }
         $slot->save();
         $this->addSlot($slot);
     } else {
         $slot = $this->getSlot($name);
     }
     if ($type != null && $slot->type != $type) {
         $slot->type = $type;
         $slot->save();
     }
     $slot->setContentRenderedFor($this);
     return $slot;
 }
 public function __construct(sfSympalContentSlot $contentSlot)
 {
     $this->_contentSlot = $contentSlot;
     $this->_content = $contentSlot->getContentRenderedFor();
 }
<?php

$app = 'sympal';
require_once dirname(__FILE__) . '/../../bootstrap/unit.php';
$t = new lime_test(7);
$sympal_configuration = $plugin_configuration->getSympalConfiguration();
$content = sfSympalContent::createNew('sfSympalPage');
$slotRenderer = new sfSympalSlotRenderer($sympal_configuration);
$t->info('1 - Test renderSlotByName()');
$t->is($content->getEditableSlotsExistOnPage(), false, '->getEditableSlotsExistOnPage() on Content begins as false');
$value = $slotRenderer->renderSlotByName('title', $content, array('edit_mode' => 'test', 'default_value' => 'testing default'));
$t->is($content->getEditableSlotsExistOnPage(), true, '->getEditableSlotsExistOnPage() is true after rendering a slot');
$t->is($slotRenderer->getOption('fake', 'default'), 'default', '->getOption() returns the default value if the option does not exist');
$t->is($slotRenderer->getOption('edit_mode', 'default'), 'test', '->getOption() returns the correct option value');
$t->is($value, 'testing default', 'Renders the default value we passed via default_value');
$content->title = 'testing';
$value = $slotRenderer->renderSlotByName('title', $content, array('edit_mode' => 'test'));
$t->is($value, 'testing', 'Renders "testing" once we set its value to testing');
$t->info('2 - Test ->renderSlot()');
$slot = new sfSympalContentSlot();
$slot->name = 'body';
$slot->is_column = false;
$slot->value = 'testing body value';
$slot->setContentRenderedFor($content);
$value = $slotRenderer->renderSlot($slot);
$t->is($value, 'testing body value', '->renderSlot() returns the correct value');