Example #1
0
 /**
  * Register JavaScript code for the grid.
  */
 protected function registerScript()
 {
     if ($this->getGrid()->isUpdate()) {
         return;
     }
     $name = Json::encode($this->getGrid()->getName());
     $baseUrl = Json::encode($this->getGrid()->getBaseUrl());
     $embedded = $this->getGrid()->isEmbedded() ? 'true' : 'false';
     $this->getPage()->register_script(Config::getGlobal('assets_url') . 'javascript/class.atkdatagrid.js');
     $this->getPage()->register_loadscript("\n      ATK.DataGrid.register({$name}, {$baseUrl}, {$embedded});\n    ");
 }
Example #2
0
 /**
  * If a search action has been defined and a search only returns one result
  * the user will be automatically redirected to the search action.
  *
  * @param DataGrid $grid data grid
  *
  * @return bool redirect active?
  */
 protected function redirectToSearchAction($grid)
 {
     $node = $this->getNode();
     $search = $grid->getPostvar('atksearch');
     // check if we are searching and a search action has been defined
     if (!is_array($search) || count($search) == 0 || !is_array($node->m_search_action) || count($node->m_search_action) == 0) {
         return false;
     }
     // check if there is only a single record in the result
     $grid->loadRecords();
     if ($grid->getCount() != 1) {
         return false;
     }
     $records = $grid->getRecords();
     foreach ($node->m_search_action as $action) {
         if (!$node->allowed($action, $records[0])) {
             continue;
         }
         // reset search so we can back to the normal admin screen if we want
         $grid->setPostvar('atksearch', array());
         $sm = SessionManager::getInstance();
         $url = $sm->sessionUrl(Tools::dispatch_url($node->atkNodeUri(), $action, array('atkselector' => $node->primaryKey($records[0]))), SessionManager::SESSION_NESTED);
         if ($grid->isUpdate()) {
             $script = 'document.location.href = ' . Json::encode($url) . ';';
             $node->getPage()->register_loadscript($script);
         } else {
             $node->redirect($url);
         }
         return true;
     }
     return false;
 }
Example #3
0
 /**
  * Renders the debug and error messages to a nice HTML string.
  *
  * @return string html string
  */
 public function renderDebugAndErrorMessages()
 {
     global $ATK_VARS, $g_debug_msg, $g_error_msg;
     // check if this is an Ajax request
     $isPartial = isset($ATK_VARS['atkpartial']);
     // only display error messages
     if (count($g_error_msg) > 0 && Config::getGlobal('display_errors') && Config::getGlobal('debug') <= 0 && !$isPartial) {
         return $this->renderPlainErrorMessages();
     } else {
         if (Config::getGlobal('debug') <= 0 || count($g_debug_msg) == 0 && count($g_error_msg) == 0) {
             return '';
         }
     }
     $expanded = !$isPartial;
     if ($expanded && array_key_exists('atkdebugstate', $_COOKIE) && @$_COOKIE['atkdebugstate'] == 'collapsed') {
         $expanded = false;
     }
     // render debug block
     $block = $this->renderDebugBlock($expanded);
     if ($isPartial) {
         $output = '<script type="text/javascript">
         ATK.Debug.addContent(' . Json::encode($block) . ');
        </script>';
     } else {
         $ui = Ui::getInstance();
         $script = Config::getGlobal('assets_url') . 'javascript/class.atkdebug.js';
         $redirect = $this->renderRedirectLink();
         $output = '
       <script type="text/javascript" src="' . $script . '"></script>
       <div id="atk_debugging_div">
         ' . $redirect . '
         ' . $block . '
       </div>';
     }
     return $output;
 }
Example #4
0
 /**
  * Function returns a generic html form for editing a record.
  *
  * @param string $mode The edit mode ("add" or "edit").
  * @param array $record The record to edit.
  * @param array $forceList A key-value array used to preset certain
  *                             fields to a certain value.
  * @param array $suppressList An array of fields that will be hidden.
  * @param string $fieldprefix If set, each form element is prefixed with
  *                             the specified prefix (used in embedded
  *                             forms)
  * @param string $template The template to use for the edit form
  * @param bool $ignoreTab Ignore the tabs an attribute should be shown on.
  *
  * @return string the edit form as a string
  */
 public function editForm($mode = 'add', $record = null, $forceList = '', $suppressList = '', $fieldprefix = '', $template = '', $ignoreTab = false)
 {
     $node = $this->m_node;
     /* get data, transform into form, return */
     $data = $node->editArray($mode, $record, $forceList, $suppressList, $fieldprefix, $ignoreTab);
     // Format some things for use in tpl.
     /* check for errors and display them */
     $tab = $node->getActiveTab();
     $error_title = '';
     $pk_err_attrib = [];
     $tabs = $node->getTabs($node->m_action);
     // Handle errors
     $errors = [];
     if (count($data['error']) > 0) {
         $error_title = '<b>' . Tools::atktext('error_formdataerror') . '</b>';
         foreach ($data['error'] as $error) {
             if ($error['err'] == 'error_primarykey_exists') {
                 $pk_err_attrib[] = $error['attrib_name'];
             } else {
                 if (count($tabs) > 1 && $error['tab']) {
                     $tabLink = $this->getTabLink($node, $error);
                     $error_tab = ' (' . Tools::atktext('error_tab') . ' ' . $tabLink . ' )';
                 } else {
                     $tabLink = null;
                     $error_tab = '';
                 }
                 if (is_array($error['label'])) {
                     $label = implode(', ', $error['label']);
                 } else {
                     if (!empty($error['label'])) {
                         $label = $error['label'];
                     } else {
                         if (!is_array($error['attrib_name'])) {
                             $label = $node->text($error['attrib_name']);
                         } else {
                             $label = [];
                             foreach ($error['attrib_name'] as $attrib) {
                                 $label[] = $node->text($attrib);
                             }
                             $label = implode(', ', $label);
                         }
                     }
                 }
                 /* Error messages should be rendered in templates using message, label and the link to the tab. */
                 $err = array('message' => $error['msg'], 'tablink' => $tabLink, 'label' => $label);
                 /*
                  * @deprecated: For backwards compatibility, we still support the msg variable as well.
                  * Although the message, tablink variables should be used instead of msg and tab.
                  */
                 $err = array_merge($err, array('msg' => $error['msg'] . $error_tab));
                 $errors[] = $err;
             }
         }
         if (count($pk_err_attrib) > 0) {
             // Make primary key error message
             $pk_err_msg = '';
             for ($i = 0; $i < count($pk_err_attrib); ++$i) {
                 $pk_err_msg .= Tools::atktext($pk_err_attrib[$i], $node->m_module, $node->m_type);
                 if ($i + 1 < count($pk_err_attrib)) {
                     $pk_err_msg .= ', ';
                 }
             }
             $errors[] = array('label' => Tools::atktext('error_primarykey_exists'), 'message' => $pk_err_msg);
         }
     }
     /* display the edit fields */
     $fields = [];
     $errorFields = [];
     $attributes = [];
     for ($i = 0, $_i = count($data['fields']); $i < $_i; ++$i) {
         $field =& $data['fields'][$i];
         $tplfield = $this->createTplField($data['fields'], $i, $mode, $tab);
         $fields[] = $tplfield;
         // make field available in numeric array
         $params[isset($field['name']) ? $field['name'] : null] = $tplfield;
         // make field available in associative array
         $attributes[isset($field['name']) ? $field['name'] : null] = $tplfield;
         // make field available in associative array
         if (!empty($field['error'])) {
             $errorFields[] = $field['id'];
         }
     }
     $ui = $this->getUi();
     $page = $this->getPage();
     $page->register_script(Config::getGlobal('assets_url') . 'javascript/formsubmit.js');
     // register fields that contain errornous values
     $page->register_scriptcode('var atkErrorFields = ' . Json::encode($errorFields) . ';');
     if (Config::getGlobal('lose_changes_warning', true)) {
         // If we are in the save or update action the user has added a nested record, has done
         // a selection using the select handler or generated an error, in either way we assume
         // the form has been changed, so we always warn the user when leaving the page.
         $isChanged = 'false';
         if (isset($record['atkerror']) && count($record['atkerror']) > 0 || isset($this->m_node->m_postvars['__atkunloadhelper']) && $this->m_node->m_postvars['__atkunloadhelper']) {
             $isChanged = 'true';
         }
         $unloadText = addslashes($this->m_node->text('lose_changes_warning'));
         $page->register_script(Config::getGlobal('assets_url') . 'javascript/class.atkunloadhelper.js');
         $page->register_loadscript("new ATK.UnloadHelper('entryform', '{$unloadText}', {$isChanged});");
     }
     $result = '';
     foreach ($data['hide'] as $hidden) {
         $result .= $hidden;
     }
     $params['activeTab'] = $tab;
     $params['fields'] = $fields;
     // add all fields as a numeric array.
     $params['attributes'] = $attributes;
     // add all fields as an associative array
     $params['errortitle'] = $error_title;
     $params['errors'] = $errors;
     // Add the list of errors.
     Tools::atkdebug("Render editform - {$template}");
     if ($template) {
         $result .= $ui->render($template, $params);
     } else {
         $tabTpl = $this->_getTabTpl($node, $tabs, $mode, $record);
         $params['fieldspart'] = $this->_renderTabs($fields, $tabTpl);
         $result .= $ui->render('editform_common.tpl', $params);
     }
     return $result;
 }
 /**
  * Fetch value for this relation based on the postvars.
  *
  * @param array $postvars
  *
  * @return mixed The value of this relation
  */
 public function fetchValue($postvars)
 {
     $ret = [];
     $vals = Json::decode($postvars[$this->fieldName()]['selected'][0][$this->getRemoteKey()], true);
     if (is_array($vals)) {
         foreach ($vals as $val) {
             $ret[][$this->getRemoteKey()] = $val;
         }
     }
     $postvars[$this->fieldName()]['selected'] = $ret;
     return $postvars[$this->fieldName()];
 }
