From ab98458399c28f04614de0e8474c1864ef4cb495 Mon Sep 17 00:00:00 2001
From: Evan Prodromou
Date: Mon, 20 Jun 2011 01:11:08 -0400
Subject: [PATCH 01/12] push regex pattern for UUID to that class
---
lib/uuid.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/uuid.php b/lib/uuid.php
index 93153504f2..386d0e2121 100644
--- a/lib/uuid.php
+++ b/lib/uuid.php
@@ -47,6 +47,7 @@ if (!defined('STATUSNET')) {
class UUID
{
+ const REGEX = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}';
protected $str = null;
/**
From cd7d0eae4a8d46bb194dc49c7b4241527c032823 Mon Sep 17 00:00:00 2001
From: Evan Prodromou
Date: Mon, 20 Jun 2011 01:11:35 -0400
Subject: [PATCH 02/12] First coded version of blog plugin
A basic blog plugin. Allows posting open-ended HTML with a title. Not yet
tested (even run).
---
plugins/Blog/BlogEntry.php | 233 +++++++++++++++++++++++++++++
plugins/Blog/BlogPlugin.php | 210 ++++++++++++++++++++++++++
plugins/Blog/blogentryform.php | 133 ++++++++++++++++
plugins/Blog/blogentrylistitem.php | 79 ++++++++++
plugins/Blog/newblogentry.php | 138 +++++++++++++++++
plugins/Blog/showblogentry.php | 86 +++++++++++
6 files changed, 879 insertions(+)
create mode 100644 plugins/Blog/BlogEntry.php
create mode 100644 plugins/Blog/BlogPlugin.php
create mode 100644 plugins/Blog/blogentryform.php
create mode 100644 plugins/Blog/blogentrylistitem.php
create mode 100644 plugins/Blog/newblogentry.php
create mode 100644 plugins/Blog/showblogentry.php
diff --git a/plugins/Blog/BlogEntry.php b/plugins/Blog/BlogEntry.php
new file mode 100644
index 0000000000..54940e06e5
--- /dev/null
+++ b/plugins/Blog/BlogEntry.php
@@ -0,0 +1,233 @@
+.
+ *
+ * @category Blog
+ * @package StatusNet
+ * @author Evan Prodromou
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ // This check helps protect against security problems;
+ // your code file can't be executed directly from the web.
+ exit(1);
+}
+
+/**
+ * Data structure for blog entries
+ *
+ * @category Blog
+ * @package StatusNet
+ * @author Evan Prodromou
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+class BlogEntry extends Managed_DataObject
+{
+ public $__table = 'blog_entry';
+
+ public $id; // UUID
+ public $profile_id; // int
+ public $title; // varchar(255)
+ public $summary; // text
+ public $content; // text
+ public $uri; // text
+ public $url; // text
+ public $created; // datetime
+ public $modified; // datetime
+
+ const TYPE = 'http://activitystrea.ms/schema/1.0/blog-entry';
+
+ static function staticGet($k, $v=null)
+ {
+ return Managed_DataObject::staticGet('blog_entry', $k, $v);
+ }
+
+ static function schemaDef()
+ {
+ return array(
+ 'description' => 'lite blog entry',
+ 'fields' => array(
+ 'id' => array('type' => 'char',
+ 'length' => 36,
+ 'not null' => true,
+ 'description' => 'Unique ID (UUID)'),
+ 'profile_id' => array('type' => 'int',
+ 'not null' => true,
+ 'description' => 'Author profile ID'),
+ 'title' => array('type' => 'varchar',
+ 'length' => 255,
+ 'description' => 'title of the entry'),
+ 'summary' => array('type' => 'text',
+ 'description' => 'initial summary'),
+ 'content' => array('type' => 'text',
+ 'description' => 'HTML content of the entry'),
+ 'uri' => array('type' => 'varchar',
+ 'length' => 255,
+ 'description' => 'URI (probably http://) for this entry'),
+ 'url' => array('type' => 'varchar',
+ 'length' => 255,
+ 'description' => 'URL (probably http://) for this entry'),
+ 'created' => array('type' => 'datetime',
+ 'not null' => true,
+ 'description' => 'date this record was created'),
+ 'modified' => array('type' => 'datetime',
+ 'not null' => true,
+ 'description' => 'date this record was created'),
+ ),
+ 'primary key' => array('id'),
+ 'foreign keys' => array(
+ 'blog_entry_profile_id_fkey' => array('profile', array('profile_id' => 'id')),
+ ),
+ 'indexes' => array(
+ 'blog_entry_created_idx' => array('created'),
+ 'blog_entry_uri_idx' => array('uri'),
+ ),
+ );
+ }
+
+ static function saveNew($profile, $title, $content, $options=null)
+ {
+ if (is_null($options)) {
+ $options = array();
+ }
+
+ $be = new BlogEntry();
+ $be->id = (string) new UUID();
+ $be->profile_id = $profile->id;
+ $be->title = htmlspecialchars($title);
+ $be->content = $content;
+
+ if (array_key_exists('summary', $options)) {
+ $be->summary = $options['summary'];
+ } else {
+ $be->summary = self::summarize($content);
+ }
+
+ $url = common_local_url('showblogentry', array('id' => $be->id));
+
+ if (!array_key_exists('uri', $options)) {
+ $options['uri'] = $url;
+ }
+
+ $be->uri = $options['uri'];
+
+ if (!array_key_exists('url', $options)) {
+ $options['url'] = $url;
+ }
+
+ $be->url = $options['url'];
+
+ if (!array_key_exists('created', $options)) {
+ $be->created = common_sql_now();
+ }
+
+ $be->created = $options['created'];
+
+ $be->modified = common_sql_now();
+
+ $be->insert();
+
+ // Use user's preferences for short URLs, if possible
+
+ try {
+ $user = $profile->getUser();
+ $shortUrl = File_redirection::makeShort($url,
+ empty($user) ? null : $user);
+ } catch (Exception $e) {
+ // Don't let this stop us.
+ $shortUrl = $url;
+ }
+
+ // XXX: this might be too long.
+
+ $options['rendered'] = $be->summary . ' ' .
+ XMLStringer::estring('a', array('href' => $shortUrl,
+ 'class' => 'blog-entry'),
+ _('More...'));
+
+ $summaryText = html_entity_decode(strip_tags($summary), ENT_QUOTES, 'UTF-8');
+
+ if (Notice::contentTooLong($summaryText)) {
+ $summaryText = substr($summaryText, 0, Notice::maxContent() - mb_strlen($shortUrl) - 2) .
+ '… ' . $shortUrl;
+ }
+
+ $content = $summaryText;
+
+ // Override this no matter what.
+
+ $options['object_type'] = self::TYPE;
+
+ $source = array_key_exists('source', $options) ?
+ $options['source'] : 'web';
+
+ Notice::saveNew($profile->id, $content, $source, $options);
+ }
+
+ /**
+ * Summarize the contents of a blog post
+ *
+ * We take the first div or paragraph of the blog post if there's a hit;
+ * Otherwise we take the whole thing.
+ *
+ * @param string $html HTML of full content
+ */
+ static function summarize($html)
+ {
+ if (preg_match('#.*?
#s', $html, $matches)) {
+ return $matches[0];
+ } else if (preg_match('#.*?
#s', $html, $matches)) {
+ return $matches[0];
+ } else {
+ return $html;
+ }
+ }
+
+ static function fromNotice($notice)
+ {
+ return BlogEntry::staticGet('uri', $notice->uri);
+ }
+
+ function getNotice()
+ {
+ return Notice::staticGet('uri', $this->uri);
+ }
+
+ function asActivityObject()
+ {
+ $obj = new ActivityObject();
+
+ $obj->id = $this->uri;
+ $obj->type = self::TYPE;
+ $obj->title = $this->title;
+ $obj->summary = $this->summary;
+ $obj->content = $this->content;
+ $obj->link = $this->url;
+
+ return $obj;
+ }
+}
diff --git a/plugins/Blog/BlogPlugin.php b/plugins/Blog/BlogPlugin.php
new file mode 100644
index 0000000000..7f8e8fd1d0
--- /dev/null
+++ b/plugins/Blog/BlogPlugin.php
@@ -0,0 +1,210 @@
+.
+ *
+ * @category Blog
+ * @package StatusNet
+ * @author Evan Prodromou
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ // This check helps protect against security problems;
+ // your code file can't be executed directly from the web.
+ exit(1);
+}
+
+/**
+ * Blog plugin
+ *
+ * Many social systems have a way to write and share long-form texts with
+ * your network. This microapp plugin lets users post blog entries.
+ *
+ * @category Blog
+ * @package StatusNet
+ * @author Evan Prodromou
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+class BlogPlugin extends MicroAppPlugin
+{
+ /**
+ * Database schema setup
+ *
+ * @see Schema
+ * @see ColumnDef
+ *
+ * @return boolean hook value; true means continue processing, false means stop.
+ */
+ function onCheckSchema()
+ {
+ $schema = Schema::get();
+
+ $schema->ensureTable('blog_entry', BlogEntry::schemaDef());
+
+ return true;
+ }
+
+ /**
+ * Load related modules when needed
+ *
+ * @param string $cls Name of the class to be loaded
+ *
+ * @return boolean hook value; true means continue processing, false means stop.
+ */
+ function onAutoload($cls)
+ {
+ $dir = dirname(__FILE__);
+
+ switch ($cls)
+ {
+ case 'NewblogentryAction':
+ case 'ShowblogentryAction':
+ include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
+ return false;
+ case 'BlogEntryForm':
+ case 'BlogEntryListItem':
+ include_once $dir . '/'.strtolower($cls).'.php';
+ return false;
+ case 'BlogEntry':
+ include_once $dir . '/'.$cls.'.php';
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ /**
+ * Map URLs to actions
+ *
+ * @param Net_URL_Mapper $m path-to-action mapper
+ *
+ * @return boolean hook value; true means continue processing, false means stop.
+ */
+ function onRouterInitialized($m)
+ {
+ $m->connect('blog/new',
+ array('action' => 'newblogentry'));
+ $m->connect('blog/:id',
+ array('action' => 'showblogentry'),
+ array('id' => UUID::REGEX));
+ return true;
+ }
+
+ function onPluginVersion(&$versions)
+ {
+ $versions[] = array('name' => 'Blog',
+ 'version' => STATUSNET_VERSION,
+ 'author' => 'Evan Prodromou',
+ 'homepage' => 'http://status.net/wiki/Plugin:Blog',
+ 'rawdescription' =>
+ _m('Let users write and share long-form texts.'));
+ return true;
+ }
+
+ function appTitle()
+ {
+ return _m('Blog');
+ }
+
+ function tag()
+ {
+ return 'blog';
+ }
+
+ function types()
+ {
+ return array(BlogEntry::TYPE);
+ }
+
+ function saveNoticeFromActivity($activity, $actor, $options=array())
+ {
+ if (count($activity->objects) != 1) {
+ // TRANS: Exception thrown when there are too many activity objects.
+ throw new ClientException(_m('Too many activity objects.'));
+ }
+
+ $entryObj = $activity->objects[0];
+
+ if ($entryObj->type != BlogEntry::TYPE) {
+ // TRANS: Exception thrown when blog plugin comes across a non-event type object.
+ throw new ClientException(_m('Wrong type for object.'));
+ }
+
+ $notice = null;
+
+ switch ($activity->verb) {
+ case ActivityVerb::POST:
+ $notice = BlogEntry::saveNew($actor,
+ $entryObj->title,
+ $entryObj->content,
+ $options);
+ break;
+ default:
+ // TRANS: Exception thrown when blog plugin comes across a undefined verb.
+ throw new ClientException(_m('Unknown verb for blog entries.'));
+ }
+
+ return $notice;
+ }
+
+ function activityObjectFromNotice($notice)
+ {
+ $entry = BlogEntry::fromNotice($notice);
+
+ if (empty($entry)) {
+ throw new ClientException(sprintf(_('No blog entry for notice %s'),
+ $notice->id));
+ }
+
+ return $entry->asActivityObject();
+ }
+
+ function entryForm($out)
+ {
+ return new BlogEntryForm($out);
+ }
+
+ function deleteRelated($notice)
+ {
+ if ($notice->object_type == BlogEntry::TYPE) {
+ $entry = BlogEntry::fromNotice($notice);
+ if (exists($entry)) {
+ $entry->delete();
+ }
+ }
+ }
+
+ function adaptNoticeListItem($nli)
+ {
+ $notice = $nli->notice;
+
+ if ($notice->object_type == BlogEntry::TYPE) {
+ return new BlogEntryListItem($nli);
+ }
+
+ return null;
+ }
+}
diff --git a/plugins/Blog/blogentryform.php b/plugins/Blog/blogentryform.php
new file mode 100644
index 0000000000..b21e76a7e8
--- /dev/null
+++ b/plugins/Blog/blogentryform.php
@@ -0,0 +1,133 @@
+.
+ *
+ * @category Blog
+ * @package StatusNet
+ * @author Evan Prodromou
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ // This check helps protect against security problems;
+ // your code file can't be executed directly from the web.
+ exit(1);
+}
+
+/**
+ * Form for creating a blog entry
+ *
+ * @category Blog
+ * @package StatusNet
+ * @author Evan Prodromou
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+class BlogEntryForm extends Form
+{
+ /**
+ * ID of the form
+ *
+ * @return int ID of the form
+ */
+ function id()
+ {
+ return 'form_new_blog_entry';
+ }
+
+ /**
+ * class of the form
+ *
+ * @return string class of the form
+ */
+ function formClass()
+ {
+ return 'form_settings ajax-notice';
+ }
+
+ /**
+ * Action of the form
+ *
+ * @return string URL of the action
+ */
+ function action()
+ {
+ return common_local_url('newblogentry');
+ }
+
+ /**
+ * Data elements of the form
+ *
+ * @return void
+ */
+ function formData()
+ {
+ $this->out->elementStart('fieldset', array('id' => 'new_blog_entry_data'));
+ $this->out->elementStart('ul', 'form_data');
+
+ $this->li();
+ $this->out->input('blog-entry-title',
+ // TRANS: Field label on blog entry form.
+ _m('LABEL','Title'),
+ null,
+ // TRANS: Field title on blog entry form.
+ _m('Title of the blog entry.'),
+ 'title');
+ $this->unli();
+
+ $this->li();
+ $this->out->textarea('blog-entry-content',
+ // TRANS: Field label on event form.
+ _m('LABEL','Text'),
+ null,
+ // TRANS: Field title on event form.
+ _m('Text of the blog entry.'),
+ 'content');
+ $this->unli();
+
+ $this->out->elementEnd('ul');
+
+ $toWidget = new ToSelector($this->out,
+ common_current_user(),
+ null);
+ $toWidget->show();
+
+ $this->out->elementEnd('fieldset');
+ }
+
+ /**
+ * Action elements
+ *
+ * @return void
+ */
+ function formActions()
+ {
+ // TRANS: Button text to save an event..
+ $this->out->submit('blog-entry-submit',
+ _m('BUTTON', 'Save'),
+ 'submit',
+ 'submit');
+ }
+}
diff --git a/plugins/Blog/blogentrylistitem.php b/plugins/Blog/blogentrylistitem.php
new file mode 100644
index 0000000000..44775d8a3d
--- /dev/null
+++ b/plugins/Blog/blogentrylistitem.php
@@ -0,0 +1,79 @@
+.
+ *
+ * @category Blog
+ * @package StatusNet
+ * @author Evan Prodromou
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ // This check helps protect against security problems;
+ // your code file can't be executed directly from the web.
+ exit(1);
+}
+
+/**
+ * NoticeListItem adapter for blog entries
+ *
+ * @category General
+ * @package StatusNet
+ * @author Evan Prodromou
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+class BlogEntryListItem extends NoticeListItemAdapter
+{
+ function showNotice()
+ {
+ $this->out->elementStart('div', 'entry-title');
+ $this->showAuthor();
+ $this->showContent();
+ $this->out->elementEnd('div');
+ }
+
+ function showContent()
+ {
+ $notice = $this->nli->notice;
+ $out = $this->nli->out;
+
+ $entry = BlogEntry::fromNotice($notice);
+
+ if (empty($entry)) {
+ throw new Exception('BlogEntryListItem used for non-blog notice.');
+ }
+
+ $out->elementStart('h4', array('class' => 'blog-entry-title'));
+ $out->element('a', array('href' => $notice->bestUrl()), $entry->title);
+ $out->elementEnd('h4');
+
+ $out->element('div', 'blog-entry-summary', $entry->summary);
+
+ // XXX: hide content initially; click More... for full text.
+
+ $out->element('div', 'blog-entry-content', $entry->content);
+ }
+}
diff --git a/plugins/Blog/newblogentry.php b/plugins/Blog/newblogentry.php
new file mode 100644
index 0000000000..94988c5335
--- /dev/null
+++ b/plugins/Blog/newblogentry.php
@@ -0,0 +1,138 @@
+.
+ *
+ * @category Blog
+ * @package StatusNet
+ * @author Evan Prodromou
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ // This check helps protect against security problems;
+ // your code file can't be executed directly from the web.
+ exit(1);
+}
+
+/**
+ * Save a new blog entry
+ *
+ * @category Action
+ * @package StatusNet
+ * @author Evan Prodromou
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+class NewblogentryAction extends Action
+{
+ protected $user;
+ protected $title;
+ protected $content;
+
+ /**
+ * For initializing members of the class.
+ *
+ * @param array $argarray misc. arguments
+ *
+ * @return boolean true
+ */
+
+ function prepare($argarray)
+ {
+ parent::prepare($argarray);
+
+ if (!$this->isPost()) {
+ throw new ClientException(_('Must be a POST.'), 405);
+ }
+
+ $this->user = common_current_user();
+
+ if (empty($this->user)) {
+ // TRANS: Client exception thrown when trying to post a blog entry while not logged in.
+ throw new ClientException(_m('Must be logged in to post a blog entry.'),
+ 403);
+ }
+
+ $this->checkSessionToken();
+
+ $this->title = $this->trimmed('title');
+
+ if (empty($this->title)) {
+ // TRANS: Client exception thrown when trying to post a blog entry without providing a title.
+ throw new ClientException(_m('Title required.'));
+ }
+
+ $this->content = $this->trimmed('content');
+
+ if (empty($this->content)) {
+ // TRANS: Client exception thrown when trying to post a blog entry without providing content.
+ throw new ClientException(_m('Content required.'));
+ }
+
+ return true;
+ }
+
+ /**
+ * Handler method
+ *
+ * @param array $argarray is ignored since it's now passed in in prepare()
+ *
+ * @return void
+ */
+
+ function handle($argarray=null)
+ {
+ $options = array();
+
+ // Does the heavy-lifting for getting "To:" information
+
+ ToSelector::fillOptions($this, $options);
+
+ $options['source'] = 'web';
+
+ $profile = $this->user->getProfile();
+
+ $saved = BlogEntry::saveNew($profile,
+ $this->title,
+ $this->content,
+ $options);
+
+ if ($this->boolean('ajax')) {
+ header('Content-Type: text/xml; charset=utf-8');
+ $this->xw->startDocument('1.0', 'UTF-8');
+ $this->elementStart('html');
+ $this->elementStart('head');
+ // TRANS: Page title after sending a notice.
+ $this->element('title', null, _m('Blog entry saved'));
+ $this->elementEnd('head');
+ $this->elementStart('body');
+ $this->showNotice($saved);
+ $this->elementEnd('body');
+ $this->elementEnd('html');
+ } else {
+ common_redirect($saved->bestUrl(), 303);
+ }
+ }
+}
diff --git a/plugins/Blog/showblogentry.php b/plugins/Blog/showblogentry.php
new file mode 100644
index 0000000000..4ddf7963e0
--- /dev/null
+++ b/plugins/Blog/showblogentry.php
@@ -0,0 +1,86 @@
+.
+ *
+ * @category Blog
+ * @package StatusNet
+ * @author Evan Prodromou
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ // This check helps protect against security problems;
+ // your code file can't be executed directly from the web.
+ exit(1);
+}
+
+/**
+ * Show a blog entry
+ *
+ * @category Blog
+ * @package StatusNet
+ * @author Evan Prodromou
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+class ShowblogentryAction extends ShownoticeAction
+{
+ protected $id;
+ protected $entry;
+
+ function getNotice()
+ {
+ $this->id = $this->trimmed('id');
+
+ $this->entry = BlogEntry::staticGet('id', $this->id);
+
+ if (empty($this->entry)) {
+ // TRANS: Client exception thrown when referring to a non-existing blog entry.
+ throw new ClientException(_m('No such entry.'), 404);
+ }
+
+ $notice = $this->entry->getNotice();
+
+ if (empty($notice)) {
+ // TRANS: Client exception thrown when referring to a non-existing blog entry.
+ throw new ClientException(_m('No such entry.'), 404);
+ }
+
+ return $notice;
+ }
+
+ /**
+ * Title of the page
+ *
+ * Used by Action class for layout.
+ *
+ * @return string page tile
+ */
+ function title()
+ {
+ // XXX: check for double-encoding
+ return (empty($this->entry->title)) ? _m('Untitled') : $this->entry->title;
+ }
+}
From a1911dc2c1dd7cf5f3c7b3b0f95de85407ba276e Mon Sep 17 00:00:00 2001
From: Evan Prodromou
Date: Mon, 20 Jun 2011 10:14:24 -0400
Subject: [PATCH 03/12] correct staticGet() declaration
---
plugins/Blog/BlogEntry.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/Blog/BlogEntry.php b/plugins/Blog/BlogEntry.php
index 54940e06e5..32915dc9c7 100644
--- a/plugins/Blog/BlogEntry.php
+++ b/plugins/Blog/BlogEntry.php
@@ -61,7 +61,7 @@ class BlogEntry extends Managed_DataObject
const TYPE = 'http://activitystrea.ms/schema/1.0/blog-entry';
- static function staticGet($k, $v=null)
+ function staticGet($k, $v=null)
{
return Managed_DataObject::staticGet('blog_entry', $k, $v);
}
From 4c9ae4fae67f2ecf273d05a0cef029a235a8c51a Mon Sep 17 00:00:00 2001
From: Evan Prodromou
Date: Mon, 20 Jun 2011 10:14:37 -0400
Subject: [PATCH 04/12] get right output context for BlogEntryListItem
---
plugins/Blog/blogentrylistitem.php | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/plugins/Blog/blogentrylistitem.php b/plugins/Blog/blogentrylistitem.php
index 44775d8a3d..287339f8c2 100644
--- a/plugins/Blog/blogentrylistitem.php
+++ b/plugins/Blog/blogentrylistitem.php
@@ -49,10 +49,11 @@ class BlogEntryListItem extends NoticeListItemAdapter
{
function showNotice()
{
- $this->out->elementStart('div', 'entry-title');
+ $out = $this->nli->out;
+ $out->elementStart('div', 'entry-title');
$this->showAuthor();
$this->showContent();
- $this->out->elementEnd('div');
+ $out->elementEnd('div');
}
function showContent()
From d51abd8830543f5bb7c061d70cbdd51aadd95ab7 Mon Sep 17 00:00:00 2001
From: Evan Prodromou
Date: Mon, 20 Jun 2011 10:20:01 -0400
Subject: [PATCH 05/12] move class BlogEntry to Blog_entry for DB_DataObject
compliance
---
plugins/Blog/BlogPlugin.php | 18 +++++++++---------
plugins/Blog/{BlogEntry.php => Blog_entry.php} | 6 +++---
plugins/Blog/blogentrylistitem.php | 2 +-
plugins/Blog/newblogentry.php | 2 +-
plugins/Blog/showblogentry.php | 2 +-
5 files changed, 15 insertions(+), 15 deletions(-)
rename plugins/Blog/{BlogEntry.php => Blog_entry.php} (98%)
diff --git a/plugins/Blog/BlogPlugin.php b/plugins/Blog/BlogPlugin.php
index 7f8e8fd1d0..89619b5f54 100644
--- a/plugins/Blog/BlogPlugin.php
+++ b/plugins/Blog/BlogPlugin.php
@@ -62,7 +62,7 @@ class BlogPlugin extends MicroAppPlugin
{
$schema = Schema::get();
- $schema->ensureTable('blog_entry', BlogEntry::schemaDef());
+ $schema->ensureTable('blog_entry', Blog_entry::schemaDef());
return true;
}
@@ -88,7 +88,7 @@ class BlogPlugin extends MicroAppPlugin
case 'BlogEntryListItem':
include_once $dir . '/'.strtolower($cls).'.php';
return false;
- case 'BlogEntry':
+ case 'Blog_entry':
include_once $dir . '/'.$cls.'.php';
return false;
default:
@@ -136,7 +136,7 @@ class BlogPlugin extends MicroAppPlugin
function types()
{
- return array(BlogEntry::TYPE);
+ return array(Blog_entry::TYPE);
}
function saveNoticeFromActivity($activity, $actor, $options=array())
@@ -148,7 +148,7 @@ class BlogPlugin extends MicroAppPlugin
$entryObj = $activity->objects[0];
- if ($entryObj->type != BlogEntry::TYPE) {
+ if ($entryObj->type != Blog_entry::TYPE) {
// TRANS: Exception thrown when blog plugin comes across a non-event type object.
throw new ClientException(_m('Wrong type for object.'));
}
@@ -157,7 +157,7 @@ class BlogPlugin extends MicroAppPlugin
switch ($activity->verb) {
case ActivityVerb::POST:
- $notice = BlogEntry::saveNew($actor,
+ $notice = Blog_entry::saveNew($actor,
$entryObj->title,
$entryObj->content,
$options);
@@ -172,7 +172,7 @@ class BlogPlugin extends MicroAppPlugin
function activityObjectFromNotice($notice)
{
- $entry = BlogEntry::fromNotice($notice);
+ $entry = Blog_entry::fromNotice($notice);
if (empty($entry)) {
throw new ClientException(sprintf(_('No blog entry for notice %s'),
@@ -189,8 +189,8 @@ class BlogPlugin extends MicroAppPlugin
function deleteRelated($notice)
{
- if ($notice->object_type == BlogEntry::TYPE) {
- $entry = BlogEntry::fromNotice($notice);
+ if ($notice->object_type == Blog_entry::TYPE) {
+ $entry = Blog_entry::fromNotice($notice);
if (exists($entry)) {
$entry->delete();
}
@@ -201,7 +201,7 @@ class BlogPlugin extends MicroAppPlugin
{
$notice = $nli->notice;
- if ($notice->object_type == BlogEntry::TYPE) {
+ if ($notice->object_type == Blog_entry::TYPE) {
return new BlogEntryListItem($nli);
}
diff --git a/plugins/Blog/BlogEntry.php b/plugins/Blog/Blog_entry.php
similarity index 98%
rename from plugins/Blog/BlogEntry.php
rename to plugins/Blog/Blog_entry.php
index 32915dc9c7..34e4ea294e 100644
--- a/plugins/Blog/BlogEntry.php
+++ b/plugins/Blog/Blog_entry.php
@@ -45,7 +45,7 @@ if (!defined('STATUSNET')) {
* @link http://status.net/
*/
-class BlogEntry extends Managed_DataObject
+class Blog_entry extends Managed_DataObject
{
public $__table = 'blog_entry';
@@ -115,7 +115,7 @@ class BlogEntry extends Managed_DataObject
$options = array();
}
- $be = new BlogEntry();
+ $be = new Blog_entry();
$be->id = (string) new UUID();
$be->profile_id = $profile->id;
$be->title = htmlspecialchars($title);
@@ -209,7 +209,7 @@ class BlogEntry extends Managed_DataObject
static function fromNotice($notice)
{
- return BlogEntry::staticGet('uri', $notice->uri);
+ return Blog_entry::staticGet('uri', $notice->uri);
}
function getNotice()
diff --git a/plugins/Blog/blogentrylistitem.php b/plugins/Blog/blogentrylistitem.php
index 287339f8c2..97a06acfa7 100644
--- a/plugins/Blog/blogentrylistitem.php
+++ b/plugins/Blog/blogentrylistitem.php
@@ -61,7 +61,7 @@ class BlogEntryListItem extends NoticeListItemAdapter
$notice = $this->nli->notice;
$out = $this->nli->out;
- $entry = BlogEntry::fromNotice($notice);
+ $entry = Blog_entry::fromNotice($notice);
if (empty($entry)) {
throw new Exception('BlogEntryListItem used for non-blog notice.');
diff --git a/plugins/Blog/newblogentry.php b/plugins/Blog/newblogentry.php
index 94988c5335..c33c69d109 100644
--- a/plugins/Blog/newblogentry.php
+++ b/plugins/Blog/newblogentry.php
@@ -114,7 +114,7 @@ class NewblogentryAction extends Action
$profile = $this->user->getProfile();
- $saved = BlogEntry::saveNew($profile,
+ $saved = Blog_entry::saveNew($profile,
$this->title,
$this->content,
$options);
diff --git a/plugins/Blog/showblogentry.php b/plugins/Blog/showblogentry.php
index 4ddf7963e0..c5aa54a4c2 100644
--- a/plugins/Blog/showblogentry.php
+++ b/plugins/Blog/showblogentry.php
@@ -54,7 +54,7 @@ class ShowblogentryAction extends ShownoticeAction
{
$this->id = $this->trimmed('id');
- $this->entry = BlogEntry::staticGet('id', $this->id);
+ $this->entry = Blog_entry::staticGet('id', $this->id);
if (empty($this->entry)) {
// TRANS: Client exception thrown when referring to a non-existing blog entry.
From 3d8b776dc75eef86be72f648b23dda7c7a25f60c Mon Sep 17 00:00:00 2001
From: Evan Prodromou
Date: Mon, 20 Jun 2011 10:26:24 -0400
Subject: [PATCH 06/12] don't double-show summary and content
---
plugins/Blog/Blog_entry.php | 6 ++++++
plugins/Blog/blogentrylistitem.php | 11 ++++++-----
2 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/plugins/Blog/Blog_entry.php b/plugins/Blog/Blog_entry.php
index 34e4ea294e..0e4df28b82 100644
--- a/plugins/Blog/Blog_entry.php
+++ b/plugins/Blog/Blog_entry.php
@@ -127,6 +127,12 @@ class Blog_entry extends Managed_DataObject
$be->summary = self::summarize($content);
}
+ // Don't save an identical summary
+
+ if ($be->summary == $be->content) {
+ $be->summary = null;
+ }
+
$url = common_local_url('showblogentry', array('id' => $be->id));
if (!array_key_exists('uri', $options)) {
diff --git a/plugins/Blog/blogentrylistitem.php b/plugins/Blog/blogentrylistitem.php
index 97a06acfa7..ee937daa77 100644
--- a/plugins/Blog/blogentrylistitem.php
+++ b/plugins/Blog/blogentrylistitem.php
@@ -71,10 +71,11 @@ class BlogEntryListItem extends NoticeListItemAdapter
$out->element('a', array('href' => $notice->bestUrl()), $entry->title);
$out->elementEnd('h4');
- $out->element('div', 'blog-entry-summary', $entry->summary);
-
- // XXX: hide content initially; click More... for full text.
-
- $out->element('div', 'blog-entry-content', $entry->content);
+ if (!empty($entry->summary)) {
+ $out->element('div', 'blog-entry-summary', $entry->summary);
+ } else {
+ // XXX: hide content initially; click More... for full text.
+ $out->element('div', 'blog-entry-content', $entry->content);
+ }
}
}
From e5126ebb773a55bc8350d4b8c77464925119ee8c Mon Sep 17 00:00:00 2001
From: Evan Prodromou
Date: Mon, 20 Jun 2011 10:48:02 -0400
Subject: [PATCH 07/12] Fine-tuning Blog_entry class
Gave it a different object type (Article), fine-tuned the summary process, and
made sure to return the saved Notice in saveNew().
---
plugins/Blog/Blog_entry.php | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/plugins/Blog/Blog_entry.php b/plugins/Blog/Blog_entry.php
index 0e4df28b82..54bd445930 100644
--- a/plugins/Blog/Blog_entry.php
+++ b/plugins/Blog/Blog_entry.php
@@ -59,7 +59,7 @@ class Blog_entry extends Managed_DataObject
public $created; // datetime
public $modified; // datetime
- const TYPE = 'http://activitystrea.ms/schema/1.0/blog-entry';
+ const TYPE = ActivityObject::ARTICLE;
function staticGet($k, $v=null)
{
@@ -170,19 +170,25 @@ class Blog_entry extends Managed_DataObject
// XXX: this might be too long.
- $options['rendered'] = $be->summary . ' ' .
- XMLStringer::estring('a', array('href' => $shortUrl,
- 'class' => 'blog-entry'),
- _('More...'));
+ if (!empty($be->summary)) {
+ $options['rendered'] = $be->summary . ' ' .
+ XMLStringer::estring('a', array('href' => $url,
+ 'class' => 'blog-entry'),
+ _('More...'));
+ $content = html_entity_decode(strip_tags($text), ENT_QUOTES, 'UTF-8');
- $summaryText = html_entity_decode(strip_tags($summary), ENT_QUOTES, 'UTF-8');
-
- if (Notice::contentTooLong($summaryText)) {
- $summaryText = substr($summaryText, 0, Notice::maxContent() - mb_strlen($shortUrl) - 2) .
- '… ' . $shortUrl;
+ } else {
+ $options['rendered'] = $be->content . ' ' .
+ XMLStringer::estring('a', array('href' => $url,
+ 'class' => 'blog-entry'),
+ _('More...'));
}
- $content = $summaryText;
+
+ if (Notice::contentTooLong($content)) {
+ $content = substr($content, 0, Notice::maxContent() - mb_strlen($shortUrl) - 2) .
+ '… ' . $shortUrl;
+ }
// Override this no matter what.
@@ -191,7 +197,9 @@ class Blog_entry extends Managed_DataObject
$source = array_key_exists('source', $options) ?
$options['source'] : 'web';
- Notice::saveNew($profile->id, $content, $source, $options);
+ $saved = Notice::saveNew($profile->id, $content, $source, $options);
+
+ return $saved;
}
/**
From 06ac0f9e9ecfabc9a6d0836cb183c316bb0f2254 Mon Sep 17 00:00:00 2001
From: Evan Prodromou
Date: Mon, 20 Jun 2011 10:49:37 -0400
Subject: [PATCH 08/12] correctly return the HTML representation of a new blog
entry
---
plugins/Blog/newblogentry.php | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/plugins/Blog/newblogentry.php b/plugins/Blog/newblogentry.php
index c33c69d109..d6421abea2 100644
--- a/plugins/Blog/newblogentry.php
+++ b/plugins/Blog/newblogentry.php
@@ -128,7 +128,8 @@ class NewblogentryAction extends Action
$this->element('title', null, _m('Blog entry saved'));
$this->elementEnd('head');
$this->elementStart('body');
- $this->showNotice($saved);
+ $nli = new NoticeListItem($saved, $this);
+ $nli->show();
$this->elementEnd('body');
$this->elementEnd('html');
} else {
From 4c5d583403d4995c3dcd0eface125f3eaf7e5df8 Mon Sep 17 00:00:00 2001
From: Evan Prodromou
Date: Mon, 20 Jun 2011 11:01:50 -0400
Subject: [PATCH 09/12] better management of HTML input
---
plugins/Blog/Blog_entry.php | 27 ++++++++++++++++++---------
plugins/Blog/blogentrylistitem.php | 8 ++++++--
2 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/plugins/Blog/Blog_entry.php b/plugins/Blog/Blog_entry.php
index 54bd445930..72cee91a79 100644
--- a/plugins/Blog/Blog_entry.php
+++ b/plugins/Blog/Blog_entry.php
@@ -118,12 +118,13 @@ class Blog_entry extends Managed_DataObject
$be = new Blog_entry();
$be->id = (string) new UUID();
$be->profile_id = $profile->id;
- $be->title = htmlspecialchars($title);
- $be->content = $content;
+ $be->title = $title; // Note: not HTML-protected
+ $be->content = self::purify($content);
if (array_key_exists('summary', $options)) {
- $be->summary = $options['summary'];
+ $be->summary = self::purify($options['summary']);
} else {
+ // Already purified
$be->summary = self::summarize($content);
}
@@ -175,13 +176,10 @@ class Blog_entry extends Managed_DataObject
XMLStringer::estring('a', array('href' => $url,
'class' => 'blog-entry'),
_('More...'));
- $content = html_entity_decode(strip_tags($text), ENT_QUOTES, 'UTF-8');
-
+ $content = html_entity_decode(strip_tags($be->summary), ENT_QUOTES, 'UTF-8');
} else {
- $options['rendered'] = $be->content . ' ' .
- XMLStringer::estring('a', array('href' => $url,
- 'class' => 'blog-entry'),
- _('More...'));
+ $options['rendered'] = $be->content;
+ $content = html_entity_decode(strip_tags($be->content), ENT_QUOTES, 'UTF-8');
}
@@ -244,4 +242,15 @@ class Blog_entry extends Managed_DataObject
return $obj;
}
+
+ /**
+ * Clean up input HTML
+ */
+ static function purify($html)
+ {
+ require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
+ $config = array('safe' => 1,
+ 'deny_attribute' => 'id,style,on*');
+ return htmLawed($html, $config);
+ }
}
diff --git a/plugins/Blog/blogentrylistitem.php b/plugins/Blog/blogentrylistitem.php
index ee937daa77..374c456028 100644
--- a/plugins/Blog/blogentrylistitem.php
+++ b/plugins/Blog/blogentrylistitem.php
@@ -72,10 +72,14 @@ class BlogEntryListItem extends NoticeListItemAdapter
$out->elementEnd('h4');
if (!empty($entry->summary)) {
- $out->element('div', 'blog-entry-summary', $entry->summary);
+ $out->elementStart('div', 'blog-entry-summary');
+ $out->raw($entry->summary);
+ $out->elementEnd('div');
} else {
// XXX: hide content initially; click More... for full text.
- $out->element('div', 'blog-entry-content', $entry->content);
+ $out->elementStart('div', 'blog-entry-content');
+ $out->raw($entry->content);
+ $out->elementEnd('div');
}
}
}
From acd1c6287d34f59f1860b4815085245b389638f7 Mon Sep 17 00:00:00 2001
From: Evan Prodromou
Date: Mon, 20 Jun 2011 11:28:46 -0400
Subject: [PATCH 10/12] correctly purify input for Blog_entry
---
plugins/Blog/Blog_entry.php | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/plugins/Blog/Blog_entry.php b/plugins/Blog/Blog_entry.php
index 72cee91a79..f3166f870a 100644
--- a/plugins/Blog/Blog_entry.php
+++ b/plugins/Blog/Blog_entry.php
@@ -114,18 +114,18 @@ class Blog_entry extends Managed_DataObject
if (is_null($options)) {
$options = array();
}
-
+
$be = new Blog_entry();
$be->id = (string) new UUID();
$be->profile_id = $profile->id;
$be->title = $title; // Note: not HTML-protected
$be->content = self::purify($content);
-
+
if (array_key_exists('summary', $options)) {
$be->summary = self::purify($options['summary']);
} else {
// Already purified
- $be->summary = self::summarize($content);
+ $be->summary = self::summarize($be->content);
}
// Don't save an identical summary
@@ -176,15 +176,15 @@ class Blog_entry extends Managed_DataObject
XMLStringer::estring('a', array('href' => $url,
'class' => 'blog-entry'),
_('More...'));
- $content = html_entity_decode(strip_tags($be->summary), ENT_QUOTES, 'UTF-8');
+ $text = html_entity_decode(strip_tags($be->summary), ENT_QUOTES, 'UTF-8');
} else {
$options['rendered'] = $be->content;
- $content = html_entity_decode(strip_tags($be->content), ENT_QUOTES, 'UTF-8');
+ $text = html_entity_decode(strip_tags($be->content), ENT_QUOTES, 'UTF-8');
}
- if (Notice::contentTooLong($content)) {
- $content = substr($content, 0, Notice::maxContent() - mb_strlen($shortUrl) - 2) .
+ if (Notice::contentTooLong($text)) {
+ $text = substr($text, 0, Notice::maxContent() - mb_strlen($shortUrl) - 2) .
'… ' . $shortUrl;
}
@@ -195,7 +195,7 @@ class Blog_entry extends Managed_DataObject
$source = array_key_exists('source', $options) ?
$options['source'] : 'web';
- $saved = Notice::saveNew($profile->id, $content, $source, $options);
+ $saved = Notice::saveNew($profile->id, $text, $source, $options);
return $saved;
}
@@ -249,8 +249,11 @@ class Blog_entry extends Managed_DataObject
static function purify($html)
{
require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
+
$config = array('safe' => 1,
'deny_attribute' => 'id,style,on*');
- return htmLawed($html, $config);
+ $pure = htmLawed($html, $config);
+
+ return $pure;
}
}
From d67b8fdae83d948bf997a7f7cdbb71b52d9481e9 Mon Sep 17 00:00:00 2001
From: Evan Prodromou
Date: Mon, 20 Jun 2011 11:34:24 -0400
Subject: [PATCH 11/12] upgrade TinyMCE to 3.4.x
---
plugins/TinyMCE/js/langs/en.js | 59 +-
.../TinyMCE/js/plugins/advhr/langs/en_dlg.js | 2 +
plugins/TinyMCE/js/plugins/advhr/rule.htm | 59 +-
plugins/TinyMCE/js/plugins/advimage/image.htm | 65 +-
.../TinyMCE/js/plugins/advimage/js/image.js | 35 +-
.../js/plugins/advimage/langs/en_dlg.js | 2 +
.../TinyMCE/js/plugins/advlink/js/advlink.js | 38 +-
.../js/plugins/advlink/langs/en_dlg.js | 6 +-
plugins/TinyMCE/js/plugins/advlink/link.htm | 65 +-
.../js/plugins/advlist/editor_plugin.js | 2 +-
.../js/plugins/advlist/editor_plugin_src.js | 13 +-
.../js/plugins/autolink/editor_plugin.js | 1 +
.../js/plugins/autolink/editor_plugin_src.js | 172 +
.../js/plugins/autoresize/editor_plugin.js | 2 +-
.../plugins/autoresize/editor_plugin_src.js | 28 +-
.../js/plugins/autosave/editor_plugin.js | 2 +-
.../js/plugins/autosave/editor_plugin_src.js | 17 +-
.../js/plugins/bbcode/editor_plugin.js | 2 +-
.../js/plugins/bbcode/editor_plugin_src.js | 2 +-
.../js/plugins/contextmenu/editor_plugin.js | 2 +-
.../plugins/contextmenu/editor_plugin_src.js | 55 +-
.../TinyMCE/js/plugins/emotions/emotions.htm | 29 +-
.../emotions/img/smiley-foot-in-mouth.gif | Bin 344 -> 342 bytes
.../plugins/emotions/img/smiley-laughing.gif | Bin 344 -> 343 bytes
.../js/plugins/emotions/img/smiley-sealed.gif | Bin 325 -> 323 bytes
.../js/plugins/emotions/img/smiley-smile.gif | Bin 345 -> 344 bytes
.../plugins/emotions/img/smiley-surprised.gif | Bin 342 -> 338 bytes
.../js/plugins/emotions/img/smiley-wink.gif | Bin 351 -> 350 bytes
.../example_dependency/editor_plugin.js | 1 +
.../example_dependency/editor_plugin_src.js | 50 +
.../js/plugins/fullpage/css/fullpage.css | 45 +-
.../js/plugins/fullpage/editor_plugin.js | 2 +-
.../js/plugins/fullpage/editor_plugin_src.js | 388 +-
.../TinyMCE/js/plugins/fullpage/fullpage.htm | 348 +-
.../js/plugins/fullpage/js/fullpage.js | 613 +-
.../js/plugins/fullscreen/editor_plugin.js | 2 +-
.../plugins/fullscreen/editor_plugin_src.js | 12 +-
.../js/plugins/inlinepopups/editor_plugin.js | 2 +-
.../plugins/inlinepopups/editor_plugin_src.js | 91 +-
.../skins/clearlooks2/img/alert.gif | Bin 818 -> 810 bytes
.../skins/clearlooks2/img/button.gif | Bin 280 -> 272 bytes
.../skins/clearlooks2/img/confirm.gif | Bin 915 -> 907 bytes
.../skins/clearlooks2/img/corners.gif | Bin 911 -> 909 bytes
.../skins/clearlooks2/img/vertical.gif | Bin 92 -> 84 bytes
.../inlinepopups/skins/clearlooks2/window.css | 2 +-
.../TinyMCE/js/plugins/layer/editor_plugin.js | 2 +-
.../js/plugins/layer/editor_plugin_src.js | 2 +
.../js/plugins/legacyoutput/editor_plugin.js | 2 +-
.../plugins/legacyoutput/editor_plugin_src.js | 57 +-
.../js/plugins/linkautodetect/changelog.txt | 9 -
.../plugins/linkautodetect/editor_plugin.js | 7 -
.../linkautodetect/editor_plugin_src.js | 141 -
.../TinyMCE/js/plugins/lists/editor_plugin.js | 1 +
.../js/plugins/lists/editor_plugin_src.js | 688 ++
.../TinyMCE/js/plugins/media/css/content.css | 6 -
.../TinyMCE/js/plugins/media/css/media.css | 9 +-
.../TinyMCE/js/plugins/media/editor_plugin.js | 2 +-
.../js/plugins/media/editor_plugin_src.js | 989 +-
.../TinyMCE/js/plugins/media/img/flash.gif | Bin 241 -> 0 bytes
.../js/plugins/media/img/flv_player.swf | Bin 11668 -> 0 bytes
.../js/plugins/media/img/quicktime.gif | Bin 303 -> 0 bytes
.../js/plugins/media/img/shockwave.gif | Bin 387 -> 0 bytes
plugins/TinyMCE/js/plugins/media/js/media.js | 957 +-
.../TinyMCE/js/plugins/media/langs/en_dlg.js | 10 +-
plugins/TinyMCE/js/plugins/media/media.htm | 571 +-
.../TinyMCE/js/plugins/media/moxieplayer.swf | Bin 0 -> 33931 bytes
.../js/plugins/nonbreaking/editor_plugin.js | 2 +-
.../plugins/nonbreaking/editor_plugin_src.js | 2 +-
.../js/plugins/noneditable/editor_plugin.js | 2 +-
.../plugins/noneditable/editor_plugin_src.js | 2 +
.../js/plugins/pagebreak/css/content.css | 1 -
.../js/plugins/pagebreak/editor_plugin.js | 2 +-
.../js/plugins/pagebreak/editor_plugin_src.js | 5 +-
.../js/plugins/pagebreak/img/trans.gif | Bin 43 -> 0 bytes
.../TinyMCE/js/plugins/paste/editor_plugin.js | 2 +-
.../js/plugins/paste/editor_plugin_src.js | 273 +-
.../js/plugins/searchreplace/editor_plugin.js | 2 +-
.../searchreplace/editor_plugin_src.js | 4 +
.../plugins/searchreplace/js/searchreplace.js | 24 +-
.../plugins/searchreplace/searchreplace.htm | 33 +-
.../js/plugins/spellchecker/editor_plugin.js | 2 +-
.../plugins/spellchecker/editor_plugin_src.js | 89 +-
plugins/TinyMCE/js/plugins/style/js/props.js | 12 +-
.../TinyMCE/js/plugins/style/langs/en_dlg.js | 9 +-
plugins/TinyMCE/js/plugins/style/props.htm | 901 +-
.../js/plugins/tabfocus/editor_plugin.js | 2 +-
.../js/plugins/tabfocus/editor_plugin_src.js | 54 +-
plugins/TinyMCE/js/plugins/table/cell.htm | 30 +-
.../TinyMCE/js/plugins/table/editor_plugin.js | 2 +-
.../js/plugins/table/editor_plugin_src.js | 160 +-
plugins/TinyMCE/js/plugins/table/js/cell.js | 53 +-
plugins/TinyMCE/js/plugins/table/js/row.js | 36 +-
plugins/TinyMCE/js/plugins/table/js/table.js | 31 +-
.../TinyMCE/js/plugins/table/langs/en_dlg.js | 3 +-
.../TinyMCE/js/plugins/table/merge_cells.htm | 22 +-
plugins/TinyMCE/js/plugins/table/row.htm | 21 +-
plugins/TinyMCE/js/plugins/table/table.htm | 107 +-
.../js/plugins/template/js/template.js | 2 +-
.../js/plugins/visualchars/editor_plugin.js | 2 +-
.../plugins/visualchars/editor_plugin_src.js | 2 +-
.../js/plugins/wordcount/editor_plugin.js | 2 +-
.../js/plugins/wordcount/editor_plugin_src.js | 54 +-
.../TinyMCE/js/plugins/xhtmlxtras/abbr.htm | 11 +-
.../TinyMCE/js/plugins/xhtmlxtras/acronym.htm | 11 +-
.../js/plugins/xhtmlxtras/attributes.htm | 11 +-
.../TinyMCE/js/plugins/xhtmlxtras/cite.htm | 9 +-
plugins/TinyMCE/js/plugins/xhtmlxtras/del.htm | 17 +-
.../js/plugins/xhtmlxtras/editor_plugin.js | 2 +-
.../plugins/xhtmlxtras/editor_plugin_src.js | 12 +-
plugins/TinyMCE/js/plugins/xhtmlxtras/ins.htm | 21 +-
.../js/plugins/xhtmlxtras/js/attributes.js | 17 +-
.../TinyMCE/js/plugins/xhtmlxtras/js/del.js | 14 +-
.../plugins/xhtmlxtras/js/element_common.js | 8 +-
.../TinyMCE/js/plugins/xhtmlxtras/js/ins.js | 17 +-
plugins/TinyMCE/js/themes/advanced/about.htm | 8 +-
plugins/TinyMCE/js/themes/advanced/anchor.htm | 10 +-
.../TinyMCE/js/themes/advanced/charmap.htm | 79 +-
.../js/themes/advanced/color_picker.htm | 19 +-
.../js/themes/advanced/editor_template.js | 2 +-
.../js/themes/advanced/editor_template_src.js | 261 +-
plugins/TinyMCE/js/themes/advanced/image.htm | 102 +-
.../js/themes/advanced/img/colorpicker.jpg | Bin 3189 -> 2584 bytes
.../TinyMCE/js/themes/advanced/img/flash.gif | Bin 0 -> 239 bytes
.../TinyMCE/js/themes/advanced/img/icons.gif | Bin 11794 -> 11790 bytes
.../TinyMCE/js/themes/advanced/img/iframe.gif | Bin 0 -> 600 bytes
.../advanced}/img/pagebreak.gif | Bin
.../js/themes/advanced/img/quicktime.gif | Bin 0 -> 301 bytes
.../advanced}/img/realmedia.gif | Bin
.../js/themes/advanced/img/shockwave.gif | Bin 0 -> 384 bytes
.../media => themes/advanced}/img/trans.gif | Bin
.../TinyMCE/js/themes/advanced/img/video.gif | Bin 0 -> 597 bytes
.../advanced}/img/windowsmedia.gif | Bin
.../TinyMCE/js/themes/advanced/js/about.js | 1 +
.../TinyMCE/js/themes/advanced/js/anchor.js | 5 +
.../TinyMCE/js/themes/advanced/js/charmap.js | 32 +-
.../js/themes/advanced/js/color_picker.js | 140 +-
.../TinyMCE/js/themes/advanced/js/image.js | 8 +-
plugins/TinyMCE/js/themes/advanced/js/link.js | 11 +-
.../js/themes/advanced/js/source_editor.js | 18 +-
.../TinyMCE/js/themes/advanced/langs/en.js | 10 +-
.../js/themes/advanced/langs/en_dlg.js | 9 +-
plugins/TinyMCE/js/themes/advanced/link.htm | 55 +-
.../TinyMCE/js/themes/advanced/shortcuts.htm | 47 +
.../themes/advanced/skins/default/content.css | 13 +-
.../advanced/skins/default/img/buttons.png | Bin 3274 -> 3133 bytes
.../advanced/skins/default/img/items.gif | Bin 70 -> 64 bytes
.../advanced/skins/default/img/tabs.gif | Bin 1326 -> 1322 bytes
.../js/themes/advanced/skins/default/ui.css | 9 +-
.../advanced/skins/highcontrast/content.css | 23 +
.../advanced/skins/highcontrast/dialog.css | 105 +
.../themes/advanced/skins/highcontrast/ui.css | 102 +
.../js/themes/advanced/skins/o2k7/content.css | 10 +
.../js/themes/advanced/skins/o2k7/dialog.css | 1 +
.../advanced/skins/o2k7/img/button_bg.png | Bin 5859 -> 2766 bytes
.../skins/o2k7/img/button_bg_black.png | Bin 3736 -> 651 bytes
.../skins/o2k7/img/button_bg_silver.png | Bin 5358 -> 2084 bytes
.../js/themes/advanced/skins/o2k7/ui.css | 12 +-
.../themes/advanced/skins/o2k7/ui_black.css | 2 +-
.../themes/advanced/skins/o2k7/ui_silver.css | 2 +-
.../js/themes/advanced/source_editor.htm | 6 +-
.../js/themes/simple/editor_template.js | 2 +-
.../js/themes/simple/editor_template_src.js | 3 +-
.../TinyMCE/js/themes/simple/img/icons.gif | Bin 1440 -> 806 bytes
plugins/TinyMCE/js/tiny_mce.js | 2 +-
plugins/TinyMCE/js/tiny_mce_popup.js | 2 +-
plugins/TinyMCE/js/tiny_mce_src.js | 9095 +++++++++++------
plugins/TinyMCE/js/utils/form_utils.js | 18 +-
plugins/TinyMCE/js/utils/mctabs.js | 105 +-
plugins/TinyMCE/js/utils/validate.js | 38 +-
169 files changed, 11238 insertions(+), 6896 deletions(-)
create mode 100644 plugins/TinyMCE/js/plugins/autolink/editor_plugin.js
create mode 100644 plugins/TinyMCE/js/plugins/autolink/editor_plugin_src.js
create mode 100644 plugins/TinyMCE/js/plugins/example_dependency/editor_plugin.js
create mode 100644 plugins/TinyMCE/js/plugins/example_dependency/editor_plugin_src.js
delete mode 100644 plugins/TinyMCE/js/plugins/linkautodetect/changelog.txt
delete mode 100644 plugins/TinyMCE/js/plugins/linkautodetect/editor_plugin.js
delete mode 100644 plugins/TinyMCE/js/plugins/linkautodetect/editor_plugin_src.js
create mode 100644 plugins/TinyMCE/js/plugins/lists/editor_plugin.js
create mode 100644 plugins/TinyMCE/js/plugins/lists/editor_plugin_src.js
delete mode 100644 plugins/TinyMCE/js/plugins/media/css/content.css
delete mode 100644 plugins/TinyMCE/js/plugins/media/img/flash.gif
delete mode 100644 plugins/TinyMCE/js/plugins/media/img/flv_player.swf
delete mode 100644 plugins/TinyMCE/js/plugins/media/img/quicktime.gif
delete mode 100644 plugins/TinyMCE/js/plugins/media/img/shockwave.gif
create mode 100644 plugins/TinyMCE/js/plugins/media/moxieplayer.swf
delete mode 100644 plugins/TinyMCE/js/plugins/pagebreak/css/content.css
delete mode 100644 plugins/TinyMCE/js/plugins/pagebreak/img/trans.gif
create mode 100644 plugins/TinyMCE/js/themes/advanced/img/flash.gif
create mode 100644 plugins/TinyMCE/js/themes/advanced/img/iframe.gif
rename plugins/TinyMCE/js/{plugins/pagebreak => themes/advanced}/img/pagebreak.gif (100%)
create mode 100644 plugins/TinyMCE/js/themes/advanced/img/quicktime.gif
rename plugins/TinyMCE/js/{plugins/media => themes/advanced}/img/realmedia.gif (100%)
create mode 100644 plugins/TinyMCE/js/themes/advanced/img/shockwave.gif
rename plugins/TinyMCE/js/{plugins/media => themes/advanced}/img/trans.gif (100%)
create mode 100644 plugins/TinyMCE/js/themes/advanced/img/video.gif
rename plugins/TinyMCE/js/{plugins/media => themes/advanced}/img/windowsmedia.gif (100%)
create mode 100644 plugins/TinyMCE/js/themes/advanced/shortcuts.htm
create mode 100644 plugins/TinyMCE/js/themes/advanced/skins/highcontrast/content.css
create mode 100644 plugins/TinyMCE/js/themes/advanced/skins/highcontrast/dialog.css
create mode 100644 plugins/TinyMCE/js/themes/advanced/skins/highcontrast/ui.css
diff --git a/plugins/TinyMCE/js/langs/en.js b/plugins/TinyMCE/js/langs/en.js
index ea4a1b0e14..8a80d46b1a 100644
--- a/plugins/TinyMCE/js/langs/en.js
+++ b/plugins/TinyMCE/js/langs/en.js
@@ -12,9 +12,54 @@ not_set:"-- Not set --",
clipboard_msg:"Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?",
clipboard_no_support:"Currently not supported by your browser, use keyboard shortcuts instead.",
popup_blocked:"Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.",
-invalid_data:"Error: Invalid values entered, these are marked in red.",
+invalid_data:"{#field} is invalid",
+invalid_data_number:"{#field} must be a number",
+invalid_data_min:"{#field} must be a number greater than {#min}",
+invalid_data_size:"{#field} must be a number or percentage",
more_colors:"More colors"
},
+colors:{
+'000000':'Black',
+'993300':'Burnt orange',
+'333300':'Dark olive',
+'003300':'Dark green',
+'003366':'Dark azure',
+'000080':'Navy Blue',
+'333399':'Indigo',
+'333333':'Very dark gray',
+'800000':'Maroon',
+'FF6600':'Orange',
+'808000':'Olive',
+'008000':'Green',
+'008080':'Teal',
+'0000FF':'Blue',
+'666699':'Grayish blue',
+'808080':'Gray',
+'FF0000':'Red',
+'FF9900':'Amber',
+'99CC00':'Yellow green',
+'339966':'Sea green',
+'33CCCC':'Turquoise',
+'3366FF':'Royal blue',
+'800080':'Purple',
+'999999':'Medium gray',
+'FF00FF':'Magenta',
+'FFCC00':'Gold',
+'FFFF00':'Yellow',
+'00FF00':'Lime',
+'00FFFF':'Aqua',
+'00CCFF':'Sky blue',
+'993366':'Brown',
+'C0C0C0':'Silver',
+'FF99CC':'Pink',
+'FFCC99':'Peach',
+'FFFF99':'Light yellow',
+'CCFFCC':'Pale green',
+'CCFFFF':'Pale cyan',
+'99CCFF':'Light sky blue',
+'CC99FF':'Plum',
+'FFFFFF':'White'
+},
contextmenu:{
align:"Alignment",
left:"Left",
@@ -151,7 +196,8 @@ langs:"Languages",
wait:"Please wait...",
sug:"Suggestions",
no_sug:"No suggestions",
-no_mpell:"No misspellings found."
+no_mpell:"No misspellings found.",
+learn_word:"Learn word"
},
pagebreak:{
desc:"Insert page break."
@@ -167,4 +213,11 @@ upper_roman:"Upper roman",
circle:"Circle",
disc:"Disc",
square:"Square"
-}}});
\ No newline at end of file
+},
+aria:{
+rich_text_area:"Rich Text Area"
+},
+wordcount:{
+words: 'Words: '
+}
+}});
\ No newline at end of file
diff --git a/plugins/TinyMCE/js/plugins/advhr/langs/en_dlg.js b/plugins/TinyMCE/js/plugins/advhr/langs/en_dlg.js
index 873bfd8d38..ad6a7b6988 100644
--- a/plugins/TinyMCE/js/plugins/advhr/langs/en_dlg.js
+++ b/plugins/TinyMCE/js/plugins/advhr/langs/en_dlg.js
@@ -1,5 +1,7 @@
tinyMCE.addI18n('en.advhr_dlg',{
+normal:"Normal",
width:"Width",
+widthunits:"Units",
size:"Height",
noshade:"No shadow"
});
\ No newline at end of file
diff --git a/plugins/TinyMCE/js/plugins/advhr/rule.htm b/plugins/TinyMCE/js/plugins/advhr/rule.htm
index fc37b2aecd..843e1f8f0b 100644
--- a/plugins/TinyMCE/js/plugins/advhr/rule.htm
+++ b/plugins/TinyMCE/js/plugins/advhr/rule.htm
@@ -8,43 +8,44 @@
-
+
\n";h.foot="\n