Example #1
0
 /**
  * Get the Text_Wiki renderer
  *
  * Singleton to get the Text_Wiki instance properly configured for the
  * TIP system. You can specify an array of rules to use in the $rules
  * array, or leave it undefined to use all the available rules.
  *
  * @param  array|null  $rules     The array of rules to enable
  * @param  string|null $toc_title TOC title or null to use a default value
  * @param  string|null $wiki_base Base URI for wiki links
  * @return Text_Wiki              The renderer
  */
 public static function &getWiki($rules = null, $toc_title = null, $wiki_base = '')
 {
     static $renderer = null;
     static $all_rules = array('Prefilter', 'Delimiter', 'Code', 'Function', 'Html', 'Raw', 'Include', 'Embed', 'Anchor', 'Heading', 'Toc', 'Horiz', 'Break', 'Blockquote', 'List', 'Deflist', 'Table', 'Image', 'Phplookup', 'Center', 'Paragraph', 'Url', 'Freelink', 'Interwiki', 'Wikilink', 'Colortext', 'Strong', 'Bold', 'Emphasis', 'Italic', 'Underline', 'Tt', 'Superscript', 'Subscript', 'Revise', 'Tighten');
     static $base_rules = array('Prefilter', 'Break', 'Paragraph', 'Tighten');
     if (is_null($renderer)) {
         require_once 'Text/Wiki.php';
         isset($toc_title) || ($toc_title = TIP::getLocale('index', 'wiki'));
         $renderer =& Text_Wiki::singleton('Default');
         $renderer->disable = array();
         $renderer->setFormatConf('Xhtml', 'charset', 'UTF-8');
         /* According to the following comment:
          * http://php.net/manual/function.htmlentities.php#78509
          * "There's no sane reason to use htmlentities() instead of htmlspecialchars()"
          */
         $renderer->setFormatConf('Xhtml', 'translate', HTML_SPECIALCHARS);
         $renderer->setRenderConf('Xhtml', 'url', array('target' => '', 'regexes' => array('|http://picasaweb\\.google\\.com/.*/photo/.*|' => array('TIP_Renderer', 'picasa2PhotoCallback'), '|http://picasaweb\\.google\\.com/.*/albumid/.*|' => array('TIP_Renderer', 'picasa2AlbumCallback'))));
         $renderer->setRenderConf('Xhtml', 'code', array('css' => 'programlisting'));
         $renderer->setRenderConf('Xhtml', 'toc', array('title' => '<p><strong>' . $toc_title . '</strong></p>', 'div_id' => 'idToc', 'use_ul' => true, 'collapse' => false));
         $renderer->setRenderConf('Xhtml', 'freelink', array('pages' => null, 'view_url' => $wiki_base, 'new_text_pos' => null));
     }
     if (is_array($rules)) {
         // Capitalize the $rules values
         $rules = array_map('ucfirst', array_map('strtolower', $rules));
         // Join the forced rules
         $rules = array_merge($rules, $base_rules);
         // Get the real rules to apply
         $rules = array_intersect($all_rules, $rules);
     } else {
         $rules = $base_rules;
     }
     $renderer->rules = $rules;
     return $renderer;
 }
Example #2
0
 /**
  * End a transaction
  *
  * End the current transaction. If there's no active transaction,
  * raise an error and return false.
  *
  * The transaction is really ended when the last started transaction
  * is closed. For instance, if you call startTransaction() twice and
  * endTransaction() once, the data will be never committed.
  * 
  * The error flag indicates if the transaction must be rolled back
  * ($commit = true) of committed ($commit = false).
  *
  * @param  bool $commit Commit (if true) or rollback (if false)
  * @return bool         true on success or false on errors
  */
 public function endTransaction($commit)
 {
     if ($this->_transaction_ref == 0) {
         TIP::error('ending a never started transaction');
         return false;
     }
     --$this->_transaction_ref;
     if ($this->_transaction_ref > 0) {
         return true;
     }
     $action = $commit ? TIP_TRANSACTION_COMMIT : TIP_TRANSACTION_ROLLBACK;
     return $this->transaction($action);
 }
Example #3
0
 protected static function checkOptions(&$options)
 {
     if (@is_string($options['data'])) {
         $options['data'] = array('path' => $options['data']);
     }
     // The data path is a required option
     if (!@is_array($options['data']) || !isset($options['data']['path'])) {
         return false;
     }
     TIP::arrayDefault($options, 'id_type', 'string');
     TIP::arrayDefault($options['data'], 'data_engine', array('id' => 'youtube2', 'type' => array('data_engine', 'xml'), 'fields_xpath' => array('id' => 'media:group/yt:videoid', 'title' => 'media:group/media:title[@type="plain"]', 'description' => 'media:group/media:description[@type="plain"]', 'swfurl' => 'media:group/media:content[@yt:format="5"]/@url', 'thumbnail120x90' => 'media:group/media:thumbnail[@width="120" and @height="90"]/@url', 'thumbnail480x360' => 'media:group/media:thumbnail[@width="480" and @height="360"]/@url', 'date' => 'media:group/yt:uploaded', 'uploader' => 'media:group/media:credit[@role="uploader"]', 'author' => 'author/name', 'duration' => 'media:group/yt:duration/@seconds', 'hits' => 'yt:statistics/@viewCount', 'favorites' => 'yt:statistics/@favoriteCount', 'rating' => 'gd:rating/@average', 'raters' => 'gd:rating/@numRaters')));
     return parent::checkOptions($options);
 }
