1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
22:
23: namespace picon;
24:
25: 26: 27: 28: 29: 30: 31: 32: 33:
34: class Form extends MarkupContainer implements FormSubmitListener
35: {
36: private $onSubmit;
37: private $onError;
38:
39: public function __construct($id, $model = null, $onSubmit = null, $onError = null)
40: {
41: parent::__construct($id, $model);
42: if($onError!=null)
43: {
44: Args::callBack($onError, 'onError');
45: $this->onError = $onError;
46: }
47: if($onSubmit!=null)
48: {
49: Args::callBack($onSubmit, 'onSubmit');
50: $this->onSubmit = $onSubmit;
51: }
52: }
53:
54: protected function onComponentTag(ComponentTag $tag)
55: {
56: parent::onComponentTag($tag);
57: $this->checkComponentTag($tag, 'form');
58: $tag->put('action', $this->urlForListener($this));
59: $tag->put('method', 'post');
60: }
61:
62: 63: 64: 65:
66: public function onEvent()
67: {
68: $formToProcess = $this;
69:
70: $submitter = $this->getSubmitingButton();
71:
72: if($submitter!=null)
73: {
74: $formToProcess = $submitter->getForm();
75: }
76: $formToProcess->process($submitter);
77: }
78:
79: public function process(FormSubmitter $submitter)
80: {
81: if($this->getRequest()->isPost())
82: {
83: $components = array();
84: $form = $this;
85: $callback = function(&$component) use (&$components, $form)
86: {
87: if($component->getForm()!=$form)
88: {
89: return Component::VISITOR_CONTINUE_TRAVERSAL_NO_DEEPER;
90: }
91: array_push($components, $component);
92: return Component::VISITOR_CONTINUE_TRAVERSAL;
93: };
94: $this->visitChildren(FormComponent::getIdentifier(), $callback);
95:
96: foreach($components as $formComponent)
97: {
98: $formComponent->inputChanged();
99: }
100:
101: $formValid = true;
102: foreach($components as $formComponent)
103: {
104: $formComponent->validate();
105: if(!$formComponent->isValid())
106: {
107: $formValid = false;
108: }
109: }
110:
111: if($formValid)
112: {
113: foreach($components as $formComponent)
114: {
115: $formComponent->updateModel();
116: }
117: $this->callSubmit($submitter);
118: }
119: else
120: {
121: $this->callOnError($submitter);
122: }
123: }
124: }
125:
126: public function isFormValid()
127: {
128: $valid = true;
129: $callback = function(FormComponent &$component) use (&$valid)
130: {
131: if(!$component->isValid())
132: {
133: $valid = false;
134: return Component::VISITOR_STOP_TRAVERSAL;
135: }
136: return Component::VISITOR_CONTINUE_TRAVERSAL;
137: };
138: $this->visitChildren(FormComponent::getIdentifier(), $callback);
139: return $valid;
140: }
141:
142: public function getSubmitingButton()
143: {
144: $button = null;
145: $request = $this->getRequest();
146: $callback = function(Button &$component) use (&$button, $request)
147: {
148: $value = $request->getPostedParameter($component->getName());
149: if($value!=null)
150: {
151: $button = $component;
152: return Component::VISITOR_STOP_TRAVERSAL;
153: }
154: return Component::VISITOR_CONTINUE_TRAVERSAL;
155: };
156: $this->visitChildren(Button::getIdentifier(), $callback);
157: return $button;
158: }
159:
160: private function callOnError($submiter)
161: {
162: $this->onError();
163: if($submiter!=null && $submiter instanceof FormSubmitter)
164: {
165: $submiter->onError();
166: }
167: }
168:
169: private function callSubmit($submiter)
170: {
171: $this->onSubmit();
172: if($submiter!=null && $submiter instanceof FormSubmitter)
173: {
174: $submiter->onSubmit();
175: }
176: }
177:
178: public function onError()
179: {
180: if(is_callable($this->onError))
181: {
182: $callable = $this->onError;
183: $callable();
184: }
185: }
186:
187: public function onSubmit()
188: {
189: if(is_callable($this->onSubmit))
190: {
191: $callable = $this->onSubmit;
192: $callable();
193: }
194: }
195:
196: public function beforeComponentRender()
197: {
198: parent::beforeComponentRender();
199: $multipart = false;
200: $callback = function(&$component) use (&$multipart)
201: {
202: if($component->isMultiPart())
203: {
204: $multipart = true;
205: }
206: return Component::VISITOR_CONTINUE_TRAVERSAL;
207: };
208: $this->visitChildren(FormComponent::getIdentifier(), $callback);
209:
210: if($multipart)
211: {
212: $this->add(new AttributeModifier('enctype', new BasicModel('multipart/form-data')));
213: }
214: }
215: }
216:
217: ?>
218: