Example #1
0
/**
 * Renders a list of form templates.
 *
 * This function returns a list of form templates,
 * wrapped in a multi-edit form widget.
 *
 * @param  string $curname The selected form
 * @return string HTML
 */
function form_list($curname)
{
    global $essential_forms, $form_types;
    $criteria = 1;
    $criteria .= callback_event('admin_criteria', 'form_list', 0, $criteria);
    $rs = safe_rows_start('*', 'txp_form', "{$criteria} order by field(type, " . join(',', quote_list(array_keys($form_types))) . ") asc, name asc");
    if ($rs) {
        $prev_type = null;
        $group_out = array();
        while ($a = nextRow($rs)) {
            extract($a);
            $active = $curname === $name;
            if ($prev_type !== $type) {
                if ($prev_type !== null) {
                    $group_out = tag(n . join(n, $group_out) . n, 'ul', array('class' => 'switcher-list'));
                    $out[] = wrapRegion($prev_type . '_forms_group', $group_out, 'form_' . $prev_type, $form_types[$prev_type], 'form_' . $prev_type);
                }
                $prev_type = $type;
                $group_out = array();
            }
            if ($active) {
                $editlink = txpspecialchars($name);
            } else {
                $editlink = eLink('form', 'form_edit', 'name', $name, $name);
            }
            if (!in_array($name, $essential_forms)) {
                $modbox = span(checkbox('selected_forms[]', txpspecialchars($name), false), array('class' => 'switcher-action'));
            } else {
                $modbox = '';
            }
            $group_out[] = tag(n . $modbox . $editlink . n, 'li', array('class' => $active ? 'active' : ''));
        }
        if ($prev_type !== null) {
            $group_out = tag(n . join(n, $group_out) . n, 'ul', array('class' => 'switcher-list'));
            $out[] = wrapRegion($prev_type . '_forms_group', $group_out, 'form_' . $prev_type, $form_types[$prev_type], 'form_' . $prev_type);
        }
        $methods = array('changetype' => array('label' => gTxt('changetype'), 'html' => formTypes('', false, 'changetype')), 'delete' => gTxt('delete'));
        $out[] = multi_edit($methods, 'form', 'form_multi_edit');
        return form(join('', $out), '', '', 'post', '', '', 'allforms_form');
    }
}
Example #2
0
 /**
  * Generates a list of authors.
  *
  * @param  array  $atts
  * @param  string $thing
  * @return string
  */
 public static function renderAuthors($atts, $thing = null)
 {
     global $thisauthor, $txp_groups;
     extract(lAtts(array('break' => '', 'class' => '', 'form' => '', 'group' => '', 'label' => '', 'labeltag' => '', 'limit' => '', 'name' => '', 'offset' => '', 'sort' => 'name ASC', 'wraptag' => ''), $atts));
     $sql = array('1 = 1');
     $sql_limit = '';
     $sql_sort = " ORDER BY " . doSlash($sort);
     if ($name) {
         $sql[] = "name IN (" . join(', ', quote_list(do_list($name))) . ")";
     }
     if ($group !== '') {
         $privs = do_list($group);
         $groups = array_flip($txp_groups);
         foreach ($privs as &$priv) {
             if (isset($groups[$priv])) {
                 $priv = $groups[$priv];
             }
         }
         $sql[] = 'convert(privs, char) in (' . join(', ', quote_list($privs)) . ')';
     }
     if ($limit !== '' || $offset) {
         $sql_limit = " LIMIT " . intval($offset) . ", " . ($limit === '' ? PHP_INT_MAX : intval($limit));
     }
     $rs = safe_rows_start("user_id as id, name, RealName as realname, email, privs, last_access", 'txp_users', join(" AND ", $sql) . " {$sql_sort} {$sql_limit}");
     if ($rs && numRows($rs)) {
         $out = array();
         if ($thing === null && $form !== '') {
             $thing = fetch_form($form);
         }
         while ($a = nextRow($rs)) {
             $oldauthor = $thisauthor;
             $thisauthor = $a;
             $out[] = parse($thing);
             $thisauthor = $oldauthor;
         }
         unset($thisauthor);
         return doLabel($label, $labeltag) . doWrap($out, $wraptag, $break, $class);
     }
     return '';
 }
Example #3
0
/**
 * Processes multi-edit actions.
 *
 * Accessing requires 'admin.edit' privileges.
 */
function admin_multi_edit()
{
    global $txp_user;
    require_privs('admin.edit');
    $selected = ps('selected');
    $method = ps('edit_method');
    $changed = array();
    $msg = '';
    if (!$selected or !is_array($selected)) {
        return author_list();
    }
    $names = safe_column('name', 'txp_users', "name IN (" . join(',', quote_list($selected)) . ") AND name != '" . doSlash($txp_user) . "'");
    if (!$names) {
        return author_list();
    }
    switch ($method) {
        case 'delete':
            $assign_assets = ps('assign_assets');
            if (!$assign_assets) {
                $msg = array('must_reassign_assets', E_ERROR);
            } elseif (in_array($assign_assets, $names)) {
                $msg = array('cannot_assign_assets_to_deletee', E_ERROR);
            } elseif (remove_user($names, $assign_assets)) {
                $changed = $names;
                callback_event('authors_deleted', '', 0, $changed);
                $msg = 'author_deleted';
            }
            break;
        case 'changeprivilege':
            if (change_user_group($names, ps('privs'))) {
                $changed = $names;
                $msg = 'author_updated';
            }
            break;
        case 'resetpassword':
            foreach ($names as $name) {
                $passwd = generate_password(PASSWORD_LENGTH);
                if (change_user_password($name, $passwd)) {
                    $email = safe_field('email', 'txp_users', "name = '" . doSlash($name) . "'");
                    if (send_new_password($passwd, $email, $name)) {
                        $changed[] = $name;
                        $msg = 'author_updated';
                    } else {
                        return author_list(array(gTxt('could_not_mail') . ' ' . txpspecialchars($name), E_ERROR));
                    }
                }
            }
            break;
    }
    if ($changed) {
        return author_list(gTxt($msg, array('{name}' => txpspecialchars(join(', ', $changed)))));
    }
    author_list($msg);
}
Example #4
0
/**
 * Renders the list of preferences.
 *
 * Plugins may add their own prefs, for example by using plugin lifecycle events or
 * raising a (pre) callback on event=admin / step=prefs_list so they are installed
 * or updated when accessing the Preferences panel. Access to the prefs can be
 * controlled by using add_privs() on 'prefs.your-prefs-event-name'.
 *
 * @param  string $message The feedback / error string to display
 */
function prefs_list($message = '')
{
    global $prefs, $txp_user;
    extract($prefs);
    pagetop(gTxt('tab_preferences'), $message);
    $locale = setlocale(LC_ALL, $locale);
    echo hed(gTxt('tab_preferences'), 1, array('class' => 'txp-heading'));
    echo n . '<div id="prefs_container" class="txp-container">' . n . '<form method="post" class="prefs-form" action="index.php">' . n . '<div class="txp-layout-textbox">';
    // TODO: remove 'custom' when custom fields are refactored.
    $core_events = array('site', 'admin', 'publish', 'feeds', 'comments', 'custom');
    $joined_core = join(',', quote_list($core_events));
    $sql = array();
    $sql[] = 'prefs_id = 1 and event != "" and type in(' . PREF_CORE . ', ' . PREF_PLUGIN . ')';
    $sql[] = "(user_name = '' or (user_name='" . doSlash($txp_user) . "' and name not in(\n            select name from " . safe_pfx('txp_prefs') . " where user_name = ''\n        )))";
    if (!get_pref('use_comments', 1, 1)) {
        $sql[] = "event != 'comments'";
    }
    $rs = safe_rows_start("*, FIELD(event,{$joined_core}) as sort_value", 'txp_prefs', join(' and ', $sql) . " ORDER BY sort_value = 0, sort_value, event, position");
    $last_event = null;
    $out = array();
    if (numRows($rs)) {
        while ($a = nextRow($rs)) {
            if (!has_privs('prefs.' . $a['event'])) {
                continue;
            }
            if ($a['event'] !== $last_event) {
                if ($last_event !== null) {
                    echo wrapRegion('prefs_group_' . $last_event, join(n, $out), 'prefs_' . $last_event, $last_event, 'prefs_' . $last_event);
                }
                $last_event = $a['event'];
                $out = array();
            }
            $label = '';
            if (!in_array($a['html'], array('yesnoradio', 'is_dst'))) {
                $label = $a['name'];
            }
            // TODO: remove exception when custom fields move to meta store.
            $help = '';
            if (strpos($a['name'], 'custom_') === false) {
                $help = $a['name'];
            }
            if ($a['html'] == 'text_input') {
                $size = INPUT_REGULAR;
            } else {
                $size = '';
            }
            $out[] = inputLabel($a['name'], pref_func($a['html'], $a['name'], $a['val'], $size), $label, $help, array('id' => 'prefs-' . $a['name']));
        }
    }
    if ($last_event === null) {
        echo graf(gTxt('no_preferences'));
    } else {
        echo wrapRegion('prefs_group_' . $last_event, join(n, $out), 'prefs_' . $last_event, $last_event, 'prefs_' . $last_event);
    }
    echo n . '</div>' . sInput('prefs_save') . eInput('prefs') . hInput('prefs_id', '1') . tInput();
    if ($last_event !== null) {
        echo graf(fInput('submit', 'Submit', gTxt('save'), 'publish'));
    }
    echo n . '</form>' . n . '</div>';
}
Example #5
0
/**
 * Renders the list of preferences.
 *
 * Plugins may add their own prefs, for example by using plugin lifecycle events
 * or raising a (pre) callback on event=admin / step=prefs_list so they are
 * installed or updated when accessing the Preferences panel. Access to the
 * prefs can be controlled by using add_privs() on 'prefs.your-prefs-event-name'.
 *
 * @param string $message The feedback / error string to display
 */