Example #4
0
 /**
  * Get the relative URI of the cached file, if it exists
  * @param  TIP_Template &$template The template to check
  * @return string|null             URI to the cache or null on errors
  */
 public function getCacheUri(&$template)
 {
     $dirs = array_merge($this->cache_root, $template->getProperty('path'));
     if (!is_readable(implode(DIRECTORY_SEPARATOR, $dirs))) {
         return null;
     }
     return TIP::buildUri($dirs);
 }
Example #5
0
 protected static function checkOptions(&$options)
 {
     TIP::arrayDefault($options, 'extension', '.rcbt');
     return parent::checkOptions($options);
 }
Example #6
0
 /**
  * Render a row to an array
  *
  * Renders $row as required by toArray(), that is append to the row
  * data some missing info (the {{id}}, {{title}} and {{tooltip}} fields).
  *
  * @param  array   &$row  The subject row
  * @param  mixed    $id   The id of the row
  * @internal
  */
 private function _rowToArray(&$row, $id)
 {
     isset($row['id']) || ($row['id'] = $id);
     // Use the custom "title_field" or
     // leave the default $row['title'] untouched
     if (isset($this->title_field) && $this->title_field != 'title') {
         $row['title'] = TIP::pickElement($this->title_field, $row);
     }
     // Try to set the custom tooltip field
     if (isset($this->tooltip_field) && $this->tooltip_field != 'tooltip') {
         $row['tooltip'] = TIP::pickElement($this->tooltip_field, $row);
     }
 }
Example #7
0
 /**
  * Perform a view action
  *
  * Runs the file identified by the 'view_template' property for the
  * specified row. The rendered result is appended to the page.
  *
  * @param  mixed $id The identifier of the row to view
  * @return bool      true on success or false on errors
  */
 protected function actionView($id)
 {
     // The query is not strictly necessary but it is still performed
     // to avoid read actions on arbitrary files
     if (is_null($row =& $this->fromRow($id, false)) || !$this->_onView($row)) {
         return false;
     }
     // Check for html file existence
     $file = TIP::buildDataPath($this->id, $id);
     if (!is_readable($file)) {
         $this->endView();
         return false;
     }
     $content =& TIP_Application::getGlobal('content');
     $this->keys['id'] = $id;
     $this->keys[$this->title_field] = str_replace('.html', '', $id);
     $this->keys['content'] = file_get_contents($file);
     $this->keys[$this->creation_field] = TIP::formatDate('datetime_sql', filectime($file));
     $this->keys[$this->edited_field] = TIP::formatDate('datetime_sql', filemtime($file));
     if (empty($this->view_template)) {
         // On empty template, output the whole html file content
         // and set a viable "title" metatag
         $content .= $this->keys['content'];
         $title =& TIP_Application::getGlobal('title');
         $title = $this->keys[$this->title_field] . ' (' . $title . ')';
     } else {
         // Use a custom template
         $content .= $this->tagRun($this->view_template);
     }
     // Discard the generated content to decrease memory consumption
     unset($this->keys);
     $this->endView();
     return true;
 }
Example #8
0
 private function _updateCount($id, $offset)
 {
     if (empty($this->count_field)) {
         return true;
     }
     // Global query (probably cached)
     if (is_null($view =& $this->startDataView())) {
         TIP::notifyError('select');
         return false;
     }
     $rows =& $view->getProperty('rows');
     $this->endView();
     if (!isset($rows[$id])) {
         TIP::warning("row not found ({$id})");
         TIP::notifyError('notfound');
         return false;
     }
     $old_row =& $rows[$id];
     $row[$this->count_field] = $old_row[$this->count_field] + $offset;
     if (!$this->data->updateRow($row, $old_row)) {
         TIP::notifyError('update');
         return false;
     }
     $old_row[$this->count_field] += $offset;
     return true;
 }
Example #9
0
 private function &_getRows(&$data, $fields)
 {
     $path = $data->getProperty('path');
     if (!array_key_exists($path, $this->_rows)) {
         if (strncmp($path, 'http://', 7) == 0) {
             $uri = $path;
             if (function_exists('curl_init')) {
                 // CURL extension available: this should be the
                 // first attempt because the dumb 'open_basedir'
                 // directive can f**k up file_get_contents()
                 $curl = curl_init();
                 curl_setopt($curl, CURLOPT_URL, $uri);
                 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
                 $xml_data = curl_exec($curl);
                 curl_close($curl);
             } else {
                 if (in_array('http', stream_get_wrappers())) {
                     // http wrapper present
                     $xml_data = file_get_contents($uri);
                 } else {
                     // No viable way to use the http protocol
                     $xml_data = false;
                 }
             }
         } else {
             $uri = TIP::buildDataPath($data->getProperty('path'));
             $xml_data = file_get_contents($uri);
         }
         $xml_tree = false;
         if (is_string($xml_data)) {
             // Work-around to let SimpleXML be happy with the f*****g
             // default namespace
             $xml_data = str_replace(' xmlns=', ' fakens=', $xml_data);
             $xml_tree = @simplexml_load_string($xml_data);
         }
         if ($xml_tree) {
             // Takes only the first element matching "base_xpath"
             $xml = reset($xml_tree->xpath($this->base_xpath));
             $this->_data =& $data;
             if (empty($fields)) {
                 $this->_fields = array_keys($this->fields_xpath);
             } else {
                 $this->_fields = $fields;
             }
             $nodes = $xml->xpath($this->row_xpath);
             $rows = $this->_nodesToRows($nodes);
             unset($nodes, $this->_fields, $this->_data);
         } else {
             $rows = array();
             TIP::error("failed to load XML file ({$uri})");
         }
         $this->_rows[$path] = $rows;
     }
     return $this->_rows[$path];
 }
Example #10
0
 /**
  * Refresh the current user
  *
  * Refreshes the user id cache of TIP::getUserId() and the privileges
  * of the yet loaded module.
  */
 private function _refreshUser()
 {
     // Refresh the new user id cache
     TIP::getUserId(true);
     // Refresh the privileges of the yet loaded modules
     $this->_refreshModule(TIP_Type::singleton('module'));
 }
Example #11
0
 private function _validate(&$row)
 {
     $this->getFields(false);
     // Keep only the keys that are fields
     $row = array_intersect_key($row, $this->_fields);
     if (isset($this->fieldset)) {
         // Apply the fieldset filter
         $row = array_intersect_key($row, array_flip($this->fieldset));
     }
     // Check for empty set
     if (empty($row)) {
         TIP::error('no valid field found');
         return false;
     }
     // Cast the set to the proper type
     $this->_castRow($row);
     return true;
 }
Example #12
0
 /**
  * Get the privilege for the specified module
  *
  * Returns the privilege for a module and the specified user.  If $user
  * is omitted, the current user id is used. Check TIP_Privilege to see how the
  * privileges are used.
  *
  * @param  string           $module The requesting module identifier
  * @param  mixed            $user   A user id
  * @return TIP_PRIVILEGE...         The requested privilege
  */
 public static function getPrivilege($module, $user = null)
 {
     static $privilege = false;
     if ($privilege === false) {
         $privilege =& TIP_Application::getSharedModule('privilege');
     }
     if ($privilege) {
         return $privilege->getPrivilege($module, $user);
     }
     return TIP::getDefaultPrivilege($module, $user);
 }
Example #13
0
 private function _render()
 {
     if (!empty($this->_tree)) {
         return true;
     }
     $filter = $this->master->getProperty('data')->order($this->date_field);
     if (is_null($view =& $this->master->startDataView($filter))) {
         return false;
     }
     $rows =& $view->getProperty('rows');
     if (empty($rows)) {
         $this->_tree = array();
         $this->master->endView();
         return true;
     }
     $tree =& $this->_tree;
     foreach ($rows as $id => &$row) {
         $action = str_replace('-id-', $id, $this->action);
         $row['url'] = TIP::buildActionUriFromTag($action, (string) $this->master);
         $row['title'] = $this->_renderField($this->title_field, $row);
         // Suppose the date is in SQL format
         $date = $row[$this->date_field];
         list($y, $m, $day) = sscanf($date, "%d-%d-%d");
         // Compute the year
         $year = sprintf('%04d', $y);
         if (!array_key_exists($year, $tree)) {
             $tree[$year] = array('title' => $year, 'url' => TIP::modifyActionUri(null, null, null, array($this->id => $year)), 'sub' => array(), 'ITEMS' => 0);
             isset($this->count_field) && ($tree[$year]['COUNT'] = 0);
         }
         ++$tree[$year]['ITEMS'];
         isset($this->count_field) && ($tree[$year]['COUNT'] += $row[$this->count_field]);
         // Compute the month
         $months =& $tree[$year]['sub'];
         $month = strftime('%B', mktime(0, 0, 0, $m, $day, $year));
         $month_id = $year . sprintf('%02d', $m);
         if (!array_key_exists($month_id, $months)) {
             $months[$month_id] = array('title' => $month, 'url' => TIP::modifyActionUri(null, null, null, array($this->id => $month_id)), 'sub' => array(), 'ITEMS' => 0);
             isset($this->count_field) && ($months[$month_id]['COUNT'] = 0);
         }
         ++$months[$month_id]['ITEMS'];
         isset($this->count_field) && ($months[$month_id]['COUNT'] += $row[$this->count_field]);
         $months[$month_id]['sub'][$id] =& $row;
         isset($this->count_field) && ($row['COUNT'] = $row[$this->count_field]);
     }
     return true;
 }
Example #14
0
 /**
  * Get a localized text
  *
  * Given an $id and a $prefix, retrieves the localized text (in the locale
  * specified by the 'locale' option of the main TIP_Application) binded to
  * "$prefix.$id". This means the data object of TIP_Locale must have a
  * series of rows with prefix.id values as the primary key.
  *
  * The choice of splitting the key in $prefix and $id allows to perform
  * a sort of cached read, that is, to avoid multiple queries, a single
  * request for a specified prefix gets all the id of this prefix.
  * If you are sure the other id are not used (such as for the TIP_Notify
  * module) you can disable the cache by passig false to $cached.
  *
  * The $context associative array contains a series of key=>value pairs
  * that can be substituted in the localized text. The get() method will
  * search in the localized text for any key enclosed by '|' and will put 
  * the corresponding value. For instance, if there is a 'size'=>200 in
  * the $context array, the text 'Max allowed size is |size|...' will
  * expand to 'Max allowed size is 200...'.
  *
  * @param  string      $id      The identifier
  * @param  string      $prefix  The prefix
  * @param  array       $context A context associative array
  * @param  bool        $cached  Whether to perform or not a cached read
  * @return string|null          The localized text or null if not found
  */
 public function get($id, $prefix, $context, $cached)
 {
     $row_id = $prefix . '.' . $id;
     if (array_key_exists($row_id, $this->_cache)) {
         // Localized text found in the TIP_Locale cache
         $row =& $this->_cache[$row_id];
     } elseif ($cached) {
         $filter = $this->data->filter('id', $prefix . '.%', 'LIKE');
         if (is_null($view =& $this->startDataView($filter))) {
             TIP::error("no way to get localized text ({$row_id})");
             return null;
         }
         $this->_cache += $view->getProperty('rows');
         $this->endView();
         if (array_key_exists($row_id, $this->_cache)) {
             $row =& $this->_cache[$row_id];
         } else {
             // $row_id not found
             $this->_cache[$row_id] = null;
             return null;
         }
     } else {
         $row =& $this->data->getRow($row_id);
         if (is_null($this->_cache[$row_id] = $row)) {
             // $row_id not found
             return null;
         }
     }
     $text = $row[$this->locale];
     if (is_null($context) || strpos($text, '|') === false) {
         return $text;
     }
     // There are some embedded keys to expand ...
     $token = explode('|', $text);
     foreach ($token as $n => $value) {
         // Odd tokens are keys
         if ($n & 1) {
             $token[$n] = array_key_exists($value, $context) ? $context[$value] : '';
         }
     }
     return implode($token);
 }
Example #15
0
 function renderEntry($node, $level, $type)
 {
     $this->_name_stack[$level] = $node['title'];
     $name = implode($this->_glue, $this->_name_stack);
     $is_container = array_key_exists('sub', $node);
     // Array rendering
     if ($is_container && $this->_array_mode & 1 || !$is_container && $this->_array_mode & 2) {
         $this->_rows[$node['id']] = $name;
     }
     // Check for maximum level
     $is_deep = isset($this->_levels) && $level >= $this->_levels;
     $is_active = $type != HTML_MENU_ENTRY_INACTIVE;
     if ($is_deep && $level > $this->_levels + 1 || $is_deep && $level > $this->_levels && !$is_active && !end($this->_html[$level - 1]['active'])) {
         return;
     }
     // Verify if the current/active row is a container
     if ($is_active) {
         $this->_is_current_container = $is_container;
     }
     // Generate the XHTML content
     $content = $node['title'];
     $indent = str_repeat('    ', $level);
     isset($node['ITEMS']) && ($content .= ' (' . $node['ITEMS'] . ')');
     $content = htmlspecialchars($content, ENT_QUOTES, 'UTF-8');
     isset($node['COUNT']) && ($content = ' <var>' . $node['COUNT'] . ' </var>' . $content);
     $is_active && ($content = '<strong>' . $content . '</strong>');
     if ($is_container) {
         // <em> for containers
         $content = '<em>' . $content . '</em>';
         $is_deep && !$is_active && ($content = '<a href="' . TIP::toHtml($node['url']) . '">' . $content . '</a>');
     } else {
         // Compute the tooltip, if defined
         isset($node['ITEMS']) && ($content .= ' (' . $node['ITEMS'] . ')');
         if (array_key_exists('tooltip', $node)) {
             $tooltip = '" title="' . htmlspecialchars($node['tooltip'], ENT_QUOTES, 'UTF-8');
         } else {
             $tooltip = '';
         }
         // Use <span> for normal entries
         $content = '<a href="' . TIP::toHtml($node['url']) . $tooltip . '"><span>' . $content . '</span></a>';
     }
     $content = "\n{$indent}  <li>{$content}";
     // Close previous <li> for non-starting entries
     isset($this->_html[$level]) && ($content = '</li>' . $content);
     if (isset($this->_html[$level])) {
         $this->_html[$level]['active'][] = $is_active;
         $this->_html[$level]['content'] .= $content;
     } else {
         $this->_html[$level] = array('active' => array($is_active), 'content' => $content);
     }
 }
Example #16
0
 /**
  * Check if a module exists
  *
  * Expands to true if the module module exists or to false
  * otherwise. This tag only checks if the logic file for the $params
  * module exists, does not load the module itsself nor change
  * the default module.
  *
  * Useful to provide conditional links between different modules.
  */
 protected function tagModuleExists($params)
 {
     $file = TIP::buildLogicPath('module', $params) . '.php';
     return is_readable($file) ? 'true' : 'false';
 }
Example #17
0
 /**
  * Type instantiation
  *
  * Gets the singleton of a configured object. $id could be any identifier
  * defined in $GLOBALS['cfg'].
  *
  * An internal register is mantained to avoid singleton() calls with the
  * same $id.
  *
  * @param  mixed    $id       Instance identifier
  * @param  bool     $required true if errors must be fatals
  * @return TIP_Type           The reference to the requested instance or
  *                            false on errors
  */
 public static function &getInstance($id, $required = true)
 {
     static $register = array();
     global $cfg;
     $id = strtolower($id);
     if (class_exists('TIP_Application')) {
         $namespace = TIP_Application::getGlobal('namespace');
         if (!empty($namespace) && isset($cfg[$namespace . '_' . $id])) {
             $id = $namespace . '_' . $id;
         }
     }
     if (array_key_exists($id, $register)) {
         return $register[$id];
     }
     if (isset($cfg[$id])) {
         $options = $cfg[$id];
         isset($options['id']) || ($options['id'] = $id);
         $instance =& TIP_Type::singleton($options);
     } else {
         $instance = null;
     }
     if (is_null($instance) && $required) {
         TIP::fatal("unable to instantiate the requested object ({$id})");
         exit;
     }
     $register[$id] =& $instance;
     return $instance;
 }
Example #18
0
 /**
  * Append a log
  *
  * Appends a log message to the data source of the logger object.
  *
  * @param string  $severity  The text of the log
  * @param string  $message   A custom message
  */
 public function log($severity, $message)
 {
     static $running = false;
     // The running flag avoid recursive calls to log()
     if ($running) {
         return false;
     } else {
         $running = true;
     }
     // Generate the backtrace
     $bt = debug_backtrace();
     // Carefully scans the backtrace to find useful informations
     // and store them in the $code array
     $code = array('origin' => '', 'tag' => '', 'action' => '', 'template' => '', 'data' => '');
     foreach ($bt as $n => $trace) {
         $function = isset($trace['function']) ? strtolower($trace['function']) : '';
         if (!isset($code['origin'])) {
             // Skip the log wrappers
             if ($function == 'log' || $function == 'warning' || $function == 'error' || $function == 'fatal') {
                 continue;
             }
             $code['origin'] = "{$trace['file']} on line {$trace['line']}";
         }
         if ($function == 'gettag') {
             if (!array_key_exists('tag', $code)) {
                 $module = $trace['class'];
                 $name = $trace['args'][0];
                 $params = $trace['args'][1];
                 if (strlen($params) > 80) {
                     $params = substr($params, 0, 77) . '...';
                 }
                 $code['tag'] = "{$module}::getTag({$name}, {$params})";
             }
             continue;
         } elseif ($function == 'callaction') {
             if (!array_key_exists('action', $code)) {
                 $module = $trace['class'];
                 $action = $trace['args'][0];
                 $code['action'] = "{$module}::callAction({$action})";
             }
             continue;
         }
         $class = isset($trace['class']) ? strtolower($trace['class']) : '';
         if ($class == 'tip_template') {
             if (!array_key_exists('template', $code)) {
                 $last =& $bt[$n - 1];
                 if (is_object($last['args'][0])) {
                     $template =& $last['args'][0];
                     $method = $last['function'];
                     $code['template'] = "{$template} on method {$method}";
                 }
             }
             continue;
         } elseif ($class == 'tip_data') {
             if (!array_key_exists('data', $code)) {
                 $last =& $bt[$n - 1];
                 if (is_object($last['args'][0])) {
                     $data =& $last['args'][0];
                     $method = $last['function'];
                     $code['data'] = "{$data} on method {$method}";
                 }
             }
             continue;
         }
     }
     unset($bt);
     $context = array('user' => TIP::getUserId(), 'when' => TIP::formatDate('datetime_sql'), 'severity' => $severity, 'message' => $message);
     $this->_cache[] = array_merge($context, $code);
     $running = false;
     return true;
 }
Example #19
0
 private function _mapType(&$field, $type)
 {
     // Fallback values
     $field['type'] = 'string';
     $field['widget'] = null;
     $field['length'] = 0;
     switch (strtoupper($type)) {
         case 'BOOL':
         case 'BOOLEAN':
             $field['type'] = 'bool';
             $field['widget'] = 'set';
             break;
         case 'BIT':
         case 'TINYINT':
         case 'SMALLINT':
         case 'MEDIUMINT':
         case 'INT':
         case 'INTEGER':
         case 'BIGINT':
             $field['type'] = 'int';
             break;
         case 'FLOAT':
         case 'DOUBLE':
         case 'DOUBLE PRECISION':
         case 'REAL':
         case 'DECIMAL':
         case 'DEC':
         case 'NUMERIC':
         case 'FIXED':
             $field['type'] = 'float';
             break;
         case 'STRING':
         case 'CHAR':
         case 'VARCHAR':
         case 'BINARY':
         case 'VARBINARY':
             $field['type'] = 'string';
             break;
         case 'TINYBLOB':
         case 'TINYTEXT':
             $field['type'] = 'string';
             $field['widget'] = 'textarea';
             $field['length'] = 255;
             break;
         case 'BLOB':
         case 'TEXT':
             $field['type'] = 'string';
             $field['widget'] = 'textarea';
             $field['length'] = 65535;
             break;
         case 'MEDIUMBLOB':
         case 'MEDIUMTEXT':
             $field['type'] = 'string';
             $field['widget'] = 'textarea';
             $field['length'] = 16777215;
             break;
         case 'LONGBLOB':
         case 'LONGTEXT':
             $field['type'] = 'string';
             $field['widget'] = 'textarea';
             $field['length'] = 4294967295.0;
             break;
         case 'ENUM':
             $field['type'] = 'string';
             $field['widget'] = 'enum';
             break;
         case 'SET':
             $field['type'] = 'string';
             $field['widget'] = 'set';
             break;
         case 'DATE':
             $field['type'] = 'string';
             $field['widget'] = 'date';
             $field['length'] = 10;
             break;
         case 'TIME':
             $field['type'] = 'string';
             $field['widget'] = 'time';
             $field['length'] = 8;
             break;
         case 'DATETIME':
             $field['type'] = 'string';
             $field['widget'] = 'datetime';
             $field['length'] = 19;
             break;
         case 'TIMESTAMP':
             $field['type'] = 'int';
             $field['widget'] = 'datetime';
             break;
         case 'YEAR':
             $field['type'] = 'string';
             $field['length'] = 4;
             break;
         default:
             $field['type'] = 'string';
             TIP::warning("field type not supported ({$type})");
     }
 }
Example #20
0
 /**
  * Get the child module
  *
  * Checks for the child module existence and caches the request.
  * If $class is not specified, no attempts are made to get the
  * child module: only the cache is returned or an error is raised.
  *
  * This method provides also a way to validate the data engine,
  * that **must** be shared between this module and the child one
  * to allow //transation protected// commits.
  *
  * @param  string|null            $class The class to use
  * @return TIP_Content|null|false        The requested child module,
  *                                       null if not needed or
  *                                       false on errors
  * @internal
  */
 private function &_getChildModule($class = null)
 {
     // The true value is used as "uncached" value
     static $child = true;
     // Check for cached result
     if ($child !== true) {
         return $child;
     }
     // Check for request without $class (no autodiscovering)
     if (is_null($class)) {
         TIP::error('No previous child request performed');
         $error = false;
         return $error;
     }
     // Check if the child module is required
     $child = TIP_Type::getInstance($this->id . '-' . $class, false);
     if (is_null($child)) {
         // No child module needed
         return $child;
     }
     // Get and check the child module
     $child_data = $child->getProperty('data');
     if (!$child_data instanceof TIP_Data) {
         TIP::error("the child module has no data (child = {$class})");
         $child = false;
     } elseif ($child_data->getProperty('engine') != $this->data->getProperty('engine')) {
         TIP::error("master and child data must share the same data engine (child = {$class})");
         $child = false;
     }
     return $child;
 }
Example #21
0
 private function &_widgetLookup(&$field, $args)
 {
     $id = $field['id'];
     $label = $this->getLocale('label.' . $id);
     $info = TIP::getLocale('comment.' . $id, $this->locale_prefix);
     if (empty($args)) {
         // Try to get the lookup module from the $cfg array
         global $cfg;
         foreach ($cfg as $module_id => &$module_options) {
             if (@$module_options['master'] == $this->id && end($module_options['type']) == 'hierarchy') {
                 $lookup_id = $module_id;
                 break;
             }
         }
     } else {
         // Explicitely defined in the widget args
         $lookup_id = $args;
     }
     // On lookup module not found, build a default one
     // by appending '_hierarchy' to this module id
     isset($lookup_id) || ($lookup_id = $this->id . '_hierarchy');
     ++$this->_tabindex;
     $element =& $this->_addElement('text', $id, array('size' => 8, 'maxlength' => 8));
     $element->setInfo($info);
     if ($this->json) {
         // Add JSON params, if needed
         $params = array('sWidget' => 'lookup', 'sUriView' => TIP::buildActionUri($lookup_id, 'view'));
         if (!is_null(TIP::getOption($lookup_id, 'search_field'))) {
             // Enable search URI
             $params['sUriSearch'] = TIP::buildActionUri($lookup_id, 'search');
         }
         $element->setComment(json_encode($params));
         // Enable AHAH interactivity
         $element->setAttribute('class', 'ahah');
     }
     return $element;
 }
Example #22
0
 public function cancelTransaction()
 {
     TIP::warning('cancelTransaction()');
     return true;
 }
Example #23
0
 /**
  * Perform a vote action
  *
  * Runs the 'vote_template' template to get a confirmation on the vote and
  * adds the vote if confirmed.
  *
  * @param  int  $id     The poll id
  * @param  int  $answer The answer id
  * @return bool         true on success or false on errors
  */
 protected function actionVote($id, $answer)
 {
     $expiration = @HTTP_Session2::get($this->id . '.expiration');
     $voting = @HTTP_Session2::get($this->id . '.voting');
     if ($voting && time() < $expiration) {
         TIP::notifyError('double');
         return false;
     }
     if (is_null($row =& $this->fromRow($id, false))) {
         return false;
     }
     if (is_null($answer_label = $this->getField('answer' . $answer))) {
         TIP::notifyError('wrongparams');
         $this->endView();
         return false;
     }
     if (@TIP::getGet('process', 'int') == 1) {
         if (!$voting) {
             TIP::notifyError('nocookies');
             $this->endView();
             return false;
         }
         $old_row = $row;
         ++$row['votes' . $answer];
         $this->_onDataRow($row);
         $this->data->updateRow($row, $old_row);
         HTTP_Session2::set($this->id . '.voting', false);
         HTTP_Session2::set($this->id . '.expiration', strtotime($this->expiration));
         $this->appendToPage($this->view_template);
     } else {
         HTTP_Session2::set($this->id . '.voting', true);
         $this->appendToPage($this->vote_template);
     }
     $this->endView();
     return true;
 }
Example #24
0
 /**
  * Update the history on a master row deletion
  *
  * Updates the linked list by skipping the deleted history row
  * before deleting the row itsself.
  */
 public function _onMasterDelete(&$row, $old_row)
 {
     $master_data =& $this->master->getProperty('data');
     $id = $row[$master_data->getProperty('primary_key')];
     $engine =& $this->data->getProperty('engine');
     $query = $this->data->rowFilter($id);
     // Start the transaction here to avoid race conditions
     if (!$engine->startTransaction()) {
         // This error must be caught here to avoid the rollback
         return false;
     }
     // Get the current version row
     if (!($view =& $this->startDataView($query))) {
         $engine->endTransaction(false);
         return false;
     }
     $current_row = $view->current();
     $this->endView();
     if (empty($current_row)) {
         // No history found: return operation done (just in case...)
         return $engine->endTransaction(true);
     }
     // Get the previous version row
     $query = $this->data->filter($this->next_field, $id);
     if (!($view =& $this->startDataView($query))) {
         $engine->endTransaction(false);
         TIP::warning("no row to delete ({$id})");
         TIP::notifyError('notfound');
         return false;
     }
     $previous_row = $view->current();
     $this->endView();
     // Perform the operations
     $done = $this->data->deleteRow($id);
     if ($done && is_array($previous_row)) {
         // Update the next_field of previous_row
         $new_previous_row = $previous_row;
         $new_previous_row[$this->next_field] = $current_row[$this->next_field];
         $done = $this->data->updateRow($new_previous_row, $previous_row);
     }
     // Close the transaction
     $done = $engine->endTransaction($done) && $done;
     return $done;
 }
Example #25
0
 private static function _renderRow($row, $options = null)
 {
     $id = TIP::toHtml($row['id']);
     $description = TIP::toHtml($row['description']);
     $src = TIP::toHtml($row['thumbnail']);
     $width = (int) $row['thumbnail_width'];
     $height = (int) $row['thumbnail_height'];
     $attrs = 'href="' . $id . '"';
     empty($description) || ($attrs .= ' title="' . $description . '"');
     isset($options['class']) && ($attrs .= ' class="' . $options['class'] . '"');
     if (isset($options['max-width']) && $width > $options['max-width']) {
         $options['max-width'] = $width;
     }
     if (isset($options['max-height']) && $height > $options['max-height']) {
         $options['max-height'] = $height;
     }
     return "<a {$attrs}><img src=\"{$src}\" width=\"{$width}\" height=\"{$height}\" alt=\"{$description}\" /></a>\n";
 }
Example #26
0
 /**
  * Perform an add action
  *
  * Overrides the default add action, assuring the 'browse_field' has a
  * valid value.
  *
  * @param  mixed $id      The identifier of the row to duplicate
  * @param  array $options Options to pass to the form() call
  * @return bool           true on success or false on errors
  */
 protected function actionAdd($id, $options = array())
 {
     // Merge the argument before the parent actionAdd(), so also
     // the defaults here defined can be overriden in configuration
     if (isset($this->form_options['add'])) {
         $options = array_merge($this->form_options['add'], $options);
     }
     // Check for the default value of 'browse_field' (the parent id)
     if (!isset($options['defaults'], $options['defaults'][$this->browse_field])) {
         // Try to get the parent id from GET or POST
         if (is_null($parent_id = $this->fromGetOrPost($this->browse_field))) {
             return false;
         }
         $options['defaults'][$this->browse_field] = $parent_id;
     } else {
         $parent_id = $options['defaults'][$this->browse_field];
     }
     TIP::arrayDefault($options, 'follower', TIP::buildActionUri($this->master, 'view', $parent_id));
     return parent::actionAdd($id, $options);
 }
Example #27
0
 /**
  * Process an add action
  *
  * Overrides the default callback providing email notification
  * when requested.
  *
  * @param  array      &$row     The subject row
  * @param  array|null  $old_row The old row or null on no old row
  * @return bool                 true on success, false on errors
  */
 public function _onAdd(&$row, $old_row)
 {
     if (!parent::_onAdd($row, $old_row)) {
         return false;
     }
     if (empty($this->notify_to)) {
         // No notification required
         return true;
     }
     $eol = "\r\n";
     $env = 'TiP-' . TIP_VERSION_BRANCH;
     $sys = 'PHP-' . phpversion();
     $headers = 'From: ' . $this->_getServerEmail() . $eol;
     $headers .= 'X-Mailer: TIP_Request module ' . "({$env}; {$sys})" . $eol;
     $headers .= 'MIME-Version: 1.0' . $eol;
     $headers .= 'Content-Type: text/plain; charset=ISO-8859-1';
     // Assign current_row, so getField() checks for values in this row
     $this->_current_row =& $row;
     ob_start();
     if ($this->tryRun($this->message_template)) {
         $message = ob_get_clean();
     } elseif (array_key_exists($this->message_template, $row)) {
         ob_end_clean();
         $message = $row[$this->message_template];
     } else {
         ob_end_clean();
         $message = 'Undefined message';
     }
     $message = wordwrap(utf8_decode($message), 66);
     if (!mail($this->notify_to, $this->subject_text, $message, $headers)) {
         TIP::warning("Unable to send an email message to {$this->notify_to}");
         return false;
     }
     return true;
 }
Example #28
0
 /**
  * Perform a browse action
  *
  * Overrides the "browse" action to substitute {terms} in the query URI.
  *
  * @param  array &$conditions The browse conditions
  * @return bool               true on success or false on errors
  */
 protected function actionBrowse(&$conditions)
 {
     // Prepare the terms: append " site:thisdomain" to limit the query
     // to the current site
     $terms = TIP::getGetOrPost('terms', 'string');
     $terms .= ' site:' . $_SERVER['SERVER_NAME'];
     $query =& $this->data->getProperty('path');
     $query = str_replace('{terms}', urlencode($terms), $query);
     return parent::actionBrowse($conditions);
 }
Example #29
0
 private function _startSession()
 {
     // Start the session
     TIP::startSession();
     $this->_session_started = true;
     // Set $_referer
     $request = HTTP_Session2::get('request');
     $referer = HTTP_Session2::get('referer');
     if (is_null($request)) {
         // Entry page or new session: the referer is the main page
         $this->_referer = null;
     } elseif ($this->_request['uri'] == $referer['uri']) {
         // Current URI equals to the old referer URI: probably a back action
         $this->_referer = null;
     } elseif ($this->_request['module'] != $request['module'] || $this->_request['action'] != $request['action']) {
         // New action: the referer is the previous request
         $this->_referer = $request;
     } else {
         // Same action: leave the old referer
         $this->_referer = $referer;
     }
     if (!is_array($this->_referer)) {
         $this->_referer = array('uri' => TIP::getHome(), 'module' => null, 'action' => null);
         $this->_referer['action'] = null;
     }
     $this->keys['REFERER'] = $this->_referer['uri'];
     // Store request and referer
     HTTP_Session2::set('referer', $this->_referer);
     HTTP_Session2::set('request', $this->_request);
     // Profiler initialization in "admin" mode
     if ($this->keys['IS_ADMIN']) {
         require_once 'Benchmark/Profiler.php';
         $GLOBALS['_tip_profiler'] = new Benchmark_Profiler();
         $GLOBALS['_tip_profiler']->start();
     }
 }
Example #30
0
 private function _getUser()
 {
     if (!array_key_exists('UID', $this->keys)) {
         if (!is_null($user = $this->fromGet('id')) && $this->privilege < TIP_PRIVILEGE_MANAGER && $user == TIP::getUserId()) {
             TIP::notifyError('denied');
             $user = null;
         }
         $this->keys['UID'] = $user;
     }
     return $this->keys['UID'];
 }