Author: boutell
Date: 2009-05-12 21:41:05 +0200 (Tue, 12 May 2009)
New Revision: 18190
Added:
plugins/pkMediaPlugin/trunk/lib/form/pkMediaVideoEmbedForm.class.php
plugins/pkMediaPlugin/trunk/lib/form/pkMediaVideoYoutubeForm.class.php
Modified:
plugins/pkMediaPlugin/trunk/README
plugins/pkMediaPlugin/trunk/UPGRADE
plugins/pkMediaPlugin/trunk/config/doctrine/schema.yml
plugins/pkMediaPlugin/trunk/lib/form/pkMediaVideoForm.class.php
plugins/pkMediaPlugin/trunk/lib/model/doctrine/PluginpkMediaItem.class.php
plugins/pkMediaPlugin/trunk/lib/pkMediaTools.php
plugins/pkMediaPlugin/trunk/modules/pkMedia/actions/actions.class.php
plugins/pkMediaPlugin/trunk/modules/pkMedia/templates/editVideoSuccess.php
plugins/pkMediaPlugin/trunk/modules/pkMedia/templates/newVideoSuccess.php
Log:
Support for other video hosts via embed codes. See the README and UPGRADE files.
You will need a new field in your schema if you are upgrading (see UPGRADE).
Modified: plugins/pkMediaPlugin/trunk/README
===================================================================
--- plugins/pkMediaPlugin/trunk/README 2009-05-12 18:40:55 UTC (rev 18189)
+++ plugins/pkMediaPlugin/trunk/README 2009-05-12 19:41:05 UTC (rev 18190)
@@ -198,11 +198,29 @@
You can also edit and delete items in context using the edit
and delete buttons.
-Since videos are hosted by YouTube and not directly hosted by the
+Since videos are hosted by YouTube (or other services when
+embed_codes is enabled) and not directly hosted by the
plugin, adding video works a little bit differently. When you add
a video you'll be invited to search YouTube to locate that video.
If you prefer you can also paste in the YouTube URL of the video directly.
+== The Embed Code Option ==
+
+If `app_pkMedia_embed_codes` is enabled via `app.yml` you can also
+paste in embed codes for other sites using a third option that appears
+when adding videos.
+
+The embed feature does filter
+irrelevant tags and text, but does not attempt to remove all
+attributes, since so many are necessary when embedding. That means
+that users could paste in unwanted JavaScript handlers or style
+attributes. So you may or may not wish to enable it. By default
+it is turned off.
+
+The embed feature requires you to supply a thumbnail image manually
+at the same time you supply the embed code. This is not necessary
+when using a YouTube URL. When you can, use YouTube.
+
== The Select Action: Selecting Media ==
Many web applications will want to embed images and video that
Modified: plugins/pkMediaPlugin/trunk/UPGRADE
===================================================================
--- plugins/pkMediaPlugin/trunk/UPGRADE 2009-05-12 18:40:55 UTC (rev 18189)
+++ plugins/pkMediaPlugin/trunk/UPGRADE 2009-05-12 19:41:05 UTC (rev 18190)
@@ -1,3 +1,9 @@
+20090510: you'll need a new field in your database:
+
+ALTER TABLE pk_media_item ADD COLUMN embed varchar(1000);
+
+* * *
+
In version 0.5 the media repository moved from web/media-items to
web/uploads/media_items for consistency with other writable folders
in web space. Version 0.5 comes with a different set of rewrite rules
Modified: plugins/pkMediaPlugin/trunk/config/doctrine/schema.yml
===================================================================
--- plugins/pkMediaPlugin/trunk/config/doctrine/schema.yml 2009-05-12
18:40:55 UTC (rev 18189)
+++ plugins/pkMediaPlugin/trunk/config/doctrine/schema.yml 2009-05-12
19:41:05 UTC (rev 18190)
@@ -39,6 +39,21 @@
type: integer(4)
height:
type: integer(4)
+
+ # If this field is non-null, it contains HTML embed/object code to
+ # be used without alteration (except for replacing _WIDTH_ and _HEIGHT_)
+ # when embedding the video. This is used to allow embedding of
+ # video hosted on services whose APIs are not directly supported
+ # by pkMediaPlugin (i.e. anything except YouTube, as of this writing).
+ # Note that this can actually be used to embed any scalable
+ # applet (Flash, Java, etc) supported by embed/object/applet/param tags
+ # although our intention is simply to support black-box Flash players.
+ #
+ # The user is required to manually supply a thumbnail when
+ # embedding a video in this way.
+ embed:
+ type: string(1000)
+
title:
type: string(200)
notnull: true
Added: plugins/pkMediaPlugin/trunk/lib/form/pkMediaVideoEmbedForm.class.php
===================================================================
--- plugins/pkMediaPlugin/trunk/lib/form/pkMediaVideoEmbedForm.class.php
(rev 0)
+++ plugins/pkMediaPlugin/trunk/lib/form/pkMediaVideoEmbedForm.class.php
2009-05-12 19:41:05 UTC (rev 18190)
@@ -0,0 +1,68 @@
+<?php
+
+class pkMediaVideoEmbedForm extends pkMediaVideoForm
+{
+ public function configure()
+ {
+ parent::configure();
+ unset($this['service_url']);
+ // TODO: custom validator looking for appropriate tags only
+ $this->setValidator('embed',
+ new sfValidatorCallback(
+ array('required' => true, 'callback' =>
'pkMediaVideoEmbedForm::validateEmbed'),
+ array('required' => "Not a valid embed code", 'invalid' => "Not a
valid embed code")));
+ $this->setWidget('thumbnail',
+ new pkWidgetFormInputFilePersistent());
+ $this->setValidator('thumbnail',
+ new pkValidatorFilePersistent(array('mime_types' =>
+ array('image/jpeg', 'image/png', 'image/gif'),
+ "required" => (!$this->getObject()->getId()))));
+ }
+ static public function validateEmbed($validator, $value, $arguments)
+ {
+ // Don't let this become a way to embed arbitrary HTML
+ $value = trim(strip_tags($value, "<embed><object><param><applet>"));
+ // Kill any text outside of tags
+ if (preg_match_all("/<.*?>/", $value, $matches))
+ {
+ $value = implode("", $matches[0]);
+ }
+ else
+ {
+ $value = '';
+ }
+ if (!strlen($value))
+ {
+ throw new sfValidatorError($validator,
$validator->getMessage('invalid'), $arguments);
+ }
+ return $value;
+ }
+ public function updateObject($values = null)
+ {
+ $object = parent::updateObject($values);
+ // If possible, get the width and height from the embed tag rather
+ // than from the thumbnail the user uploaded, which is likely to be
+ // a mismatch quite often. If the embed tag has percentages we don't
+ // want to match, just let the thumbnail dimensions win
+ if (preg_match("/width\s*=\s*([\"'])(\d+)\\1/i", $object->embed, $matches))
+ {
+ $object->width = $matches[2];
+ }
+ if (preg_match("/height\s*=\s*([\"'])(\d+)\\1/i", $object->embed,
$matches))
+ {
+ $object->height = $matches[2];
+ }
+ // Put placeholders in the embed/applet/object tags
+ $object->embed = preg_replace(
+ array(
+ "/width\s*=\s*([\"'])\d+%?\\1/i",
+ "/height\s*=\s*([\"'])\d+%?\\1/i",
+ "/alt\s*\s*([\"']).*?\\1/i"),
+ array(
+ "width=\"_WIDTH_\"",
+ "height=\"_HEIGHT_\"",
+ "alt=\"_TITLE_\""),
+ $object->embed);
+ return $object;
+ }
+}
Modified: plugins/pkMediaPlugin/trunk/lib/form/pkMediaVideoForm.class.php
===================================================================
--- plugins/pkMediaPlugin/trunk/lib/form/pkMediaVideoForm.class.php
2009-05-12 18:40:55 UTC (rev 18189)
+++ plugins/pkMediaPlugin/trunk/lib/form/pkMediaVideoForm.class.php
2009-05-12 19:41:05 UTC (rev 18190)
@@ -5,10 +5,23 @@
public function configure()
{
unset($this['id'], $this['type'], $this['slug'], $this['width'],
$this['height'], $this['format']);
- $this->setValidator('service_url',
- new sfValidatorUrl(
- array('required' => true, 'trim' => true),
- array('required' => "Not a valid YouTube URL")));
+ $object = $this->getObject();
+// if ($object->embed)
+// {
+// unset($this['service_url']);
+// $this->setValidator('embed',
+// new sfValidatorText(
+// array('required' => true, 'trim' => true),
+// array('required' => "Not a valid embed code")));
+// }
+// else
+// {
+// unset($this['embed']);
+ $this->setValidator('service_url',
+ new sfValidatorUrl(
+ array('required' => true, 'trim' => true),
+ array('required' => "Not a valid YouTube URL")));
+// }
}
public function updateObject($values = null)
{
Added: plugins/pkMediaPlugin/trunk/lib/form/pkMediaVideoYoutubeForm.class.php
===================================================================
--- plugins/pkMediaPlugin/trunk/lib/form/pkMediaVideoYoutubeForm.class.php
(rev 0)
+++ plugins/pkMediaPlugin/trunk/lib/form/pkMediaVideoYoutubeForm.class.php
2009-05-12 19:41:05 UTC (rev 18190)
@@ -0,0 +1,14 @@
+<?php
+
+class pkMediaVideoYoutubeForm extends pkMediaVideoForm
+{
+ public function configure()
+ {
+ parent::configure();
+ unset($this['embed']);
+ $this->setValidator('service_url',
+ new sfValidatorUrl(
+ array('required' => true, 'trim' => true),
+ array('required' => "Not a valid YouTube URL")));
+ }
+}
Modified:
plugins/pkMediaPlugin/trunk/lib/model/doctrine/PluginpkMediaItem.class.php
===================================================================
--- plugins/pkMediaPlugin/trunk/lib/model/doctrine/PluginpkMediaItem.class.php
2009-05-12 18:40:55 UTC (rev 18189)
+++ plugins/pkMediaPlugin/trunk/lib/model/doctrine/PluginpkMediaItem.class.php
2009-05-12 19:41:05 UTC (rev 18190)
@@ -116,8 +116,8 @@
{
if ($height === false)
{
- // Scale the height
- $height = floor(($width * $this->width / $this->height) + 0.5);
+ // Scale the height. I had this backwards
+ $height = floor(($width * $this->height / $this->width) + 0.5);
}
// Accessible alt title
$title = htmlspecialchars($this->getTitle());
@@ -125,6 +125,13 @@
// Think about whether that's possible.
if ($this->getType() === 'video')
{
+ if ($this->embed)
+ {
+ // Solution for non-YouTube videos based on a manually
+ // provided thumbnail and embed code
+ return str_replace(array('_TITLE_', '_WIDTH_', '_HEIGHT_'),
+ array($title, $width, $height), $this->embed);
+ }
// TODO: less YouTube-specific
$serviceUrl = $this->getServiceUrl();
$embeddedUrl = $this->youtubeUrlToEmbeddedUrl($serviceUrl);
Modified: plugins/pkMediaPlugin/trunk/lib/pkMediaTools.php
===================================================================
--- plugins/pkMediaPlugin/trunk/lib/pkMediaTools.php 2009-05-12 18:40:55 UTC
(rev 18189)
+++ plugins/pkMediaPlugin/trunk/lib/pkMediaTools.php 2009-05-12 19:41:05 UTC
(rev 18190)
@@ -150,6 +150,7 @@
'selected_resizeType' => 'c',
'show_width' => 720,
'show_height' => 720,
+ 'embed_codes' => false,
'apikeys' => array()
);
static public function getOption($name)
Modified: plugins/pkMediaPlugin/trunk/modules/pkMedia/actions/actions.class.php
===================================================================
--- plugins/pkMediaPlugin/trunk/modules/pkMedia/actions/actions.class.php
2009-05-12 18:40:55 UTC (rev 18189)
+++ plugins/pkMediaPlugin/trunk/modules/pkMedia/actions/actions.class.php
2009-05-12 19:41:05 UTC (rev 18190)
@@ -355,11 +355,21 @@
$this->forward404Unless($item->userHasPrivilege('edit'));
}
$this->item = $item;
- $this->form = new pkMediaVideoForm($item);
- if ($request->hasParameter('pk_media_item[]'))
+ $subclass = 'pkMediaVideoYoutubeForm';
+ $embed = false;
+ $parameters = $request->getParameter('pk_media_item');
+ if (pkMediaTools::getOption('embed_codes') &&
+ (($item && strlen($item->embed)) || (isset($parameters['embed']))))
{
- $parameters = $request->getParameter('pk_media_item[]');
- $this->form->bind($parameters);
+ $subclass = 'pkMediaVideoEmbedForm';
+ $embed = true;
+ }
+ $this->form = new $subclass($item);
+ if ($parameters)
+ {
+ $files = $request->getFiles('pk_media_item');
+ $this->form->bind($parameters, $files);
+
do
{
// first_pass forces the user to interact with the form
@@ -373,68 +383,93 @@
{
break;
}
- $url = $this->form->getValue("service_url");
- // TODO: migrate this into the model and a
- // YouTube-specific support class
- if (!preg_match("/youtube.com.*\?.*v=([\w\-\+]+)/",
- $url, $matches))
+ // TODO: this is pretty awful factoring, I should have separate actions
+ // and migrate more of this code into the model layer
+ if ($embed)
{
- $this->serviceError = true;
- break;
+ $embed = $this->form->getValue("embed");
+ $thumbnail = $this->form->getValue('thumbnail');
+ // The base implementation for saving files gets confused when
+ // $file is not set, a situation that our code tolerates as useful
+ // because if you're updating a record containing an image you
+ // often don't need to submit a new one.
+ unset($this->form['thumbnail']);
+ $object = $this->form->getObject();
+ if ($thumbnail)
+ {
+ $object->preSaveImage($thumbnail->getTempName());
+ }
+ $this->form->save();
+ if ($thumbnail)
+ {
+ $object->saveImage($thumbnail->getTempName());
+ }
}
- // YouTube thumbnails are always JPEG
- $format = 'jpg';
- $videoid = $matches[1];
- $feed = "http://gdata.youtube.com/feeds/api/videos/$videoid";
- $entry = simplexml_load_file($feed);
- // get nodes in media: namespace for media information
- $media = $entry->children('http://search.yahoo.com/mrss/');
-
- // get a more canonical video player URL
- $attrs = $media->group->player->attributes();
- $canonicalUrl = $attrs['url'];
- // get biggest video thumbnail
- foreach ($media->group->thumbnail as $thumbnail)
+ else
{
- $attrs = $thumbnail->attributes();
- if ((!isset($widest)) || (($attrs['width'] + 0) >
- ($widest['width'] + 0)))
+ $url = $this->form->getValue("service_url");
+ // TODO: migrate this into the model and a
+ // YouTube-specific support class
+ if (!preg_match("/youtube.com.*\?.*v=([\w\-\+]+)/",
+ $url, $matches))
{
- $widest = $attrs;
+ $this->serviceError = true;
+ break;
}
- }
- // The YouTube API doesn't report the original width and height of
- // the video stream, so we use the largest thumbnail, which in practice
- // is the same thing on YouTube.
- if (isset($widest))
- {
- $thumbnail = $widest['url'];
- // Turn them into actual numbers instead of weird XML wrapper things
- $width = $widest['width'] + 0;
- $height = $widest['height'] + 0;
- }
- if (!isset($thumbnail))
- {
- $this->serviceError = true;
- break;
- }
- // Grab a local copy of the thumbnail, and get the pain
- // over with all at once in a predictable way if
- // the service provider fails to give it to us.
+ // YouTube thumbnails are always JPEG
+ $format = 'jpg';
+ $videoid = $matches[1];
+ $feed = "http://gdata.youtube.com/feeds/api/videos/$videoid";
+ $entry = simplexml_load_file($feed);
+ // get nodes in media: namespace for media information
+ $media = $entry->children('http://search.yahoo.com/mrss/');
+
+ // get a more canonical video player URL
+ $attrs = $media->group->player->attributes();
+ $canonicalUrl = $attrs['url'];
+ // get biggest video thumbnail
+ foreach ($media->group->thumbnail as $thumbnail)
+ {
+ $attrs = $thumbnail->attributes();
+ if ((!isset($widest)) || (($attrs['width'] + 0) >
+ ($widest['width'] + 0)))
+ {
+ $widest = $attrs;
+ }
+ }
+ // The YouTube API doesn't report the original width and height of
+ // the video stream, so we use the largest thumbnail, which in
practice
+ // is the same thing on YouTube.
+ if (isset($widest))
+ {
+ $thumbnail = $widest['url'];
+ // Turn them into actual numbers instead of weird XML wrapper
things
+ $width = $widest['width'] + 0;
+ $height = $widest['height'] + 0;
+ }
+ if (!isset($thumbnail))
+ {
+ $this->serviceError = true;
+ break;
+ }
+ // Grab a local copy of the thumbnail, and get the pain
+ // over with all at once in a predictable way if
+ // the service provider fails to give it to us.
- $thumbnailCopy = pkFiles::getTemporaryFilename();
- if (!copy($thumbnail, $thumbnailCopy))
- {
- $this->serviceError = true;
- break;
+ $thumbnailCopy = pkFiles::getTemporaryFilename();
+ if (!copy($thumbnail, $thumbnailCopy))
+ {
+ $this->serviceError = true;
+ break;
+ }
+ $object = $this->form->getObject();
+ $new = !$object->getId();
+ $object->preSaveImage($thumbnailCopy);
+ $object->setServiceUrl($url);
+ $this->form->save();
+ $object->saveImage($thumbnailCopy);
+ unlink($thumbnailCopy);
}
- $object = $this->form->getObject();
- $new = !$object->getId();
- $object->preSaveImage($thumbnailCopy);
- $object->setServiceUrl($url);
- $this->form->save();
- $object->saveImage($thumbnailCopy);
- unlink($thumbnailCopy);
return $this->redirect("pkMedia/resumeWithPage");
} while (false);
}
Modified:
plugins/pkMediaPlugin/trunk/modules/pkMedia/templates/editVideoSuccess.php
===================================================================
--- plugins/pkMediaPlugin/trunk/modules/pkMedia/templates/editVideoSuccess.php
2009-05-12 18:40:55 UTC (rev 18189)
+++ plugins/pkMediaPlugin/trunk/modules/pkMedia/templates/editVideoSuccess.php
2009-05-12 19:41:05 UTC (rev 18190)
@@ -36,9 +36,23 @@
<?php endif ?>
<?php echo $form['title']->render() ?>
</div>
- <div class="form-row service-url">
- <?php echo $form['service_url']->renderRow() ?>
- </div>
+ <?php if (isset($form['service_url'])): ?>
+ <div class="form-row service-url">
+ <?php echo $form['service_url']->renderRow() ?>
+ </div>
+ <?php endif ?>
+ <?php if (isset($form['embed'])): ?>
+ <div class="form-row embed">
+ <?php echo $form['embed']->renderRow() ?>
+ </div>
+ <div class="form-row thumbnail">
+ <?php echo $form['thumbnail']->renderLabel() ?>
+ <?php if (!$sf_params->get('first_pass')): ?>
+ <?php echo $form['thumbnail']->renderError() ?>
+ <?php endif ?>
+ <?php echo $form['thumbnail']->render() ?>
+ </div>
+ <?php endif ?>
<div class="form-row description">
<?php echo $form['description']->renderLabel() ?>
<?php echo $form['description']->renderError() ?>
Modified:
plugins/pkMediaPlugin/trunk/modules/pkMedia/templates/newVideoSuccess.php
===================================================================
--- plugins/pkMediaPlugin/trunk/modules/pkMedia/templates/newVideoSuccess.php
2009-05-12 18:40:55 UTC (rev 18189)
+++ plugins/pkMediaPlugin/trunk/modules/pkMedia/templates/newVideoSuccess.php
2009-05-12 19:41:05 UTC (rev 18190)
@@ -14,8 +14,12 @@
<div id="pk-media-video-buttons">
<?php echo link_to_function("Search YouTube<span></span>",
"$('#pk-media-video-search-form').show();
$('#pk-media-video-buttons').hide();
$('#pk-media-video-search-heading').show();", array("class" => "pk-btn")) ?>
- <?php echo link_to_function("Add by URL<span></span>",
+ <?php echo link_to_function("Add by YouTube URL<span></span>",
"$('#pk-media-video-add-by-url-form').show();
$('#pk-media-video-buttons').hide();
$('#pk-media-video-add-by-url-heading').show();", array("class" => "pk-btn"))
?>
+ <?php if (pkMediaTools::getOption('embed_codes')): ?>
+ <?php echo link_to_function("Add by Embed Code<span></span>",
+ "$('#pk-media-video-add-by-embed-form').show();
$('#pk-media-video-buttons').hide();
$('#pk-media-video-add-by-embed-heading').show();", array("class" => "pk-btn"))
?>
+ <?php endif ?>
<span class="or">or</span>
<?php echo link_to("Cancel<span></span>",
"pkMedia/resumeWithPage",
@@ -23,7 +27,9 @@
</div>
<h4 id="pk-media-video-search-heading">Search YouTube</h3>
<h4 id="pk-media-video-add-by-url-heading">Add by URL</h3>
-
+ <?php if (pkMediaTools::getOption('embed_codes')): ?>
+ <h4 id="pk-media-video-add-by-embed-heading">Add by Embed
Code</h3>
+ <?php endif ?>
<?php echo jq_form_remote_tag(array(
'url' => 'pkMedia/videoSearch',
'update' => 'pk-media-video-search-form'),
@@ -52,6 +58,28 @@
</div>
</form>
+ <?php if (pkMediaTools::getOption('embed_codes')): ?>
+ <form id="pk-media-video-add-by-embed-form"
method="POST" action="<?php echo url_for("pkMedia/editVideo") ?>">
+
+ <div class="form-row
example">
+ <p>Example: <?php echo
htmlspecialchars('<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
width="437" height="291" ...</object>') ?></p>
+ <input type="hidden" name="first_pass"
value="1" />
+ </div>
+
+ <div class="form-row"
style="position:relative">
+ <label for="pk-media-video-embed">Embed
code</label>
+ <input type="text"
id="pk-media-video-embed" name="pk_media_item[embed]" value="" />
+
+ <div
id="pk-media-video-add-by-embed-form-submit">
+ <input type="submit" value="Go"
class="submit" />
+ <span
class="or">or</span>
+ <?php echo
link_to_function("Cancel<span></span>",
"$('#pk-media-video-add-by-embed-form').hide();
$('#pk-media-video-add-by-embed-heading').hide();
$('#pk-media-video-buttons').show();", array("class" => "pk-cancel")) ?>
+ </div>
+
+ </div>
+
+ </form>
+ <?php endif ?>
</div>
</div>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"symfony SVN" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/symfony-svn?hl=en
-~----------~----~----~----~------~----~------~--~---