Example #6
0
 /**
  * Re-render / refresh the attribute with the given name.
  *
  * @param string $name attribute name
  */
 public function refreshAttribute($name)
 {
     if ($this->isInitial()) {
         return;
     }
     $offset = count($this->getNode()->getPage()->getLoadScripts());
     $error = [];
     $editArray = array('fields' => array());
     $this->m_node->getAttribute($name)->addToEditArray($this->getMode(), $editArray, $this->getRecord(), $error, $this->getFieldPrefix());
     $scriptCode = '';
     foreach ($editArray['fields'] as $field) {
         $element = str_replace('.', '_', $this->getNode()->atkNodeUri() . '_' . $field['id']);
         $value = Json::encode(Tools::atk_iconv(Tools::atkGetCharset(), 'UTF-8', $field['html']));
         // Json::encode excepts string in UTF-8
         $scriptCode .= "if (\$('{$element}')) { \$('{$element}').update({$value}); } ";
     }
     $this->getNode()->getPage()->register_loadscript($scriptCode, $offset);
 }
Example #7
0
 /**
  * Returns a JavaScript call to save the current grid's contents when in edit mode.
  *
  * @return string JavaScript call (might need escaping when used in HTML code)
  */
 public function getSaveCall()
 {
     $sm = SessionManager::getInstance();
     $url = $sm->sessionUrl(Tools::dispatch_url($this->getNode()->atkNodeUri(), 'multiupdate', array('output' => 'json')), SessionManager::SESSION_PARTIAL);
     return 'ATK.DataGrid.save(' . Json::encode($this->getName()) . ', ' . Json::encode($url) . ');';
 }
Example #8
0
 /**
  * Initialize and calls the dependencies.
  *
  * @param array $record record
  * @param string $fieldPrefix the prefix for this attribute in an HTML form
  * @param string $mode add/edit mode
  * @param bool $noCall only initialize dependencies, without calling them
  */
 public function initDependencies(&$record, $fieldPrefix, $mode, $noCall = false)
 {
     if (count($this->getDependencies()) == 0) {
         return;
     }
     if (!$noCall) {
         $this->_callDependencies($record, $fieldPrefix, $mode, true);
     }
     $action = $this->getOwnerInstance()->m_action;
     if ($action == null) {
         $action = $mode == 'add' ? 'add' : 'edit';
     }
     $url = Tools::partial_url($this->getOwnerInstance()->atkNodeUri(), $action, 'attribute.' . $this->fieldName() . '.dependencies', array('atkdata' => array('fieldPrefix' => $fieldPrefix, 'mode' => $mode)));
     $url = Json::encode($url);
     $this->getOwnerInstance()->getPage()->register_script(Config::getGlobal('assets_url') . 'javascript/class.atkattribute.js');
     $code = "ATK.Attribute.callDependencies({$url}, el);";
     $this->addOnChangeHandler($code);
 }
