Merge branch 'feedsub-wizard' into 1.0.x

This commit is contained in:
Brion Vibber 2011-03-15 17:50:30 -07:00
commit 826e21ccf3
15 changed files with 412 additions and 11 deletions

View File

@ -35,6 +35,9 @@ class SubMirrorPlugin extends Plugin
{
$m->connect('settings/mirror',
array('action' => 'mirrorsettings'));
$m->connect('settings/mirror/add/:provider',
array('action' => 'mirrorsettings'),
array('provider' => '[A-Za-z0-9_-]+'));
$m->connect('settings/mirror/add',
array('action' => 'addmirror'));
$m->connect('settings/mirror/edit',

View File

@ -59,11 +59,27 @@ class AddMirrorAction extends BaseMirrorAction
function prepare($args)
{
parent::prepare($args);
$this->feedurl = $this->validateFeedUrl($this->trimmed('feedurl'));
$feedurl = $this->getFeedUrl();
$this->feedurl = $this->validateFeedUrl($feedurl);
$this->profile = $this->profileForFeed($this->feedurl);
return true;
}
function getFeedUrl()
{
$provider = $this->trimmed('provider');
switch ($provider) {
case 'feed':
return $this->trimmed('feedurl');
case 'twitter':
$screenie = $this->trimmed('screen_name');
$base = 'http://api.twitter.com/1/statuses/user_timeline.atom?screen_name=';
return $base . urlencode($screenie);
default:
throw new Exception('Internal form error: unrecognized feed provider.');
}
}
function saveMirror()
{
if ($this->oprofile->subscribe()) {

View File

@ -68,7 +68,7 @@ abstract class BaseMirrorAction extends Action
if (common_valid_http_url($url)) {
return $url;
} else {
$this->clientError(_m("Invalid feed URL."));
$this->clientError(sprintf(_m("Invalid feed URL: %s"), $url));
}
}

View File

@ -65,18 +65,30 @@ class MirrorSettingsAction extends SettingsAction
function showContent()
{
$user = common_current_user();
$provider = $this->trimmed('provider');
if ($provider) {
$this->showAddFeedForm($provider);
} else {
$this->elementStart('div', array('id' => 'add-mirror'));
$this->showAddWizard();
$this->elementEnd('div');
$this->showAddFeedForm();
$mirror = new SubMirror();
$mirror->subscriber = $user->id;
if ($mirror->find()) {
while ($mirror->fetch()) {
$this->showFeedForm($mirror);
$mirror = new SubMirror();
$mirror->subscriber = $user->id;
if ($mirror->find()) {
while ($mirror->fetch()) {
$this->showFeedForm($mirror);
}
}
}
}
function showAddWizard()
{
$form = new AddMirrorWizard($this);
$form->show();
}
function showFeedForm($mirror)
{
$profile = Profile::staticGet('id', $mirror->subscribed);
@ -88,10 +100,47 @@ class MirrorSettingsAction extends SettingsAction
function showAddFeedForm()
{
$form = new AddMirrorForm($this);
switch ($this->arg('provider')) {
case 'statusnet':
break;
case 'twitter':
$form = new AddTwitterMirrorForm($this);
break;
case 'wordpress':
break;
case 'linkedin':
break;
case 'feed':
default:
$form = new AddMirrorForm($this);
}
$form->show();
}
/**
*
* @param array $args
*
* @todo move the ajax display handling to common code
*/
function handle($args)
{
if ($this->boolean('ajax')) {
header('Content-Type: text/html;charset=utf-8');
$this->elementStart('html');
$this->elementStart('head');
$this->element('title', null, _('Provider add'));
$this->elementEnd('head');
$this->elementStart('body');
$this->showAddFeedForm();
$this->elementEnd('body');
$this->elementEnd('html');
} else {
return parent::handle($args);
}
}
/**
* Handle a POST request
*
@ -108,4 +157,16 @@ class MirrorSettingsAction extends SettingsAction
$nav = new SubGroupNav($this, common_current_user());
$nav->show();
}
function showScripts()
{
parent::showScripts();
$this->script('plugins/SubMirror/js/mirrorsettings.js');
}
function showStylesheets()
{
parent::showStylesheets();
$this->cssLink('plugins/SubMirror/css/mirrorsettings.css');
}
}

View File

@ -0,0 +1,26 @@
/* undo insane stuff from core styles */
#add-mirror-wizard img {
display: inline;
}
/* we need #something to override most of the #content crap */
#add-mirror-wizard {
margin-left: 20px;
margin-right: 20px;
}
#add-mirror-wizard .provider-list table {
width: 100%;
}
#add-mirror-wizard .provider-heading img {
vertical-align: middle;
}
#add-mirror-wizard .provider-heading {
cursor: pointer;
}
#add-mirror-wizard .provider-detail fieldset {
margin-top: 8px; /* hack */
margin-bottom: 8px; /* hack */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,47 @@
$(function() {
/**
* Append 'ajax=1' parameter onto URL.
*/
function ajaxize(url) {
if (url.indexOf('?') == '-1') {
return url + '?ajax=1';
} else {
return url + '&ajax=1';
}
}
var addMirror = $('#add-mirror');
var wizard = $('#add-mirror-wizard');
if (wizard.length > 0) {
var list = wizard.find('.provider-list');
var providers = list.find('.provider-heading');
providers.click(function(event) {
console.log(this);
var targetUrl = $(this).find('a').attr('href');
if (targetUrl) {
// Make sure we don't accidentally follow the direct link
event.preventDefault();
var node = this;
function showNew() {
var detail = $('<div class="provider-detail" style="display: none"></div>').insertAfter(node);
detail.load(ajaxize(targetUrl), function(responseText, testStatus, xhr) {
detail.slideDown('fast', function() {
detail.find('input[type="text"]').focus();
});
});
}
var old = addMirror.find('.provider-detail');
if (old.length) {
old.slideUp('fast', function() {
old.remove();
showNew();
});
} else {
showNew();
}
}
});
}
});

View File

@ -49,6 +49,7 @@ class AddMirrorForm extends Form
*/
function formData()
{
$this->out->hidden('provider', 'feed');
$this->out->elementStart('fieldset');
$this->out->elementStart('ul');
@ -67,7 +68,7 @@ class AddMirrorForm extends Form
$this->out->elementEnd('fieldset');
}
private function doInput($id, $name, $label, $value=null, $instructions=null)
protected function doInput($id, $name, $label, $value=null, $instructions=null)
{
$this->out->element('label', array('for' => $id), $label);
$attrs = array('name' => $name,

View File

@ -0,0 +1,187 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package StatusNet
* @copyright 2010-2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
class AddMirrorWizard extends Widget
{
/**
* Name of the form
*
* Sub-classes should overload this with the name of their form.
*
* @return void
*/
function formLegend()
{
}
/**
* Visible or invisible data elements
*
* Display the form fields that make up the data of the form.
* Sub-classes should overload this to show their data.
*
* @return void
*/
function show()
{
$this->out->elementStart('div', array('id' => 'add-mirror-wizard'));
$providers = $this->providers();
$this->showProviders($providers);
$this->out->elementEnd('div');
}
function providers()
{
return array(
/*
// We could accept hostname & username combos here, or
// webfingery combinations as for remote users.
array(
'id' => 'statusnet',
'name' => _m('StatusNet'),
),
*/
// Accepts a Twitter username and pulls their user timeline as a
// public Atom feed. Requires a working alternate hub which, one
// hopes, is getting timely updates.
array(
'id' => 'twitter',
'name' => _m('Twitter'),
),
/*
// WordPress was on our list some whiles ago, but not sure
// what we can actually do here. Search on Wordpress.com hosted
// sites, or ?
array(
'id' => 'wordpress',
'name' => _m('WordPress'),
),
*/
/*
// In theory, Facebook lets you pull public updates over RSS,
// but the URLs for your own update feed that I can find from
// 2009-era websites no longer seem to work and there's no
// good current documentation. May not still be available...
// Mirroring from an FB account is probably better done with
// the dedicated plugin. (As of March 2011)
array(
'id' => 'facebook',
'name' => _m('Facebook'),
),
*/
/*
// LinkedIn doesn't currently seem to have public feeds
// for users or groups (March 2011)
array(
'id' => 'linkedin',
'name' => _m('LinkedIn'),
),
*/
array(
'id' => 'feed',
'name' => _m('RSS or Atom feed'),
),
);
}
function showProviders(array $providers)
{
$out = $this->out;
$out->elementStart('div', 'provider-list');
$out->element('h2', null, _m('Select a feed provider'));
$out->elementStart('table');
foreach ($providers as $provider) {
$icon = common_path('plugins/SubMirror/images/providers/' . $provider['id'] . '.png');
$targetUrl = common_local_url('mirrorsettings', array('provider' => $provider['id']));
$out->elementStart('tr', array('class' => 'provider'));
$out->elementStart('td');
$out->elementStart('div', 'provider-heading');
$out->element('img', array('src' => $icon));
$out->element('a', array('href' => $targetUrl), $provider['name']);
$out->elementEnd('div');
$out->elementEnd('td');
$out->elementEnd('tr');
}
$out->elementEnd('table');
$out->elementEnd('div');
}
/**
* Buttons for form actions
*
* Submit and cancel buttons (or whatever)
* Sub-classes should overload this to show their own buttons.
*
* @return void
*/
function formActions()
{
}
/**
* ID of the form
*
* Should be unique on the page. Sub-classes should overload this
* to show their own IDs.
*
* @return string ID of the form
*/
function id()
{
return 'add-mirror-wizard';
}
/**
* Action of the form.
*
* URL to post to. Should be overloaded by subclasses to give
* somewhere to post to.
*
* @return string URL to post to
*/
function action()
{
return common_local_url('addmirror');
}
/**
* Class of the form.
*
* @return string the form's class
*/
function formClass()
{
return 'form_settings';
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package StatusNet
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
class AddTwitterMirrorForm extends AddMirrorForm
{
/**
* Visible or invisible data elements
*
* Display the form fields that make up the data of the form.
* Sub-classes should overload this to show their data.
*
* @return void
*/
function formData()
{
$this->out->hidden('provider', 'twitter');
$this->out->elementStart('fieldset');
$this->out->elementStart('ul');
$this->li();
$this->doInput('addmirror-feedurl',
'screen_name',
_m('Twitter username:'),
$this->out->trimmed('screen_name'));
$this->unli();
$this->li();
$this->out->submit('addmirror-save', _m('BUTTON','Add feed'));
$this->unli();
$this->out->elementEnd('ul');
$this->out->elementEnd('fieldset');
}
}