From 12de05107e4c8b006bde6ee8916f34eb476d08da Mon Sep 17 00:00:00 2001 From: donncha Date: Fri, 13 Jun 2008 17:21:00 +0000 Subject: WP Merge with revision 8075 git-svn-id: http://svn.automattic.com/wordpress-mu/trunk@1328 7be80a69-a1ef-0310-a953-fb0f7c49ff36 --- wp-includes/Text/Diff.php | 413 +++++ wp-includes/Text/Diff/Engine/native.php | 437 +++++ wp-includes/Text/Diff/Engine/shell.php | 164 ++ wp-includes/Text/Diff/Engine/string.php | 234 +++ wp-includes/Text/Diff/Engine/xdiff.php | 63 + wp-includes/Text/Diff/Renderer.php | 237 +++ wp-includes/Text/Diff/Renderer/inline.php | 170 ++ wp-includes/author-template.php | 115 +- wp-includes/bookmark-template.php | 107 +- wp-includes/bookmark.php | 67 +- wp-includes/cache.php | 152 +- wp-includes/canonical.php | 38 +- wp-includes/capabilities.php | 4 +- wp-includes/category-template.php | 13 +- wp-includes/class.wp-dependencies.php | 193 +++ wp-includes/class.wp-scripts.php | 89 + wp-includes/class.wp-styles.php | 71 + wp-includes/classes.php | 12 +- wp-includes/comment-template.php | 4 +- wp-includes/comment.php | 92 +- wp-includes/default-filters.php | 2 + wp-includes/formatting.php | 7 + wp-includes/functions.php | 46 +- wp-includes/functions.wp-scripts.php | 77 + wp-includes/functions.wp-styles.php | 45 + wp-includes/general-template.php | 103 +- wp-includes/js/autosave.js | 15 +- wp-includes/js/jquery/jquery.form.js | 1744 ++++++++++---------- wp-includes/js/jquery/jquery.js | 8 +- wp-includes/js/jquery/suggest.js | 2 +- wp-includes/js/jquery/ui.core.js | 2 + wp-includes/js/jquery/ui.sortable.js | 2 + wp-includes/js/jquery/ui.tabs.js | 529 +----- wp-includes/js/prototype.js | 2 +- wp-includes/js/quicktags.js | 50 +- wp-includes/js/scriptaculous/MIT-LICENSE | 40 +- wp-includes/js/scriptaculous/prototype.js | 2 +- wp-includes/js/scriptaculous/scriptaculous.js | 2 +- wp-includes/js/scriptaculous/unittest.js | 2 +- wp-includes/js/thickbox/thickbox.css | 16 +- wp-includes/js/tinymce/langs/wp-langs.php | 2 +- .../js/tinymce/plugins/autosave/editor_plugin.js | 2 +- .../plugins/directionality/editor_plugin.js | 2 +- .../js/tinymce/plugins/fullscreen/editor_plugin.js | 2 +- .../js/tinymce/plugins/fullscreen/fullscreen.htm | 2 +- .../tinymce/plugins/inlinepopups/editor_plugin.js | 2 +- .../js/tinymce/plugins/inlinepopups/template.htm | 2 +- wp-includes/js/tinymce/plugins/media/css/media.css | 84 +- .../js/tinymce/plugins/media/editor_plugin.js | 2 +- wp-includes/js/tinymce/plugins/media/js/media.js | 21 +- wp-includes/js/tinymce/plugins/media/media.htm | 14 +- wp-includes/js/tinymce/plugins/paste/blank.htm | 44 +- wp-includes/js/tinymce/plugins/paste/css/blank.css | 28 +- .../js/tinymce/plugins/paste/css/pasteword.css | 6 +- .../js/tinymce/plugins/paste/editor_plugin.js | 2 +- wp-includes/js/tinymce/plugins/paste/pastetext.htm | 68 +- wp-includes/js/tinymce/plugins/paste/pasteword.htm | 58 +- .../js/tinymce/plugins/safari/editor_plugin.js | 2 +- .../js/tinymce/plugins/spellchecker/config.php | 42 +- .../tinymce/plugins/spellchecker/css/content.css | 2 +- .../tinymce/plugins/spellchecker/editor_plugin.js | 2 +- .../js/tinymce/plugins/wordpress/editor_plugin.js | 12 +- .../tinymce/plugins/wpeditimage/css/editimage.css | 167 ++ .../js/tinymce/plugins/wpeditimage/editimage.html | 262 +++ .../tinymce/plugins/wpeditimage/editor_plugin.js | 138 ++ .../js/tinymce/plugins/wpeditimage/img/delete.png | Bin 0 -> 1638 bytes .../js/tinymce/plugins/wpeditimage/img/image.png | Bin 0 -> 3701 bytes .../js/tinymce/plugins/wpeditimage/js/editimage.js | 471 ++++++ wp-includes/js/tinymce/themes/advanced/about.htm | 6 +- wp-includes/js/tinymce/themes/advanced/anchor.htm | 4 +- wp-includes/js/tinymce/themes/advanced/charmap.htm | 4 +- .../js/tinymce/themes/advanced/color_picker.htm | 6 +- .../js/tinymce/themes/advanced/editor_template.js | 2 +- wp-includes/js/tinymce/themes/advanced/image.htm | 8 +- .../js/tinymce/themes/advanced/img/icons.gif | Bin 11532 -> 11505 bytes .../js/tinymce/themes/advanced/js/color_picker.js | 12 +- wp-includes/js/tinymce/themes/advanced/js/image.js | 2 +- wp-includes/js/tinymce/themes/advanced/link.htm | 10 +- .../themes/advanced/skins/default/content.css | 5 + .../tinymce/themes/advanced/skins/o2k7/content.css | 5 + .../themes/advanced/skins/wp_theme/content.css | 2 +- .../themes/advanced/skins/wp_theme/dialog.css | 2 +- .../js/tinymce/themes/advanced/source_editor.htm | 4 +- wp-includes/js/tinymce/tiny_mce.js | 2 +- wp-includes/js/tinymce/tiny_mce_config.php | 18 +- wp-includes/js/tinymce/tiny_mce_ext.js | 3 +- wp-includes/js/tinymce/tiny_mce_popup.js | 4 +- wp-includes/js/tinymce/utils/editable_selects.js | 122 +- wp-includes/js/tinymce/utils/form_utils.js | 398 ++--- wp-includes/js/tinymce/utils/mclayer.js | 420 ++--- wp-includes/js/tinymce/utils/mctabs.js | 150 +- wp-includes/js/tinymce/utils/validate.js | 438 ++--- wp-includes/js/tinymce/wp-mce-help.php | 8 +- wp-includes/kses.php | 4 +- wp-includes/l10n.php | 32 +- wp-includes/link-template.php | 92 +- wp-includes/media.php | 9 +- wp-includes/pluggable.php | 274 ++- wp-includes/plugin.php | 7 +- wp-includes/post-template.php | 169 +- wp-includes/post.php | 505 ++++-- wp-includes/query.php | 86 +- wp-includes/rss.php | 19 +- wp-includes/script-loader.php | 688 +++----- wp-includes/shortcodes.php | 17 + wp-includes/taxonomy.php | 19 +- wp-includes/template-loader.php | 6 +- wp-includes/theme.php | 50 +- wp-includes/user.php | 31 +- wp-includes/version.php | 4 +- wp-includes/widgets.php | 51 +- wp-includes/wp-db.php | 17 +- wp-includes/wp-diff.php | 318 ++++ 113 files changed, 7341 insertions(+), 3502 deletions(-) create mode 100644 wp-includes/Text/Diff.php create mode 100644 wp-includes/Text/Diff/Engine/native.php create mode 100644 wp-includes/Text/Diff/Engine/shell.php create mode 100644 wp-includes/Text/Diff/Engine/string.php create mode 100644 wp-includes/Text/Diff/Engine/xdiff.php create mode 100644 wp-includes/Text/Diff/Renderer.php create mode 100644 wp-includes/Text/Diff/Renderer/inline.php create mode 100644 wp-includes/class.wp-dependencies.php create mode 100644 wp-includes/class.wp-scripts.php create mode 100644 wp-includes/class.wp-styles.php create mode 100644 wp-includes/functions.wp-scripts.php create mode 100644 wp-includes/functions.wp-styles.php create mode 100644 wp-includes/js/jquery/ui.core.js create mode 100644 wp-includes/js/jquery/ui.sortable.js create mode 100644 wp-includes/js/tinymce/plugins/wpeditimage/css/editimage.css create mode 100644 wp-includes/js/tinymce/plugins/wpeditimage/editimage.html create mode 100644 wp-includes/js/tinymce/plugins/wpeditimage/editor_plugin.js create mode 100644 wp-includes/js/tinymce/plugins/wpeditimage/img/delete.png create mode 100644 wp-includes/js/tinymce/plugins/wpeditimage/img/image.png create mode 100644 wp-includes/js/tinymce/plugins/wpeditimage/js/editimage.js create mode 100644 wp-includes/wp-diff.php (limited to 'wp-includes') diff --git a/wp-includes/Text/Diff.php b/wp-includes/Text/Diff.php new file mode 100644 index 0000000..f8a974c --- /dev/null +++ b/wp-includes/Text/Diff.php @@ -0,0 +1,413 @@ +, and is used/adapted with his permission. + * + * $Horde: framework/Text_Diff/Diff.php,v 1.26 2008/01/04 10:07:49 jan Exp $ + * + * Copyright 2004 Geoffrey T. Dairiki + * Copyright 2004-2008 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @package Text_Diff + * @author Geoffrey T. Dairiki + */ +class Text_Diff { + + /** + * Array of changes. + * + * @var array + */ + var $_edits; + + /** + * Computes diffs between sequences of strings. + * + * @param string $engine Name of the diffing engine to use. 'auto' + * will automatically select the best. + * @param array $params Parameters to pass to the diffing engine. + * Normally an array of two arrays, each + * containing the lines from a file. + */ + function Text_Diff($engine, $params) + { + // Backward compatibility workaround. + if (!is_string($engine)) { + $params = array($engine, $params); + $engine = 'auto'; + } + + if ($engine == 'auto') { + $engine = extension_loaded('xdiff') ? 'xdiff' : 'native'; + } else { + $engine = basename($engine); + } + + require_once 'Text/Diff/Engine/' . $engine . '.php'; + $class = 'Text_Diff_Engine_' . $engine; + $diff_engine = new $class(); + + $this->_edits = call_user_func_array(array($diff_engine, 'diff'), $params); + } + + /** + * Returns the array of differences. + */ + function getDiff() + { + return $this->_edits; + } + + /** + * Computes a reversed diff. + * + * Example: + * + * $diff = new Text_Diff($lines1, $lines2); + * $rev = $diff->reverse(); + * + * + * @return Text_Diff A Diff object representing the inverse of the + * original diff. Note that we purposely don't return a + * reference here, since this essentially is a clone() + * method. + */ + function reverse() + { + if (version_compare(zend_version(), '2', '>')) { + $rev = clone($this); + } else { + $rev = $this; + } + $rev->_edits = array(); + foreach ($this->_edits as $edit) { + $rev->_edits[] = $edit->reverse(); + } + return $rev; + } + + /** + * Checks for an empty diff. + * + * @return boolean True if two sequences were identical. + */ + function isEmpty() + { + foreach ($this->_edits as $edit) { + if (!is_a($edit, 'Text_Diff_Op_copy')) { + return false; + } + } + return true; + } + + /** + * Computes the length of the Longest Common Subsequence (LCS). + * + * This is mostly for diagnostic purposes. + * + * @return integer The length of the LCS. + */ + function lcs() + { + $lcs = 0; + foreach ($this->_edits as $edit) { + if (is_a($edit, 'Text_Diff_Op_copy')) { + $lcs += count($edit->orig); + } + } + return $lcs; + } + + /** + * Gets the original set of lines. + * + * This reconstructs the $from_lines parameter passed to the constructor. + * + * @return array The original sequence of strings. + */ + function getOriginal() + { + $lines = array(); + foreach ($this->_edits as $edit) { + if ($edit->orig) { + array_splice($lines, count($lines), 0, $edit->orig); + } + } + return $lines; + } + + /** + * Gets the final set of lines. + * + * This reconstructs the $to_lines parameter passed to the constructor. + * + * @return array The sequence of strings. + */ + function getFinal() + { + $lines = array(); + foreach ($this->_edits as $edit) { + if ($edit->final) { + array_splice($lines, count($lines), 0, $edit->final); + } + } + return $lines; + } + + /** + * Removes trailing newlines from a line of text. This is meant to be used + * with array_walk(). + * + * @param string $line The line to trim. + * @param integer $key The index of the line in the array. Not used. + */ + function trimNewlines(&$line, $key) + { + $line = str_replace(array("\n", "\r"), '', $line); + } + + /** + * Determines the location of the system temporary directory. + * + * @static + * + * @access protected + * + * @return string A directory name which can be used for temp files. + * Returns false if one could not be found. + */ + function _getTempDir() + { + $tmp_locations = array('/tmp', '/var/tmp', 'c:\WUTemp', 'c:\temp', + 'c:\windows\temp', 'c:\winnt\temp'); + + /* Try PHP's upload_tmp_dir directive. */ + $tmp = ini_get('upload_tmp_dir'); + + /* Otherwise, try to determine the TMPDIR environment variable. */ + if (!strlen($tmp)) { + $tmp = getenv('TMPDIR'); + } + + /* If we still cannot determine a value, then cycle through a list of + * preset possibilities. */ + while (!strlen($tmp) && count($tmp_locations)) { + $tmp_check = array_shift($tmp_locations); + if (@is_dir($tmp_check)) { + $tmp = $tmp_check; + } + } + + /* If it is still empty, we have failed, so return false; otherwise + * return the directory determined. */ + return strlen($tmp) ? $tmp : false; + } + + /** + * Checks a diff for validity. + * + * This is here only for debugging purposes. + */ + function _check($from_lines, $to_lines) + { + if (serialize($from_lines) != serialize($this->getOriginal())) { + trigger_error("Reconstructed original doesn't match", E_USER_ERROR); + } + if (serialize($to_lines) != serialize($this->getFinal())) { + trigger_error("Reconstructed final doesn't match", E_USER_ERROR); + } + + $rev = $this->reverse(); + if (serialize($to_lines) != serialize($rev->getOriginal())) { + trigger_error("Reversed original doesn't match", E_USER_ERROR); + } + if (serialize($from_lines) != serialize($rev->getFinal())) { + trigger_error("Reversed final doesn't match", E_USER_ERROR); + } + + $prevtype = null; + foreach ($this->_edits as $edit) { + if ($prevtype == get_class($edit)) { + trigger_error("Edit sequence is non-optimal", E_USER_ERROR); + } + $prevtype = get_class($edit); + } + + return true; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + */ +class Text_MappedDiff extends Text_Diff { + + /** + * Computes a diff between sequences of strings. + * + * This can be used to compute things like case-insensitve diffs, or diffs + * which ignore changes in white-space. + * + * @param array $from_lines An array of strings. + * @param array $to_lines An array of strings. + * @param array $mapped_from_lines This array should have the same size + * number of elements as $from_lines. The + * elements in $mapped_from_lines and + * $mapped_to_lines are what is actually + * compared when computing the diff. + * @param array $mapped_to_lines This array should have the same number + * of elements as $to_lines. + */ + function Text_MappedDiff($from_lines, $to_lines, + $mapped_from_lines, $mapped_to_lines) + { + assert(count($from_lines) == count($mapped_from_lines)); + assert(count($to_lines) == count($mapped_to_lines)); + + parent::Text_Diff($mapped_from_lines, $mapped_to_lines); + + $xi = $yi = 0; + for ($i = 0; $i < count($this->_edits); $i++) { + $orig = &$this->_edits[$i]->orig; + if (is_array($orig)) { + $orig = array_slice($from_lines, $xi, count($orig)); + $xi += count($orig); + } + + $final = &$this->_edits[$i]->final; + if (is_array($final)) { + $final = array_slice($to_lines, $yi, count($final)); + $yi += count($final); + } + } + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff_Op { + + var $orig; + var $final; + + function &reverse() + { + trigger_error('Abstract method', E_USER_ERROR); + } + + function norig() + { + return $this->orig ? count($this->orig) : 0; + } + + function nfinal() + { + return $this->final ? count($this->final) : 0; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff_Op_copy extends Text_Diff_Op { + + function Text_Diff_Op_copy($orig, $final = false) + { + if (!is_array($final)) { + $final = $orig; + } + $this->orig = $orig; + $this->final = $final; + } + + function &reverse() + { + $reverse = &new Text_Diff_Op_copy($this->final, $this->orig); + return $reverse; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff_Op_delete extends Text_Diff_Op { + + function Text_Diff_Op_delete($lines) + { + $this->orig = $lines; + $this->final = false; + } + + function &reverse() + { + $reverse = &new Text_Diff_Op_add($this->orig); + return $reverse; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff_Op_add extends Text_Diff_Op { + + function Text_Diff_Op_add($lines) + { + $this->final = $lines; + $this->orig = false; + } + + function &reverse() + { + $reverse = &new Text_Diff_Op_delete($this->final); + return $reverse; + } + +} + +/** + * @package Text_Diff + * @author Geoffrey T. Dairiki + * + * @access private + */ +class Text_Diff_Op_change extends Text_Diff_Op { + + function Text_Diff_Op_change($orig, $final) + { + $this->orig = $orig; + $this->final = $final; + } + + function &reverse() + { + $reverse = &new Text_Diff_Op_change($this->final, $this->orig); + return $reverse; + } + +} diff --git a/wp-includes/Text/Diff/Engine/native.php b/wp-includes/Text/Diff/Engine/native.php new file mode 100644 index 0000000..aa5bca5 --- /dev/null +++ b/wp-includes/Text/Diff/Engine/native.php @@ -0,0 +1,437 @@ + 2, and some optimizations) are from + * Geoffrey T. Dairiki . The original PHP version of this + * code was written by him, and is used/adapted with his permission. + * + * Copyright 2004-2008 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @author Geoffrey T. Dairiki + * @package Text_Diff + */ +class Text_Diff_Engine_native { + + function diff($from_lines, $to_lines) + { + array_walk($from_lines, array('Text_Diff', 'trimNewlines')); + array_walk($to_lines, array('Text_Diff', 'trimNewlines')); + + $n_from = count($from_lines); + $n_to = count($to_lines); + + $this->xchanged = $this->ychanged = array(); + $this->xv = $this->yv = array(); + $this->xind = $this->yind = array(); + unset($this->seq); + unset($this->in_seq); + unset($this->lcs); + + // Skip leading common lines. + for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) { + if ($from_lines[$skip] !== $to_lines[$skip]) { + break; + } + $this->xchanged[$skip] = $this->ychanged[$skip] = false; + } + + // Skip trailing common lines. + $xi = $n_from; $yi = $n_to; + for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++) { + if ($from_lines[$xi] !== $to_lines[$yi]) { + break; + } + $this->xchanged[$xi] = $this->ychanged[$yi] = false; + } + + // Ignore lines which do not exist in both files. + for ($xi = $skip; $xi < $n_from - $endskip; $xi++) { + $xhash[$from_lines[$xi]] = 1; + } + for ($yi = $skip; $yi < $n_to - $endskip; $yi++) { + $line = $to_lines[$yi]; + if (($this->ychanged[$yi] = empty($xhash[$line]))) { + continue; + } + $yhash[$line] = 1; + $this->yv[] = $line; + $this->yind[] = $yi; + } + for ($xi = $skip; $xi < $n_from - $endskip; $xi++) { + $line = $from_lines[$xi]; + if (($this->xchanged[$xi] = empty($yhash[$line]))) { + continue; + } + $this->xv[] = $line; + $this->xind[] = $xi; + } + + // Find the LCS. + $this->_compareseq(0, count($this->xv), 0, count($this->yv)); + + // Merge edits when possible. + $this->_shiftBoundaries($from_lines, $this->xchanged, $this->ychanged); + $this->_shiftBoundaries($to_lines, $this->ychanged, $this->xchanged); + + // Compute the edit operations. + $edits = array(); + $xi = $yi = 0; + while ($xi < $n_from || $yi < $n_to) { + assert($yi < $n_to || $this->xchanged[$xi]); + assert($xi < $n_from || $this->ychanged[$yi]); + + // Skip matching "snake". + $copy = array(); + while ($xi < $n_from && $yi < $n_to + && !$this->xchanged[$xi] && !$this->ychanged[$yi]) { + $copy[] = $from_lines[$xi++]; + ++$yi; + } + if ($copy) { + $edits[] = &new Text_Diff_Op_copy($copy); + } + + // Find deletes & adds. + $delete = array(); + while ($xi < $n_from && $this->xchanged[$xi]) { + $delete[] = $from_lines[$xi++]; + } + + $add = array(); + while ($yi < $n_to && $this->ychanged[$yi]) { + $add[] = $to_lines[$yi++]; + } + + if ($delete && $add) { + $edits[] = &new Text_Diff_Op_change($delete, $add); + } elseif ($delete) { + $edits[] = &new Text_Diff_Op_delete($delete); + } elseif ($add) { + $edits[] = &new Text_Diff_Op_add($add); + } + } + + return $edits; + } + + /** + * Divides the Largest Common Subsequence (LCS) of the sequences (XOFF, + * XLIM) and (YOFF, YLIM) into NCHUNKS approximately equally sized + * segments. + * + * Returns (LCS, PTS). LCS is the length of the LCS. PTS is an array of + * NCHUNKS+1 (X, Y) indexes giving the diving points between sub + * sequences. The first sub-sequence is contained in (X0, X1), (Y0, Y1), + * the second in (X1, X2), (Y1, Y2) and so on. Note that (X0, Y0) == + * (XOFF, YOFF) and (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM). + * + * This function assumes that the first lines of the specified portions of + * the two files do not match, and likewise that the last lines do not + * match. The caller must trim matching lines from the beginning and end + * of the portions it is going to specify. + */ + function _diag ($xoff, $xlim, $yoff, $ylim, $nchunks) + { + $flip = false; + + if ($xlim - $xoff > $ylim - $yoff) { + /* Things seems faster (I'm not sure I understand why) when the + * shortest sequence is in X. */ + $flip = true; + list ($xoff, $xlim, $yoff, $ylim) + = array($yoff, $ylim, $xoff, $xlim); + } + + if ($flip) { + for ($i = $ylim - 1; $i >= $yoff; $i--) { + $ymatches[$this->xv[$i]][] = $i; + } + } else { + for ($i = $ylim - 1; $i >= $yoff; $i--) { + $ymatches[$this->yv[$i]][] = $i; + } + } + + $this->lcs = 0; + $this->seq[0]= $yoff - 1; + $this->in_seq = array(); + $ymids[0] = array(); + + $numer = $xlim - $xoff + $nchunks - 1; + $x = $xoff; + for ($chunk = 0; $chunk < $nchunks; $chunk++) { + if ($chunk > 0) { + for ($i = 0; $i <= $this->lcs; $i++) { + $ymids[$i][$chunk - 1] = $this->seq[$i]; + } + } + + $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $chunk) / $nchunks); + for (; $x < $x1; $x++) { + $line = $flip ? $this->yv[$x] : $this->xv[$x]; + if (empty($ymatches[$line])) { + continue; + } + $matches = $ymatches[$line]; + reset($matches); + while (list(, $y) = each($matches)) { + if (empty($this->in_seq[$y])) { + $k = $this->_lcsPos($y); + assert($k > 0); + $ymids[$k] = $ymids[$k - 1]; + break; + } + } + while (list(, $y) = each($matches)) { + if ($y > $this->seq[$k - 1]) { + assert($y <= $this->seq[$k]); + /* Optimization: this is a common case: next match is + * just replacing previous match. */ + $this->in_seq[$this->seq[$k]] = false; + $this->seq[$k] = $y; + $this->in_seq[$y] = 1; + } elseif (empty($this->in_seq[$y])) { + $k = $this->_lcsPos($y); + assert($k > 0); + $ymids[$k] = $ymids[$k - 1]; + } + } + } + } + + $seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff); + $ymid = $ymids[$this->lcs]; + for ($n = 0; $n < $nchunks - 1; $n++) { + $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks); + $y1 = $ymid[$n] + 1; + $seps[] = $flip ? array($y1, $x1) : array($x1, $y1); + } + $seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim); + + return array($this->lcs, $seps); + } + + function _lcsPos($ypos) + { + $end = $this->lcs; + if ($end == 0 || $ypos > $this->seq[$end]) { + $this->seq[++$this->lcs] = $ypos; + $this->in_seq[$ypos] = 1; + return $this->lcs; + } + + $beg = 1; + while ($beg < $end) { + $mid = (int)(($beg + $end) / 2); + if ($ypos > $this->seq[$mid]) { + $beg = $mid + 1; + } else { + $end = $mid; + } + } + + assert($ypos != $this->seq[$end]); + + $this->in_seq[$this->seq[$end]] = false; + $this->seq[$end] = $ypos; + $this->in_seq[$ypos] = 1; + return $end; + } + + /** + * Finds LCS of two sequences. + * + * The results are recorded in the vectors $this->{x,y}changed[], by + * storing a 1 in the element for each line that is an insertion or + * deletion (ie. is not in the LCS). + * + * The subsequence of file 0 is (XOFF, XLIM) and likewise for file 1. + * + * Note that XLIM, YLIM are exclusive bounds. All line numbers are + * origin-0 and discarded lines are not counted. + */ + function _compareseq ($xoff, $xlim, $yoff, $ylim) + { + /* Slide down the bottom initial diagonal. */ + while ($xoff < $xlim && $yoff < $ylim + && $this->xv[$xoff] == $this->yv[$yoff]) { + ++$xoff; + ++$yoff; + } + + /* Slide up the top initial diagonal. */ + while ($xlim > $xoff && $ylim > $yoff + && $this->xv[$xlim - 1] == $this->yv[$ylim - 1]) { + --$xlim; + --$ylim; + } + + if ($xoff == $xlim || $yoff == $ylim) { + $lcs = 0; + } else { + /* This is ad hoc but seems to work well. $nchunks = + * sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5); $nchunks = + * max(2,min(8,(int)$nchunks)); */ + $nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1; + list($lcs, $seps) + = $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks); + } + + if ($lcs == 0) { + /* X and Y sequences have no common subsequence: mark all + * changed. */ + while ($yoff < $ylim) { + $this->ychanged[$this->yind[$yoff++]] = 1; + } + while ($xoff < $xlim) { + $this->xchanged[$this->xind[$xoff++]] = 1; + } + } else { + /* Use the partitions to split this problem into subproblems. */ + reset($seps); + $pt1 = $seps[0]; + while ($pt2 = next($seps)) { + $this->_compareseq ($pt1[0], $pt2[0], $pt1[1], $pt2[1]); + $pt1 = $pt2; + } + } + } + + /** + * Adjusts inserts/deletes of identical lines to join changes as much as + * possible. + * + * We do something when a run of changed lines include a line at one end + * and has an excluded, identical line at the other. We are free to + * choose which identical line is included. `compareseq' usually chooses + * the one at the beginning, but usually it is cleaner to consider the + * following identical line to be the "change". + * + * This is extracted verbatim from analyze.c (GNU diffutils-2.7). + */ + function _shiftBoundaries($lines, &$changed, $other_changed) + { + $i = 0; + $j = 0; + + assert('count($lines) == count($changed)'); + $len = count($lines); + $other_len = count($other_changed); + + while (1) { + /* Scan forward to find the beginning of another run of + * changes. Also keep track of the corresponding point in the + * other file. + * + * Throughout this code, $i and $j are adjusted together so that + * the first $i elements of $changed and the first $j elements of + * $other_changed both contain the same number of zeros (unchanged + * lines). + * + * Furthermore, $j is always kept so that $j == $other_len or + * $other_changed[$j] == false. */ + while ($j < $other_len && $other_changed[$j]) { + $j++; + } + + while ($i < $len && ! $changed[$i]) { + assert('$j < $other_len && ! $other_changed[$j]'); + $i++; $j++; + while ($j < $other_len && $other_changed[$j]) { + $j++; + } + } + + if ($i == $len) { + break; + } + + $start = $i; + + /* Find the end of this run of changes. */ + while (++$i < $len && $changed[$i]) { + continue; + } + + do { + /* Record the length of this run of changes, so that we can + * later determine whether the run has grown. */ + $runlength = $i - $start; + + /* Move the changed region back, so long as the previous + * unchanged line matches the last changed one. This merges + * with previous changed regions. */ + while ($start > 0 && $lines[$start - 1] == $lines[$i - 1]) { + $changed[--$start] = 1; + $changed[--$i] = false; + while ($start > 0 && $changed[$start - 1]) { + $start--; + } + assert('$j > 0'); + while ($other_changed[--$j]) { + continue; + } + assert('$j >= 0 && !$other_changed[$j]'); + } + + /* Set CORRESPONDING to the end of the changed run, at the + * last point where it corresponds to a changed run in the + * other file. CORRESPONDING == LEN means no such point has + * been found. */ + $corresponding = $j < $other_len ? $i : $len; + + /* Move the changed region forward, so long as the first + * changed line matches the following unchanged one. This + * merges with following changed regions. Do this second, so + * that if there are no merges, the changed region is moved + * forward as far as possible. */ + while ($i < $len && $lines[$start] == $lines[$i]) { + $changed[$start++] = false; + $changed[$i++] = 1; + while ($i < $len && $changed[$i]) { + $i++; + } + + assert('$j < $other_len && ! $other_changed[$j]'); + $j++; + if ($j < $other_len && $other_changed[$j]) { + $corresponding = $i; + while ($j < $other_len && $other_changed[$j]) { + $j++; + } + } + } + } while ($runlength != $i - $start); + + /* If possible, move the fully-merged run of changes back to a + * corresponding run in the other file. */ + while ($corresponding < $i) { + $changed[--$start] = 1; + $changed[--$i] = 0; + assert('$j > 0'); + while ($other_changed[--$j]) { + continue; + } + assert('$j >= 0 && !$other_changed[$j]'); + } + } + } + +} diff --git a/wp-includes/Text/Diff/Engine/shell.php b/wp-includes/Text/Diff/Engine/shell.php new file mode 100644 index 0000000..7e9629f --- /dev/null +++ b/wp-includes/Text/Diff/Engine/shell.php @@ -0,0 +1,164 @@ + + * @package Text_Diff + * @since 0.3.0 + */ +class Text_Diff_Engine_shell { + + /** + * Path to the diff executable + * + * @var string + */ + var $_diffCommand = 'diff'; + + /** + * Returns the array of differences. + * + * @param array $from_lines lines of text from old file + * @param array $to_lines lines of text from new file + * + * @return array all changes made (array with Text_Diff_Op_* objects) + */ + function diff($from_lines, $to_lines) + { + array_walk($from_lines, array('Text_Diff', 'trimNewlines')); + array_walk($to_lines, array('Text_Diff', 'trimNewlines')); + + $temp_dir = Text_Diff::_getTempDir(); + + // Execute gnu diff or similar to get a standard diff file. + $from_file = tempnam($temp_dir, 'Text_Diff'); + $to_file = tempnam($temp_dir, 'Text_Diff'); + $fp = fopen($from_file, 'w'); + fwrite($fp, implode("\n", $from_lines)); + fclose($fp); + $fp = fopen($to_file, 'w'); + fwrite($fp, implode("\n", $to_lines)); + fclose($fp); + $diff = shell_exec($this->_diffCommand . ' ' . $from_file . ' ' . $to_file); + unlink($from_file); + unlink($to_file); + + if (is_null($diff)) { + // No changes were made + return array(new Text_Diff_Op_copy($from_lines)); + } + + $from_line_no = 1; + $to_line_no = 1; + $edits = array(); + + // Get changed lines by parsing something like: + // 0a1,2 + // 1,2c4,6 + // 1,5d6 + preg_match_all('#^(\d+)(?:,(\d+))?([adc])(\d+)(?:,(\d+))?$#m', $diff, + $matches, PREG_SET_ORDER); + + foreach ($matches as $match) { + if (!isset($match[5])) { + // This paren is not set every time (see regex). + $match[5] = false; + } + + if ($match[3] == 'a') { + $from_line_no--; + } + + if ($match[3] == 'd') { + $to_line_no--; + } + + if ($from_line_no < $match[1] || $to_line_no < $match[4]) { + // copied lines + assert('$match[1] - $from_line_no == $match[4] - $to_line_no'); + array_push($edits, + new Text_Diff_Op_copy( + $this->_getLines($from_lines, $from_line_no, $match[1] - 1), + $this->_getLines($to_lines, $to_line_no, $match[4] - 1))); + } + + switch ($match[3]) { + case 'd': + // deleted lines + array_push($edits, + new Text_Diff_Op_delete( + $this->_getLines($from_lines, $from_line_no, $match[2]))); + $to_line_no++; + break; + + case 'c': + // changed lines + array_push($edits, + new Text_Diff_Op_change( + $this->_getLines($from_lines, $from_line_no, $match[2]), + $this->_getLines($to_lines, $to_line_no, $match[5]))); + break; + + case 'a': + // added lines + array_push($edits, + new Text_Diff_Op_add( + $this->_getLines($to_lines, $to_line_no, $match[5]))); + $from_line_no++; + break; + } + } + + if (!empty($from_lines)) { + // Some lines might still be pending. Add them as copied + array_push($edits, + new Text_Diff_Op_copy( + $this->_getLines($from_lines, $from_line_no, + $from_line_no + count($from_lines) - 1), + $this->_getLines($to_lines, $to_line_no, + $to_line_no + count($to_lines) - 1))); + } + + return $edits; + } + + /** + * Get lines from either the old or new text + * + * @access private + * + * @param array &$text_lines Either $from_lines or $to_lines + * @param int &$line_no Current line number + * @param int $end Optional end line, when we want to chop more + * than one line. + * + * @return array The chopped lines + */ + function _getLines(&$text_lines, &$line_no, $end = false) + { + if (!empty($end)) { + $lines = array(); + // We can shift even more + while ($line_no <= $end) { + array_push($lines, array_shift($text_lines)); + $line_no++; + } + } else { + $lines = array(array_shift($text_lines)); + $line_no++; + } + + return $lines; + } + +} diff --git a/wp-includes/Text/Diff/Engine/string.php b/wp-includes/Text/Diff/Engine/string.php new file mode 100644 index 0000000..1a0bd3f --- /dev/null +++ b/wp-includes/Text/Diff/Engine/string.php @@ -0,0 +1,234 @@ + + * $patch = file_get_contents('example.patch'); + * $diff = new Text_Diff('string', array($patch)); + * $renderer = new Text_Diff_Renderer_inline(); + * echo $renderer->render($diff); + * + * + * $Horde: framework/Text_Diff/Diff/Engine/string.php,v 1.7 2008/01/04 10:07:50 jan Exp $ + * + * Copyright 2005 Örjan Persson + * Copyright 2005-2008 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you did + * not receive this file, see http://opensource.org/licenses/lgpl-license.php. + * + * @author Örjan Persson + * @package Text_Diff + * @since 0.2.0 + */ +class Text_Diff_Engine_string { + + /** + * Parses a unified or context diff. + * + * First param contains the whole diff and the second can be used to force + * a specific diff type. If the second parameter is 'autodetect', the + * diff will be examined to find out which type of diff this is. + * + * @param string $diff The diff content. + * @param string $mode The diff mode of the content in $diff. One of + * 'context', 'unified', or 'autodetect'. + * + * @return array List of all diff operations. + */ + function diff($diff, $mode = 'autodetect') + { + if ($mode != 'autodetect' && $mode != 'context' && $mode != 'unified') { + return PEAR::raiseError('Type of diff is unsupported'); + } + + if ($mode == 'autodetect') { + $context = strpos($diff, '***'); + $unified = strpos($diff, '---'); + if ($context === $unified) { + return PEAR::raiseError('Type of diff could not be detected'); + } elseif ($context === false || $context === false) { + $mode = $context !== false ? 'context' : 'unified'; + } else { + $mode = $context < $unified ? 'context' : 'unified'; + } + } + + // split by new line and remove the diff header + $diff = explode("\n", $diff); + array_shift($diff); + array_shift($diff); + + if ($mode == 'context') { + return $this->parseContextDiff($diff); + } else { + return $this->parseUnifiedDiff($diff); + } + } + + /** + * Parses an array containing the unified diff. + * + * @param array $diff Array of lines. + * + * @return array List of all diff operations. + */ + function parseUnifiedDiff($diff) + { + $edits = array(); + $end = count($diff) - 1; + for ($i = 0; $i < $end;) { + $diff1 = array(); + switch (substr($diff[$i], 0, 1)) { + case ' ': + do { + $diff1[] = substr($diff[$i], 1); + } while (++$i < $end && substr($diff[$i], 0, 1) == ' '); + $edits[] = &new Text_Diff_Op_copy($diff1); + break; + + case '+': + // get all new lines + do { + $diff1[] = substr($diff[$i], 1); + } while (++$i < $end && substr($diff[$i], 0, 1) == '+'); + $edits[] = &new Text_Diff_Op_add($diff1); + break; + + case '-': + // get changed or removed lines + $diff2 = array(); + do { + $diff1[] = substr($diff[$i], 1); + } while (++$i < $end && substr($diff[$i], 0, 1) == '-'); + + while ($i < $end && substr($diff[$i], 0, 1) == '+') { + $diff2[] = substr($diff[$i++], 1); + } + if (count($diff2) == 0) { + $edits[] = &new Text_Diff_Op_delete($diff1); + } else { + $edits[] = &new Text_Diff_Op_change($diff1, $diff2); + } + break; + + default: + $i++; + break; + } + } + + return $edits; + } + + /** + * Parses an array containing the context diff. + * + * @param array $diff Array of lines. + * + * @return array List of all diff operations. + */ + function parseContextDiff(&$diff) + { + $edits = array(); + $i = $max_i = $j = $max_j = 0; + $end = count($diff) - 1; + while ($i < $end && $j < $end) { + while ($i >= $max_i && $j >= $max_j) { + // Find the boundaries of the diff output of the two files + for ($i = $j; + $i < $end && substr($diff[$i], 0, 3) == '***'; + $i++); + for ($max_i = $i; + $max_i < $end && substr($diff[$max_i], 0, 3) != '---'; + $max_i++); + for ($j = $max_i; + $j < $end && substr($diff[$j], 0, 3) == '---'; + $j++); + for ($max_j = $j; + $max_j < $end && substr($diff[$max_j], 0, 3) != '***'; + $max_j++); + } + + // find what hasn't been changed + $array = array(); + while ($i < $max_i && + $j < $max_j && + strcmp($diff[$i], $diff[$j]) == 0) { + $array[] = substr($diff[$i], 2); + $i++; + $j++; + } + + while ($i < $max_i && ($max_j-$j) <= 1) { + if ($diff[$i] != '' && substr($diff[$i], 0, 1) != ' ') { + break; + } + $array[] = substr($diff[$i++], 2); + } + + while ($j < $max_j && ($max_i-$i) <= 1) { + if ($diff[$j] != '' && substr($diff[$j], 0, 1) != ' ') { + break; + } + $array[] = substr($diff[$j++], 2); + } + if (count($array) > 0) { + $edits[] = &new Text_Diff_Op_copy($array); + } + + if ($i < $max_i) { + $diff1 = array(); + switch (substr($diff[$i], 0, 1)) { + case '!': + $diff2 = array(); + do { + $diff1[] = substr($diff[$i], 2); + if ($j < $max_j && substr($diff[$j], 0, 1) == '!') { + $diff2[] = substr($diff[$j++], 2); + } + } while (++$i < $max_i && substr($diff[$i], 0, 1) == '!'); + $edits[] = &new Text_Diff_Op_change($diff1, $diff2); + break; + + case '+': + do { + $diff1[] = substr($diff[$i], 2); + } while (++$i < $max_i && substr($diff[$i], 0, 1) == '+'); + $edits[] = &new Text_Diff_Op_add($diff1); + break; + + case '-': + do { + $diff1[] = substr($diff[$i], 2); + } while (++$i < $max_i && substr($diff[$i], 0, 1) == '-'); + $edits[] = &new Text_Diff_Op_delete($diff1); + break; + } + } + + if ($j < $max_j) { + $diff2 = array(); + switch (substr($diff[$j], 0, 1)) { + case '+': + do { + $diff2[] = substr($diff[$j++], 2); + } while ($j < $max_j && substr($diff[$j], 0, 1) == '+'); + $edits[] = &new Text_Diff_Op_add($diff2); + break; + + case '-': + do { + $diff2[] = substr($diff[$j++], 2); + } while ($j < $max_j && substr($diff[$j], 0, 1) == '-'); + $edits[] = &new Text_Diff_Op_delete($diff2); + break; + } + } + } + + return $edits; + } + +} diff --git a/wp-includes/Text/Diff/Engine/xdiff.php b/wp-includes/Text/Diff/Engine/xdiff.php new file mode 100644 index 0000000..a39a4be --- /dev/null +++ b/wp-includes/Text/Diff/Engine/xdiff.php @@ -0,0 +1,63 @@ + + * @package Text_Diff + */ +class Text_Diff_Engine_xdiff { + + /** + */ + function diff($from_lines, $to_lines) + { + array_walk($from_lines, array('Text_Diff', 'trimNewlines')); + array_walk($to_lines, array('Text_Diff', 'trimNewlines')); + + /* Convert the two input arrays into strings for xdiff processing. */ + $from_string = implode("\n", $from_lines); + $to_string = implode("\n", $to_lines); + + /* Diff the two strings and convert the result to an array. */ + $diff = xdiff_string_diff($from_string, $to_string, count($to_lines)); + $diff = explode("\n", $diff); + + /* Walk through the diff one line at a time. We build the $edits + * array of diff operations by reading the first character of the + * xdiff output (which is in the "unified diff" format). + * + * Note that we don't have enough information to detect "changed" + * lines using this approach, so we can't add Text_Diff_Op_changed + * instances to the $edits array. The result is still perfectly + * valid, albeit a little less descriptive and efficient. */ + $edits = array(); + foreach ($diff as $line) { + switch ($line[0]) { + case ' ': + $edits[] = &new Text_Diff_Op_copy(array(substr($line, 1))); + break; + + case '+': + $edits[] = &new Text_Diff_Op_add(array(substr($line, 1))); + break; + + case '-': + $edits[] = &new Text_Diff_Op_delete(array(substr($line, 1))); + break; + } + } + + return $edits; + } + +} diff --git a/wp-includes/Text/Diff/Renderer.php b/wp-includes/Text/Diff/Renderer.php new file mode 100644 index 0000000..5d226b4 --- /dev/null +++ b/wp-includes/Text/Diff/Renderer.php @@ -0,0 +1,237 @@ + $value) { + $v = '_' . $param; + if (isset($this->$v)) { + $this->$v = $value; + } + } + } + + /** + * Get any renderer parameters. + * + * @return array All parameters of this renderer object. + */ + function getParams() + { + $params = array(); + foreach (get_object_vars($this) as $k => $v) { + if ($k[0] == '_') { + $params[substr($k, 1)] = $v; + } + } + + return $params; + } + + /** + * Renders a diff. + * + * @param Text_Diff $diff A Text_Diff object. + * + * @return string The formatted output. + */ + function render($diff) + { + $xi = $yi = 1; + $block = false; + $context = array(); + + $nlead = $this->_leading_context_lines; + $ntrail = $this->_trailing_context_lines; + + $output = $this->_startDiff(); + + $diffs = $diff->getDiff(); + foreach ($diffs as $i => $edit) { + /* If these are unchanged (copied) lines, and we want to keep + * leading or trailing context lines, extract them from the copy + * block. */ + if (is_a($edit, 'Text_Diff_Op_copy')) { + /* Do we have any diff blocks yet? */ + if (is_array($block)) { + /* How many lines to keep as context from the copy + * block. */ + $keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail; + if (count($edit->orig) <= $keep) { + /* We have less lines in the block than we want for + * context => keep the whole block. */ + $block[] = $edit; + } else { + if ($ntrail) { + /* Create a new block with as many lines as we need + * for the trailing context. */ + $context = array_slice($edit->orig, 0, $ntrail); + $block[] = &new Text_Diff_Op_copy($context); + } + /* @todo */ + $output .= $this->_block($x0, $ntrail + $xi - $x0, + $y0, $ntrail + $yi - $y0, + $block); + $block = false; + } + } + /* Keep the copy block as the context for the next block. */ + $context = $edit->orig; + } else { + /* Don't we have any diff blocks yet? */ + if (!is_array($block)) { + /* Extract context lines from the preceding copy block. */ + $context = array_slice($context, count($context) - $nlead); + $x0 = $xi - count($context); + $y0 = $yi - count($context); + $block = array(); + if ($context) { + $block[] = &new Text_Diff_Op_copy($context); + } + } + $block[] = $edit; + } + + if ($edit->orig) { + $xi += count($edit->orig); + } + if ($edit->final) { + $yi += count($edit->final); + } + } + + if (is_array($block)) { + $output .= $this->_block($x0, $xi - $x0, + $y0, $yi - $y0, + $block); + } + + return $output . $this->_endDiff(); + } + + function _block($xbeg, $xlen, $ybeg, $ylen, &$edits) + { + $output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen)); + + foreach ($edits as $edit) { + switch (strtolower(get_class($edit))) { + case 'text_diff_op_copy': + $output .= $this->_context($edit->orig); + break; + + case 'text_diff_op_add': + $output .= $this->_added($edit->final); + break; + + case 'text_diff_op_delete': + $output .= $this->_deleted($edit->orig); + break; + + case 'text_diff_op_change': + $output .= $this->_changed($edit->orig, $edit->final); + break; + } + } + + return $output . $this->_endBlock(); + } + + function _startDiff() + { + return ''; + } + + function _endDiff() + { + return ''; + } + + function _blockHeader($xbeg, $xlen, $ybeg, $ylen) + { + if ($xlen > 1) { + $xbeg .= ',' . ($xbeg + $xlen - 1); + } + if ($ylen > 1) { + $ybeg .= ',' . ($ybeg + $ylen - 1); + } + + // this matches the GNU Diff behaviour + if ($xlen && !$ylen) { + $ybeg--; + } elseif (!$xlen) { + $xbeg--; + } + + return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg; + } + + function _startBlock($header) + { + return $header . "\n"; + } + + function _endBlock() + { + return ''; + } + + function _lines($lines, $prefix = ' ') + { + return $prefix . implode("\n$prefix", $lines) . "\n"; + } + + function _context($lines) + { + return $this->_lines($lines, ' '); + } + + function _added($lines) + { + return $this->_lines($lines, '> '); + } + + function _deleted($lines) + { + return $this->_lines($lines, '< '); + } + + function _changed($orig, $final) + { + return $this->_deleted($orig) . "---\n" . $this->_added($final); + } + +} diff --git a/wp-includes/Text/Diff/Renderer/inline.php b/wp-includes/Text/Diff/Renderer/inline.php new file mode 100644 index 0000000..b547ff2 --- /dev/null +++ b/wp-includes/Text/Diff/Renderer/inline.php @@ -0,0 +1,170 @@ +'; + + /** + * Suffix for inserted text. + */ + var $_ins_suffix = ''; + + /** + * Prefix for deleted text. + */ + var $_del_prefix = ''; + + /** + * Suffix for deleted text. + */ + var $_del_suffix = ''; + + /** + * Header for each change block. + */ + var $_block_header = ''; + + /** + * What are we currently splitting on? Used to recurse to show word-level + * changes. + */ + var $_split_level = 'lines'; + + function _blockHeader($xbeg, $xlen, $ybeg, $ylen) + { + return $this->_block_header; + } + + function _startBlock($header) + { + return $header; + } + + function _lines($lines, $prefix = ' ', $encode = true) + { + if ($encode) { + array_walk($lines, array(&$this, '_encode')); + } + + if ($this->_split_level == 'words') { + return implode('', $lines); + } else { + return implode("\n", $lines) . "\n"; + } + } + + function _added($lines) + { + array_walk($lines, array(&$this, '_encode')); + $lines[0] = $this->_ins_prefix . $lines[0]; + $lines[count($lines) - 1] .= $this->_ins_suffix; + return $this->_lines($lines, ' ', false); + } + + function _deleted($lines, $words = false) + { + array_walk($lines, array(&$this, '_encode')); + $lines[0] = $this->_del_prefix . $lines[0]; + $lines[count($lines) - 1] .= $this->_del_suffix; + return $this->_lines($lines, ' ', false); + } + + function _changed($orig, $final) + { + /* If we've already split on words, don't try to do so again - just + * display. */ + if ($this->_split_level == 'words') { + $prefix = ''; + while ($orig[0] !== false && $final[0] !== false && + substr($orig[0], 0, 1) == ' ' && + substr($final[0], 0, 1) == ' ') { + $prefix .= substr($orig[0], 0, 1); + $orig[0] = substr($orig[0], 1); + $final[0] = substr($final[0], 1); + } + return $prefix . $this->_deleted($orig) . $this->_added($final); + } + + $text1 = implode("\n", $orig); + $text2 = implode("\n", $final); + + /* Non-printing newline marker. */ + $nl = "\0"; + + /* We want to split on word boundaries, but we need to + * preserve whitespace as well. Therefore we split on words, + * but include all blocks of whitespace in the wordlist. */ + $diff = new Text_Diff($this->_splitOnWords($text1, $nl), + $this->_splitOnWords($text2, $nl)); + + /* Get the diff in inline format. */ + $renderer = new Text_Diff_Renderer_inline(array_merge($this->getParams(), + array('split_level' => 'words'))); + + /* Run the diff and get the output. */ + return str_replace($nl, "\n", $renderer->render($diff)) . "\n"; + } + + function _splitOnWords($string, $newlineEscape = "\n") + { + // Ignore \0; otherwise the while loop will never finish. + $string = str_replace("\0", '', $string); + + $words = array(); + $length = strlen($string); + $pos = 0; + + while ($pos < $length) { + // Eat a word with any preceding whitespace. + $spaces = strspn(substr($string, $pos), " \n"); + $nextpos = strcspn(substr($string, $pos + $spaces), " \n"); + $words[] = str_replace("\n", $newlineEscape, substr($string, $pos, $spaces + $nextpos)); + $pos += $spaces + $nextpos; + } + + return $words; + } + + function _encode(&$string) + { + $string = htmlspecialchars($string); + } + +} diff --git a/wp-includes/author-template.php b/wp-includes/author-template.php index bcc9290..f78e046 100644 --- a/wp-includes/author-template.php +++ b/wp-includes/author-template.php @@ -2,12 +2,16 @@ /** * Author Template functions for use in themes. * + * These functions must be used within the WordPress Loop. + * + * @link http://codex.wordpress.org/Author_Templates + * * @package WordPress * @subpackage Template */ /** - * get_the_author() - Get the author of the current post in the Loop. + * Retrieve the author of the current post. * * @since 1.5 * @uses $authordata The current author's DB object. @@ -22,21 +26,22 @@ function get_the_author($deprecated = '') { } /** - * the_author() - Echo the name of the author of the current post in the Loop. + * Display the name of the author of the current post. * - * The behavior of this function is based off of old functionality predating get_the_author(). - * This function is not deprecated, but is designed to echo the value from get_the_author() - * and as an result of any old theme that might still use the old behavior will also - * pass the value from get_the_author(). + * The behavior of this function is based off of old functionality predating + * get_the_author(). This function is not deprecated, but is designed to echo + * the value from get_the_author() and as an result of any old theme that might + * still use the old behavior will also pass the value from get_the_author(). * - * The normal, expected behavior of this function is to echo the author and not return it. - * However, backwards compatiability has to be maintained. + * The normal, expected behavior of this function is to echo the author and not + * return it. However, backwards compatiability has to be maintained. * * @since 0.71 * @see get_the_author() + * @link http://codex.wordpress.org/Template_Tags/the_author * * @param string $deprecated Deprecated. - * @param string $deprecated_echo Echo the string or return it. Deprecated, use get_the_author(). + * @param string $deprecated_echo Echo the string or return it. * @return string The author's display name, from get_the_author(). */ function the_author($deprecated = '', $deprecated_echo = true) { @@ -46,7 +51,7 @@ function the_author($deprecated = '', $deprecated_echo = true) { } /** - * get_the_author_description() - Get the description of the author of the current post in the Loop. + * Retrieve the description of the author of the current post. * * @since 1.5 * @uses $authordata The current author's DB object. @@ -58,8 +63,9 @@ function get_the_author_description() { } /** - * the_author_description() - Echo the description of the author of the current post in the Loop. + * Display the description of the author of the current post. * + * @link http://codex.wordpress.org/Template_Tags/the_author_description * @since 1.0.0 * @see get_the_author_description() */ @@ -68,7 +74,7 @@ function the_author_description() { } /** - * get_the_author_login() - Get the login name of the author of the current post in the Loop. + * Retrieve the login name of the author of the current post. * * @since 1.5 * @uses $authordata The current author's DB object. @@ -80,8 +86,9 @@ function get_the_author_login() { } /** - * the_author_login() - Echo the login name of the author of the current post in the Loop. + * Display the login name of the author of the current post. * + * @link http://codex.wordpress.org/Template_Tags/the_author_login * @since 0.71 * @see get_the_author_login() */ @@ -90,7 +97,7 @@ function the_author_login() { } /** - * get_the_author_firstname() - Get the first name of the author of the current post in the Loop. + * Retrieve the first name of the author of the current post. * * @since 1.5 * @uses $authordata The current author's DB object. @@ -102,8 +109,9 @@ function get_the_author_firstname() { } /** - * the_author_firstname() - Echo the first name of the author of the current post in the Loop. + * Display the first name of the author of the current post. * + * @link http://codex.wordpress.org/Template_Tags/the_author_firstname * @since 0.71 * @uses get_the_author_firstname() */ @@ -112,7 +120,7 @@ function the_author_firstname() { } /** - * get_the_author_lastname() - Get the last name of the author of the current post in the Loop. + * Retrieve the last name of the author of the current post. * * @since 1.5 * @uses $authordata The current author's DB object. @@ -124,8 +132,9 @@ function get_the_author_lastname() { } /** - * the_author_lastname() - Echo the last name of the author of the current post in the Loop. + * Display the last name of the author of the current post. * + * @link http://codex.wordpress.org/Template_Tags/the_author_lastname * @since 0.71 * @uses get_the_author_lastname() */ @@ -134,7 +143,7 @@ function the_author_lastname() { } /** - * get_the_author_nickname() - Get the nickname of the author of the current post in the Loop. + * Retrieve the nickname of the author of the current post. * * @since 1.5 * @uses $authordata The current author's DB object. @@ -146,8 +155,9 @@ function get_the_author_nickname() { } /** - * the_author_nickname() - Echo the nickname of the author of the current post in the Loop. + * Display the nickname of the author of the current post. * + * @link http://codex.wordpress.org/Template_Tags/the_author_nickname * @since 0.71 * @uses get_the_author_nickname() */ @@ -156,7 +166,7 @@ function the_author_nickname() { } /** - * get_the_author_ID() - Get the ID of the author of the current post in the Loop. + * Retrieve the ID of the author of the current post. * * @since 1.5 * @uses $authordata The current author's DB object. @@ -168,8 +178,9 @@ function get_the_author_ID() { } /** - * the_author_ID() - Echo the ID of the author of the current post in the Loop. + * Display the ID of the author of the current post. * + * @http://codex.wordpress.org/Template_Tags/the_author_ID * @since 0.71 * @uses get_the_author_ID() */ @@ -178,7 +189,7 @@ function the_author_ID() { } /** - * get_the_author_email() - Get the email of the author of the current post in the Loop. + * Retrieve the email of the author of the current post. * * @since 1.5 * @uses $authordata The current author's DB object. @@ -190,8 +201,9 @@ function get_the_author_email() { } /** - * the_author_email() - Echo the email of the author of the current post in the Loop. + * Display the email of the author of the current post. * + * @link http://codex.wordpress.org/Template_Tags/the_author_email * @since 0.71 * @uses get_the_author_email() */ @@ -200,7 +212,7 @@ function the_author_email() { } /** - * get_the_author_url() - Get the URL to the home page of the author of the current post in the Loop. + * Retrieve the URL to the home page of the author of the current post. * * @since 1.5 * @uses $authordata The current author's DB object. @@ -216,8 +228,9 @@ function get_the_author_url() { } /** - * the_author_url() - Echo the URL to the home page of the author of the current post in the Loop. + * Display the URL to the home page of the author of the current post. * + * @link http://codex.wordpress.org/Template_Tags/the_author_url * @since 0.71 * @uses get_the_author_url() */ @@ -226,8 +239,12 @@ function the_author_url() { } /** - * the_author_link() - If the author has a home page set, echo an HTML link, otherwise just echo the author's name. + * Display either author's link or author's name. + * + * If the author has a home page set, echo an HTML link, otherwise just echo the + * author's name. * + * @link http://codex.wordpress.org/Template_Tags/the_author_link * @since 2.1 * @uses get_the_author_url() * @uses the_author() @@ -241,7 +258,7 @@ function the_author_link() { } /** - * get_the_author_icq() - Get the ICQ number of the author of the current post in the Loop. + * Retrieve the ICQ number of the author of the current post. * * @since 1.5 * @uses $authordata The current author's DB object. @@ -253,8 +270,9 @@ function get_the_author_icq() { } /** - * the_author_icq() - Echo the ICQ number of the author of the current post in the Loop. + * Display the ICQ number of the author of the current post. * + * @link http://codex.wordpress.org/Template_Tags/the_author_icq * @since 0.71 * @see get_the_author_icq() */ @@ -263,7 +281,7 @@ function the_author_icq() { } /** - * get_the_author_aim() - Get the AIM name of the author of the current post in the Loop. + * Retrieve the AIM name of the author of the current post. * * @since 1.5 * @uses $authordata The current author's DB object. @@ -275,8 +293,9 @@ function get_the_author_aim() { } /** - * the_author_aim() - Echo the AIM name of the author of the current post in the Loop. + * Display the AIM name of the author of the current post. * + * @link http://codex.wordpress.org/Template_Tags/the_author_aim * @since 0.71 * @see get_the_author_aim() */ @@ -285,7 +304,7 @@ function the_author_aim() { } /** - * get_the_author_yim() - Get the Yahoo! IM name of the author of the current post in the Loop. + * Retrieve the Yahoo! IM name of the author of the current post. * * @since 1.5 * @uses $authordata The current author's DB object. @@ -297,8 +316,9 @@ function get_the_author_yim() { } /** - * the_author_yim() - Echo the Yahoo! IM name of the author of the current post in the Loop. + * Display the Yahoo! IM name of the author of the current post. * + * @link http://codex.wordpress.org/Template_Tags/the_author_yim * @since 0.71 * @see get_the_author_yim() */ @@ -307,7 +327,7 @@ function the_author_yim() { } /** - * get_the_author_msn() - Get the MSN address of the author of the current post in the Loop. + * Retrieve the MSN address of the author of the current post. * * @since 1.5 * @uses $authordata The current author's DB object. @@ -319,8 +339,9 @@ function get_the_author_msn() { } /** - * the_author_msn() - Echo the MSN address of the author of the current post in the Loop. + * Display the MSN address of the author of the current post. * + * @link http://codex.wordpress.org/Template_Tags/the_author_msn * @since 0.71 * @see get_the_author_msn() */ @@ -329,7 +350,7 @@ function the_author_msn() { } /** - * get_the_author_posts() - Get the number of posts by the author of the current post in the Loop. + * Retrieve the number of posts by the author of the current post. * * @since 1.5 * @uses $post The current post in the Loop's DB object. @@ -342,8 +363,9 @@ function get_the_author_posts() { } /** - * the_author_posts() - Echo the number of posts by the author of the current post in the Loop. + * Display the number of posts by the author of the current post. * + * @link http://codex.wordpress.org/Template_Tags/the_author_posts * @since 0.71 * @uses get_the_author_posts() Echos returned value from function. */ @@ -352,11 +374,13 @@ function the_author_posts() { } /** - * the_author_posts_link() - Echo an HTML link to the author page of the author of the current post in the Loop. + * Display an HTML link to the author page of the author of the current post. * - * Does just echo get_author_posts_url() function, like the others do. The reason for this, - * is that another function is used to help in printing the link to the author's posts. + * Does just echo get_author_posts_url() function, like the others do. The + * reason for this, is that another function is used to help in printing the + * link to the author's posts. * + * @link http://codex.wordpress.org/Template_Tags/the_author_posts_link * @since 1.2 * @uses $authordata The current author's DB object. * @uses get_author_posts_url() @@ -374,7 +398,7 @@ function the_author_posts_link($deprecated = '') { } /** - * get_author_posts_url() - Get the URL to the author page of the author of the current post in the Loop. + * Retrieve the URL to the author page of the author of the current post. * * @since 2.1 * @uses $wp_rewrite WP_Rewrite @@ -404,7 +428,7 @@ function get_author_posts_url($author_id, $author_nicename = '') { } /** - * get_author_name() - Get the specified author's preferred display name. + * Retrieve the specified author's preferred display name. * * @since 1.0.0 * @param int $auth_id The ID of the author. @@ -416,16 +440,19 @@ function get_author_name( $auth_id ) { } /** - * wp_list_authors() - List all the authors of the blog, with several options available. + * List all the authors of the blog, with several options available. * - * optioncount (boolean) (false): Show the count in parenthesis next to the author's name. - * exclude_admin (boolean) (true): Exclude the 'admin' user that is installed by default. + * optioncount (boolean) (false): Show the count in parenthesis next to the + * author's name. + * exclude_admin (boolean) (true): Exclude the 'admin' user that is installed by + * default. * show_fullname (boolean) (false): Show their full names. * hide_empty (boolean) (true): Don't show authors without any posts. * feed (string) (''): If isn't empty, show links to author's feeds. * feed_image (string) (''): If isn't empty, use this image to link to feeds. * echo (boolean) (true): Set to false to return the output, instead of echoing. * + * @link http://codex.wordpress.org/Template_Tags/wp_list_authors * @since 1.2 * @param array $args The argument array. * @return null|string The output, if echo is set to false. diff --git a/wp-includes/bookmark-template.php b/wp-includes/bookmark-template.php index f85d5c4..13f1f2e 100644 --- a/wp-includes/bookmark-template.php +++ b/wp-includes/bookmark-template.php @@ -7,24 +7,31 @@ */ /** - * _walk_bookmarks() - The formatted output of a list of bookmarks + * The formatted output of a list of bookmarks * * The $bookmarks array must contain bookmark objects and will be iterated over * to retrieve the bookmark to be used in the output. * - * The output is formatted as HTML with no way to change that format. However, what - * is between, before, and after can be changed. The link itself will be HTML. + * The output is formatted as HTML with no way to change that format. However, + * what is between, before, and after can be changed. The link itself will be + * HTML. * - * This function is used internally by wp_list_bookmarks() and should not be used by - * themes. + * This function is used internally by wp_list_bookmarks() and should not be + * used by themes. * * The defaults for overwriting are: - * 'show_updated' - Default is 0 (integer). Will show the time of when the bookmark was last updated. - * 'show_description' - Default is 0 (integer). Whether to show the description of the bookmark. - * 'show_images' - Default is 1 (integer). Whether to show link image if available. - * 'before' - Default is '
  • ' (string). The html or text to prepend to each bookmarks. - * 'after' - Default is '
  • ' (string). The html or text to append to each bookmarks. - * 'between' - Default is '\n' (string). The string for use in between the link, description, and image. + * 'show_updated' - Default is 0 (integer). Will show the time of when the + * bookmark was last updated. + * 'show_description' - Default is 0 (integer). Whether to show the description + * of the bookmark. + * 'show_images' - Default is 1 (integer). Whether to show link image if + * available. + * 'before' - Default is '
  • ' (string). The html or text to prepend to each + * bookmarks. + * 'after' - Default is '
  • ' (string). The html or text to append to each + * bookmarks. + * 'between' - Default is '\n' (string). The string for use in between the link, + * description, and image. * 'show_rating' - Default is 0 (integer). Whether to show the link rating. * * @since 2.1 @@ -113,44 +120,68 @@ function _walk_bookmarks($bookmarks, $args = '' ) { } /** - * wp_list_bookmarks() - Retrieve or echo all of the bookmarks + * Retrieve or echo all of the bookmarks * * List of default arguments are as follows: - * 'orderby' - Default is 'name' (string). How to order the links by. String is based off of the bookmark scheme. - * 'order' - Default is 'ASC' (string). Either 'ASC' or 'DESC'. Orders in either ascending or descending order. - * 'limit' - Default is -1 (integer) or show all. The amount of bookmarks to display. - * 'category' - Default is empty string (string). Include the links in what category ID(s). - * 'category_name' - Default is empty string (string). Get links by category name. - * 'hide_invisible' - Default is 1 (integer). Whether to show (default) or hide links marked as 'invisible'. - * 'show_updated' - Default is 0 (integer). Will show the time of when the bookmark was last updated. - * 'echo' - Default is 1 (integer). Whether to echo (default) or return the formatted bookmarks. - * 'categorize' - Default is 1 (integer). Whether to show links listed by category (default) or show links in one column. + * 'orderby' - Default is 'name' (string). How to order the links by. String is + * based off of the bookmark scheme. + * 'order' - Default is 'ASC' (string). Either 'ASC' or 'DESC'. Orders in either + * ascending or descending order. + * 'limit' - Default is -1 (integer) or show all. The amount of bookmarks to + * display. + * 'category' - Default is empty string (string). Include the links in what + * category ID(s). + * 'category_name' - Default is empty string (string). Get links by category + * name. + * 'hide_invisible' - Default is 1 (integer). Whether to show (default) or hide + * links marked as 'invisible'. + * 'show_updated' - Default is 0 (integer). Will show the time of when the + * bookmark was last updated. + * 'echo' - Default is 1 (integer). Whether to echo (default) or return the + * formatted bookmarks. + * 'categorize' - Default is 1 (integer). Whether to show links listed by + * category (default) or show links in one column. * - * These options define how the Category name will appear before the category links are displayed, if 'categorize' is 1. - * If 'categorize' is 0, then it will display for only the 'title_li' string and only if 'title_li' is not empty. - * 'title_li' - Default is 'Bookmarks' (translatable string). What to show before the links appear. - * 'title_before' - Default is '

    ' (string). The HTML or text to show before the 'title_li' string. - * 'title_after' - Default is '

    ' (string). The HTML or text to show after the 'title_li' string. - * 'class' - Default is 'linkcat' (string). The CSS class to use for the 'title_li'. + * These options define how the Category name will appear before the category + * links are displayed, if 'categorize' is 1. If 'categorize' is 0, then it will + * display for only the 'title_li' string and only if 'title_li' is not empty. + * 'title_li' - Default is 'Bookmarks' (translatable string). What to show + * before the links appear. + * 'title_before' - Default is '

    ' (string). The HTML or text to show before + * the 'title_li' string. + * 'title_after' - Default is '

    ' (string). The HTML or text to show after + * the 'title_li' string. + * 'class' - Default is 'linkcat' (string). The CSS class to use for the + * 'title_li'. * - * 'category_before' - Default is '
  • '. String must contain '%id' and '%class' to get - * the id of the category and the 'class' argument. These are used for formatting in themes. Argument will be displayed - * before the 'title_before' argument. - * 'category_after' - Default is '
  • ' (string). The HTML or text that will appear after the list of links. + * 'category_before' - Default is '
  • '. String must + * contain '%id' and '%class' to get + * the id of the category and the 'class' argument. These are used for + * formatting in themes. + * Argument will be displayed before the 'title_before' argument. + * 'category_after' - Default is '
  • ' (string). The HTML or text that will + * appear after the list of links. * * These are only used if 'categorize' is set to 1 or true. - * 'category_orderby' - Default is 'name'. How to order the bookmark category based on term scheme. - * 'category_order' - Default is 'ASC'. Set the order by either ASC (ascending) or DESC (descending). + * 'category_orderby' - Default is 'name'. How to order the bookmark category + * based on term scheme. + * 'category_order' - Default is 'ASC'. Set the order by either ASC (ascending) + * or DESC (descending). * - * @see _walk_bookmarks() For other arguments that can be set in this function and passed to _walk_bookmarks(). - * @see get_bookmarks() For other arguments that can be set in this function and passed to get_bookmarks(). + * @see _walk_bookmarks() For other arguments that can be set in this function + * and passed to _walk_bookmarks(). + * @see get_bookmarks() For other arguments that can be set in this function and + * passed to get_bookmarks(). + * @link http://codex.wordpress.org/Template_Tags/wp_list_bookmarks * * @since 2.1 - * @uses _list_bookmarks() Used to iterate over all of the bookmarks and return the html + * @uses _list_bookmarks() Used to iterate over all of the bookmarks and return + * the html * @uses get_terms() Gets all of the categories that are for links. * * @param string|array $args Optional. Overwrite the defaults of the function - * @return string|null Will only return if echo option is set to not echo. Default is not return anything. + * @return string|null Will only return if echo option is set to not echo. + * Default is not return anything. */ function wp_list_bookmarks($args = '') { $defaults = array( @@ -172,7 +203,7 @@ function wp_list_bookmarks($args = '') { if ( $categorize ) { //Split the bookmarks into ul's for each category - $cats = get_terms('link_category', "category_name=$category_name&include=$category&orderby=$category_orderby&order=$category_order&hierarchical=0"); + $cats = get_terms('link_category', array('category_name' => $category_name, 'include' => $category, 'orderby' => $category_orderby, 'order' => $category_order, 'hierarchical' => 0)); foreach ( (array) $cats as $cat ) { $params = array_merge($r, array('category'=>$cat->term_id)); diff --git a/wp-includes/bookmark.php b/wp-includes/bookmark.php index 776d519..260dbaf 100644 --- a/wp-includes/bookmark.php +++ b/wp-includes/bookmark.php @@ -7,7 +7,7 @@ */ /** - * get_bookmark() - Get Bookmark data based on ID + * Retrieve Bookmark data based on ID * * @since 2.1 * @uses $wpdb Database Object @@ -37,7 +37,7 @@ function get_bookmark($bookmark_id, $output = OBJECT, $filter = 'raw') { } /** - * get_bookmark_field() - Gets single bookmark data item or field. + * Retrieve single bookmark data item or field. * * @since 2.3 * @uses get_bookmark() Gets bookmark object using $bookmark as ID @@ -65,7 +65,7 @@ function get_bookmark_field( $field, $bookmark, $context = 'display' ) { } /** - * get_link() - Returns bookmark data based on ID. + * Retrieve bookmark data based on ID. * * @since 2.0 * @deprecated Use get_bookmark() @@ -80,25 +80,35 @@ function get_link($bookmark_id, $output = OBJECT, $filter = 'raw') { } /** - * get_bookmarks() - Retrieves the list of bookmarks + * Retrieves the list of bookmarks * * Attempts to retrieve from the cache first based on MD5 hash of arguments. If * that fails, then the query will be built from the arguments and executed. The * results will be stored to the cache. * * List of default arguments are as follows: - * 'orderby' - Default is 'name' (string). How to order the links by. String is based off of the bookmark scheme. - * 'order' - Default is 'ASC' (string). Either 'ASC' or 'DESC'. Orders in either ascending or descending order. - * 'limit' - Default is -1 (integer) or show all. The amount of bookmarks to display. - * 'category' - Default is empty string (string). Include the links in what category ID(s). - * 'category_name' - Default is empty string (string). Get links by category name. - * 'hide_invisible' - Default is 1 (integer). Whether to show (default) or hide links marked as 'invisible'. - * 'show_updated' - Default is 0 (integer). Will show the time of when the bookmark was last updated. - * 'include' - Default is empty string (string). Include other categories separated by commas. - * 'exclude' - Default is empty string (string). Exclude other categories separated by commas. + * 'orderby' - Default is 'name' (string). How to order the links by. String is + * based off of the bookmark scheme. + * 'order' - Default is 'ASC' (string). Either 'ASC' or 'DESC'. Orders in either + * ascending or descending order. + * 'limit' - Default is -1 (integer) or show all. The amount of bookmarks to + * display. + * 'category' - Default is empty string (string). Include the links in what + * category ID(s). + * 'category_name' - Default is empty string (string). Get links by category + * name. + * 'hide_invisible' - Default is 1 (integer). Whether to show (default) or hide + * links marked as 'invisible'. + * 'show_updated' - Default is 0 (integer). Will show the time of when the + * bookmark was last updated. + * 'include' - Default is empty string (string). Include other categories + * separated by commas. + * 'exclude' - Default is empty string (string). Exclude other categories + * separated by commas. * * @since 2.1 * @uses $wpdb Database Object + * @link http://codex.wordpress.org/Template_Tags/get_bookmarks * * @param string|array $args List of arguments to overwrite the defaults * @return array List of bookmark row objects @@ -226,12 +236,13 @@ function get_bookmarks($args = '') { } /** - * sanitize_bookmark() - Sanitizes all bookmark fields + * Sanitizes all bookmark fields * * @since 2.3 * * @param object|array $bookmark Bookmark row - * @param string $context Optional, default is 'display'. How to filter the fields + * @param string $context Optional, default is 'display'. How to filter the + * fields * @return object|array Same type as $bookmark but with fields sanitized. */ function sanitize_bookmark($bookmark, $context = 'display') { @@ -254,25 +265,27 @@ function sanitize_bookmark($bookmark, $context = 'display') { } /** - * sanitize_bookmark_field() - Sanitizes a bookmark field + * Sanitizes a bookmark field * - * Sanitizes the bookmark fields based on what the field name is. If the field has a - * strict value set, then it will be tested for that, else a more generic filtering is - * applied. After the more strict filter is applied, if the $context is 'raw' then the - * value is immediately return. + * Sanitizes the bookmark fields based on what the field name is. If the field + * has a strict value set, then it will be tested for that, else a more generic + * filtering is applied. After the more strict filter is applied, if the + * $context is 'raw' then the value is immediately return. * - * Hooks exist for the more generic cases. With the 'edit' context, the 'edit_$field' - * filter will be called and passed the $value and $bookmark_id respectively. With the - * 'db' context, the 'pre_$field' filter is called and passed the value. The 'display' - * context is the final context and has the $field has the filter name and is passed the - * $value, $bookmark_id, and $context respectively. + * Hooks exist for the more generic cases. With the 'edit' context, the + * 'edit_$field' filter will be called and passed the $value and $bookmark_id + * respectively. With the 'db' context, the 'pre_$field' filter is called and + * passed the value. The 'display' context is the final context and has the + * $field has the filter name and is passed the $value, $bookmark_id, and + * $context respectively. * * @since 2.3 * * @param string $field The bookmark field * @param mixed $value The bookmark field value * @param int $bookmark_id Bookmark ID - * @param string $context How to filter the field value. Either 'raw', 'edit', 'attribute', 'js', 'db', or 'display' + * @param string $context How to filter the field value. Either 'raw', 'edit', + * 'attribute', 'js', 'db', or 'display' * @return mixed The filtered value */ function sanitize_bookmark_field($field, $value, $bookmark_id, $context) { @@ -318,7 +331,7 @@ function sanitize_bookmark_field($field, $value, $bookmark_id, $context) { } /** - * delete_get_bookmark_cache() - Deletes entire bookmark cache + * Deletes entire bookmark cache * * @since 2.1 * @uses wp_cache_delete() Deletes the contents of 'get_bookmarks' diff --git a/wp-includes/cache.php b/wp-includes/cache.php index 9736da4..cfdab82 100644 --- a/wp-includes/cache.php +++ b/wp-includes/cache.php @@ -2,12 +2,14 @@ /** * Object Cache API * + * @link http://codex.wordpress.org/Function_Reference/WP_Cache + * * @package WordPress * @subpackage Cache */ /** - * wp_cache_add() - Adds data to the cache, if the cache key doesn't aleady exist + * Adds data to the cache, if the cache key doesn't aleady exist. * * @since 2.0 * @uses $wp_object_cache Object Cache Class @@ -26,11 +28,12 @@ function wp_cache_add($key, $data, $flag = '', $expire = 0) { } /** - * wp_cache_close() - Closes the cache + * Closes the cache. * - * This function has ceased to do anything since WordPress 2.5. - * The functionality was removed along with the rest of the - * persistant cache. + * This function has ceased to do anything since WordPress 2.5. The + * functionality was removed along with the rest of the persistant cache. This + * does not mean that plugins can't implement this function when they need to + * make sure that the cache is cleaned up after WordPress no longer needs it. * * @since 2.0 * @@ -41,7 +44,7 @@ function wp_cache_close() { } /** - * wp_cache_delete() - Removes the cache contents matching ID and flag + * Removes the cache contents matching ID and flag. * * @since 2.0 * @uses $wp_object_cache Object Cache Class @@ -58,7 +61,7 @@ function wp_cache_delete($id, $flag = '') { } /** - * wp_cache_flush() - Removes all cache items + * Removes all cache items. * * @since 2.0 * @uses $wp_object_cache Object Cache Class @@ -73,7 +76,7 @@ function wp_cache_flush() { } /** - * wp_cache_get() - Retrieves the cache contents from the cache by ID and flag + * Retrieves the cache contents from the cache by ID and flag. * * @since 2.0 * @uses $wp_object_cache Object Cache Class @@ -81,7 +84,8 @@ function wp_cache_flush() { * * @param int|string $id What the contents in the cache are called * @param string $flag Where the cache contents are grouped - * @return bool|mixed False on failure to retrieve contents or the cache contents on success + * @return bool|mixed False on failure to retrieve contents or the cache + * contents on success */ function wp_cache_get($id, $flag = '') { global $wp_object_cache; @@ -90,7 +94,7 @@ function wp_cache_get($id, $flag = '') { } /** - * wp_cache_init() - Sets up Object Cache Global and assigns it + * Sets up Object Cache Global and assigns it. * * @since 2.0 * @global WP_Object_Cache $wp_object_cache WordPress Object Cache @@ -100,7 +104,7 @@ function wp_cache_init() { } /** - * wp_cache_replace() - Replaces the contents of the cache with new data + * Replaces the contents of the cache with new data. * * @since 2.0 * @uses $wp_object_cache Object Cache Class @@ -119,7 +123,7 @@ function wp_cache_replace($key, $data, $flag = '', $expire = 0) { } /** - * wp_cache_set() - Saves the data to the cache + * Saves the data to the cache. * * @since 2.0 * @uses $wp_object_cache Object Cache Class @@ -137,17 +141,41 @@ function wp_cache_set($key, $data, $flag = '', $expire = 0) { return $wp_object_cache->set($key, $data, $flag, $expire); } +/** + * Adds a group or set of groups to the list of global groups. + * + * @since 2.6 + * + * @param string|array $groups A group or an array of groups to add + */ +function wp_cache_add_global_groups( $groups ) { + // Default cache doesn't persist so nothing to do here. + return; +} + +/** + * Adds a group or set of groups to the list of non-persistent groups. + * + * @since 2.6 + * + * @param string|array $groups A group or an array of groups to add + */ +function wp_cache_add_non_persistent_groups( $groups ) { + // Default cache doesn't persist so nothing to do here. + return; +} + /** * WordPress Object Cache * - * The WordPress Object Cache is used to save on trips to the database. - * The Object Cache stores all of the cache data to memory and makes the - * cache contents available by using a key, which is used to name and - * later retrieve the cache contents. + * The WordPress Object Cache is used to save on trips to the database. The + * Object Cache stores all of the cache data to memory and makes the cache + * contents available by using a key, which is used to name and later retrieve + * the cache contents. * - * The Object Cache can be replaced by other caching mechanisms by placing - * files in the wp-content folder which is looked at in wp-settings. If - * that file exists, then this file will not be included. + * The Object Cache can be replaced by other caching mechanisms by placing files + * in the wp-content folder which is looked at in wp-settings. If that file + * exists, then this file will not be included. * * @package WordPress * @subpackage Cache @@ -173,15 +201,6 @@ class WP_Object_Cache { */ var $non_existant_objects = array (); - /** - * Object caches that are global - * - * @var array - * @access private - * @since 2.0 - */ - var $global_groups = array ('users', 'userlogins', 'usermeta', 'site-options', 'site-lookup', 'blog-lookup', 'blog-details'); - /** * The amount of times the cache data was already stored in the cache. * @@ -200,27 +219,12 @@ class WP_Object_Cache { */ var $cache_misses = 0; - function maybe_localize_group( $group ) { - global $wpdb; - - if ( empty($group) ) - $group = 'default'; - - $pre_test = substr( $group, 0, strpos( $group, '-' ) ); - if( $pre_test != '' && $pre_test == intval( $pre_test ) ) - return $group; // already localized. - $prefix = ''; - if (true !== array_search($group, $this->global_groups)) - $prefix = $wpdb->blogid . '-'; - - return "$prefix$group"; - } - /** * Adds data to the cache if it doesn't already exist. * * @uses WP_Object_Cache::get Checks to see if the cache already has data. - * @uses WP_Object_Cache::set Sets the data after the checking the cache contents existance. + * @uses WP_Object_Cache::set Sets the data after the checking the cache + * contents existance. * * @since 2.0 * @@ -243,24 +247,24 @@ class WP_Object_Cache { /** * Remove the contents of the cache ID in the group * - * If the cache ID does not exist in the group and $force parameter - * is set to false, then nothing will happen. The $force parameter - * is set to false by default. + * If the cache ID does not exist in the group and $force parameter is set + * to false, then nothing will happen. The $force parameter is set to false + * by default. * - * On success the group and the id will be added to the + * On success the group and the id will be added to the * $non_existant_objects property in the class. * * @since 2.0 * * @param int|string $id What the contents in the cache are called * @param string $group Where the cache contents are grouped - * @param bool $force Optional. Whether to force the unsetting of the cache ID in the group + * @param bool $force Optional. Whether to force the unsetting of the cache + * ID in the group * @return bool False if the contents weren't deleted and true on success */ function delete($id, $group = 'default', $force = false) { if (empty ($group)) $group = 'default'; - $group = $this->maybe_localize_group( $group ); if (!$force && false === $this->get($id, $group, false)) return false; @@ -286,26 +290,26 @@ class WP_Object_Cache { /** * Retrieves the cache contents, if it exists * - * The contents will be first attempted to be retrieved by searching - * by the ID in the cache group. If the cache is hit (success) then - * the contents are returned. + * The contents will be first attempted to be retrieved by searching by the + * ID in the cache group. If the cache is hit (success) then the contents + * are returned. * - * On failure, the $non_existant_objects property is checked and if - * the cache group and ID exist in there the cache misses will not be - * incremented. If not in the nonexistant objects property, then the - * cache misses will be incremented and the cache group and ID will - * be added to the nonexistant objects. + * On failure, the $non_existant_objects property is checked and if the + * cache group and ID exist in there the cache misses will not be + * incremented. If not in the nonexistant objects property, then the cache + * misses will be incremented and the cache group and ID will be added to + * the nonexistant objects. * * @since 2.0 * * @param int|string $id What the contents in the cache are called * @param string $group Where the cache contents are grouped - * @return bool|mixed False on failure to retrieve contents or the cache contents on success + * @return bool|mixed False on failure to retrieve contents or the cache + * contents on success */ function get($id, $group = 'default') { if (empty ($group)) $group = 'default'; - $group = $this->maybe_localize_group( $group ); if (isset ($this->cache[$group][$id])) { $this->cache_hits += 1; @@ -345,15 +349,14 @@ class WP_Object_Cache { /** * Sets the data contents into the cache * - * The cache contents is grouped by the $group parameter followed - * by the $id. This allows for duplicate ids in unique groups. - * Therefore, naming of the group should be used with care and - * should follow normal function naming guidelines outside of - * core WordPress usage. + * The cache contents is grouped by the $group parameter followed by the + * $id. This allows for duplicate ids in unique groups. Therefore, naming of + * the group should be used with care and should follow normal function + * naming guidelines outside of core WordPress usage. * - * The $expire parameter is not used, because the cache will - * automatically expire for each time a page is accessed and PHP - * finishes. The method is more for cache plugins which use files. + * The $expire parameter is not used, because the cache will automatically + * expire for each time a page is accessed and PHP finishes. The method is + * more for cache plugins which use files. * * @since 2.0 * @@ -366,7 +369,6 @@ class WP_Object_Cache { function set($id, $data, $group = 'default', $expire = '') { if (empty ($group)) $group = 'default'; - $group = $this->maybe_localize_group( $group ); if (NULL === $data) $data = ''; @@ -382,8 +384,8 @@ class WP_Object_Cache { /** * Echos the stats of the caching. * - * Gives the cache hits, and cache misses. Also prints every cached - * group, key and the data. + * Gives the cache hits, and cache misses. Also prints every cached group, + * key and the data. * * @since 2.0 */ @@ -421,7 +423,11 @@ class WP_Object_Cache { * @return null|WP_Object_Cache If cache is disabled, returns null. */ function __construct() { - register_shutdown_function(array(&$this, "__destruct")); /** @todo This should be moved to the PHP4 style constructor, PHP5 already calls __destruct() */ + /** + * @todo This should be moved to the PHP4 style constructor, PHP5 + * already calls __destruct() + */ + register_shutdown_function(array(&$this, "__destruct")); } /** diff --git a/wp-includes/canonical.php b/wp-includes/canonical.php index 5ad4457..4c58027 100644 --- a/wp-includes/canonical.php +++ b/wp-includes/canonical.php @@ -2,7 +2,8 @@ /** * Canonical API to handle WordPress Redirecting * - * Based on "Permalink Redirect" from Scott Yang and "Enforce www. Preference" by Mark Jaquith + * Based on "Permalink Redirect" from Scott Yang and "Enforce www. Preference" + * by Mark Jaquith * * @author Scott Yang * @author Mark Jaquith @@ -11,31 +12,34 @@ */ /** - * redirect_canonical() - Redirects incoming links to the proper URL based on the site url + * Redirects incoming links to the proper URL based on the site url * - * Search engines consider www.somedomain.com and somedomain.com to be two different URLs - * when they both go to the same location. This SEO enhancement prevents penality for - * duplicate content by redirecting all incoming links to one or the other. + * Search engines consider www.somedomain.com and somedomain.com to be two + * different URLs when they both go to the same location. This SEO enhancement + * prevents penality for duplicate content by redirecting all incoming links to + * one or the other. * - * Prevents redirection for feeds, trackbacks, searches, comment popup, and admin URLs. - * Does not redirect on IIS, page/post previews, and on form data. + * Prevents redirection for feeds, trackbacks, searches, comment popup, and + * admin URLs. Does not redirect on IIS, page/post previews, and on form data. * - * Will also attempt to find the correct link when a user enters a URL that does not exist - * based on exact WordPress query. Will instead try to parse the URL or query in an attempt - * to figure the correct page to go to. + * Will also attempt to find the correct link when a user enters a URL that does + * not exist based on exact WordPress query. Will instead try to parse the URL + * or query in an attempt to figure the correct page to go to. * * @since 2.3 * @uses $wp_rewrite * @uses $is_IIS * - * @param string $requested_url Optional. The URL that was requested, used to figure if redirect is needed. + * @param string $requested_url Optional. The URL that was requested, used to + * figure if redirect is needed. * @param bool $do_redirect Optional. Redirect to the new URL. - * @return null|false|string Null, if redirect not needed. False, if redirect not needed or the string of the URL + * @return null|false|string Null, if redirect not needed. False, if redirect + * not needed or the string of the URL */ function redirect_canonical($requested_url=null, $do_redirect=true) { global $wp_rewrite, $is_IIS; - if ( is_feed() || is_trackback() || is_search() || is_comments_popup() || is_admin() || $is_IIS || ( isset($_POST) && count($_POST) ) || is_preview() ) + if ( is_feed() || is_trackback() || is_search() || is_comments_popup() || is_admin() || $is_IIS || ( isset($_POST) && count($_POST) ) || is_preview() || is_robots() ) return; if ( !$requested_url ) { @@ -137,7 +141,8 @@ function redirect_canonical($requested_url=null, $do_redirect=true) { // www.example.com vs example.com $user_home = @parse_url(get_option('home')); - $redirect['host'] = $user_home['host']; + if ( isset($user_home['host']) ) + $redirect['host'] = $user_home['host']; // Handle ports if ( isset($user_home['port']) ) @@ -210,12 +215,13 @@ function redirect_canonical($requested_url=null, $do_redirect=true) { } /** - * redirect_guess_404_permalink() - Tries to guess correct post based on query vars + * Attempts to guess correct post based on query vars * * @since 2.3 * @uses $wpdb * - * @return bool|string Returns False, if it can't find post, returns correct location on success. + * @return bool|string Returns False, if it can't find post, returns correct + * location on success. */ function redirect_guess_404_permalink() { global $wpdb; diff --git a/wp-includes/capabilities.php b/wp-includes/capabilities.php index 85eaa77..875173d 100644 --- a/wp-includes/capabilities.php +++ b/wp-includes/capabilities.php @@ -34,7 +34,7 @@ class WP_Roles { } } - function add_role($role, $display_name, $capabilities = '') { + function add_role($role, $display_name, $capabilities = array()) { if ( isset($this->roles[$role]) ) return; @@ -465,7 +465,7 @@ function get_role($role) { return $wp_roles->get_role($role); } -function add_role($role, $display_name, $capabilities = '') { +function add_role($role, $display_name, $capabilities = array()) { global $wp_roles; if ( ! isset($wp_roles) ) diff --git a/wp-includes/category-template.php b/wp-includes/category-template.php index ba24302..1217276 100644 --- a/wp-includes/category-template.php +++ b/wp-includes/category-template.php @@ -185,9 +185,12 @@ function in_category( $category ) { // Check if the current post is in the given if ( empty($category) ) return false; - $cat_ID = get_cat_ID($category); - if ( $cat_ID ) - $category = $cat_ID; + // If category is not an int, check to see if it's a name + if ( ! is_int($category) ) { + $cat_ID = get_cat_ID($category); + if ( $cat_ID ) + $category = $cat_ID; + } $categories = get_object_term_cache($post->ID, 'category'); if ( false === $categories ) @@ -272,7 +275,7 @@ function wp_list_categories($args = '') { 'style' => 'list', 'show_count' => 0, 'hide_empty' => 1, 'use_desc_for_title' => 1, 'child_of' => 0, 'feed' => '', 'feed_type' => '', - 'feed_image' => '', 'exclude' => '', + 'feed_image' => '', 'exclude' => '', 'current_category' => 0, 'hierarchical' => true, 'title_li' => __('Categories'), 'echo' => 1, 'depth' => 0 ); @@ -309,7 +312,7 @@ function wp_list_categories($args = '') { else $output .= '' . $show_option_all . ''; - if ( is_category() ) + if ( empty( $r['current_category'] ) && is_category() ) $r['current_category'] = $wp_query->get_queried_object_id(); if ( $hierarchical ) diff --git a/wp-includes/class.wp-dependencies.php b/wp-includes/class.wp-dependencies.php new file mode 100644 index 0000000..1f7bb8d --- /dev/null +++ b/wp-includes/class.wp-dependencies.php @@ -0,0 +1,193 @@ +queue : (array) $handles; + $this->all_deps( $handles ); + + foreach( $this->to_do as $handle ) { + if ( !in_array($handle, $this->done) && isset($this->registered[$handle]) ) { + if ( $this->registered[$handle]->src ) { // Else it defines a group. + $this->do_item( $handle ); + } + $this->done[] = $handle; + } + } + + $this->to_do = array(); + return $this->done; + } + + function do_item( $handle ) { + return isset($this->registered[$handle]); + } + + /** + * Determines dependencies + * + * Recursively builds array of items to process taking dependencies into account. Does NOT catch infinite loops. + * + + * @param mixed handles Accepts (string) dep name or (array of strings) dep names + * @param bool recursion Used internally when function calls itself + */ + function all_deps( $handles, $recursion = false ) { + if ( !$handles = (array) $handles ) + return false; + + foreach ( $handles as $handle ) { + $handle = explode('?', $handle); + if ( isset($handle[1]) ) + $this->args[$handle[0]] = $handle[1]; + $handle = $handle[0]; + + if ( isset($this->to_do[$handle]) ) // Already grobbed it and its deps + continue; + + $keep_going = true; + if ( !isset($this->registered[$handle]) ) + $keep_going = false; // Script doesn't exist + elseif ( $this->registered[$handle]->deps && array_diff($this->registered[$handle]->deps, array_keys($this->registered)) ) + $keep_going = false; // Script requires deps which don't exist (not a necessary check. efficiency?) + elseif ( $this->registered[$handle]->deps && !$this->all_deps( $this->registered[$handle]->deps, true ) ) + $keep_going = false; // Script requires deps which don't exist + + if ( !$keep_going ) { // Either script or its deps don't exist. + if ( $recursion ) + return false; // Abort this branch. + else + continue; // We're at the top level. Move on to the next one. + } + + $this->to_do[$handle] = true; + } + + if ( !$recursion ) // at the end + $this->to_do = array_keys( $this->to_do ); + return true; + } + + /** + * Adds item + * + * Adds the item only if no item of that name already exists + * + * @param string handle Script name + * @param string src Script url + * @param array deps (optional) Array of script names on which this script depends + * @param string ver (optional) Script version (used for cache busting) + * @return array Hierarchical array of dependencies + */ + function add( $handle, $src, $deps = array(), $ver = false, $args = null ) { + if ( isset($this->registered[$handle]) ) + return false; + $this->registered[$handle] = new _WP_Dependency( $handle, $src, $deps, $ver, $args ); + return true; + } + + /** + * Adds extra data + * + * Adds data only if script has already been added + * + * @param string handle Script name + * @param string data_name Name of object in which to store extra data + * @param array data Array of extra data + * @return bool success + */ + function add_data( $handle, $data_name, $data ) { + if ( !isset($this->registered[$handle]) ) + return false; + return $this->registered[$handle]->add_data( $data_name, $data ); + } + + function remove( $handles ) { + foreach ( (array) $handles as $handle ) + unset($this->registered[$handle]); + } + + function enqueue( $handles ) { + foreach ( (array) $handles as $handle ) { + $handle = explode('?', $handle); + if ( !in_array($handle[0], $this->queue) && isset($this->registered[$handle[0]]) ) { + $this->queue[] = $handle[0]; + if ( isset($handle[1]) ) + $this->args[$handle[0]] = $handle[1]; + } + } + } + + function dequeue( $handles ) { + foreach ( (array) $handles as $handle ) + unset( $this->queue[$handle] ); + } + + function query( $handle, $list = 'registered' ) { // registered, queue, done, to_do + switch ( $list ) : + case 'registered': + case 'scripts': // back compat + if ( isset($this->registered[$handle]) ) + return $this->registered[$handle]; + break; + case 'to_print': // back compat + case 'printed': // back compat + if ( 'to_print' == $list ) + $list = 'to_do'; + else + $list = 'printed'; + default: + if ( in_array($handle, $this->$list) ) + return true; + break; + endswitch; + return false; + } + +} + +class _WP_Dependency { + var $handle; + var $src; + var $deps = array(); + var $ver = false; + var $args = null; + + var $extra = array(); + + function _WP_Dependency() { + @list($this->handle, $this->src, $this->deps, $this->ver, $this->args) = func_get_args(); + if ( !is_array($this->deps) ) + $this->deps = array(); + if ( !$this->ver ) + $this->ver = false; + } + + function add_data( $name, $data ) { + if ( !is_scalar($name) ) + return false; + $this->extra[$name] = $data; + return true; + } +} diff --git a/wp-includes/class.wp-scripts.php b/wp-includes/class.wp-scripts.php new file mode 100644 index 0000000..d829c8e --- /dev/null +++ b/wp-includes/class.wp-scripts.php @@ -0,0 +1,89 @@ +do_items( $handles ); + } + + function print_scripts_l10n( $handle ) { + if ( empty($this->registered[$handle]->extra['l10n']) || empty($this->registered[$handle]->extra['l10n'][0]) || !is_array($this->registered[$handle]->extra['l10n'][1]) ) + return false; + + $object_name = $this->registered[$handle]->extra['l10n'][0]; + + echo "\n"; + + return true; + } + + function do_item( $handle ) { + if ( !parent::do_item($handle) ) + return false; + + $ver = $this->registered[$handle]->ver ? $this->registered[$handle]->ver : $this->default_version; + if ( isset($this->args[$handle]) ) + $ver .= '&' . $this->args[$handle]; + + $src = $this->registered[$handle]->src; + if ( !preg_match('|^https?://|', $src) ) { + $src = $this->base_url . $src; + } + + $src = add_query_arg('ver', $ver, $src); + $src = clean_url(apply_filters( 'script_loader_src', $src, $handle )); + + $this->print_scripts_l10n( $handle ); + + echo "\n"; + + return true; + } + + /** + * Localizes a script + * + * Localizes only if script has already been added + * + * @param string handle Script name + * @param string object_name Name of JS object to hold l10n info + * @param array l10n Array of JS var name => localized string + * @return bool Successful localization + */ + function localize( $handle, $object_name, $l10n ) { + if ( !$object_name || !$l10n ) + return false; + return $this->add_data( $handle, 'l10n', array( $object_name, $l10n ) ); + } + + function all_deps( $handles, $recursion = false ) { + $r = parent::all_deps( $handles, $recursion ); + if ( !$recursion ) + $this->to_do = apply_filters( 'print_scripts_array', $this->to_do ); + return $r; + } +} diff --git a/wp-includes/class.wp-styles.php b/wp-includes/class.wp-styles.php new file mode 100644 index 0000000..f6a6d79 --- /dev/null +++ b/wp-includes/class.wp-styles.php @@ -0,0 +1,71 @@ +registered[$handle]->ver ? $this->registered[$handle]->ver : $this->default_version; + if ( isset($this->args[$handle]) ) + $ver .= '&' . $this->args[$handle]; + + if ( isset($this->registered[$handle]->args) ) + $media = attribute_escape( $this->registered[$handle]->args ); + else + $media = 'all'; + + $href = $this->_css_href( $this->registered[$handle]->src, $ver, $handle ); + + $end_cond = ''; + if ( isset($this->registered[$handle]->extra['conditional']) && $this->registered[$handle]->extra['conditional'] ) { + echo "\n"; + } + + echo apply_filters( 'style_loader_tag', "\n", $handle ); + if ( 'rtl' === $this->text_direction && isset($this->registered[$handle]->extra['rtl']) && $this->registered[$handle]->extra['rtl'] ) { + if ( is_bool( $this->registered[$handle]->extra['rtl'] ) ) + $rtl_href = str_replace( '.css', '-rtl.css', $href ); + else + $rtl_href = $this->_css_href( $this->registered[$handle]->extra['rtl'], $ver, "$handle-rtl" ); + + echo apply_filters( 'style_loader_tag', "\n", $handle ); + } + + echo $end_cond; + + // Could do something with $this->registered[$handle]->extra here to print out extra CSS rules +// echo "\n"; + + return true; + } + + function all_deps( $handles, $recursion = false ) { + $r = parent::all_deps( $handles, $recursion ); + if ( !$recursion ) + $this->to_do = apply_filters( 'print_styles_array', $this->to_do ); + return $r; + } + + function _css_href( $src, $ver, $handle ) { + if ( !preg_match('|^https?://|', $src) ) { + $src = $this->base_url . $src; + } + + $src = add_query_arg('ver', $ver, $src); + $src = apply_filters( 'style_loader_src', $src, $handle ); + return clean_url( $src ); + } + +} diff --git a/wp-includes/classes.php b/wp-includes/classes.php index 0d866fa..a454bef 100644 --- a/wp-includes/classes.php +++ b/wp-includes/classes.php @@ -26,6 +26,7 @@ class WP { global $wp_rewrite; $this->query_vars = array(); + $taxonomy_query_vars = array(); if ( is_array($extra_query_vars) ) $this->extra_query_vars = & $extra_query_vars; @@ -140,6 +141,10 @@ class WP { $this->public_query_vars = apply_filters('query_vars', $this->public_query_vars); + foreach ( $GLOBALS['wp_taxonomies'] as $taxonomy => $t ) + if ( isset($t->query_var) ) + $taxonomy_query_vars[$t->query_var] = $taxonomy; + for ($i=0; $ipublic_query_vars); $i += 1) { $wpvar = $this->public_query_vars[$i]; if (isset($this->extra_query_vars[$wpvar])) @@ -153,8 +158,13 @@ class WP { elseif (!empty($perma_query_vars[$wpvar])) $this->query_vars[$wpvar] = $perma_query_vars[$wpvar]; - if ( !empty( $this->query_vars[$wpvar] ) ) + if ( !empty( $this->query_vars[$wpvar] ) ) { $this->query_vars[$wpvar] = (string) $this->query_vars[$wpvar]; + if ( in_array( $wpvar, $taxonomy_query_vars ) ) { + $this->query_vars['taxonomy'] = $taxonomy_query_vars[$wpvar]; + $this->query_vars['term'] = $this->query_vars[$wpvar]; + } + } } foreach ($this->private_query_vars as $var) { diff --git a/wp-includes/comment-template.php b/wp-includes/comment-template.php index 1354ca4..6e605a7 100644 --- a/wp-includes/comment-template.php +++ b/wp-includes/comment-template.php @@ -389,7 +389,7 @@ function comments_number( $zero = false, $one = false, $more = false, $deprecate $number = get_comments_number($id); if ( $number > 1 ) - $output = str_replace('%', $number, ( false === $more ) ? __('% Comments') : $more); + $output = str_replace('%', number_format_i18n($number), ( false === $more ) ? __('% Comments') : $more); elseif ( $number == 0 ) $output = ( false === $zero ) ? __('No Comments') : $zero; else // must be one @@ -665,7 +665,7 @@ function comments_template( $file = '/comments.php' ) { if ( file_exists( $include ) ) require( $include ); else - require( ABSPATH . 'wp-content/themes/default/comments.php'); + require( WP_CONTENT_DIR . '/themes/default/comments.php'); } /** diff --git a/wp-includes/comment.php b/wp-includes/comment.php index 57af654..944fe00 100644 --- a/wp-includes/comment.php +++ b/wp-includes/comment.php @@ -241,7 +241,7 @@ function get_comment_count( $post_id = 0 ) { $where = ''; if ( $post_id > 0 ) { - $where = "WHERE comment_post_ID = {$post_id}"; + $where = $wpdb->prepare("WHERE comment_post_ID = %d", $post_id); } $totals = (array) $wpdb->get_results(" @@ -344,7 +344,7 @@ function wp_allow_comment($commentdata) { $post_author = $wpdb->get_var($wpdb->prepare("SELECT post_author FROM $wpdb->posts WHERE ID = %d LIMIT 1", $comment_post_ID)); } - if ( $userdata && ( $user_id == $post_author || $user->has_cap('level_9') ) ) { + if ( $userdata && ( $user_id == $post_author || $user->has_cap('moderate_comments') ) ) { // The author and the admins get respect. $approved = 1; } else { @@ -379,7 +379,7 @@ function check_comment_flood_db( $ip, $email, $date ) { global $wpdb; if ( current_user_can( 'manage_options' ) ) return; // don't throttle admins - if ( $lasttime = $wpdb->get_var("SELECT comment_date_gmt FROM $wpdb->comments WHERE comment_author_IP = '$ip' OR comment_author_email = '$email' ORDER BY comment_date DESC LIMIT 1") ) { + if ( $lasttime = $wpdb->get_var( $wpdb->prepare("SELECT comment_date_gmt FROM $wpdb->comments WHERE comment_author_IP = %s OR comment_author_email = %s ORDER BY comment_date DESC LIMIT 1", $ip, $email) ) ) { $time_lastcomment = mysql2date('U', $lasttime); $time_newcomment = mysql2date('U', $date); $flood_die = apply_filters('comment_flood_filter', false, $time_lastcomment, $time_newcomment); @@ -448,29 +448,38 @@ function wp_blacklist_check($author, $email, $url, $comment, $user_ip, $user_age return false; } -function wp_count_comments() { +function wp_count_comments( $post_id = 0 ) { global $wpdb; - $count = wp_cache_get('comments', 'counts'); + $post_id = (int) $post_id; + + $count = wp_cache_get("comments-{$post_id}", 'counts'); if ( false !== $count ) return $count; - $count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} GROUP BY comment_approved", ARRAY_A ); + $where = ''; + if( $post_id > 0 ) + $where = $wpdb->prepare( "WHERE comment_post_ID = %d", $post_id ); + + $count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} {$where} GROUP BY comment_approved", ARRAY_A ); + $total = 0; $stats = array( ); $approved = array('0' => 'moderated', '1' => 'approved', 'spam' => 'spam'); foreach( (array) $count as $row_num => $row ) { + $total += $row['num_comments']; $stats[$approved[$row['comment_approved']]] = $row['num_comments']; } + $stats['total_comments'] = $total; foreach ( $approved as $key ) { if ( empty($stats[$key]) ) $stats[$key] = 0; } $stats = (object) $stats; - wp_cache_set('comments', $stats, 'counts'); + wp_cache_set("comments-{$post_id}", $stats, 'counts'); return $stats; } @@ -495,7 +504,7 @@ function wp_delete_comment($comment_id) { $comment = get_comment($comment_id); - if ( ! $wpdb->query("DELETE FROM $wpdb->comments WHERE comment_ID='$comment_id' LIMIT 1") ) + if ( ! $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->comments WHERE comment_ID = %d LIMIT 1", $comment_id) ) ) return false; $post_id = $comment->comment_post_ID; @@ -578,7 +587,7 @@ function wp_get_current_commenter() { */ function wp_insert_comment($commentdata) { global $wpdb; - extract($commentdata, EXTR_SKIP); + extract(stripslashes_deep($commentdata), EXTR_SKIP); if ( ! isset($comment_author_IP) ) $comment_author_IP = ''; @@ -593,11 +602,10 @@ function wp_insert_comment($commentdata) { if ( ! isset($user_id) ) $user_id = 0; - $result = $wpdb->query("INSERT INTO $wpdb->comments + $result = $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->comments (comment_post_ID, comment_author, comment_author_email, comment_author_url, comment_author_IP, comment_date, comment_date_gmt, comment_content, comment_approved, comment_agent, comment_type, comment_parent, user_id) - VALUES - ('$comment_post_ID', '$comment_author', '$comment_author_email', '$comment_author_url', '$comment_author_IP', '$comment_date', '$comment_date_gmt', '$comment_content', '$comment_approved', '$comment_agent', '$comment_type', '$comment_parent', '$user_id') - "); + VALUES (%d, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %d, %d)", + $comment_post_ID, $comment_author, $comment_author_email, $comment_author_url, $comment_author_IP, $comment_date, $comment_date_gmt, $comment_content, $comment_approved, $comment_agent, $comment_type, $comment_parent, $user_id) ); $id = (int) $wpdb->insert_id; @@ -722,18 +730,17 @@ function wp_set_comment_status($comment_id, $comment_status) { switch ( $comment_status ) { case 'hold': - $query = "UPDATE $wpdb->comments SET comment_approved='0' WHERE comment_ID='$comment_id' LIMIT 1"; + $query = $wpdb->prepare("UPDATE $wpdb->comments SET comment_approved='0' WHERE comment_ID = %d LIMIT 1", $comment_id); break; case 'approve': - $query = "UPDATE $wpdb->comments SET comment_approved='1' WHERE comment_ID='$comment_id' LIMIT 1"; + $query = $wpdb->prepare("UPDATE $wpdb->comments SET comment_approved='1' WHERE comment_ID = %d LIMIT 1", $comment_id); if ( get_option('comments_notify') ) { $comment = get_comment($comment_id); wp_notify_postauthor($comment_id, $comment->comment_type); } - break; case 'spam': - $query = "UPDATE $wpdb->comments SET comment_approved='spam' WHERE comment_ID='$comment_id' LIMIT 1"; + $query = $wpdb->prepare("UPDATE $wpdb->comments SET comment_approved='spam' WHERE comment_ID = %d LIMIT 1", $comment_id); break; case 'delete': return wp_delete_comment($comment_id); @@ -781,22 +788,29 @@ function wp_update_comment($commentarr) { $commentarr = wp_filter_comment( $commentarr ); // Now extract the merged array. - extract($commentarr, EXTR_SKIP); + extract(stripslashes_deep($commentarr), EXTR_SKIP); $comment_content = apply_filters('comment_save_pre', $comment_content); $comment_date_gmt = get_gmt_from_date($comment_date); - $wpdb->query( - "UPDATE $wpdb->comments SET - comment_content = '$comment_content', - comment_author = '$comment_author', - comment_author_email = '$comment_author_email', - comment_approved = '$comment_approved', - comment_author_url = '$comment_author_url', - comment_date = '$comment_date', - comment_date_gmt = '$comment_date_gmt' - WHERE comment_ID = $comment_ID" ); + $wpdb->query( $wpdb->prepare("UPDATE $wpdb->comments SET + comment_content = %s, + comment_author = %s, + comment_author_email = %s, + comment_approved = %s, + comment_author_url = %s, + comment_date = %s, + comment_date_gmt = %s + WHERE comment_ID = %d", + $comment_content, + $comment_author, + $comment_author_email, + $comment_approved, + $comment_author_url, + $comment_date, + $comment_date_gmt, + $comment_ID) ); $rval = $wpdb->rows_affected; @@ -892,8 +906,8 @@ function wp_update_comment_count_now($post_id) { return false; $old = (int) $post->comment_count; - $new = (int) $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = '$post_id' AND comment_approved = '1'"); - $wpdb->query("UPDATE $wpdb->posts SET comment_count = '$new' WHERE ID = '$post_id'"); + $new = (int) $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1'", $post_id) ); + $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET comment_count = %d WHERE ID = %d", $new, $post_id) ); if ( 'page' == $post->post_type ) clean_page_cache( $post_id ); @@ -987,18 +1001,22 @@ function discover_pingback_server_uri($url, $timeout_bytes = 2048) { $pingback_server_url_len = $pingback_href_end - $pingback_href_start; $pingback_server_url = substr($contents, $pingback_href_start, $pingback_server_url_len); // We may find rel="pingback" but an incomplete pingback URL - if ( $pingback_server_url_len > 0 ) // We got it! + if ( $pingback_server_url_len > 0 ) { // We got it! + fclose($fp); return $pingback_server_url; + } } $byte_count += strlen($line); if ( $byte_count > $timeout_bytes ) { // It's no use going further, there probably isn't any pingback // server to find in this file. (Prevents loading large files.) + fclose($fp); return false; } } // We didn't find anything. + fclose($fp); return false; } @@ -1021,7 +1039,7 @@ function do_all_pings() { // Do Enclosures while ($enclosure = $wpdb->get_row("SELECT * FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_encloseme' LIMIT 1")) { - $wpdb->query("DELETE FROM {$wpdb->postmeta} WHERE post_id = {$enclosure->ID} AND meta_key = '_encloseme';"); + $wpdb->query( $wpdb->prepare("DELETE FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key = '_encloseme';", $enclosure->ID) ); do_enclose($enclosure->post_content, $enclosure->ID); } @@ -1048,11 +1066,11 @@ function do_all_pings() { function do_trackbacks($post_id) { global $wpdb; - $post = $wpdb->get_row("SELECT * FROM $wpdb->posts WHERE ID = $post_id"); + $post = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->posts WHERE ID = %d", $post_id) ); $to_ping = get_to_ping($post_id); $pinged = get_pung($post_id); if ( empty($to_ping) ) { - $wpdb->query("UPDATE $wpdb->posts SET to_ping = '' WHERE ID = '$post_id'"); + $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = '' WHERE ID = %d", $post_id) ); return; } @@ -1073,7 +1091,7 @@ function do_trackbacks($post_id) { trackback($tb_ping, $post_title, $excerpt, $post_id); $pinged[] = $tb_ping; } else { - $wpdb->query("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, '$tb_ping', '')) WHERE ID = '$post_id'"); + $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, '$tb_ping', '')) WHERE ID = %d", $post_id) ); } } } @@ -1238,8 +1256,8 @@ function trackback($trackback_url, $title, $excerpt, $ID) { @fclose($fs); $tb_url = addslashes( $tb_url ); - $wpdb->query("UPDATE $wpdb->posts SET pinged = CONCAT(pinged, '\n', '$tb_url') WHERE ID = '$ID'"); - return $wpdb->query("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, '$tb_url', '')) WHERE ID = '$ID'"); + $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET pinged = CONCAT(pinged, '\n', '$tb_url') WHERE ID = %d", $ID) ); + return $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, '$tb_url', '')) WHERE ID = %d", $ID) ); } /** diff --git a/wp-includes/default-filters.php b/wp-includes/default-filters.php index 857de94..bba6608 100644 --- a/wp-includes/default-filters.php +++ b/wp-includes/default-filters.php @@ -175,9 +175,11 @@ add_action('do_pings', 'do_all_pings', 10, 1); add_action('do_robots', 'do_robots'); add_action('sanitize_comment_cookies', 'sanitize_comment_cookies'); add_action('admin_print_scripts', 'wp_print_scripts', 20); +add_action('admin_print_styles', 'wp_print_styles', 20); add_action('init', 'smilies_init', 5); add_action( 'plugins_loaded', 'wp_maybe_load_widgets', 0 ); add_action( 'shutdown', 'wp_ob_end_flush_all', 1); +add_action( 'pre_post_update', 'wp_save_post_revision' ); add_action('publish_post', '_publish_post_hook', 5, 1); add_action('future_post', '_future_post_hook', 5, 2); add_action('future_page', '_future_post_hook', 5, 2); diff --git a/wp-includes/formatting.php b/wp-includes/formatting.php index 052445d..c49b663 100644 --- a/wp-includes/formatting.php +++ b/wp-includes/formatting.php @@ -839,6 +839,9 @@ function human_time_diff( $from, $to = '' ) { function wp_trim_excerpt($text) { // Fakes an excerpt if needed if ( '' == $text ) { $text = get_the_content(''); + + $text = strip_shortcodes( $text ); + $text = apply_filters('the_content', $text); $text = str_replace(']]>', ']]>', $text); $text = strip_tags($text); @@ -1129,6 +1132,10 @@ function wp_richedit_pre($text) { $output = str_replace('<', '&lt;', $output); $output = str_replace('>', '&gt;', $output); + // These should be entities too + $output = str_replace('<', '<', $output); + $output = str_replace('>', '>', $output); + return apply_filters('richedit_pre', $output); } diff --git a/wp-includes/functions.php b/wp-includes/functions.php index 89b4333..a4a5914 100644 --- a/wp-includes/functions.php +++ b/wp-includes/functions.php @@ -1071,7 +1071,7 @@ function wp_upload_dir( $time = NULL ) { $siteurl = get_option( 'siteurl' ); $upload_path = get_option( 'upload_path' ); if ( trim($upload_path) === '' ) - $upload_path = 'wp-content/uploads'; + $upload_path = WP_CONTENT_DIR . '/uploads'; $dir = $upload_path; // $dir is absolute, $path is (maybe) relative to ABSPATH @@ -1556,8 +1556,8 @@ function wp_ob_end_flush_all() { */ function require_wp_db() { global $wpdb; - if ( file_exists( ABSPATH . 'wp-content/db.php' ) ) - require_once( ABSPATH . 'wp-content/db.php' ); + if ( file_exists( WP_CONTENT_DIR . '/db.php' ) ) + require_once( WP_CONTENT_DIR . '/db.php' ); else require_once( ABSPATH . WPINC . '/wp-db.php' ); } @@ -1566,8 +1566,8 @@ function dead_db() { global $wpdb; // Load custom DB error template, if present. - if ( file_exists( ABSPATH . 'wp-content/db-error.php' ) ) { - require_once( ABSPATH . 'wp-content/db-error.php' ); + if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) { + require_once( WP_CONTENT_DIR . '/db-error.php' ); die(); } @@ -1668,9 +1668,9 @@ function _deprecated_function($function, $version, $replacement=null) { // Allow plugin to filter the output error trigger if( defined('WP_DEBUG') && ( true === WP_DEBUG ) && apply_filters( 'deprecated_function_trigger_error', true )) { if( !is_null($replacement) ) - trigger_error( printf( __("%1$s is deprecated since version %2$s! Use %3$s instead."), $function, $version, $replacement ) ); + trigger_error( sprintf( __('%1$s is deprecated since version %2$s! Use %3$s instead.'), $function, $version, $replacement ) ); else - trigger_error( printf( __("%1$s is deprecated since version %2$s with no alternative available."), $function, $version ) ); + trigger_error( sprintf( __('%1$s is deprecated since version %2$s with no alternative available.'), $function, $version ) ); } } @@ -1703,9 +1703,9 @@ function _deprecated_file($file, $version, $replacement=null) { // Allow plugin to filter the output error trigger if( defined('WP_DEBUG') && ( true === WP_DEBUG ) && apply_filters( 'deprecated_file_trigger_error', true )) { if( !is_null($replacement) ) - trigger_error( printf( __("%1$s is deprecated since version %2$s! Use %3$s instead."), $file, $version, $replacement ) ); + trigger_error( sprintf( __('%1$s is deprecated since version %2$s! Use %3$s instead.'), $file, $version, $replacement ) ); else - trigger_error( printf( __("%1$s is deprecated since version %2$s with no alternative available."), $file, $version ) ); + trigger_error( sprintf( __('%1$s is deprecated since version %2$s with no alternative available.'), $file, $version ) ); } } @@ -1763,4 +1763,32 @@ function validate_file( $file, $allowed_files = '' ) { return 0; } +function is_ssl() { + return ( 'on' == strtolower($_SERVER['HTTPS']) ) ? true : false; +} + +function force_ssl_login($force = '') { + static $forced; + + if ( '' != $force ) { + $old_forcded = $forced; + $forced = $force; + return $old_forced; + } + + return $forced; +} + +function force_ssl_admin($force = '') { + static $forced; + + if ( '' != $force ) { + $old_forcded = $forced; + $forced = $force; + return $old_forced; + } + + return $forced; +} + ?> diff --git a/wp-includes/functions.wp-scripts.php b/wp-includes/functions.wp-scripts.php new file mode 100644 index 0000000..87995a4 --- /dev/null +++ b/wp-includes/functions.wp-scripts.php @@ -0,0 +1,77 @@ +do_items( $handles ); +} + +function wp_register_script( $handle, $src, $deps = array(), $ver = false ) { + global $wp_scripts; + if ( !is_a($wp_scripts, 'WP_Scripts') ) + $wp_scripts = new WP_Scripts(); + + $wp_scripts->add( $handle, $src, $deps, $ver ); +} + +/** + * Localizes a script + * + * Localizes only if script has already been added + * + * @see WP_Script::localize() + */ +function wp_localize_script( $handle, $object_name, $l10n ) { + global $wp_scripts; + if ( !is_a($wp_scripts, 'WP_Scripts') ) + return false; + + return $wp_scripts->localize( $handle, $object_name, $l10n ); +} + +function wp_deregister_script( $handle ) { + global $wp_scripts; + if ( !is_a($wp_scripts, 'WP_Scripts') ) + $wp_scripts = new WP_Scripts(); + + $wp_scripts->remove( $handle ); +} + +/** + * Equeues script + * + * Registers the script if src provided (does NOT overwrite) and enqueues. + * + * @see WP_Script::add(), WP_Script::enqueue() +*/ +function wp_enqueue_script( $handle, $src = false, $deps = array(), $ver = false ) { + global $wp_scripts; + if ( !is_a($wp_scripts, 'WP_Scripts') ) + $wp_scripts = new WP_Scripts(); + + if ( $src ) { + $_handle = explode('?', $handle); + $wp_scripts->add( $_handle[0], $src, $deps, $ver ); + } + $wp_scripts->enqueue( $handle ); +} diff --git a/wp-includes/functions.wp-styles.php b/wp-includes/functions.wp-styles.php new file mode 100644 index 0000000..8a38282 --- /dev/null +++ b/wp-includes/functions.wp-styles.php @@ -0,0 +1,45 @@ +do_items( $handles ); +} + +function wp_register_style( $handle, $src, $deps = array(), $ver = false, $media = false ) { + global $wp_styles; + if ( !is_a($wp_styles, 'WP_Styles') ) + $wp_styles = new WP_Styles(); + + $wp_styles->add( $handle, $src, $deps, $ver, $media ); +} + +function wp_deregister_style( $handle ) { + global $wp_styles; + if ( !is_a($wp_styles, 'WP_Styles') ) + $wp_styles = new WP_Styles(); + + $wp_styles->remove( $handle ); +} + +function wp_enqueue_style( $handle, $src = false, $deps = array(), $ver = false, $media = false ) { + global $wp_styles; + if ( !is_a($wp_styles, 'WP_Styles') ) + $wp_styles = new WP_Styles(); + + if ( $src ) { + $_handle = explode('?', $handle); + $wp_styles->add( $_handle[0], $src, $deps, $ver, $media ); + } + $wp_styles->enqueue( $handle ); +} diff --git a/wp-includes/general-template.php b/wp-includes/general-template.php index 4a7f1bb..afc6c56 100644 --- a/wp-includes/general-template.php +++ b/wp-includes/general-template.php @@ -7,7 +7,7 @@ function get_header() { if ( file_exists( TEMPLATEPATH . '/header.php') ) load_template( TEMPLATEPATH . '/header.php'); else - load_template( ABSPATH . 'wp-content/themes/default/header.php'); + load_template( WP_CONTENT_DIR . '/themes/default/header.php'); } @@ -16,7 +16,7 @@ function get_footer() { if ( file_exists( TEMPLATEPATH . '/footer.php') ) load_template( TEMPLATEPATH . '/footer.php'); else - load_template( ABSPATH . 'wp-content/themes/default/footer.php'); + load_template( WP_CONTENT_DIR . '/themes/default/footer.php'); } @@ -27,15 +27,15 @@ function get_sidebar( $name = null ) { elseif ( file_exists( TEMPLATEPATH . '/sidebar.php') ) load_template( TEMPLATEPATH . '/sidebar.php'); else - load_template( ABSPATH . 'wp-content/themes/default/sidebar.php'); + load_template( WP_CONTENT_DIR . '/themes/default/sidebar.php'); } function wp_loginout() { if ( ! is_user_logged_in() ) - $link = '' . __('Log in') . ''; + $link = '' . __('Log in') . ''; else - $link = '' . __('Log out') . ''; + $link = '' . __('Log out') . ''; echo apply_filters('loginout', $link); } @@ -45,11 +45,11 @@ function wp_register( $before = '
  • ', $after = '
  • ' ) { if ( ! is_user_logged_in() ) { if ( get_option('users_can_register') ) - $link = $before . '' . __('Register') . '' . $after; + $link = $before . '' . __('Register') . '' . $after; else $link = ''; } else { - $link = $before . '' . __('Site Admin') . '' . $after; + $link = $before . '' . __('Site Admin') . '' . $after; } echo apply_filters('register', $link); @@ -233,6 +233,19 @@ function wp_title($sep = '»', $display = true, $seplocation = '') { $title = strip_tags( apply_filters( 'single_post_title', $post->post_title ) ); } + // If there's a taxonomy + if ( is_tax() ) { + $taxonomy = get_query_var( 'taxonomy' ); + $tax = get_taxonomy( $taxonomy ); + $tax = $tax->label; + $term = $wp_query->get_queried_object(); + $term = $term->name; + if ( 'right' == $seplocation ) + $title = "$term $sep $tax"; + else + $title = "$tax $sep $term"; + } + $prefix = ''; if ( !empty($title) ) $prefix = " $sep "; @@ -814,7 +827,7 @@ function get_post_time( $d = 'U', $gmt = false ) { // returns timestamp $time = $post->post_date; $time = mysql2date($d, $time); - return apply_filters('get_the_time', $time, $d, $gmt); + return apply_filters('get_post_time', $time, $d, $gmt); } @@ -1115,34 +1128,76 @@ function wp_admin_css_color($key, $name, $url, $colors = array()) { $_wp_admin_css_colors[$key] = (object) array('name' => $name, 'url' => $url, 'colors' => $colors); } +/** + * wp_admin_css_uri() - Outputs the URL of a WordPress admin CSS file + * + * @see WP_Styles::_css_href and its style_loader_src filter. + * + * @param string $file file relative to wp-admin/ without its ".css" extension. + */ + function wp_admin_css_uri( $file = 'wp-admin' ) { if ( defined('WP_INSTALLING') ) { $_file = "./$file.css"; } else { - if ( 'css/colors' == $file || 'css/colors-rtl' == $file ) { - global $_wp_admin_css_colors; - $color = get_user_option('admin_color'); - if ( empty($color) || !isset($_wp_admin_css_colors[$color]) ) - $color = 'fresh'; - $color = $_wp_admin_css_colors[$color]; - $_file = $color->url; - $_file = ('css/colors-rtl' == $file) ? str_replace('.css','-rtl.css',$_file) : $_file; - } else { - $_file = get_option( 'siteurl' ) . "/wp-admin/$file.css"; - } + $_file = admin_url("$file.css"); } $_file = add_query_arg( 'version', get_bloginfo( 'version' ), $_file ); return apply_filters( 'wp_admin_css_uri', $_file, $file ); } -function wp_admin_css( $file = 'wp-admin' ) { +/** + * wp_admin_css() - Enqueues or directly prints a stylesheet link to the specified CSS file. + * + * "Intelligently" decides to enqueue or to print the CSS file. + * If the wp_print_styles action has *not* yet been called, the CSS file will be enqueued. + * If the wp_print_styles action *has* been called, the CSS link will be printed. + * Printing may be forced by passing TRUE as the $force_echo (second) parameter. + * + * For backward compatibility with WordPress 2.3 calling method: + * If the $file (first) parameter does not correspond to a registered CSS file, we assume $file is a + * file relative to wp-admin/ without its ".css" extension. A stylesheet link to that generated URL is printed. + * + * @package WordPress + * @since 2.3 + * + * @uses $wp_styles WordPress Styles Object + * + * @param string $file Style handle name or file name (without ".css" extension) relative to wp-admin/ + * @param bool $force_echo Optional. Force the stylesheet link to be printed rather than enqueued. + */ + +function wp_admin_css( $file = 'wp-admin', $force_echo = false ) { + global $wp_styles; + if ( !is_a($wp_styles, 'WP_Styles') ) + $wp_styles = new WP_Styles(); + + // For backward compatibility + $handle = 0 === strpos( $file, 'css/' ) ? substr( $file, 4 ) : $file; - echo apply_filters( 'wp_admin_css', "\n", $file ); - if ( 'rtl' == get_bloginfo( 'text_direction' ) ) { - $rtl = ( 'wp-admin' == $file ) ? 'rtl' : "$file-rtl"; - echo apply_filters( 'wp_admin_css', "\n", $rtl ); + if ( $wp_styles->query( $handle ) ) { + if ( $force_echo || did_action( 'wp_print_styles' ) ) // we already printed the style queue. Print this one immediately + wp_print_styles( $handle ); + else // Add to style queue + wp_enqueue_style( $handle ); + return; } + + echo apply_filters( 'wp_admin_css', "\n", $file ); + if ( 'rtl' == get_bloginfo( 'text_direction' ) ) + echo apply_filters( 'wp_admin_css', "\n", "$file-rtl" ); +} + +/** + * Enqueues the default ThickBox js and css. + * If any of the settings need to be changed, this can be done with another js file + * similar to media-upload.js and theme-preview.js. That file should require array('thickbox') + * to ensure it is loaded after. + */ +function add_thickbox() { + wp_enqueue_script( 'thickbox' ); + wp_enqueue_style( 'thickbox' ); } /** diff --git a/wp-includes/js/autosave.js b/wp-includes/js/autosave.js index b0a2fa5..2f77920 100644 --- a/wp-includes/js/autosave.js +++ b/wp-includes/js/autosave.js @@ -154,8 +154,13 @@ var autosave = function() { doAutoSave = false; /* Gotta do this up here so we can check the length when tinyMCE is in use */ - if ( rich ) { tinyMCE.triggerSave(); } - + if ( rich ) { + var ed = tinyMCE.activeEditor; + if ( 'mce_fullscreen' == ed.id ) + tinyMCE.get('content').setContent(ed.getContent({format : 'raw'}), {format : 'raw'}); + tinyMCE.get('content').save(); + } + post_data["content"] = jQuery("#content").val(); if ( jQuery('#post_name').val() ) post_data["post_name"] = jQuery('#post_name').val(); @@ -168,8 +173,6 @@ var autosave = function() { autosave_disable_buttons(); var origStatus = jQuery('#original_post_status').val(); - if ( 'draft' != origStatus ) // autosave currently only turned on for drafts - doAutoSave = false; autosaveLast = jQuery("#title").val()+jQuery("#content").val(); goodcats = ([]); @@ -182,9 +185,9 @@ var autosave = function() { post_data["comment_status"] = 'open'; if ( jQuery("#ping_status").attr("checked") ) post_data["ping_status"] = 'open'; - if ( jQuery("#excerpt") ) + if ( jQuery("#excerpt").size() ) post_data["excerpt"] = jQuery("#excerpt").val(); - if ( jQuery("#post_author") ) + if ( jQuery("#post_author").size() ) post_data["post_author"] = jQuery("#post_author").val(); // Don't run while the TinyMCE spellcheck is on. Why? Who knows. diff --git a/wp-includes/js/jquery/jquery.form.js b/wp-includes/js/jquery/jquery.form.js index 9b10cab..2ee5c96 100644 --- a/wp-includes/js/jquery/jquery.form.js +++ b/wp-includes/js/jquery/jquery.form.js @@ -1,872 +1,872 @@ -/* - * jQuery Form Plugin - * version: 2.02 (12/16/2007) - * @requires jQuery v1.1 or later - * - * Examples at: http://malsup.com/jquery/form/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - * Revision: $Id$ - */ - (function($) { -/** - * ajaxSubmit() provides a mechanism for submitting an HTML form using AJAX. - * - * ajaxSubmit accepts a single argument which can be either a success callback function - * or an options Object. If a function is provided it will be invoked upon successful - * completion of the submit and will be passed the response from the server. - * If an options Object is provided, the following attributes are supported: - * - * target: Identifies the element(s) in the page to be updated with the server response. - * This value may be specified as a jQuery selection string, a jQuery object, - * or a DOM element. - * default value: null - * - * url: URL to which the form data will be submitted. - * default value: value of form's 'action' attribute - * - * type: The method in which the form data should be submitted, 'GET' or 'POST'. - * default value: value of form's 'method' attribute (or 'GET' if none found) - * - * data: Additional data to add to the request, specified as key/value pairs (see $.ajax). - * - * beforeSubmit: Callback method to be invoked before the form is submitted. - * default value: null - * - * success: Callback method to be invoked after the form has been successfully submitted - * and the response has been returned from the server - * default value: null - * - * dataType: Expected dataType of the response. One of: null, 'xml', 'script', or 'json' - * default value: null - * - * semantic: Boolean flag indicating whether data must be submitted in semantic order (slower). - * default value: false - * - * resetForm: Boolean flag indicating whether the form should be reset if the submit is successful - * - * clearForm: Boolean flag indicating whether the form should be cleared if the submit is successful - * - * - * The 'beforeSubmit' callback can be provided as a hook for running pre-submit logic or for - * validating the form data. If the 'beforeSubmit' callback returns false then the form will - * not be submitted. The 'beforeSubmit' callback is invoked with three arguments: the form data - * in array format, the jQuery object, and the options object passed into ajaxSubmit. - * The form data array takes the following form: - * - * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ] - * - * If a 'success' callback method is provided it is invoked after the response has been returned - * from the server. It is passed the responseText or responseXML value (depending on dataType). - * See jQuery.ajax for further details. - * - * - * The dataType option provides a means for specifying how the server response should be handled. - * This maps directly to the jQuery.httpData method. The following values are supported: - * - * 'xml': if dataType == 'xml' the server response is treated as XML and the 'success' - * callback method, if specified, will be passed the responseXML value - * 'json': if dataType == 'json' the server response will be evaluted and passed to - * the 'success' callback, if specified - * 'script': if dataType == 'script' the server response is evaluated in the global context - * - * - * Note that it does not make sense to use both the 'target' and 'dataType' options. If both - * are provided the target will be ignored. - * - * The semantic argument can be used to force form serialization in semantic order. - * This is normally true anyway, unless the form contains input elements of type='image'. - * If your form must be submitted with name/value pairs in semantic order and your form - * contains an input of type='image" then pass true for this arg, otherwise pass false - * (or nothing) to avoid the overhead for this logic. - * - * - * When used on its own, ajaxSubmit() is typically bound to a form's submit event like this: - * - * $("#form-id").submit(function() { - * $(this).ajaxSubmit(options); - * return false; // cancel conventional submit - * }); - * - * When using ajaxForm(), however, this is done for you. - * - * @example - * $('#myForm').ajaxSubmit(function(data) { - * alert('Form submit succeeded! Server returned: ' + data); - * }); - * @desc Submit form and alert server response - * - * - * @example - * var options = { - * target: '#myTargetDiv' - * }; - * $('#myForm').ajaxSubmit(options); - * @desc Submit form and update page element with server response - * - * - * @example - * var options = { - * success: function(responseText) { - * alert(responseText); - * } - * }; - * $('#myForm').ajaxSubmit(options); - * @desc Submit form and alert the server response - * - * - * @example - * var options = { - * beforeSubmit: function(formArray, jqForm) { - * if (formArray.length == 0) { - * alert('Please enter data.'); - * return false; - * } - * } - * }; - * $('#myForm').ajaxSubmit(options); - * @desc Pre-submit validation which aborts the submit operation if form data is empty - * - * - * @example - * var options = { - * url: myJsonUrl.php, - * dataType: 'json', - * success: function(data) { - * // 'data' is an object representing the the evaluated json data - * } - * }; - * $('#myForm').ajaxSubmit(options); - * @desc json data returned and evaluated - * - * - * @example - * var options = { - * url: myXmlUrl.php, - * dataType: 'xml', - * success: function(responseXML) { - * // responseXML is XML document object - * var data = $('myElement', responseXML).text(); - * } - * }; - * $('#myForm').ajaxSubmit(options); - * @desc XML data returned from server - * - * - * @example - * var options = { - * resetForm: true - * }; - * $('#myForm').ajaxSubmit(options); - * @desc submit form and reset it if successful - * - * @example - * $('#myForm).submit(function() { - * $(this).ajaxSubmit(); - * return false; - * }); - * @desc Bind form's submit event to use ajaxSubmit - * - * - * @name ajaxSubmit - * @type jQuery - * @param options object literal containing options which control the form submission process - * @cat Plugins/Form - * @return jQuery - */ -$.fn.ajaxSubmit = function(options) { - if (typeof options == 'function') - options = { success: options }; - - options = $.extend({ - url: this.attr('action') || window.location.toString(), - type: this.attr('method') || 'GET' - }, options || {}); - - // hook for manipulating the form data before it is extracted; - // convenient for use with rich editors like tinyMCE or FCKEditor - var veto = {}; - $.event.trigger('form.pre.serialize', [this, options, veto]); - if (veto.veto) return this; - - var a = this.formToArray(options.semantic); - if (options.data) { - for (var n in options.data) - a.push( { name: n, value: options.data[n] } ); - } - - // give pre-submit callback an opportunity to abort the submit - if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) return this; - - // fire vetoable 'validate' event - $.event.trigger('form.submit.validate', [a, this, options, veto]); - if (veto.veto) return this; - - var q = $.param(a);//.replace(/%20/g,'+'); - - if (options.type.toUpperCase() == 'GET') { - options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; - options.data = null; // data is null for 'get' - } - else - options.data = q; // data is the query string for 'post' - - var $form = this, callbacks = []; - if (options.resetForm) callbacks.push(function() { $form.resetForm(); }); - if (options.clearForm) callbacks.push(function() { $form.clearForm(); }); - - // perform a load on the target only if dataType is not provided - if (!options.dataType && options.target) { - var oldSuccess = options.success || function(){}; - callbacks.push(function(data) { - if (this.evalScripts) - $(options.target).attr("innerHTML", data).evalScripts().each(oldSuccess, arguments); - else // jQuery v1.1.4 - $(options.target).html(data).each(oldSuccess, arguments); - }); - } - else if (options.success) - callbacks.push(options.success); - - options.success = function(data, status) { - for (var i=0, max=callbacks.length; i < max; i++) - callbacks[i](data, status, $form); - }; - - // are there files to upload? - var files = $('input:file', this).fieldValue(); - var found = false; - for (var j=0; j < files.length; j++) - if (files[j]) - found = true; - - // options.iframe allows user to force iframe mode - if (options.iframe || found) { - // hack to fix Safari hang (thanks to Tim Molendijk for this) - // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d - if ($.browser.safari && options.closeKeepAlive) - $.get(options.closeKeepAlive, fileUpload); - else - fileUpload(); - } - else - $.ajax(options); - - // fire 'notify' event - $.event.trigger('form.submit.notify', [this, options]); - return this; - - - // private function for handling file uploads (hat tip to YAHOO!) - function fileUpload() { - var form = $form[0]; - var opts = $.extend({}, $.ajaxSettings, options); - - var id = 'jqFormIO' + $.fn.ajaxSubmit.counter++; - var $io = $('