PageRenderTime 51ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/user/components/Relation.php

http://yii-user-management.googlecode.com/
PHP | 806 lines | 429 code | 98 blank | 279 comment | 88 complexity | 33064ba9ac56f02de8b9db5723b95d53 MD5 | raw file
  1. <?php
  2. /*
  3. The Relation widget is used in forms, where the User can choose
  4. between a selection of model elements, that this models belongs to.
  5. It is able to handle BELONGS_TO, HAS_ONE and MANY_MANY Relations. The Relation
  6. type is detected automatically from the Model 'relations()' section.
  7. The Widget has different styles in which it can render the possible choices.
  8. Use the 'style' option to set the appropriate style.
  9. The following example shows how to use Relation with a minimal config,
  10. assuming we have a Model "Post" and "User", where one User belongs
  11. to a Post:
  12. <pre>
  13. $this->widget('application.components.Relation', array(
  14. 'model' => 'Post',
  15. 'relation' => 'user'
  16. 'fields' => 'username' // show the field "username" of the parent element
  17. ));
  18. </pre>
  19. Results in a drop down list in which the user can choose between
  20. all available Users in the Database. The shown field of the
  21. Table "User" is "username" in this example.
  22. You can choose the Style of your Widget in the 'style' option.
  23. Note that a Many_Many Relation always gets rendered as a Listbox,
  24. since you can select multiple Elements.
  25. 'fields' can be an array or an string.
  26. If you pass an array to 'fields', the Widget will display every field in
  27. this array. If you want to show further sub-relations, separate the values
  28. with '.', for example: 'fields' => 'array('parent.grandparent.description')
  29. Optional Parameters:
  30. You can use 'field' => 'post_userid' if the field in the model
  31. that represents the foreign model is called different than in the
  32. relation
  33. Use 'relatedPk' => 'id_of_user' if the primary Key of the Foreign
  34. Model differs from the one given in the relation.
  35. Normally you shouldn´t use this fields cause the Widget get the relations
  36. automatically from the relation.
  37. Use 'allowEmpty' to let the user be able to choose no parent. If you
  38. set this to a string, this string will be displayed with the available
  39. choices.
  40. With 'showAddButton' => 'false' you can disable the 'create new Foreignkey'
  41. Button generated beside the Selectbox.
  42. Define the AddButtonString with 'addButtonString' => 'Add...'. This string
  43. is set default to '+'
  44. When using the '+' button you most likely want to return to where you came.
  45. To accomplish this, we pass a 'returnTo' parameter by $_GET.
  46. The Controller can send the user back to where he came from this way:
  47. <pre>
  48. if($model->save())
  49. if(isset($_GET['returnTo']))
  50. $this->redirect(array(urldecode($_GET['returnTo'])));
  51. </pre>
  52. Using the 'style' option we can configure how our Widget gets rendered.
  53. The following styles are available:
  54. Selectbox (default), Listbox, Checkbox and in MANY_MANY relations 'twopane'
  55. The style is case insensitive so one can use dropdownlist or dropDownList.
  56. Use the option 'createAction' if the action to add additional foreign Model
  57. options differs from 'create'.
  58. With 'parentObjects' you can limit the Parent Elements that are being shown.
  59. It takes an array of elements that could be returned from an scope or
  60. an SQL Query.
  61. The parentObjects can be grouped, for example, with
  62. 'groupParentsBy' => 'city'
  63. Use the option 'htmlOptions' to pass any html Options to the
  64. Selectbox/Listbox form element.
  65. Full Example:
  66. <pre>
  67. $this->widget('application.components.Relation', array(
  68. 'model' => 'Post',
  69. 'field' => 'Userid',
  70. 'style' => 'ListBox',
  71. 'parentObjects' => Parentmodel::model()->findAll('userid = 17'),
  72. 'groupParentsBy' => 'city',
  73. 'relation' => 'user',
  74. 'relatedPk' => 'id_of_user',
  75. 'fields' => array( 'username', 'username.group.groupid' ),
  76. 'delimiter' => ' -> ', // default: ' | '
  77. 'returnTo' => 'model/create',
  78. 'addButtonLink' => 'othercontroller/otheraction', // default: ''
  79. 'showAddButton' => 'click here to add a new User', // default: ''
  80. 'htmlOptions' => array('style' => 'width: 100px;')
  81. ));
  82. </pre>
  83. @author Herbert Maschke <thyseus@gmail.com>
  84. @version 0.97 (after 1.0rc5)
  85. @since 1.1
  86. */
  87. class Relation extends CWidget
  88. {
  89. // this Variable holds an instance of the Object
  90. protected $_model;
  91. // this Variable holds an instance of the related Object
  92. protected $_relatedModel;
  93. // draw the relation of which model?
  94. public $model;
  95. // which relation should be rendered?
  96. public $relation;
  97. public $field;
  98. // the Primary Key of the foreign Model
  99. public $relatedPk;
  100. // a field or an array of fields that determine which field values
  101. // should be rendered in the selection
  102. public $fields;
  103. // if this is set, the User is able to select no related model
  104. // if this is set to a string, this string will be presented
  105. public $allowEmpty = 0;
  106. // Preselect which items?
  107. public $preselect = false;
  108. // disable this to hide the Add Button
  109. // set this to a string to set the String to be displayed
  110. public $showAddButton = false;
  111. public $addButtonLink = '';
  112. // Set this to false to generate a Link rather than a LinkButton
  113. // This is useful when Javascript is not available
  114. public $useLinkButton = true;
  115. // use this to set the link where the user should return to after
  116. // clicking the add Button
  117. public $returnLink;
  118. // How the label of a row should be rendered. {id} will be replaced by the
  119. // id of the model. You can also insert every field that is available in the
  120. // parent object.
  121. // Use {fields} to display all fields delimited by $this->delimiter
  122. // Use {myFuncName} to evaluate a user-contributed function specified in the
  123. // $functions array as 'myFuncName'=>'code to be evaluated'. The code for
  124. // these functions are evaluated under the context of the controller
  125. // rendering the current Relation widget ($this refers to the controller).
  126. // Old way, not encouraged anymore: Use {func0} to {funcX} to evaluate user-
  127. // contributed functions specified in the $functions array as a keyless
  128. // string entry of 'code to be evaluated'.
  129. // Example of code:
  130. //
  131. // 'template' => '#{id} : {fields} ({title}) Allowed other Models: {func0} {func1} {preferredWay}',
  132. // 'functions' => array(
  133. // "CHtml::checkBoxList('parent{id}', '', CHtml::listData(Othermodel::model()->findAll(), 'id', 'title'));",
  134. // '$this->funcThatReturnsText();'
  135. // 'preferredWay' => '$this->instructMe();'
  136. // ),
  137. public $template = '{fields}';
  138. // User-contributed functions, see comment for $template.
  139. public $functions = array();
  140. // If true, all the user-contributed functions in $functions will be
  141. // substituted in $htmlOptions['template'] as well.
  142. // If an array of function names, all the listed functions will be
  143. // substituted in $htmlOptions['template'] as well.
  144. public $functionsInHtmlOptionsTemplate = false;
  145. // how should multiple fields be delimited
  146. public $delimiter = " | ";
  147. // style of the selection Widget
  148. public $style = "dropDownList";
  149. public $htmlOptions = array();
  150. public $parentObjects = 0;
  151. public $orderParentsBy = 0;
  152. public $groupParentsBy = 0;
  153. // override this for complicated MANY_MANY relations:
  154. public $manyManyTable = '';
  155. public $manyManyTableLeft = '';
  156. public $manyManyTableRight = '';
  157. public $num = 1;
  158. public function init()
  159. {
  160. if(!is_object($this->model)) {
  161. if(!$this->_model = new $this->model) {
  162. throw new CException(
  163. Yii::t('yii','Relation widget is not able to instantiate the given Model'));
  164. }
  165. }
  166. else
  167. $this->_model = $this->model;
  168. // Instantiate Model and related Model
  169. foreach($this->_model->relations() as $key => $value)
  170. {
  171. if(strcmp($this->relation, $key) == 0)
  172. {
  173. // $key = Name of the Relation
  174. // $value[0] = Type of the Relation
  175. // $value[1] = Related Model
  176. // $value[2] = Related Field or Many_Many Table
  177. switch($value[0])
  178. {
  179. case 'CBelongsToRelation':
  180. case 'CHasOneRelation':
  181. $this->_relatedModel = new $value[1];
  182. if(!isset($this->field))
  183. {
  184. $this->field = $value[2];
  185. }
  186. break;
  187. case 'CManyManyRelation':
  188. preg_match_all('/^.*\(/', $value[2], $matches);
  189. $this->manyManyTable = substr($matches[0][0], 0, strlen($matches[0][0]) -1);
  190. preg_match_all('/\(.*,/', $value[2], $matches);
  191. $this->manyManyTableLeft = substr($matches[0][0], 1, strlen($matches[0][0]) - 2);
  192. preg_match_all('/,.*\)/', $value[2], $matches);
  193. $this->manyManyTableRight = substr($matches[0][0], 2, strlen($matches[0][0]) - 3);
  194. $this->_relatedModel = new $value[1];
  195. break;
  196. }
  197. }
  198. }
  199. if(!is_object($this->_relatedModel))
  200. throw new CException(
  201. Yii::t('yii','Relation widget cannot find the given Relation('.$this->relation.')'));
  202. if(!isset($this->relatedPk) || $this->relatedPk == "")
  203. {
  204. $this->relatedPk = $this->_relatedModel->tableSchema->primaryKey;
  205. }
  206. if(!isset($this->fields) || $this->fields == "" || $this->fields == array())
  207. throw new CException(Yii::t('yii','Widget "Relation" has been run without fields Option(string or array)'));
  208. }
  209. // Check if model-value contains '.' and generate -> directives:
  210. public function getModelData($model, $field)
  211. {
  212. if(strstr($field, '.'))
  213. {
  214. $data = explode('.', $field);
  215. $value = $model->getRelated($data[0])->$data[1];
  216. } else
  217. $value = $model->$field;
  218. return $value;
  219. }
  220. /**
  221. * This function fetches all needed data of the related Object and returns
  222. * them in an array that is prepared for use in ListData.
  223. */
  224. public function getRelatedData()
  225. {
  226. /* At first we determine, if we want to display all parent Objects, or
  227. * if the User supplied an list of Objects */
  228. if(is_object($this->parentObjects)) // a single Element
  229. {
  230. $parentobjects = array($this->parentObjects);
  231. }
  232. else if(is_array($this->parentObjects)) // Only show this elements
  233. {
  234. $parentobjects = $this->parentObjects;
  235. }
  236. else // Show all Parent elements
  237. {
  238. $parentobjects = CActiveRecord::model(get_class($this->_relatedModel))->findAll();
  239. }
  240. if($this->allowEmpty)
  241. if(is_string($this->allowEmpty))
  242. $dataArray[0] = $this->allowEmpty;
  243. else
  244. $dataArray[0] = Yii::t('app', 'None');
  245. foreach($parentobjects as $obj)
  246. {
  247. if(!is_array($this->fields))
  248. $this->fields = array($this->fields);
  249. $fields = '';
  250. $i = 0;
  251. foreach($this->fields as $field)
  252. {
  253. $rule = sprintf('{%s}',$field);
  254. $rules[$rule] = $obj->$field;
  255. if($i++ > 0)
  256. $fields .= $this->delimiter;
  257. $fields .= $this->getModelData($obj, $field);
  258. }
  259. $defaultrules = array(
  260. '{fields}' => $fields,
  261. '{id}' => $obj->{$obj->tableSchema->primaryKey});
  262. // Look for user-contributed functions and evaluate them
  263. if($this->functions != array())
  264. {
  265. foreach($this->functions as $key => $function)
  266. {
  267. // If the key is of type string, it's assumed to be a named function,
  268. // used like {myFuncName}.
  269. // If the key is an integer, it's assumed to be an unnamed function used
  270. // the old way, {funcX} where X is its index in the functions array.
  271. // We keep the integer support mostly for backwards compatibility, the
  272. // new way is encouraged.
  273. if(is_string($key)) {
  274. $funcrules[sprintf('{%s}', $key)] = $this->controller->evaluateExpression(
  275. strtr($function, $defaultrules));
  276. } else {
  277. $funcrules[sprintf('{func%d}', $key)] = $this->controller->evaluateExpression(
  278. strtr($function, $defaultrules));
  279. }
  280. }
  281. }
  282. // Merge the evaluated rules, if exist
  283. if(isset($funcrules))
  284. $rules = array_merge($rules, $funcrules);
  285. // Merge the default rules into our ruleset
  286. $rules = array_merge($rules, $defaultrules);
  287. // Apply the rules to the template
  288. $value = strtr($this->template, $rules);
  289. // Apply the user contributed functions to $htmlOptions's template, if requested.
  290. if(isset($this->htmlOptions['template']) && $this->functionsInHtmlOptionsTemplate !== false && isset($funcrules) && is_array($funcrules)) {
  291. if(is_array($this->functionsInHtmlOptionsTemplate))
  292. {
  293. $funcrulesToUse = array();
  294. foreach($this->functionsInHtmlOptionsTemplate as $functionName) {
  295. $functionName = sprintf('{%s}', $functionName);
  296. if(isset($funcrules[$functionName])) {
  297. $funcrulesToUse[$functionName] = $funcrules[$functionName];
  298. }
  299. }
  300. $this->htmlOptions['template'] = strtr($this->htmlOptions['template'], $funcrulesToUse);
  301. }
  302. else
  303. {
  304. $this->htmlOptions['template'] = strtr($this->htmlOptions['template'], $funcrules);
  305. }
  306. }
  307. if($this->groupParentsBy != '')
  308. {
  309. $dataArray[$obj->{$this->groupParentsBy}][$obj->{$this->relatedPk}] = CHtml::encode($value);
  310. }
  311. else
  312. {
  313. $dataArray[$obj->{$this->relatedPk}] = CHtml::encode($value);
  314. }
  315. }
  316. if(!isset($dataArray) || !is_array($dataArray))
  317. $dataArray = array();
  318. return $dataArray;
  319. }
  320. /**
  321. * Retrieves the Assigned Objects of the MANY_MANY related Table
  322. */
  323. public function getAssignedObjects()
  324. {
  325. if($this->_model->{$this->_model->tableSchema->primaryKey}) {
  326. $sql = sprintf('select * from %s where %s = %s',
  327. $this->manyManyTable,
  328. $this->manyManyTableLeft,
  329. $this->_model->{$this->_model->tableSchema->primaryKey});
  330. $result = Yii::app()->db->createCommand($sql)->queryAll();
  331. foreach($result as $foreignObject) {
  332. $id = $foreignObject[$this->manyManyTableRight];
  333. $objects[$id] = $this->_relatedModel->findByPk($id);
  334. }
  335. }
  336. // also add assigned models that are not yet saved in the database
  337. foreach($this->_model->{$this->relation} as $relobj)
  338. if(is_object($relobj))
  339. $objects[$relobj->id] = $relobj;
  340. else if(is_numeric($relobj))
  341. $objects[$relobj] = $relobj;
  342. return isset($objects) ? $objects : array();
  343. }
  344. /**
  345. * Retrieves the not Assigned Objects of the MANY_MANY related Table
  346. * This is used in the two-pane style view.
  347. */
  348. public function getNotAssignedObjects()
  349. {
  350. foreach($this->getRelatedData() as $key => $value)
  351. {
  352. if(!array_key_exists($key, $this->getAssignedObjects()))
  353. {
  354. $objects[$key] = $this->_relatedModel->findByPk($key);
  355. }
  356. }
  357. return $objects ? $objects : array();
  358. }
  359. /**
  360. * Gets the Values of the given Object or Objects depending on the
  361. * $this->fields the widget requests
  362. */
  363. public function getObjectValues($objects)
  364. {
  365. if(is_array($objects)) {
  366. foreach($objects as $object) {
  367. $attributeValues[$object->primaryKey] = $object->{$this->fields};
  368. }
  369. }
  370. else if(is_object($objects)) {
  371. $attributeValues[$object->primaryKey] = $objects->{$this->fields};
  372. }
  373. return isset($attributeValues) ? $attributeValues : array();
  374. }
  375. /*
  376. * How will the Listbox of the MANY_MANY Assignment be called?
  377. */
  378. public function getListBoxName($ajax = false)
  379. {
  380. if($ajax) {
  381. return sprintf('%s_%s',
  382. get_class($this->_model),
  383. get_class($this->_relatedModel)
  384. );
  385. } else {
  386. return sprintf('%s[%s]',
  387. get_class($this->_model),
  388. get_class($this->_relatedModel)
  389. );
  390. }
  391. }
  392. public function getListBoxId()
  393. {
  394. return sprintf('%s_%s',
  395. get_class($this->_model),
  396. get_class($this->_relatedModel)
  397. );
  398. }
  399. public function renderBelongsToSelection() {
  400. if(strcasecmp($this->style, "dropDownList") == 0)
  401. echo CHtml::ActiveDropDownList(
  402. $this->_model,
  403. $this->field,
  404. $this->getRelatedData(),
  405. $this->htmlOptions);
  406. else if(strcasecmp($this->style, "listbox") == 0)
  407. echo CHtml::ActiveListBox(
  408. $this->_model,
  409. $this->field,
  410. $this->getRelatedData(),
  411. $this->htmlOptions);
  412. else if(strcasecmp($this->style, "checkbox") == 0)
  413. echo CHtml::ActiveCheckBoxList(
  414. $this->_model,
  415. $this->field,
  416. $this->getRelatedData(),
  417. $this->htmlOptions);
  418. }
  419. public function renderManyManySelection() {
  420. if(strcasecmp($this->style, 'twopane') == 0)
  421. $this->renderTwoPaneSelection();
  422. else if(strcasecmp($this->style, 'checkbox') == 0)
  423. $this->renderCheckBoxListSelection();
  424. else if(strcasecmp($this->style, 'dropDownList') == 0)
  425. $this->renderManyManyDropDownListSelection();
  426. else
  427. $this->renderOnePaneSelection();
  428. }
  429. /*
  430. * Renders one dropDownList per selectable related Element.
  431. * The users can add additional entries with the + and remove entries
  432. * with the - Button. Once a element is selected, the same element in
  433. * the other dropdownlists gets removed, so the user can only choose each
  434. * element only once.
  435. */
  436. public function renderManyManyDropDownListSelection() {
  437. // Do we need do display all or only a subset of parent elements?
  438. if($this->parentObjects != 0)
  439. $relatedmodels = $this->parentObjects;
  440. else
  441. $relatedmodels = $this->_relatedModel->findAll();
  442. Yii::app()->clientScript->registerScript('relation', "
  443. function remove_selection(id) {
  444. option = '<option value=\"'+id+'\" class=\"option_'+id+'\">'+$('#option_'+id).html()+'</option>';
  445. $('#selection_'+id).remove();
  446. $('#option_'+id).remove();
  447. $('#removelink_'+id).remove();
  448. $('#".$this->getListBoxId()."').append(option);
  449. }
  450. ", CClientScript::POS_HEAD);
  451. $remove_link = CHtml::image(
  452. Yii::app()->getAssetManager()->publish(
  453. Yii::getPathOfAlias('zii.widgets.assets.gridview').'/delete.png'));
  454. Yii::app()->clientScript->registerScript('relation', "
  455. $('#".$this->getListBoxId()."').bind('change', function() {
  456. id = $(this).val();
  457. if(id != 0) {
  458. option = $('.option_' + id);
  459. selection = '<li id=\"option_'+id+'\">' + option.html() + '</li>';
  460. hiddeninput = '<input type=\"hidden\" id=\"selection_'+id+'\" name=\"selection_'+id+'\" />';
  461. remove_link = '<a id=\"removelink_'+id+'\" style=\"float:right;\" onclick=\"remove_selection('+id+')\">".$remove_link. "</a>';
  462. clear = '<div style=\"clear: both;\"></div>';
  463. $('#selected').append(remove_link);
  464. $('#selected').append(hiddeninput);
  465. $('#selected').append(selection);
  466. $('#selected').append(clear);
  467. option.remove();
  468. }
  469. });
  470. ");
  471. // before we render our dropdownlists, we need to gather <option>
  472. // parameters that we pass over to CHtml::dropDownList
  473. $options = array();
  474. $assigned = array();
  475. foreach($relatedmodels as $key => $obj) {
  476. if($this->isAssigned($obj->id)) {
  477. $assigned[$obj->id] = $obj->{$this->fields};
  478. unset($relatedmodels[$key]);
  479. }
  480. else
  481. $options[$obj->id] = array('class' => "option_{$obj->id}");
  482. }
  483. echo CHtml::dropDownList($this->getListBoxName(),
  484. 0,
  485. CHtml::listData(
  486. array_merge(
  487. array('0' => $this->allowEmpty), $relatedmodels),
  488. $this->relatedPk,
  489. $this->fields), array(
  490. 'options' => $options,
  491. )
  492. );
  493. echo '<ul id="selected">';
  494. if(isset($assigned) && $assigned)
  495. foreach($assigned as $key => $option) {
  496. printf('<a id="removelink_%d" style="float: right;" onclick="remove_selection(%d)"> %s </a>', $key, $key, $remove_link);
  497. printf('<input type="hidden" id="selection_%d" name="selection_%d">', $key, $key);
  498. printf('<li id="option_%d">%s</li>', $key, $option);
  499. }
  500. echo '</ul>';
  501. /* $uniqueid = $this->_relatedModel->tableSchema->name;
  502. $js_init = "
  503. var removed_elements = [];
  504. ";
  505. Yii::app()->clientScript->registerScript('dropdown_init', $js_init);
  506. $addbutton = sprintf('i'.$this->num.' = %d; maxi'.$this->num.' = %d;',
  507. count($this->getAssignedObjects()) + 1,
  508. count($relatedmodels));
  509. Yii::app()->clientScript->registerScript(
  510. 'addbutton_'.$uniqueid.'_'.$this->num, $addbutton);
  511. // Javascript that handles the action when a element gets selected
  512. $js_dropdownlist_change = "
  513. // element = parseInt($(this).val());
  514. // $('.option_{$uniqueid}_'+element).remove();
  515. ";
  516. // before we render our dropdownlists, we need to gather <option>
  517. // parameters that // we pass over to CHtml::dropDownList
  518. $options = array();
  519. foreach($relatedmodels as $obj) {
  520. $options[$obj->id] = array('class' => "option_{$uniqueid}_{$obj->id}");
  521. }
  522. $i = 0;
  523. foreach($relatedmodels as $obj) {
  524. $isAssigned = $this->isAssigned($obj->id);
  525. echo CHtml::openTag('div', array(
  526. 'id' => sprintf('div_%s_%d', $uniqueid, $i),
  527. 'style' => $i != 1 && !$isAssigned ? 'display:none;' : '',
  528. ));
  529. echo CHtml::dropDownList(sprintf('%s[%d]',
  530. $this->getListBoxName(),
  531. $i),
  532. $isAssigned ? $obj->id : 0,
  533. CHtml::listData(
  534. array_merge(
  535. array('0' => $this->allowEmpty), $relatedmodels),
  536. $this->relatedPk,
  537. $this->fields), array(
  538. 'options' => $options,
  539. 'onchange' => $js_dropdownlist_change
  540. )
  541. );
  542. echo CHtml::button('-', array('id' => sprintf('sub_%s_%d',
  543. $uniqueid,
  544. $i)));
  545. echo CHtml::closeTag('div');
  546. $jsadd = "
  547. $('#add_{$uniqueid}').click(function() {
  548. alert($(\"select[name='{$this->getListBoxName()}[\"+i{$this->num}+\"]']\").val());
  549. if($(\"select[name='{$this->getListBoxName()}[\"+i{$this->num}+\"]']\").val() != '') {
  550. $('#div_{$uniqueid}_' + i{$this->num}).show();
  551. if(i{$this->num} <= maxi{$this->num}) i{$this->num}++;
  552. }
  553. });
  554. ";
  555. $jssub = "
  556. $('#sub_{$uniqueid}_{$i}').click(function() {
  557. $('#div_{$uniqueid}_{$i}').hide();
  558. $(\"select[name='{$this->getListBoxName()}[{$i}]]\").val('');
  559. if(i{$this->num} >= 1) i{$this->num}--;
  560. });
  561. ";
  562. Yii::app()->clientScript->registerScript('subbutton_'.$uniqueid.'_'.$i, $jssub);
  563. $i++;
  564. }
  565. Yii::app()->clientScript->registerScript('addbutton_'.$uniqueid, $jsadd);
  566. echo '&nbsp;';
  567. echo CHtml::button('+', array('id' => sprintf('add_%s', $uniqueid)));
  568. */
  569. }
  570. public function isAssigned($id)
  571. {
  572. return in_array($id, array_keys($this->getAssignedObjects()));
  573. }
  574. public static function retrieveValues($data)
  575. {
  576. $return_array= array();
  577. foreach($data as $key => $value) {
  578. if(substr($key, 0, 10) == 'selection_') {
  579. $data = explode('_', $key);
  580. $data = $data[1];
  581. $return_array[$data] = $data;
  582. }
  583. }
  584. return $return_array;
  585. }
  586. public function renderCheckBoxListSelection()
  587. {
  588. $keys = array_keys($this->getAssignedObjects());
  589. if(isset($this->preselect) && $this->preselect != false)
  590. $keys = $this->preselect;
  591. echo CHtml::CheckBoxList($this->getListBoxName(),
  592. $keys,
  593. $this->getRelatedData(),
  594. $this->htmlOptions);
  595. }
  596. public function renderOnePaneSelection()
  597. {
  598. $keys = array_keys($this->getAssignedObjects());
  599. echo CHtml::ListBox($this->getListBoxName(),
  600. $keys,
  601. $this->getRelatedData(),
  602. array('multiple' => 'multiple'));
  603. }
  604. public function handleAjaxRequest($_POST) {
  605. print_r($_POST);
  606. }
  607. public function renderTwoPaneSelection()
  608. {
  609. echo CHtml::ListBox($this->getListBoxName(),
  610. array(),
  611. $this->getObjectValues($this->getAssignedObjects()),
  612. array('multiple' => 'multiple'));
  613. $ajax =
  614. array(
  615. 'type'=>'POST',
  616. 'data'=>array('yeah'),
  617. 'update'=>'#' . $this->getListBoxName(true),
  618. );
  619. echo CHtml::ajaxSubmitButton('<<',
  620. array('assign'),
  621. $ajax
  622. );
  623. $ajax =
  624. array(
  625. 'type'=>'POST',
  626. 'update'=>'#not_'.$this->getListBoxName(true)
  627. );
  628. echo CHtml::ajaxSubmitButton('>>',
  629. array('assign','revoke'=>1),
  630. $ajax);//,
  631. //$data['revoke']);
  632. echo CHtml::ListBox('not_' . $this->getListBoxName(),
  633. array(),
  634. $this->getObjectValues($this->getNotAssignedObjects()),
  635. array('multiple' => 'multiple'));
  636. }
  637. public function run()
  638. {
  639. if($this->manyManyTable != '')
  640. $this->renderManyManySelection();
  641. else
  642. $this->renderBelongsToSelection();
  643. if($this->showAddButton !== false)
  644. {
  645. $this->renderAddButton();
  646. }
  647. }
  648. protected function renderAddButton()
  649. {
  650. if(!isset($this->returnLink) or $this->returnLink == "")
  651. $this->returnLink = get_class($this->model) . "/create";
  652. if(isset($_POST['returnUrl']))
  653. echo CHtml::hiddenField('returnUrl', $_POST['returnUrl']);
  654. else
  655. echo CHtml::hiddenField('returnUrl', Yii::app()->request->hostInfo . Yii::app()->request->requestUri);
  656. if($this->addButtonLink != '')
  657. $link = $this->addButtonLink;
  658. else
  659. $link = array(get_class($this->_relatedModel) . "/create");
  660. $string = '<br />' . Yii::t('app', 'Add new') . ' ' . Yii::t('app', get_class($this->_relatedModel));
  661. if(!$this->useLinkButton) {
  662. echo CHtml::Link(
  663. is_string($this->showAddButton)
  664. ? $this->showAddButton
  665. : $string, $link);
  666. } else {
  667. echo CHtml::LinkButton(
  668. is_string($this->showAddButton)
  669. ? $this->showAddButton
  670. : $string,
  671. array('submit' => $link));
  672. }
  673. }
  674. }