function prefs_list($message = '')
{
    global $prefs, $txp_user;
    extract($prefs);
    pagetop(gTxt('tab_preferences'), $message);
    $locale = setlocale(LC_ALL, $locale);
    echo n . '<form class="prefs-form" id="prefs_form" method="post" action="index.php">';
    // TODO: remove 'custom' when custom fields are refactored.
    $core_events = array('site', 'admin', 'publish', 'feeds', 'comments', 'custom');
    $joined_core = join(',', quote_list($core_events));
    $sql = array();
    $sql[] = 'prefs_id = 1 and event != "" and type in(' . PREF_CORE . ', ' . PREF_PLUGIN . ')';
    $sql[] = "(user_name = '' OR (user_name = '" . doSlash($txp_user) . "' AND name NOT IN (\n            SELECT name FROM " . safe_pfx('txp_prefs') . " WHERE user_name = ''\n        )))";
    if (!get_pref('use_comments', 1, 1)) {
        $sql[] = "event != 'comments'";
    }
    $rs = safe_rows_start("*, FIELD(event, {$joined_core}) AS sort_value", 'txp_prefs', join(" AND ", $sql) . " ORDER BY sort_value = 0, sort_value, event, position");
    $last_event = null;
    $out = array();
    $build = array();
    $groupOut = array();
    if (numRows($rs)) {
        while ($a = nextRow($rs)) {
            if (!has_privs('prefs.' . $a['event'])) {
                continue;
            }
            if ($a['event'] !== $last_event) {
                if ($last_event !== null) {
                    $build[] = tag(hed(gTxt($last_event), 2, array('id' => 'prefs_group_' . $last_event . '-label')) . join(n, $out), 'section', array('class' => 'txp-prefs-group', 'id' => 'prefs_group_' . $last_event, 'aria-labelledby' => 'prefs_group_' . $last_event . '-label'));
                    $groupOut[] = n . tag(href(gTxt($last_event), '#prefs_group_' . $last_event, array('data-txp-pane' => $last_event, 'data-txp-token' => form_token())), 'li');
                }
                $last_event = $a['event'];
                $out = array();
            }
            $label = '';
            if (!in_array($a['html'], array('yesnoradio', 'is_dst'))) {
                $label = $a['name'];
            }
            // TODO: remove exception when custom fields move to meta store.
            $help = '';
            if (strpos($a['name'], 'custom_') === false) {
                $help = $a['name'];
            }
            if ($a['html'] == 'text_input') {
                $size = INPUT_REGULAR;
            } else {
                $size = '';
            }
            $out[] = inputLabel($a['name'], pref_func($a['html'], $a['name'], $a['val'], $size), $label, $help, array('class' => 'txp-form-field', 'id' => 'prefs-' . $a['name']));
        }
    }
    if ($last_event === null) {
        echo graf(gTxt('no_preferences'));
    } else {
        $build[] = tag(hed(gTxt($last_event), 2, array('id' => 'prefs_group_' . $last_event . '-label')) . join(n, $out), 'section', array('class' => 'txp-prefs-group', 'id' => 'prefs_group_' . $last_event, 'aria-labelledby' => 'prefs_group_' . $last_event . '-label'));
        $groupOut[] = n . tag(href(gTxt($last_event), '#prefs_group_' . $last_event, array('data-txp-pane' => $last_event, 'data-txp-token' => form_token())), 'li') . n;
        echo hed(gTxt('tab_preferences'), 1, array('class' => 'txp-heading')) . n . '<div class="txp-layout-4col-cell-1alt">' . wrapGroup('all_preferences', n . tag(join($groupOut), 'ul', array('class' => 'switcher-list')), 'all_preferences');
        if ($last_event !== null) {
            echo graf(fInput('submit', 'Submit', gTxt('save'), 'publish'), array('class' => 'txp-save'));
        }
        echo n . '</div>' . n . '<div class="txp-layout-4col-cell-2-3-4">' . join(n, $build) . n . '</div>' . sInput('prefs_save') . eInput('prefs') . hInput('prefs_id', '1') . tInput();
    }
    echo n . '</form>';
}
Example #6
0
/**
 * Processes multi-edit actions.
 */
function section_multi_edit()
{
    global $txp_user, $all_pages, $all_styles;
    extract(psa(array('edit_method', 'selected')));
    if (!$selected || !is_array($selected)) {
        return sec_section_list();
    }
    $key = $val = '';
    switch ($edit_method) {
        case 'delete':
            return section_delete();
            break;
        case 'changepage':
            $val = ps('uses_page');
            if (in_array($val, $all_pages, true)) {
                $key = 'page';
            }
            break;
        case 'changecss':
            $val = ps('css');
            if (in_array($val, $all_styles, true)) {
                $key = 'css';
            }
            break;
        case 'changeonfrontpage':
            $key = 'on_frontpage';
            $val = (int) ps('on_frontpage');
            break;
        case 'changesyndicate':
            $key = 'in_rss';
            $val = (int) ps('in_rss');
            break;
        case 'changesearchable':
            $key = 'searchable';
            $val = (int) ps('searchable');
            break;
    }
    $sections = safe_column('name', 'txp_section', "name in (" . join(',', quote_list($selected)) . ")");
    if ($key && $sections) {
        if (safe_update('txp_section', "{$key} = '" . doSlash($val) . "'", "name in (" . join(',', quote_list($sections)) . ")")) {
            sec_section_list(gTxt('section_updated', array('{name}' => join(', ', $sections))));
            return;
        }
    }
    sec_section_list();
}
Example #7
0
/**
 * Processes multi-edit actions.
 *
 * Accessing requires 'admin.edit' privileges.
 */
