silverstripe /
silverstripe-widgets
| 1 | <?php |
||
| 2 | |||
| 3 | namespace SilverStripe\Widgets\Model; |
||
| 4 | |||
| 5 | use SilverStripe\Admin\LeftAndMain; |
||
| 6 | use SilverStripe\Control\Controller; |
||
| 7 | use SilverStripe\Control\Director; |
||
| 8 | use SilverStripe\Core\ClassInfo; |
||
| 9 | |||
| 10 | /** |
||
| 11 | * Optional controller for every widget which has its own logic, e.g. in forms. |
||
| 12 | * |
||
| 13 | * It always handles a single widget, usually passed in as a database |
||
| 14 | * identifier through the controller URL. Needs to be constructed as a nested |
||
| 15 | * controller within a {@link ContentController}. |
||
| 16 | * |
||
| 17 | * ## Forms |
||
| 18 | * You can add forms like in any other SilverStripe controller. If you need |
||
| 19 | * access to the widget from within a form, you can use |
||
| 20 | * `$this->controller->getWidget()` inside the form logic. |
||
| 21 | * |
||
| 22 | * Note: Widget controllers currently only work on {@link Page} objects, |
||
| 23 | * because the logic is implemented in {@link ContentController->handleWidget()}. |
||
| 24 | * Copy this logic and the URL rules to enable it for other controllers. |
||
| 25 | * |
||
| 26 | * @package widgets |
||
| 27 | */ |
||
| 28 | class WidgetController extends Controller |
||
| 29 | { |
||
| 30 | /** |
||
| 31 | * @var Widget |
||
| 32 | */ |
||
| 33 | protected $widget; |
||
| 34 | |||
| 35 | /** |
||
| 36 | * @var array |
||
| 37 | */ |
||
| 38 | private static $allowed_actions = array( |
||
|
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
| 39 | 'editablesegment' |
||
| 40 | ); |
||
| 41 | |||
| 42 | /** |
||
| 43 | * @param Widget $widget |
||
| 44 | */ |
||
| 45 | public function __construct($widget = null) |
||
| 46 | { |
||
| 47 | if ($widget) { |
||
| 48 | $this->widget = $widget; |
||
| 49 | $this->failover = $widget; |
||
| 50 | } |
||
| 51 | |||
| 52 | parent::__construct(); |
||
| 53 | } |
||
| 54 | |||
| 55 | /** |
||
| 56 | * @param string $action |
||
| 57 | * @return string |
||
| 58 | */ |
||
| 59 | public function Link($action = null) |
||
| 60 | { |
||
| 61 | $id = ($this->widget) ? $this->widget->ID : null; |
||
| 62 | $segment = Controller::join_links('widget', $id, $action); |
||
| 63 | |||
| 64 | $page = Director::get_current_page(); |
||
| 65 | if ($page && !($page instanceof WidgetController)) { |
||
| 66 | return $page->Link($segment); |
||
| 67 | } |
||
| 68 | |||
| 69 | if ($controller = $this->getParentController()) { |
||
| 70 | return $controller->Link($segment); |
||
| 71 | } |
||
| 72 | |||
| 73 | return $segment; |
||
| 74 | } |
||
| 75 | |||
| 76 | /** |
||
| 77 | * Cycles up the controller stack until it finds a non-widget controller |
||
| 78 | * This is needed becauseController::currreturns the widget controller, |
||
| 79 | * which means anyLinkfunction turns into endless loop. |
||
| 80 | * |
||
| 81 | * @return Controller |
||
| 82 | */ |
||
| 83 | public function getParentController() |
||
| 84 | { |
||
| 85 | foreach (Controller::$controller_stack as $controller) { |
||
| 86 | if (!($controller instanceof WidgetController)) { |
||
| 87 | return $controller; |
||
| 88 | } |
||
| 89 | } |
||
| 90 | return false; |
||
|
0 ignored issues
–
show
|
|||
| 91 | } |
||
| 92 | |||
| 93 | /** |
||
| 94 | * @return Widget |
||
| 95 | */ |
||
| 96 | public function getWidget() |
||
| 97 | { |
||
| 98 | return $this->widget; |
||
| 99 | } |
||
| 100 | |||
| 101 | /** |
||
| 102 | * Overloaded from {@link Widget->Content()} to allow for controller / form |
||
| 103 | * linking. |
||
| 104 | * |
||
| 105 | * @return string HTML |
||
| 106 | */ |
||
| 107 | public function Content() |
||
| 108 | { |
||
| 109 | return $this->renderWith(array_reverse(ClassInfo::ancestry(get_class($this->widget)))); |
||
| 110 | } |
||
| 111 | |||
| 112 | /** |
||
| 113 | * Overloaded from {@link Widget->WidgetHolder()} to allow for controller/ |
||
| 114 | * form linking. |
||
| 115 | * |
||
| 116 | * @return string HTML |
||
| 117 | */ |
||
| 118 | public function WidgetHolder() |
||
| 119 | { |
||
| 120 | return $this->renderWith("WidgetHolder"); |
||
| 121 | } |
||
| 122 | |||
| 123 | /** |
||
| 124 | * Uses the `WidgetEditor.ss` template and {@link Widget->editablesegment()} |
||
| 125 | * to render a administrator-view of the widget. It is assumed that this |
||
| 126 | * view contains form elements which are submitted and saved through |
||
| 127 | * {@link WidgetAreaEditor} within the CMS interface. |
||
| 128 | * |
||
| 129 | * @return string HTML |
||
| 130 | */ |
||
| 131 | public function editablesegment() |
||
| 132 | { |
||
| 133 | // use left and main to set the html config |
||
| 134 | $leftandmain = LeftAndMain::create(); |
||
| 135 | $leftandmain->setRequest($this->getRequest()); |
||
| 136 | $leftandmain->doInit(); |
||
| 137 | |||
| 138 | // Decode if fully qualified - @see Widget::ClassName |
||
| 139 | $className = str_replace('_', '\\', $this->urlParams['ID']); |
||
| 140 | if (class_exists($className) && is_subclass_of($className, Widget::class)) { |
||
| 141 | $obj = new $className(); |
||
| 142 | return $obj->EditableSegment(); |
||
| 143 | } else { |
||
| 144 | user_error("Bad widget class: $className", E_USER_WARNING); |
||
| 145 | return "Bad widget class name given"; |
||
| 146 | } |
||
| 147 | } |
||
| 148 | } |
||
| 149 |