Example #9
0
 /**
  * Returns a piece of html code that can be used in a form to edit this
  * attribute's value. (Month will be a dropdownbox, year and day text fields).
  *
  * @todo We can't show a calendar when we have a year dropdown?
  * @todo The calendar doesn't use the min/max values?
  *
  * @param array $record Array with 3 fields (year, month, day)
  * @param string $id html id
  * @param string $name html name
  * @param string $fieldprefix The fieldprefix
  * @param string $postfix
  * @param string $mode The mode ('add' or 'edit')
  * @param bool $obligatory Is this field obligatory or not
  *
  * @return string Piece a of HTML Code
  */
 public function draw($record = [], $id, $name, $fieldprefix = '', $postfix = '', $mode = '', $obligatory = false)
 {
     $result = '';
     // go in simplemode when a pda is detected
     if (BrowserInfo::detectPDA()) {
         $this->setSimpleMode(true);
     }
     $this->m_yeardropdown = false;
     if (!$this->m_simplemode) {
         self::registerScriptsAndStyles(!$this->hasFlag(self::AF_DATE_NO_CALENDAR));
     }
     $fieldname = $name . $postfix;
     /* text mode? */
     if ($this->hasFlag(self::AF_DATE_STRING) || $mode == 'list') {
         $value =& $record[$this->fieldName()];
         if (is_array($value)) {
             $value = adodb_date($this->m_date_format_edit, adodb_mktime(0, 0, 0, $value['month'], $value['day'], $value['year']));
         } elseif ($obligatory) {
             $value = adodb_date($this->m_date_format_edit);
         } else {
             $value = '';
         }
         $fieldname = $fieldname . '[date]';
         $result = '<input type="text" id="' . $id . '" class="atkdateattribute form-control" name="' . $fieldname . '" value="' . $value . '">';
         if (!$this->hasFlag(self::AF_DATE_NO_CALENDAR) && $mode != 'list') {
             $format = str_replace(array('y', 'Y', 'm', 'n', 'j', 'd'), array('yy', 'y', 'mm', 'm', 'd', 'dd'), $this->m_date_format_edit);
             $mondayFirst = 'false';
             if (is_bool(Tools::atktext('date_monday_first'))) {
                 $mondayFirst = Tools::atktext('date_monday_first') === true ? 'true' : $mondayFirst;
             }
             $result .= ' <input ' . $this->getCSSClassAttribute(['btn', 'btn-default', 'button', 'atkbutton', 'form-control']) . ' type="button" value="..." onclick="return showCalendar(\'' . $id . '\', \'' . $id . '\', \'' . $format . '\', false, ' . $mondayFirst . ');">';
         }
         return $result;
     }
     /* this field */
     $field = Tools::atkArrayNvl($record, $this->fieldName());
     $str_format = $this->m_date_format_edit;
     /* currently selected date */
     if (is_array($field) && $field['year'] == 0 && $field['month'] == 0 && $field['day'] == 0) {
         $current = null;
     } elseif (!is_array($field) && empty($field)) {
         $current = null;
     } elseif (is_array($field)) {
         if ($this->checkDateArray($field)) {
             $current = adodb_mktime(0, 0, 0, $field['month'], $field['day'], $field['year']);
         } else {
             $current = null;
             Tools::triggerError($record, $this->fieldName(), 'error_date_invalid');
         }
     } else {
         $date = self::dateArray($field);
         if ($this->checkDateArray($date)) {
             $current = adodb_mktime(0, 0, 0, $date['month'], $date['day'], $date['year']);
         } else {
             $current = null;
         }
     }
     /* minimum date */
     $minimum = $mode != 'search' ? $this->m_date_min : 0;
     if ($minimum != 0) {
         $str_min = adodb_date('Ymd', $minimum);
     } else {
         $str_min = 0;
     }
     /* maximum date */
     $maximum = $mode != 'search' ? $this->m_date_max : 0;
     if ($maximum != 0) {
         $str_max = adodb_date('Ymd', $maximum);
     } else {
         $str_max = 0;
     }
     $current = $this->getValidCurrentDate($current, $minimum, $maximum, $mode);
     /* get dates in array format */
     if ($current !== null) {
         $current = adodb_getdate($current);
     }
     if (!empty($minimum)) {
         $minimum = adodb_getdate($minimum);
     }
     if (!empty($maximum)) {
         $maximum = adodb_getdate($maximum);
     }
     /* minimum and maximum */
     $current['d_min'] = !empty($minimum) && $current['year'] == $minimum['year'] && $current['mon'] == $minimum['mon'] ? $minimum['mday'] : 1;
     $current['d_max'] = !empty($maximum) && $current['year'] == $maximum['year'] && $current['mon'] == $maximum['mon'] ? $maximum['mday'] : $this->getDays($current);
     $current['m_min'] = !empty($minimum) && $current['year'] == $minimum['year'] ? $minimum['mon'] : 1;
     $current['m_max'] = !empty($maximum) && $current['year'] == $maximum['year'] ? $maximum['mon'] : 12;
     $current['y_min'] = !empty($minimum) ? $minimum['year'] : 0;
     $current['y_max'] = !empty($maximum) ? $maximum['year'] : 0;
     /* small date selections, never possible is field isn't obligatory (no min/max date) */
     if (!empty($maximum) && !empty($minimum) && $str_max - $str_min < 25) {
         $str_script = '';
         if (count($this->m_onchangecode)) {
             $this->_renderChangeHandler($fieldprefix);
             $str_script = $this->getHtmlId($fieldprefix) . '_onChange(this);';
         }
         $result = '<select id="' . $id . '" name="' . $fieldname . '" onChange="' . $str_script . '" class="form-control select-standard">';
         for ($i = $str_min; $i <= $str_max; ++$i) {
             $tmp_date = adodb_getdate(adodb_mktime(0, 0, 0, substr($i, 4, 2), substr($i, 6, 2), substr($i, 0, 4)));
             $result .= '<option value="' . $i . '"' . ($current !== null && $tmp_date[0] == $current[0] ? ' selected' : '') . '>' . $this->formatDate($tmp_date, $str_format, !$this->hasFlag(self::AF_DATE_EDIT_NO_DAY)) . '</option>';
         }
         $result .= '</select>';
         return $result;
     }
     if ($this->hasFlag(self::AF_DATE_EMPTYFIELD)) {
         $emptyfield = true;
     } else {
         if (!$obligatory) {
             $emptyfield = true;
         } else {
             $emptyfield = false;
         }
     }
     $info = array('format' => $str_format, 'min' => $str_min, 'max' => $str_max, 'emptyfield' => $emptyfield, 'weekday' => !$this->hasFlag(self::AF_DATE_EDIT_NO_DAY));
     if (!$this->m_simplemode) {
         $result .= '<div class="' . $this->get_class_name() . ' form-inline"><script language="javascript">var atkdateattribute_' . $id . ' = ' . Json::encode($info) . ';</script>';
     }
     /* other date selections */
     $weekdayFormat = null;
     $str_script = '';
     for ($i = 0; $i < strlen($str_format); ++$i) {
         /* javascript method */
         if (!$this->m_simplemode) {
             $str_script = "AdjustDate(this, '" . $id . "');";
         }
         if (count($this->m_onchangecode)) {
             $this->_renderChangeHandler($fieldprefix);
             $str_script .= $this->getHtmlId($fieldprefix) . '_onChange(this);';
         }
         /* year input box */
         if ($str_format[$i] == 'y' || $str_format[$i] == 'Y') {
             $result .= $this->renderYear($id, $fieldname, $str_script, $current, $str_format[$i], $obligatory);
         } elseif ($str_format[$i] == 'D' || $str_format[$i] == 'l') {
             $weekdayFormat = $str_format[$i];
         } elseif ($str_format[$i] == 'j' || $str_format[$i] == 'd') {
             $result .= $this->renderDay($id, $fieldname, $str_script, $current, $str_format[$i], $obligatory, $weekdayFormat);
         } elseif ($str_format[$i] == 'm' || $str_format[$i] == 'n' || $str_format[$i] == 'M' || $str_format[$i] == 'F') {
             $result .= $this->renderMonth($id, $fieldname, $str_script, $current, $str_format[$i], $obligatory);
         } else {
             $result .= $str_format[$i];
         }
     }
     if (!$this->hasFlag(self::AF_DATE_NO_CALENDAR) && !$this->m_yeardropdown && !$this->m_simplemode && $mode != 'list') {
         $mondayFirst = 'false';
         if (is_bool(Tools::atktext('date_monday_first'))) {
             $mondayFirst = Tools::atktext('date_monday_first') === true ? 'true' : $mondayFirst;
         }
         $result .= ' <input ' . $this->getCSSClassAttribute(array('button', 'atkbutton', 'btn', 'btn-default', 'form-control')) . ' type="reset" value="..." onclick="return showCalendar(\'' . $id . '\', \'' . $id . '[year]\', \'y-mm-dd\', true, ' . $mondayFirst . ');">';
     }
     if (!$this->m_simplemode) {
         $result .= '</div>';
         // form-inline
     }
     return $result;
 }