function admin_multi_edit()
{
    global $txp_user;
    require_privs('admin.edit');
    $selected = ps('selected');
    $method = ps('edit_method');
    $changed = array();
    $msg = '';
    if (!$selected or !is_array($selected)) {
        return author_list();
    }
    $clause = '';
    if ($method === 'resetpassword') {
        $clause = " AND last_access IS NOT NULL";
    } elseif ($method === 'resendactivation') {
        $clause = " AND last_access IS NULL";
    }
    $names = safe_column("name", 'txp_users', "name IN (" . join(',', quote_list($selected)) . ") AND name != '" . doSlash($txp_user) . "'" . $clause);
    if (!$names) {
        return author_list();
    }
    switch ($method) {
        case 'delete':
            $assign_assets = ps('assign_assets');
            if (!$assign_assets) {
                $msg = array('must_reassign_assets', E_ERROR);
            } elseif (in_array($assign_assets, $names)) {
                $msg = array('cannot_assign_assets_to_deletee', E_ERROR);
            } elseif (remove_user($names, $assign_assets)) {
                $changed = $names;
                callback_event('authors_deleted', '', 0, $changed);
                $msg = 'author_deleted';
            }
            break;
        case 'changeprivilege':
            if (change_user_group($names, ps('privs'))) {
                $changed = $names;
                $msg = 'author_updated';
            }
            break;
        case 'resetpassword':
            foreach ($names as $name) {
                send_reset_confirmation_request($name);
                $changed[] = $name;
            }
            $msg = 'password_reset_confirmation_request_sent';
            break;
        case 'resendactivation':
            foreach ($names as $name) {
                send_account_activation($name);
                $changed[] = $name;
            }
            $msg = 'resend_activation_request_sent';
            break;
    }
    if ($changed) {
        return author_list(gTxt($msg, array('{name}' => txpspecialchars(join(', ', $changed)))));
    }
    author_list($msg);
}
Example #8
0
 /**
  * Gets an SQL clause for this method based on the criteria.
  *
  * @todo Case-sensitive searches
  *
  * @param string $search_term The value to search for
  * @param int    $verbatim    Whether the search term is in quotes (1) or not (0)
  */
 public function getCriteria($search_term, $verbatim)
 {
     $clause = array();
     foreach ($this->columns as $column) {
         if (isset($this->aliases[$column])) {
             foreach ($this->aliases[$column] as $dbval => $aliases) {
                 $terms = do_list($search_term);
                 foreach ($terms as $idx => $term) {
                     if ($this->findAlias($term, $aliases, $this->type) !== false) {
                         $terms[$idx] = $dbval;
                     }
                 }
                 $search_term = join(',', $terms);
             }
         }
         if ($this->options['can_list']) {
             $operator = ' in ';
             $value = '(' . join(',', quote_list(do_list($search_term))) . ')';
         } elseif ($this->type === 'boolean') {
             $clause[] = "convert(" . $column . ", char) = '" . $search_term . "'";
             continue;
         } elseif ($verbatim && !$this->options['always_like']) {
             $operator = ' = ';
             $value = doQuote($search_term);
         } elseif ($this->type === 'find_in_set') {
             $clause[] = "find_in_set('" . $search_term . "', " . $column . " )";
             continue;
         } elseif ($this->type === 'numeric') {
             $clause[] = "convert(" . $column . ", char) = '" . $search_term . "'";
             continue;
         } else {
             $operator = ' like ';
             $value = doQuote("%{$search_term}%");
         }
         $clause[] = join($operator, array($column, $value));
     }
     return $clause;
 }
Example #9
0
/**
 * Changes a user's group.
 *
 * On a successful run, will trigger a 'user.change_group > done' callback event.
 *
 * @param   string|array $user  Updated users
 * @param   int          $group The new group
 * @return  bool         FALSE on error
 * @since   4.6.0
 * @package User
 * @example
 * if (change_user_group('john', 1))
 * {
 *     echo "'john' is now publisher.";
 * }
 */
function change_user_group($user, $group)
{
    $levels = get_groups();
    if (!$user || !isset($levels[$group])) {
        return false;
    }
    $names = join(',', quote_list((array) $user));
    if (safe_update('txp_users', 'privs = ' . intval($group), "name in ({$names})") === false) {
        return false;
    }
    callback_event('user.change_group', 'done', 0, compact('user', 'group'));
    return true;
}
Example #10
0
function mem_form_select_section($atts)
{
    extract(mem_form_lAtts(array('exclude' => '', 'sort' => 'name ASC', 'delimiter' => ','), $atts, false));
    if (!empty($exclude)) {
        $exclusion = array_map('trim', split($delimiter, preg_replace('/[\\r\\n\\t\\s]+/', ' ', $exclude)));
        $exclusion = array_map('strtolower', $exclusion);
        if (count($exclusion)) {
            $exclusion = join($delimiter, quote_list($exclusion));
        }
    }
    $where = empty($exclusion) ? '1=1' : 'LOWER(name) NOT IN (' . $exclusion . ')';
    $sort = empty($sort) ? '' : ' ORDER BY ' . doSlash($sort);
    $rs = safe_rows('name, title', 'txp_section', $where . $sort);
    $items = array();
    $values = array();
    if ($rs) {
        foreach ($rs as $r) {
            $items[] = $r['title'];
            $values[] = $r['name'];
        }
    }
    unset($atts['exclude'], $atts['sort']);
    $atts['items'] = join($delimiter, $items);
    $atts['values'] = join($delimiter, $values);
    return mem_form_select($atts);
}
Example #11
0
 * Textpattern is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Textpattern. If not, see <http://www.gnu.org/licenses/>.
 */
if (!defined('TXP_UPDATE')) {
    exit("Nothing here. You can't access this file directly.");
}
safe_alter('textpattern', "MODIFY textile_body    VARCHAR(32) NOT NULL DEFAULT '1'");
safe_alter('textpattern', "MODIFY textile_excerpt VARCHAR(32) NOT NULL DEFAULT '1'");
safe_update('txp_prefs', "name = 'pane_article_textfilter_help_visible'", "name = 'pane_article_textile_help_visible'");
// Rejig preferences panel.
$core_ev = join(',', quote_list(array('site', 'admin', 'publish', 'feeds', 'custom', 'comments')));
// 1) Increase event column size.
safe_alter('txp_prefs', "MODIFY event VARCHAR(255) NOT NULL DEFAULT 'publish'");
safe_alter('txp_prefs', "MODIFY html  VARCHAR(255) NOT NULL DEFAULT 'text_input'");
// 2) Remove basic/advanced distinction.
safe_update('txp_prefs', "type = '" . PREF_CORE . "'", "type = '" . PREF_PLUGIN . "' AND event IN ({$core_ev})");
// 3) Consolidate existing prefs into better groups.
safe_update('txp_prefs', "event = 'site'", "name IN ('sitename', 'siteurl', 'site_slogan', 'production_status', 'gmtoffset', 'auto_dst', 'is_dst', 'dateformat', 'archive_dateformat', 'permlink_mode', 'doctype', 'logging', 'use_comments', 'expire_logs_after')");
// 4) Reorder existing prefs into a more logical progression.
safe_update('txp_prefs', "position = '230'", "name = 'expire_logs_after'");
safe_update('txp_prefs', "position = '340'", "name = 'max_url_len'");
safe_update('txp_prefs', "position = '160'", "name = 'comments_sendmail'");
safe_update('txp_prefs', "position = '180'", "name = 'comments_are_ol'");
safe_update('txp_prefs', "position = '200'", "name = 'comment_means_site_updated'");
safe_update('txp_prefs', "position = '220'", "name = 'comments_require_name'");
safe_update('txp_prefs', "position = '240'", "name = 'comments_require_email'");
Example #12
0
 /** Add a FIELD() expression to the ORDER BY array.
  *  For preserving an arbitrary sort order, e.g. '7,5,12,1'
  *  Note that FIELD() is a MySQL-specific function (not standard SQL)
  *  @param field Column name
  *  @param list Comma-separated list, or array, of values in order
  */
 public function order_by_field($field, $list)
 {
     if (is_string($list)) {
         $list = do_list($list);
     }
     if (count($list)) {
         $this->order_by[] = 'field(' . self::quote($field) . ', ' . implode(', ', quote_list(doSlash($list))) . ')';
     }
     return $this;
 }
Example #13
0
function section_list($atts, $thing = null)
{
    global $sitename, $s, $thissection;
    extract(lAtts(array('active_class' => '', 'break' => br, 'class' => __FUNCTION__, 'default_title' => $sitename, 'exclude' => '', 'form' => '', 'include_default' => '', 'label' => '', 'labeltag' => '', 'sections' => '', 'sort' => '', 'wraptag' => '', 'offset' => '', 'limit' => ''), $atts));
    $sql_limit = '';
    $sql_sort = doSlash($sort);
    $sql = array();
    $sql[] = 1;
    if ($limit !== '' || $offset) {
        $sql_limit = ' limit ' . intval($offset) . ', ' . ($limit === '' ? PHP_INT_MAX : intval($limit));
    }
    if ($sections) {
        if ($include_default) {
            $sections .= ', default';
        }
        $sections = join(',', quote_list(do_list($sections)));
        $sql[] = "name in ({$sections})";
        if (!$sql_sort) {
            $sql_sort = "field(name, {$sections})";
        }
    } else {
        if ($exclude) {
            $exclude = join(',', quote_list(do_list($exclude)));
            $sql[] = "name not in ({$exclude})";
        }
        if (!$include_default) {
            $sql[] = "name != 'default'";
        }
        if (!$sql_sort) {
            $sql_sort = 'name asc';
        }
    }
    if ($include_default) {
        $sql_sort = "name != 'default', " . $sql_sort;
    }
    $rs = safe_rows_start('name, title', 'txp_section', join(' and ', $sql) . ' order by ' . $sql_sort . $sql_limit);
    if ($rs && ($last = numRows($rs))) {
        $out = array();
        $count = 0;
        if (isset($thissection)) {
            $old_section = $thissection;
        }
        while ($a = nextRow($rs)) {
            ++$count;
            extract($a);
            if ($name == 'default') {
                $title = $default_title;
            }
            if ($form === '' && $thing === null) {
                $url = pagelinkurl(array('s' => $name));
                $out[] = tag(txpspecialchars($title), 'a', (($active_class and 0 == strcasecmp($s, $name)) ? ' class="' . txpspecialchars($active_class) . '"' : '') . ' href="' . $url . '"');
            } else {
                $thissection = array('name' => $name, 'title' => $title, 'is_first' => $count == 1, 'is_last' => $count == $last);
                if ($thing === null && $form !== '') {
                    $out[] = parse_form($form);
                } else {
                    $out[] = parse($thing);
                }
            }
        }
        $thissection = isset($old_section) ? $old_section : null;
        if ($out) {
            return doLabel($label, $labeltag) . doWrap($out, $wraptag, $break, $class);
        }
    }
    return '';
}
Example #14
0
function smd_ebook_create()
{
    global $smd_ebook_prefs, $img_dir;
    @(include_once txpath . '/lib/classTextile.php');
    @(include_once txpath . '/publish.php');
    // for parse()
    $textile = new Textile();
    $template = smd_ebook_templates();
    $msg = '';
    $report = $toc = $ncx = $reps = $sheets = $lfout = array();
    // Generate a temporary folder name to store all files in.
    // It's based on the passed params so if you're regenerating the same book
    // and don't alter the POST payload, you'll overwrite stuff in the previous
    // folder for this book. Just keeps the clutter down..
    $ebook_folder = 'smd_ebook_' . substr(md5(serialize($_POST)), 0, 12);
    $ebook_path = get_pref('tempdir') . DS . $ebook_folder . DS;
    if (!is_readable($ebook_path)) {
        mkdir($ebook_path);
    }
    // Store the current type for next time this user creates a book
    $bType = ps('smd_ebook_type');
    set_pref('smd_ebook_type', doSlash($bType), 'smd_ebook', PREF_HIDDEN, 'text_input', 0, PREF_PRIVATE);
    $is_mobi = $bType === 'mobi';
    $is_epub = $bType === 'zip';
    $outfile = trim(ps('smd_ebook_pubfile'));
    // If used, it's without extension
    // Get Textile and encoding options
    $encoding = get_pref('smd_ebook_encoding', $smd_ebook_prefs['smd_ebook_encoding']['default']);
    $which = get_pref('smd_ebook_textile', $smd_ebook_prefs['smd_ebook_textile']['default']);
    $txt_description = in_list('description', $which);
    $txt_authornote = in_list('authornote', $which);
    // Build up a giant replacement table which is then substituted into
    // the various templates before passing to the generator
    // Set up the TOC wrappers
    $toc_wrap = get_pref('smd_ebook_toc_wraptag', $smd_ebook_prefs['smd_ebook_toc_wraptag']['default']);
    $toc_class = get_pref('smd_ebook_toc_class', $smd_ebook_prefs['smd_ebook_toc_class']['default']);
    $wrapit = $toc_wrap === 'ol' ? '#' : '*';
    $article_cnt = $ncx_cnt = $elem_cnt = $img_cnt = 0;
    $article_refs = $article_spines = $guide_refs = $landmarks = $master_image_refs = array();
    // Page break, stylesheets and heading references
    $pbr = get_pref('smd_ebook_page_break', $smd_ebook_prefs['smd_ebook_page_break']['default']);
    $css = get_pref('smd_ebook_stylesheet', $smd_ebook_prefs['smd_ebook_stylesheet']['default']);
    $hdg = get_pref('smd_ebook_heading_level', $smd_ebook_prefs['smd_ebook_heading_level']['default']);
    if ($css) {
        $css_list = quote_list(do_list($css));
        $sheets = $css_list ? safe_rows('name, css', 'txp_css', "name IN (" . join(',', $css_list) . ")") : array();
    }
    $sheetlist = $sheetcontent = array();
    $sheet_count = 0;
    foreach ($sheets as $stylething) {
        $content = trim($stylething['css']);
        if ($is_mobi && $content) {
            // Inline style tags
            $sheetlist[] = '<style type="text/css">' . $content . '</style>';
        } elseif ($is_epub && $content) {
            // External stylesheet references
            $sheetname = $stylething['name'] . '.css';
            $sheetlist[] = '<link rel="stylesheet" media="screen" href="' . $sheetname . '" />';
            $sheetcontent[$stylething['name']] = $content;
            // Add them to the manifest and listfile
            $article_refs[] = '<item id="smd_ebook_style_' . $sheet_count . '" media-type="text/css" href="' . $sheetname . '" />';
            $lfout[] = $sheetname;
        }
        $sheet_count++;
    }
    $sheet = join(n, $sheetlist);
    // The values used in the 'doc' template
    $html_from = array('{smd_ebook_doctype}', '{smd_ebook_namespace}', '{smd_ebook_charset}', '{smd_ebook_encoding}', '{smd_ebook_title}', '{smd_ebook_chaptitle}', '{smd_ebook_stylesheet}', '{smd_ebook_contents}');
    // Loop for each article in the collection
    foreach (ps('smd_ebook_articles') as $artid) {
        $article_cnt++;
        $id = str_replace('smd_ebook_article_', '', $artid);
        $row = safe_row('*, UNIX_TIMESTAMP(Posted) AS uPosted, UNIX_TIMESTAMP(LastMod) AS uModified', 'textpattern', "ID = '" . doSlash($id) . "'");
        if ($row) {
            // Initialize a few things
            $note_content = '';
            $image_list = array();
            $reps['{smd_ebook_file_name}'] = $cur_file = $row['url_title'] . '.html';
            $reps['{smd_ebook_encoding}'] = $encoding;
            // Each of the items starting !isset() are only ever loaded _once_ from the
            // first article in which they are found.
            // Begin by setting up the file names
            if (!isset($firstfile)) {
                $firstfile = $row['url_title'] . '.html';
                $filebase = sanitizeForFile($outfile === '' ? $row['url_title'] : $outfile);
                $listfile = $filebase . '.smd';
                $notefile = $filebase . '_notes.html';
                $toc_file = $filebase . '_toc.html';
                $ncx_file = $filebase . '.ncx';
                $end_file = $filebase . '_end.html';
                $opf_file = $filebase . '.opf';
                $lmk_file = $filebase . '_landmark.html';
                $cover_file = 'cover.html';
                $container_file = 'container.xml';
                $mimetype_file = 'mimetype';
                $toc_ref = 'toc';
            }
            // Populate the unique ID entries direcly into the .opf template,
            // as they're only used once each
            if (!isset($reps['{smd_ebook_uid_ref}'])) {
                $val = ps('smd_ebook_fld_uid');
                if (strpos($val, 'SMD_FLD_') !== false) {
                    $valfld = str_replace('SMD_FLD_', '', $val);
                    $val = isset($row[$valfld]) ? $row[$valfld] : '';
                }
                $uid = trim($val) === '' ? smd_ebook_uid() : $val;
                $is_isbn = smd_ebook_is_isbn($uid);
                $is_uuid = preg_match('/^[0-9a-f]{8,8}\\-[0-9a-f]{4,4}\\-[0-9a-f]{4,4}\\-[0-9a-f]{4,4}\\-[0-9a-f]{12,12}$/i', $uid) === 1;
                $full_uid = $reps['{smd_ebook_uid_ref}'] = $is_uuid ? 'urn:uuid:' . $uid : ($is_isbn ? 'urn:isbn:' . $uid : $uid);
                $template['opf'] = str_replace('{smd_ebook_uid_ref}', $uid ? ' unique-identifier="uid"' : '', $template['opf']);
                $template['opf'] = str_replace('{smd_ebook_md_uid}', $uid ? '<dc:identifier id="uid">' . $full_uid . '</dc:identifier>' : '', $template['opf']);
                $template['ncx'] = str_replace('{smd_ebook_dtb_uid}', $uid ? '<meta name="dtb:uid" content="' . $full_uid . '" />' : '', $template['ncx']);
            }
            // Language
            if (!isset($reps['{smd_ebook_md_lang}'])) {
                $lang = get_pref('language');
                $reps['{smd_ebook_md_lang}'] = '<dc:language>' . $lang . '</dc:language>';
                $reps['{smd_ebook_lang}'] = $lang;
            }
            // Author can come from:
            //  1) an article field
            //  2) the current logged in user
            //  3) user-supplied at book creation time
            //  4) hard-coded in plugin settings
            if (!isset($reps['{smd_ebook_md_creator}'])) {
                $val = ps('smd_ebook_fld_author');
                if (strpos($val, 'SMD_FLD_') !== false) {
                    $valfld = str_replace('SMD_FLD_', '', $val);
                    $val = isset($row[$valfld]) ? $valfld === 'AuthorID' ? get_author_name($row[$valfld]) : $row[$valfld] : '';
                }
                if ($val) {
                    $reps['{smd_ebook_md_creator}'] = '<dc:creator>' . $val . '</dc:creator>';
                    $reps['{smd_ebook_creator}'] = $val;
                }
            }
            // Doctype, namespace and charset
            if (!isset($reps['{smd_ebook_doctype}'])) {
                if ($is_mobi) {
                    $reps['{smd_ebook_doctype}'] = '';
                    $reps['{smd_ebook_namespace}'] = '';
                    $reps['{smd_ebook_charset}'] = '<meta http-equiv="Content-Type" content="text/html; charset=' . $encoding . '">';
                } elseif ($is_epub) {
                    $reps['{smd_ebook_doctype}'] = '<?xml version="1.0" encoding="' . $encoding . '"?>' . n . '<!DOCTYPE html>';
                    $reps['{smd_ebook_namespace}'] = ' xmlns="http://www.w3.org/1999/xhtml"';
                    $reps['{smd_ebook_charset}'] = '<meta charset="' . $encoding . '" />';
                }
            }
            // Publication / modification date
            if (!isset($reps['{smd_ebook_md_date}'])) {
                $reps['{smd_ebook_md_date}'] = '<dc:date>' . strftime('%Y-%m-%dT%H:%M:%SZ', $row['uPosted']) . '</dc:date>';
            }
            if (!isset($reps['{smd_ebook_md_modified}'])) {
                $reps['{smd_ebook_md_modified}'] = '<meta property="dcterms:modified">' . strftime('%Y-%m-%dT%H:%M:%SZ', $row['uModified']) . '</meta>';
            }
            // Cover image
            if (!isset($reps['{smd_ebook_md_cover}'])) {
                if (isset($row['Image'])) {
                    $img = safe_row('*', 'txp_image', "id='" . intval($row['Image']) . "'");
                    // Only GIFs, JPGs or PNGs need apply
                    if ($img) {
                        $mime_type = $img['ext'] === '.jpg' || $img['ext'] === '.jpeg' ? 'image/jpeg' : ($img['ext'] === '.gif' ? 'image/gif' : ($img['ext'] === '.png' ? 'image/png' : ''));
                        if ($mime_type) {
                            $img_file = $img['id'] . $img['ext'];
                            $reps['{smd_ebook_md_cover}'] = '<meta name="cover" content="cover-image" />';
                            if ($is_epub) {
                                $img_dest = 'cover' . $img['ext'];
                                $ret = copy(get_pref('path_to_site') . DS . $img_dir . DS . $img_file, $ebook_path . $img_dest);
                                if ($ret) {
                                    // Write the cover image HTML
                                    $fp = fopen($ebook_path . $cover_file, "wb");
                                    $from = array('{smd_ebook_image_link}', '{smd_ebook_image_alt}');
                                    $to = array($img_dest, $img['alt']);
                                    fwrite($fp, str_replace($from, $to, $template['cov']));
                                    fclose($fp);
                                    $reps['{smd_ebook_manifest_cover}'] = '<item id="cover" media-type="application/xhtml+xml" href="cover.html" />' . n . t . t . '<item id="cover-image" properties="cover-image" media-type="' . $mime_type . '" href="' . $img_dest . '" />';
                                    $lfout[] = $img_dest;
                                }
                            } else {
                                $reps['{smd_ebook_manifest_cover}'] = '<item id="cover-image" media-type="' . $mime_type . '" href="' . get_pref('path_to_site') . DS . $img_dir . DS . $img_file . '" />';
                            }
                        }
                    }
                }
            }
            // The following values can either come from the given field or be used verbatim
            // Firstly the title, description, subject, publisher and chapter title
            $setMany = array('chaptitle');
            foreach (array('title', 'description', 'subject', 'publisher', 'chaptitle') as $thingy) {
                if (in_array($thingy, $setMany) || !isset($reps['{smd_ebook_md_' . $thingy . '}'])) {
                    $val = ps('smd_ebook_fld_' . $thingy);
                    if (strpos($val, 'SMD_FLD_') !== false) {
                        $valfld = str_replace('SMD_FLD_', '', $val);
                        $val = isset($row[$valfld]) ? $row[$valfld] : '';
                    }
                    if ($val) {
                        // Textile the content?
                        $content = isset($txt_[$thingy]) && $txt_[$thingy] ? trim($textile->TextileThis($val)) : trim($val);
                        if (!in_array($thingy, $setMany)) {
                            $reps['{smd_ebook_md_' . $thingy . '}'] = '<dc:' . $thingy . '>' . $content . '</dc:' . $thingy . '>';
                        }
                        // There are two titles: one for the metadata and one raw so if the title
                        // has just been found, populate the raw title too
                        if ($thingy === 'title') {
                            $reps['{smd_ebook_title}'] = $content;
                        } elseif ($thingy === 'chaptitle') {
                            // Chapter title has an associated heading level
                            $reps['{smd_ebook_chaptitle}'] = '<h' . $hdg . '>' . $content . '</h' . $hdg . '>';
                        }
                    }
                }
            }
            // Price (SRP) can also come from a field but it needs some special jiggery pokery
            if (!isset($reps['{smd_ebook_md_srp}'])) {
                $val = ps('smd_ebook_fld_srp');
                if (strpos($val, 'SMD_FLD_') !== false) {
                    $valfld = str_replace('SMD_FLD_', '', $val);
                    $val = isset($row[$valfld]) ? $row[$valfld] : '';
                }
                if ($val) {
                    $parts = do_list($val, '|');
                    $parts[0] = $parts[0] ? $parts[0] : '0.00';
                    $parts[1] = isset($parts[1]) && $parts[1] ? $parts[1] : get_pref('smd_ebook_currency', $smd_ebook_prefs['smd_ebook_currency']['default']);
                    $reps['{smd_ebook_md_srp}'] = '<SRP Currency="' . $parts[1] . '">' . $parts[0] . '</SRP>';
                }
            }
            // Authornote is slightly different because it needs storing as a file,
            // and needs adding to the .ncx (but not to the ToC)
            if (!isset($reps['{smd_ebook_manifest_authornote}'])) {
                $val = ps('smd_ebook_fld_authornote');
                if (strpos($val, 'SMD_FLD_') !== false) {
                    $valfld = str_replace('SMD_FLD_', '', $val);
                    $val = isset($row[$valfld]) ? $row[$valfld] : '';
                }
                if ($val) {
                    $reps['{smd_ebook_manifest_authornote}'] = '<item id="smd_ebook_notes" media-type="application/xhtml+xml" href="' . $notefile . '" />';
                    $reps['{smd_ebook_spine_authornote}'] = '<itemref idref="smd_ebook_notes" />';
                    $guide_refs['notes'] = '<reference type="notes" title="' . gTxt('smd_ebook_lbl_authornote') . '" href="' . $notefile . '" />';
                    $note_content = '<span id="smd_ebook_notes"></span>' . ($txt_authornote ? $textile->TextileThis($val) : $val);
                    // While it's 99% likely the actual title used for the eventual book has been found,
                    // there's a slim chance it hasn't. In that case, the current row's title is used as a fallback
                    $note_title = isset($reps['{smd_ebook_title}']) ? $reps['{smd_ebook_title}'] : $row['Title'];
                    $note_content = str_replace($html_from, array($reps['{smd_ebook_doctype}'], $reps['{smd_ebook_namespace}'], $reps['{smd_ebook_charset}'], $encoding, $note_title, '', $sheet, $note_content), $template['doc']);
                    $fp = fopen($ebook_path . $notefile, "wb");
                    fwrite($fp, trim($note_content));
                    fclose($fp);
                    $lfout[] = $notefile;
                    // Add it to the .ncx
                    $ncx_cnt++;
                    $from = array('{smd_ebook_file_name}', '{smd_ebook_nav_label}', '{smd_ebook_nav_hash}', '{smd_ebook_nav_idx}');
                    $to = array($notefile, gTxt('smd_ebook_lbl_authornote'), 'smd_ebook_notes', $ncx_cnt);
                    $ncx[] = str_replace($from, $to, $template['nav']);
                }
            }
            // Note:
            //  1) a full (well-formed, hopefully) HTML file (from <html>...</html>) is generated
            //     here so the loadHTML() method is happy. The body will need reinjecting into
            //     the template after the ToC has been generated.
            //  2) The current HTML file's title is used instead of the overall book title.
            //  3) parse() is called twice to simulate secondpass. TODO: fix this
            $chap_title = isset($reps['{smd_ebook_chaptitle}']) ? $reps['{smd_ebook_chaptitle}'] : '';
            article_format_info($row);
            // Load article context
            $html_content = str_replace($html_from, array($reps['{smd_ebook_doctype}'], $reps['{smd_ebook_namespace}'], $reps['{smd_ebook_charset}'], $encoding, $row['Title'], $chap_title, $sheet, parse(parse($row['Body_html']))), $template['doc']);
            // Trawl through the HTML content, either:
            //  a) pulling out the given ToC entries.
            //  b) automatically creating ToC entries if the pref allows.
            //  c) finding images to copy into the ePub file structure.
            $autotoc = get_pref('smd_ebook_auto_toc', $smd_ebook_prefs['smd_ebook_auto_toc']['default']);
            // Convert the list of heading numbers into a string of numbers suitable
            // for using inside square brackets of a regex
            $autohed = get_pref('smd_ebook_auto_toc_headings', $smd_ebook_prefs['smd_ebook_auto_toc_headings']['default']);
            $autohed = join('', do_list($autohed));
            $doc = new DOMDocument();
            // Use UNIX line endings to prevent &#13; appearing in the saved XML
            $html_content = preg_replace('/\\r\\n/', "\n", $html_content);
            $dom_ok = $doc->loadHTML($html_content);
            if ($dom_ok) {
                $items = $doc->getElementsByTagName('*');
                $offset = $toc_cnt = 0;
                foreach ($items as $item) {
                    if ($autotoc && !$item->hasAttribute('id') && preg_match('/h([' . $autohed . '])/i', $item->nodeName, $matches)) {
                        // It's a heading. Make the anchor chain based on the heading level
                        $anchor_parts = array_fill(0, $matches[1], 'sub');
                        $anchor = join('-', $anchor_parts) . ++$elem_cnt;
                        $item->setAttribute('id', $anchor);
                    }
                    if ($item->hasAttribute('id')) {
                        $ncx_cnt++;
                        $toc_cnt++;
                        $hashval = $item->getAttribute('id');
                        if (!isset($guide_refs['text']) && $toc_cnt === 1) {
                            $guide_href = $firstfile . ($hashval && $is_mobi ? '#' . $hashval : '');
                            $guide_refs['text'] = '<reference type="text" title="' . gTxt('smd_ebook_lbl_text') . '" href="' . $guide_href . '" />';
                            $landmarks['bodymatter'] = href(gTxt('smd_ebook_lbl_text'), $guide_href, ' epub:type="bodymatter"');
                        }
                        // mb_convert_encoding() seems to bypass the odd behaviour where apostrophes
                        // would appear in the TOC as ’. This may actually be a band-aid to circumvent
                        // problems with the encoding in DOMDocument: perhaps if appropriate encoding is
                        // used there, this hack won't be necessary
                        //						$node = mb_convert_encoding(trim($item->nodeValue), 'HTML-ENTITIES', 'utf-8');
                        $node = trim($item->nodeValue);
                        $from = array('{smd_ebook_file_name}', '{smd_ebook_nav_label}', '{smd_ebook_nav_hash}', '{smd_ebook_nav_idx}');
                        $to = array($cur_file, $node, $hashval, $ncx_cnt);
                        $ncx[] = str_replace($from, $to, $template['nav']);
                        // Now it's the turn of the HTML TOC. Utilise Textile here to
                        // create the toc list from ul or ol syntax
                        $hashBits = do_list($hashval, '-');
                        $indent = count($hashBits);
                        if ($toc_cnt == 1 && $indent > 1) {
                            // Doesn't start with h1 (begins h2, maybe) so scale back the indent.
                            // Without this, Textile produces invalid markup.
                            $offset = $indent - 1;
                        }
                        $toc_cls = $toc_cnt == 1 && $toc_class ? '(' . $toc_class . ')' : '';
                        $toc[] = str_pad('', max(1, $indent - $offset), $wrapit) . $toc_cls . ' ' . href($node, $cur_file . '#' . $hashval);
                    }
                    // For ePub books, images need to be extracted separately
                    if ($is_epub && $item->nodeName === 'img') {
                        $src = $item->getAttribute('src');
                        $bits = pathinfo($src);
                        $mime_type = $bits['extension'] === 'jpg' || $bits['extension'] === 'jpeg' ? 'image/jpeg' : ($bits['extension'] === 'gif' ? 'image/gif' : ($bits['extension'] === 'png' ? 'image/png' : ''));
                        if ($mime_type) {
                            $img = safe_row('*', 'txp_image', "id='" . intval($bits['filename']) . "'");
                            $img['name'] = trim($img['name']);
                            if ($img) {
                                $ret = copy(get_pref('path_to_site') . DS . $img_dir . DS . $bits['basename'], $ebook_path . $bits['basename']);
                                if ($ret) {
                                    if (!in_array($bits['basename'], $master_image_refs)) {
                                        $from = array('{smd_ebook_image_link}', '{smd_ebook_image_type}', '{smd_ebook_image_id}');
                                        $to = array('images' . DS . $bits['basename'], $mime_type, 'image-' . $img_cnt);
                                        $article_refs[] = str_replace($from, $to, $template['img']);
                                        $master_image_refs[] = $bits['basename'];
                                        $img_cnt++;
                                    }
                                    // Add the file to the list of inline images, destined for the .smd file.
                                    // This list of images is merged with $lfout _after_ the chapter HTML
                                    // content, so a list of images in the chapter appear below it
                                    if (!in_array($bits['basename'], $image_list)) {
                                        $image_list[] = $bits['basename'];
                                    }
                                }
                            }
                        }
                    }
                }
                // Grab any changes just made to the DOM tree in case anchors have been added.
                // Note _only_ the <body> is extracted since the XML headers that come with a full
                // saveXML() get in the way. Also note that saveHTML() is not being used because its
                // 'node' parameter wasn't added until PHP 5.3.6 which would affect the plugin's
                // base requirements.
                // Hackish: remove the body tag wrapper with substr() so when the html_content
                // is shoved back into the template (which has a body tag already) there's no
                // tag duplication
                $html_content = substr($doc->saveXML($doc->getElementsByTagName('body')->item(0)), 6, -7);
                // Swap out any line break placeholders. Note that the line break is replaced twice:
                // once to get rid of any surrounding <p> tags that Textile may have introduced around
                // the marker, and again in case a few of them didn't get paragraph tags.
                $html_content = str_replace('<p>' . $pbr . '</p>', '<mbp:pagebreak />', $html_content);
                $html_content = str_replace($pbr, '<mbp:pagebreak />', $html_content);
                // Pass the extracted <body> tree into the doc template again so it regenerates
                // the full <html>...</html> document.
                $html_content = str_replace($html_from, array($reps['{smd_ebook_doctype}'], $reps['{smd_ebook_namespace}'], $reps['{smd_ebook_charset}'], $encoding, $row['Title'], '', $sheet, $html_content), $template['doc']);
            } else {
                trigger_error(gTxt('smd_ebook_malformed'), E_WARNING);
            }
            $ebook_item = 'smd_ebook_item_' . $article_cnt;
            // Guide items require special dispensation and can override built-in items
            // such as 'text' (a.k.a. bodymatter / start page / welcome / start) and 'toc',
            // but not cover image or notes.
            $valid_guide_refs = array('acknowledgments', 'appendix', 'afterword', 'bibliography', 'bodymatter', 'colophon', 'conclusion', 'contributors', 'copyright-page', 'dedication', 'epigraph', 'epilogue', 'errata', 'foreword', 'glossary', 'imprint', 'index', 'introduction', 'loi', 'lot', 'other-credits', 'preamble', 'preface', 'prologue', 'titlepage', 'toc');
            $val = 'custom_' . get_pref('smd_ebook_fld_guide');
            $val = isset($row[$val]) ? $row[$val] : '';
            $guides = do_list($val);
            foreach ($guides as $guide_ref) {
                $guide_name = do_list($guide_ref, '|');
                $guide_hash = do_list($guide_name[0], '#');
                $guide_ref = $lmk_ref = strtolower($guide_hash[0]);
                if ($guide_ref && in_array($guide_ref, $valid_guide_refs)) {
                    switch ($guide_ref) {
                        case 'bodymatter':
                            $guide_ref = 'text';
                            break;
                        case 'toc':
                            $toc_file = $cur_file;
                            $toc_ref = $ebook_item;
                            break;
                    }
                    $guide_title = isset($guide_name[1]) ? $guide_name[1] : gTxt('smd_ebook_lbl_' . str_replace('-', '_', $guide_ref));
                    $guide_href = $cur_file . (isset($guide_hash[1]) ? '#' . $guide_hash[1] : '');
                    $guide_refs[$guide_ref] = '<reference type="' . $guide_ref . '" title="' . $guide_title . '" href="' . $guide_href . '" />';
                    $landmarks[$lmk_ref] = href($guide_title, $guide_href, ' epub:type="' . $lmk_ref . '"');
                }
            }
            // Write the final HTML document to the file system
            $fp = fopen($ebook_path . $cur_file, "wb");
            fwrite($fp, trim($html_content));
            fclose($fp);
            $lfout[] = $cur_file;
            $lfout = array_merge($lfout, $image_list);
            $article_refs[] = '<item id="' . $ebook_item . '" media-type="application/xhtml+xml" href="' . $row['url_title'] . '.html" />';
            $article_spines[] = '<itemref idref="' . $ebook_item . '" />';
        }
    }
    // Ensure any NULL replacements are cleared or throw errors
    $reps['{smd_ebook_opf_file}'] = !isset($reps['{smd_ebook_opf_file}']) ? '' : $reps['{smd_ebook_opf_file}'];
    $reps['{smd_ebook_doctype}'] = !isset($reps['{smd_ebook_doctype}']) ? '' : $reps['{smd_ebook_doctype}'];
    $reps['{smd_ebook_namespace}'] = !isset($reps['{smd_ebook_namespace}']) ? '' : $reps['{smd_ebook_namespace}'];
    $reps['{smd_ebook_charset}'] = !isset($reps['{smd_ebook_charset}']) ? '' : $reps['{smd_ebook_charset}'];
    $reps['{smd_ebook_chaptitle}'] = !isset($reps['{smd_ebook_chaptitle}']) ? '' : $reps['{smd_ebook_chaptitle}'];
    $reps['{smd_ebook_creator}'] = !isset($reps['{smd_ebook_creator}']) ? '' : $reps['{smd_ebook_creator}'];
    $reps['{smd_ebook_md_creator}'] = !isset($reps['{smd_ebook_md_creator}']) ? '' : $reps['{smd_ebook_md_creator}'];
    $reps['{smd_ebook_md_description}'] = !isset($reps['{smd_ebook_md_description}']) ? '' : $reps['{smd_ebook_md_description}'];
    $reps['{smd_ebook_md_subject}'] = !isset($reps['{smd_ebook_md_subject}']) ? '' : $reps['{smd_ebook_md_subject}'];
    $reps['{smd_ebook_md_publisher}'] = !isset($reps['{smd_ebook_md_publisher}']) ? '' : $reps['{smd_ebook_md_publisher}'];
    $reps['{smd_ebook_md_srp}'] = !isset($reps['{smd_ebook_md_srp}']) ? '' : $reps['{smd_ebook_md_srp}'];
    if (!isset($reps['{smd_ebook_md_cover}'])) {
        $reps['{smd_ebook_md_cover}'] = '';
        $reps['{smd_ebook_manifest_cover}'] = '';
    }
    if (!isset($reps['{smd_ebook_manifest_authornote}'])) {
        $reps['{smd_ebook_manifest_authornote}'] = '';
        $reps['{smd_ebook_spine_authornote}'] = '';
    }
    // All the replacements are set up so prepare for book generation
    // First, create the TOC and write it to the filesystem
    if ($toc_cnt > 0) {
        $reps['{smd_ebook_spine_toc}'] = '<itemref idref="' . $toc_ref . '" />';
        if (!isset($guide_refs['toc'])) {
            $reps['{smd_ebook_manifest_toc}'] = '<item id="' . $toc_ref . '" media-type="application/xhtml+xml" href="' . $toc_file . '" />';
            $guide_refs['toc'] = '<reference type="toc" title="' . gTxt('smd_ebook_lbl_toc') . '" href="' . $toc_file . '" />';
            $landmarks['toc'] = href(gTxt('smd_ebook_lbl_toc'), $toc_file, ' epub:type="toc"');
            $html_toc = $textile->TextileThis(join(n, $toc));
            $final_toc = str_replace(array('{smd_ebook_toc_list}', '{smd_ebook_stylesheet}', '{smd_ebook_toc}'), array($html_toc, $sheet, gTxt('smd_ebook_lbl_toc')), $template['toc']);
            $fp = fopen($ebook_path . $toc_file, "wb");
            fwrite($fp, trim($final_toc));
            fclose($fp);
            $lfout[] = $toc_file;
        } else {
            $reps['{smd_ebook_manifest_toc}'] = '';
        }
    } else {
        $reps['{smd_ebook_manifest_toc}'] = '';
        $reps['{smd_ebook_spine_toc}'] = '';
    }
    // Add the ncx waypoints to the reps array and generate the .ncx file
    if ($ncx_cnt > 0) {
        $reps['{smd_ebook_ncx_doctype}'] = $is_mobi ? '<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN" "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd">' : '';
        $reps['{smd_ebook_ncx_map}'] = join(n, $ncx);
        $reps['{smd_ebook_manifest_ncx}'] = '<item id="ncx" media-type="application/x-dtbncx+xml" href="' . $ncx_file . '" />';
        //		$reps['{smd_ebook_spine_ncx}'] = '<itemref idref="ncx" />';
        $reps['{smd_ebook_spine_ncx_ref}'] = 'toc="ncx"';
        $ncx_file_content = trim(strtr($template['ncx'], $reps));
        $fp = fopen($ebook_path . $ncx_file, "wb");
        fwrite($fp, $ncx_file_content);
        fclose($fp);
        $lfout[] = $ncx_file;
    } else {
        $reps['{smd_ebook_manifest_ncx}'] = '';
        //		$reps['{smd_ebook_spine_ncx}'] = '';
        $reps['{smd_ebook_spine_ncx_ref}'] = '';
    }
    if ($is_epub) {
        // Create supplemental files for ePub format
        // First the mimetype
        $fp = fopen($ebook_path . $mimetype_file, "wb");
        fwrite($fp, 'application/epub+zip');
        fclose($fp);
        // Then the container
        $fp = fopen($ebook_path . $container_file, "wb");
        $from = array('{smd_ebook_opf_file}');
        $to = array($opf_file);
        fwrite($fp, str_replace($from, $to, $template['inf']));
        fclose($fp);
        // Then the landmarks
        $lmk_list = array();
        foreach ($landmarks as $type => $landmark) {
            $lmk_list[] = tag($landmark, 'li');
        }
        $fp = fopen($ebook_path . $lmk_file, "wb");
        $from = array('{smd_ebook_guide}', '{smd_ebook_encoding}', '{smd_ebook_lang}', '{smd_ebook_landmarks}');
        $to = array(gTxt('smd_ebook_guide'), $encoding, $lang, join(n . t, $lmk_list));
        fwrite($fp, str_replace($from, $to, $template['lmk']));
        fclose($fp);
        $article_refs[] = '<item id="landmarks" media-type="application/xhtml+xml" href="' . $lmk_file . '" />';
        $lfout[] = $lmk_file;
        // Then any stylesheets
        foreach ($sheetcontent as $sheet => $content) {
            $fp = fopen($ebook_path . $sheet . '.css', "wb");
            fwrite($fp, $content);
            fclose($fp);
        }
        // Transform .ncx to .end, if necessary, and generate manifest + spine entries.
        // END (Epub Navigation Document) supersedes the deprecated NCX in ePub3.
        if ($ncx_cnt > 0) {
            if (class_exists('XSLTProcessor')) {
                $xslt = new XSLTProcessor();
                $xslt->importStylesheet(new SimpleXMLElement($template['ncx2end']));
                $ebook_end = $xslt->transformToXml(new SimpleXMLElement($ncx_file_content));
            } else {
                $ebook_end = str_replace(array('{smd_ebook_toc_list}', '{smd_ebook_toc}'), array($html_toc, gTxt('smd_ebook_lbl_toc')), $template['end']);
            }
            $fp = fopen($ebook_path . $end_file, "wb");
            fwrite($fp, trim($ebook_end));
            fclose($fp);
            $lfout[] = $end_file;
        }
        $reps['{smd_ebook_md_x}'] = '';
        $reps['{smd_ebook_guide_cover}'] = '<reference type="cover" title="Cover" href="cover.html" />';
        $reps['{smd_ebook_spine_cover}'] = '<itemref idref="cover" linear="no" />';
        $reps['{smd_ebook_manifest_end}'] = '<item id="end" properties="nav" href="' . $end_file . '" media-type="application/xhtml+xml" />';
    } elseif ($is_mobi) {
        $reps['{smd_ebook_md_x}'] = str_replace(array('{smd_ebook_encoding}', '{smd_ebook_md_srp}'), array($encoding, $reps['{smd_ebook_md_srp}']), $template['xmd']);
        $reps['{smd_ebook_guide_cover}'] = '';
        $reps['{smd_ebook_spine_cover}'] = '';
        $reps['{smd_ebook_manifest_end}'] = '';
        $reps['{smd_ebook_landmark_nav}'] = '';
    }
    // Build the remaining manifest replacements and generate the OPF
    $reps['{smd_ebook_guide_extras}'] = $guide_refs ? join(n . t . t, $guide_refs) : '';
    $reps['{smd_ebook_manifest_items}'] = join(n . t . t, $article_refs);
    $reps['{smd_ebook_spine_items}'] = join(n, $article_spines);
    $opf_file_content = strtr($template['opf'], $reps);
    $fp = fopen($ebook_path . $opf_file, "wb");
    fwrite($fp, trim($opf_file_content));
    fclose($fp);
    $lfout[] = $opf_file;
    // Write the listfile, which contains a list of all the files used in this stage
    $fp = fopen($ebook_path . $listfile, "wb");
    fwrite($fp, join(n, $lfout));
    fclose($fp);
    // Hand off to Stage 2 to do the deed
    smd_ebook_generate($listfile, $opf_file, $bType, $ebook_folder);
}
Example #15
0
function zem_event_list($atts, $thing = NULL)
{
    global $zem_thiseventcal, $pretext;
    extract(lAtts(array('wraptag' => '', 'class' => __FUNCTION__, 'break' => '', 'breakclass' => '', 'form' => 'zem_event_display', 'sort' => safe_pfx('zem_event_date') . '.event_date asc, ' . safe_pfx('zem_event_date') . '.event_time asc', 'date_from' => gps('date_from') ? gps('date_from') : 'today', 'date_to' => gps('date_to') ? gps('date_to') : '', 'date' => gps('date'), 'label' => '', 'labeltag' => '', 'limit' => '', 'category' => gps('c') ? gps('c') : @$pretext['c'], 'section' => '', 'all_categories' => gps('all_categories'), 'location' => gps('location'), 'all_locations' => gps('all_locations'), 'debug' => 0), $atts));
    if ($thing === NULL) {
        $thing = fetch_form($form);
    }
    $where = safe_pfx('zem_event_calendar') . '.id=' . safe_pfx('zem_event_date') . '.event_id and ' . safe_pfx('zem_event_calendar') . '.article_id = ' . safe_pfx('textpattern') . '.ID and ' . safe_pfx('textpattern') . '.Status >= 4 and ' . safe_pfx('textpattern') . '.Posted <= now()';
    if ($date) {
        @(list($y, $m, $d) = explode('-', $date));
        if ($y and $m and $d) {
            $date_from = $date_to = "{$y}-{$m}-{$d}";
        } elseif ($y and $m) {
            $date_from = "{$y}-{$m}-01";
            $date_to = strftime('%Y-%m-%d', strtotime('-1 day', strtotime('+1 month', strtotime($date_from))));
        } elseif ($y) {
            $date_from = "{$y}-01-01";
            $date_to = "{$y}-12-31";
        } elseif ($t = zem_strtotime($date)) {
            $date_from = strftime('%Y-%m-%d', $t);
            $date_to = strftime('%Y-%m-%d', $t);
        }
    }
    $w = zem_event_timeq($date_from, $date_to);
    if ($w) {
        $where .= ' and ' . join(' and ', $w);
    }
    if ($section) {
        $sections = do_list($section);
        $where .= " and textpattern.Section IN (" . join(',', quote_list($sections)) . ")";
    }
    if ($location and !$all_locations) {
        // location could be an array if it came from gps()
        if (is_array($location)) {
            $locs = $location;
        } else {
            $locs = do_list($location);
        }
        $where .= " and location IN (" . join(',', quote_list($locs)) . ")";
    }
    if ($q = gps('q')) {
        $where .= " and (name rlike '" . doSlash($q) . "' or description rlike '" . doSlash($q) . "')";
    }
    if ($category and !$all_categories) {
        // category could be an array if it came from gps()
        if (is_array($category)) {
            $cats = $category;
        } else {
            $cats = do_list($category);
        }
        $cats_id = safe_column('id', 'txp_category', "type='event' and name IN (" . join(',', quote_list($cats)) . ")");
        if (!$cats_id) {
            $cats_id = array(0);
        }
        $where = safe_pfx('zem_event_calendar') . ".id=" . safe_pfx('zem_event_category') . ".k1 and " . safe_pfx('zem_event_category') . ".k2 IN (" . join(',', quote_list($cats_id)) . ") and " . $where;
        $grand_total = safe_count('zem_event_calendar,zem_event_date,textpattern,zem_event_category', $where . ' group by ' . safe_pfx('zem_event_calendar') . '.id order by ' . $sort, $debug);
        $lim = zem_event_paginate($limit, $grand_total);
        $rs = safe_rows_start(safe_pfx('zem_event_calendar') . '.*, ' . safe_pfx('zem_event_date') . '.*, ' . safe_pfx('textpattern') . '.*, unix_timestamp(Posted) as uPosted', 'zem_event_calendar,zem_event_date,textpattern,zem_event_category', $where . ' group by ' . safe_pfx('zem_event_calendar') . '.id order by ' . $sort . $lim, $debug);
    } else {
        $grand_total = safe_count('zem_event_calendar,zem_event_date,textpattern', $where . ' order by ' . $sort, $debug);
        $lim = zem_event_paginate($limit, $grand_total);
        $rs = safe_rows_start('*, unix_timestamp(Posted) as uPosted', 'zem_event_calendar,zem_event_date,textpattern', $where . ' order by ' . $sort . $lim, $debug);
    }
    $out = array();
    while ($row = nextRow($rs)) {
        article_push();
        $zem_thiseventcal = $row;
        populateArticleData($row);
        $out[] = parse($thing);
        $zem_thiseventcal = NULL;
        article_pop();
    }
    return doTag($label, $labeltag, $class) . doWrap($out, $wraptag, $break, $class, $breakclass);
}