forked from GNUsocial/gnu-social
Merge branch '0.8.x' of git://gitorious.org/laconica/dev into dev/0.8.x
This commit is contained in:
commit
003c63e587
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,8 +1,10 @@
|
||||
avatar/*
|
||||
files/*
|
||||
_darcs/*
|
||||
logs/*
|
||||
config.php
|
||||
.htaccess
|
||||
httpd.conf
|
||||
*.tmproj
|
||||
dataobject.ini
|
||||
*~
|
||||
@ -10,3 +12,7 @@ dataobject.ini
|
||||
*.orig
|
||||
*.rej
|
||||
.#*
|
||||
*.swp
|
||||
.buildpath
|
||||
.project
|
||||
.settings
|
||||
|
35
EVENTS.txt
35
EVENTS.txt
@ -82,3 +82,38 @@ StartNoticeSave: before inserting a notice (good place for content filters)
|
||||
EndNoticeSave: after inserting a notice and related code
|
||||
- $notice: notice that was saved (with ID and URI)
|
||||
|
||||
StartShowLocalNavBlock: Showing the local nav menu
|
||||
- $action: the current action
|
||||
|
||||
EndShowLocalNavBlock: At the end of the local nav menu
|
||||
- $action: the current action
|
||||
|
||||
StartShowHTML: Chance to set document headers (e.g., content type, charset, language), DOCTYPE and html element properties
|
||||
- $action: the current action
|
||||
|
||||
EndShowHTML: Showing after the html element
|
||||
- $action: the current action
|
||||
|
||||
StartPublicGroupNav: Showing the public group nav menu
|
||||
- $action: the current action
|
||||
|
||||
EndPublicGroupNav: At the end of the public group nav menu
|
||||
- $action: the current action
|
||||
|
||||
StartSubGroupNav: Showing the subscriptions group nav menu
|
||||
- $action: the current action
|
||||
|
||||
EndSubGroupNav: At the end of the subscriptions group nav menu
|
||||
- $action: the current action
|
||||
|
||||
RouterInitialized: After the router instance has been initialized
|
||||
- $m: the Net_URL_Mapper that has just been set up
|
||||
|
||||
StartLogout: Before logging out
|
||||
- $action: the logout action
|
||||
|
||||
EndLogout: After logging out
|
||||
- $action: the logout action
|
||||
|
||||
ArgsInitialized: After the argument array has been initialized
|
||||
- $args: associative array of arguments, can be modified
|
||||
|
278
README
278
README
@ -2,8 +2,8 @@
|
||||
README
|
||||
------
|
||||
|
||||
Laconica 0.7.1 ("West of the Fields")
|
||||
6 February 2009
|
||||
Laconica 0.7.3 ("You Are The Everything")
|
||||
7 April 2009
|
||||
|
||||
This is the README file for Laconica, the Open Source microblogging
|
||||
platform. It includes installation instructions, descriptions of
|
||||
@ -71,54 +71,29 @@ for additional terms.
|
||||
New this version
|
||||
================
|
||||
|
||||
This is a minor bug-fix release since version 0.7.0, released Jan 29
|
||||
2009. Notable changes this version:
|
||||
This is a minor bug-fix and feature release since version 0.7.2.1,
|
||||
released Mar 11 2009. Notable changes this version:
|
||||
|
||||
- Vast improvement in auto-linking to URLs.
|
||||
- Link to group search from user's group page
|
||||
- Improved interface in Facebook application
|
||||
- Fix bad redirects in delete notice
|
||||
- Updated PostgreSQL database creation script
|
||||
- Show filesize in avatar/logo upload
|
||||
- Vastly improved avatar/logo upload
|
||||
- Allow re-authentication with OpenID
|
||||
- Correctly link hashtabs inside parens and brackets
|
||||
- Group and avatar image transparency works
|
||||
- Better handling of commands through the Web and Ajax channels
|
||||
- Fix links for profile page feeds
|
||||
- Fixed destroy method in API
|
||||
- Fix endpoint of Connect menu when XMPP disabled
|
||||
- Show number of group members
|
||||
- Enable configuration files in /etc/laconica/
|
||||
|
||||
Changes in version 0.7.0:
|
||||
|
||||
- Support for groups. Users can join groups and send themed notices
|
||||
to those groups. All other members of the group receive the notices.
|
||||
- Laconica-specific extensions to the Twitter API.
|
||||
- A Facebook application.
|
||||
- A massive UI redesign. The HTML generated by Laconica has changed
|
||||
significantly, to make theming easier and to give a more open look
|
||||
by default. Also, sidebar.
|
||||
- Massive code hygiene changes to move towards compliance with the PEAR
|
||||
coding standards and to support the new UI redesign.
|
||||
- Began the breakup of util.php -- moved about 30% of code to a views
|
||||
hierarchy.
|
||||
- UI elements for statistical information (like top posters or most
|
||||
popular groups) added in a sidebar.
|
||||
- include Javascript badge by Kent Brewster.
|
||||
- Updated online documentation.
|
||||
- Cropping of user avatars using Jcrop.
|
||||
- fix for Twitter bridge to not send "Expect:" headers.
|
||||
- add 'dm' as a synonym for 'd' in commands.
|
||||
- Upgrade upstream version of jQuery to 1.3.
|
||||
- Upgrade upstream version of PHP-OpenID to 2.1.2.
|
||||
- Move OpenMicroBlogging specification to its own repository.
|
||||
- Make tag-based RSS streams work.
|
||||
- Additional locales: Bulgarian, Catalan, Greek, Hebrew, simplified
|
||||
Chinese, Telugu, Taiwanese Chinese, Vietnamese,
|
||||
- PostgreSQL updates.
|
||||
- Nasty bug in Twitter bridge that wouldn't verify with Twitter
|
||||
- A plugin to allow a templating language for customization
|
||||
- A plugin for Piwik Analytics engine
|
||||
- A bookmarklet for posting a notice about a Web page you're reading
|
||||
- A welcome notice ('welcomebot') and default subscription for new users
|
||||
- Support for SSL for some or all pages on the site
|
||||
- Better handling of empty notice lists on many pages
|
||||
- Major improvements to the Twitter friend-sync offline processing
|
||||
- subscribers, subscriptions, groups are listed on the Personal page.
|
||||
- "Invite" link restored to main menu
|
||||
- Better memory handling in FOAF output
|
||||
- Fix for SUP support (FriendFeed)
|
||||
- Correct and intelligent redirect HTTP status codes
|
||||
- Fix DB collations for search and sort
|
||||
- Better H1s and Titles using user full names
|
||||
- Fixes to make the linkback plugin operational
|
||||
- Better indication that a notice is being published by Ajax (spinner)
|
||||
- Better and unified Atom output
|
||||
- Hiding "register" and "join now" messages when site is closed
|
||||
- ping, twitter and facebook queuehandlers working better
|
||||
- Updated RPM spec
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
@ -222,9 +197,9 @@ especially if you've previously installed PHP/MySQL packages.
|
||||
1. Unpack the tarball you downloaded on your Web server. Usually a
|
||||
command like this will work:
|
||||
|
||||
tar zxf laconica-0.7.1.tar.gz
|
||||
tar zxf laconica-0.7.3.tar.gz
|
||||
|
||||
...which will make a laconica-0.7.1 subdirectory in your current
|
||||
...which will make a laconica-0.7.3 subdirectory in your current
|
||||
directory. (If you don't have shell access on your Web server, you
|
||||
may have to unpack the tarball on your local computer and FTP the
|
||||
files to the server.)
|
||||
@ -232,7 +207,7 @@ especially if you've previously installed PHP/MySQL packages.
|
||||
2. Move the tarball to a directory of your choosing in your Web root
|
||||
directory. Usually something like this will work:
|
||||
|
||||
mv laconica-0.7.1 /var/www/mublog
|
||||
mv laconica-0.7.3 /var/www/mublog
|
||||
|
||||
This will make your Laconica instance available in the mublog path of
|
||||
your server, like "http://example.net/mublog". "microblog" or
|
||||
@ -240,21 +215,28 @@ especially if you've previously installed PHP/MySQL packages.
|
||||
configure virtual hosts on your web server, you can try setting up
|
||||
"http://micro.example.net/" or the like.
|
||||
|
||||
3. You should also take this moment to make your avatar subdirectory
|
||||
3. Make your target directory writeable by the Web server.
|
||||
|
||||
chmod a+w /var/www/mublog/
|
||||
|
||||
On some systems, this will probably work:
|
||||
|
||||
chgrp www-data /var/www/mublog/
|
||||
chmod g+w /var/www/mublog/
|
||||
|
||||
If your Web server runs as another user besides "www-data", try
|
||||
that user's default group instead. As a last resort, you can create
|
||||
a new group like "mublog" and add the Web server's user to the group.
|
||||
|
||||
4. You should also take this moment to make your avatar subdirectory
|
||||
writeable by the Web server. An insecure way to do this is:
|
||||
|
||||
chmod a+w /var/www/mublog/avatar
|
||||
|
||||
On some systems, this will probably work:
|
||||
You can also make the avatar directory writeable by the Web server
|
||||
group, as noted above.
|
||||
|
||||
chgrp www-data /var/www/mublog/avatar
|
||||
chmod g+w /var/www/mublog/avatar
|
||||
|
||||
If your Web server runs as another user besides "www-data", try
|
||||
that user's default group instead. As a last resort, you can create
|
||||
a new group like "avatar" and add the Web server's user to the group.
|
||||
|
||||
4. Create a database to hold your microblog data. Something like this
|
||||
5. Create a database to hold your microblog data. Something like this
|
||||
should work:
|
||||
|
||||
mysqladmin -u "username" --password="password" create laconica
|
||||
@ -267,63 +249,55 @@ especially if you've previously installed PHP/MySQL packages.
|
||||
a tool like PHPAdmin to create a database. Check your hosting
|
||||
service's documentation for how to create a new MySQL database.)
|
||||
|
||||
5. Run the laconica.sql SQL script in the db subdirectory to create
|
||||
the database tables in the database. A typical system would work
|
||||
like this:
|
||||
|
||||
mysql -u "username" --password="password" laconica < /var/www/mublog/db/laconica.sql
|
||||
|
||||
You may want to test by logging into the database and checking that
|
||||
the tables were created. Here's an example:
|
||||
|
||||
SHOW TABLES;
|
||||
|
||||
6. Create a new database account that Laconica will use to access the
|
||||
database. If you have shell access, this will probably work from the
|
||||
MySQL shell:
|
||||
|
||||
GRANT SELECT,INSERT,DELETE,UPDATE on laconica.*
|
||||
GRANT ALL on laconica.*
|
||||
TO 'lacuser'@'localhost'
|
||||
IDENTIFIED BY 'lacpassword';
|
||||
|
||||
You should change 'lacuser' and 'lacpassword' to your preferred new
|
||||
username and password. You may want to test logging in as this new
|
||||
user and testing that you can SELECT from some of the tables in the
|
||||
DB (use SHOW TABLES to see which ones are there).
|
||||
username and password. You may want to test logging in to MySQL as
|
||||
this new user.
|
||||
|
||||
7. Copy the config.php.sample in the Laconica directory to config.php.
|
||||
7. In a browser, navigate to the Laconica install script; something like:
|
||||
|
||||
8. Edit config.php to set the basic configuration for your system.
|
||||
(See descriptions below for basic config options.) Note that there
|
||||
are lots of options and if you try to do them all at once, you will
|
||||
have a hard time making sure what's working and what's not. So,
|
||||
stick with the basics at first. In particular, customizing the
|
||||
'site' and 'db' settings will almost definitely be needed.
|
||||
http://yourserver.example.com/mublog/install.php
|
||||
|
||||
9. At this point, you should be able to navigate in a browser to your
|
||||
microblog's main directory and see the "Public Timeline", which
|
||||
will be empty. If not, magic has happened! You can now register a
|
||||
new user, post some notices, edit your profile, etc. However, you
|
||||
may want to wait to do that stuff if you think you can set up
|
||||
"fancy URLs" (see below), since some URLs are stored in the database.
|
||||
Enter the database connection information and your site name. The
|
||||
install program will configure your site and install the initial,
|
||||
almost-empty database.
|
||||
|
||||
8. You should now be able to navigate to your microblog's main directory
|
||||
and see the "Public Timeline", which will be empty. If not, magic
|
||||
has happened! You can now register a new user, post some notices,
|
||||
edit your profile, etc. However, you may want to wait to do that stuff
|
||||
if you think you can set up "fancy URLs" (see below), since some
|
||||
URLs are stored in the database.
|
||||
|
||||
Fancy URLs
|
||||
----------
|
||||
|
||||
By default, Laconica will have big long sloppy URLs that are hard for
|
||||
people to remember or use. For example, a user's home profile might be
|
||||
By default, Laconica will use URLs that include the main PHP program's
|
||||
name in them. For example, a user's home profile might be
|
||||
found at:
|
||||
|
||||
http://example.org/mublog/index.php?action=showstream&nickname=fred
|
||||
http://example.org/mublog/index.php/mublog/fred
|
||||
|
||||
On certain systems that don't support this kind of syntax, they'll
|
||||
look like this:
|
||||
|
||||
http://example.org/mublog/index.php?p=mublog/fred
|
||||
|
||||
It's possible to configure the software so it looks like this instead:
|
||||
|
||||
http://example.org/mublog/fred
|
||||
|
||||
These "fancy URLs" are more readable and memorable for users. To use
|
||||
fancy URLs, you must either have Apache 2.2.x with .htaccess enabled
|
||||
and mod_redirect enabled, -OR- know how to configure "url redirection"
|
||||
in your server.
|
||||
fancy URLs, you must either have Apache 2.x with .htaccess enabled and
|
||||
mod_redirect enabled, -OR- know how to configure "url redirection" in
|
||||
your server.
|
||||
|
||||
1. Copy the htaccess.sample file to .htaccess in your Laconica
|
||||
directory. Note: if you have control of your server's httpd.conf or
|
||||
@ -348,10 +322,6 @@ like:
|
||||
If you changed your HTTP server configuration, you may need to restart
|
||||
the server first.
|
||||
|
||||
If you have problems with the .htaccess file on versions of Apache
|
||||
earlier than 2.2.x, try changing the regular expressions in the
|
||||
htaccess.sample file that use "\w" to just use ".".
|
||||
|
||||
Sphinx
|
||||
------
|
||||
|
||||
@ -511,7 +481,7 @@ server is probably a good idea for high-volume sites.
|
||||
needs as a parameter the install path; if you run it from the
|
||||
Laconica dir, "." should suffice.
|
||||
|
||||
This will run six (for now) queue handlers:
|
||||
This will run eight (for now) queue handlers:
|
||||
|
||||
* xmppdaemon.php - listens for new XMPP messages from users and stores
|
||||
them as notices in the database.
|
||||
@ -525,6 +495,10 @@ This will run six (for now) queue handlers:
|
||||
of registered users.
|
||||
* xmppconfirmhandler.php - sends confirmation messages to registered
|
||||
users.
|
||||
* twitterqueuehandler.php - sends queued notices to Twitter for user
|
||||
who have opted to set up Twitter bridging.
|
||||
* facebookqueuehandler.php - sends queued notices to Facebook for users
|
||||
of the built-in Facebook application.
|
||||
|
||||
Note that these queue daemons are pretty raw, and need your care. In
|
||||
particular, they leak memory, and you may want to restart them on a
|
||||
@ -557,6 +531,53 @@ Sample cron job:
|
||||
# Update Twitter friends subscriptions every half hour
|
||||
0,30 * * * * /path/to/php /path/to/laconica/scripts/synctwitterfriends.php>&/dev/null
|
||||
|
||||
Built-in Facebook Application
|
||||
-----------------------------
|
||||
|
||||
Laconica's Facebook application allows your users to automatically
|
||||
update their Facebook statuses with their latest notices, invite
|
||||
their friends to use the app (and thus your site), view their notice
|
||||
timelines, and post notices -- all from within Facebook. The application
|
||||
is built into Laconica and runs on your host. For automatic Facebook
|
||||
status updating to work you will need to enable queuing and run the
|
||||
facebookqueuehandler.php daemon (see the "Queues and daemons" section
|
||||
above).
|
||||
|
||||
Quick setup instructions*:
|
||||
|
||||
Install the Facebook Developer application on Facebook:
|
||||
|
||||
http://www.facebook.com/developers/
|
||||
|
||||
Use it to create a new application and generate an API key and secret.
|
||||
Uncomment the Facebook app section of your config.php and copy in the
|
||||
key and secret, e.g.:
|
||||
|
||||
# Config section for the built-in Facebook application
|
||||
$config['facebook']['apikey'] = 'APIKEY';
|
||||
$config['facebook']['secret'] = 'SECRET';
|
||||
|
||||
In Facebook's application editor, specify the following URLs for your app:
|
||||
|
||||
- Callback URL: http://example.net/mublog/facebook/
|
||||
- Post-Remove URL: http://example.net/mublog/facebook/remove
|
||||
- Post-Add Redirect URL: http://apps.facebook.com/yourapp/
|
||||
- Canvas URL: http://apps.facebook.com/yourapp/
|
||||
|
||||
(Replace 'example.net' with your host's URL, 'mublog' with the path
|
||||
to your Laconica installation, and 'yourapp' with the name of the
|
||||
Facebook application you created.)
|
||||
|
||||
Additionally, Choose "Web" for Application type in the Advanced tab.
|
||||
In the "Canvas setting" section, choose the "FBML" for Render Method,
|
||||
"Smart Size" for IFrame size, and "Full width (760px)" for Canvas Width.
|
||||
Everything else can be left with default values.
|
||||
|
||||
*For more detailed instructions please see the installation guide on the
|
||||
Laconica wiki:
|
||||
|
||||
http://laconi.ca/trac/wiki/FacebookApplication
|
||||
|
||||
Sitemaps
|
||||
--------
|
||||
|
||||
@ -597,7 +618,7 @@ to these resources.
|
||||
Themes
|
||||
------
|
||||
|
||||
There are two themes shipped with this version of Laconica: "stoica",
|
||||
There are two themes shipped with this version of Laconica: "identica",
|
||||
which is what the Identi.ca site uses, and "default", which is a good
|
||||
basis for other sites.
|
||||
|
||||
@ -676,7 +697,7 @@ Upgrading
|
||||
If you've been using Laconica 0.6, 0.5 or lower, or if you've been
|
||||
tracking the "git" version of the software, you will probably want
|
||||
to upgrade and keep your existing data. There is no automated upgrade
|
||||
procedure in Laconica 0.7.1. Try these step-by-step instructions; read
|
||||
procedure in Laconica 0.7.3. Try these step-by-step instructions; read
|
||||
to the end first before trying them.
|
||||
|
||||
0. Download Laconica and set up all the prerequisites as if you were
|
||||
@ -703,16 +724,19 @@ to the end first before trying them.
|
||||
directory to your new directory.
|
||||
9. Copy htaccess.sample to .htaccess in the new directory. Change the
|
||||
RewriteBase to use the correct path.
|
||||
10. Rebuild the database. Go to your Laconica directory and run the
|
||||
rebuilddb.sh script like this:
|
||||
10. Rebuild the database. For MySQL, go to your Laconica directory and
|
||||
run the rebuilddb.sh script like this:
|
||||
|
||||
./scripts/rebuilddb.sh rootuser rootpassword database db/laconica.sql
|
||||
|
||||
Here, rootuser and rootpassword are the username and password for a
|
||||
user who can drop and create databases as well as tables; typically
|
||||
that's _not_ the user Laconica runs as.
|
||||
11. Use mysql client to log into your database and make sure that the
|
||||
notice, user, profile, subscription etc. tables are non-empty.
|
||||
For PostgreSQL databases there is an equivalent, rebuilddb_psql.sh,
|
||||
which operates slightly differently. Read the documentation in that
|
||||
script before running it.
|
||||
11. Use mysql or psql client to log into your database and make sure that
|
||||
the notice, user, profile, subscription etc. tables are non-empty.
|
||||
12. Turn back on the Web server, and check that things still work.
|
||||
13. Turn back on XMPP bots and email maildaemon. Note that the XMPP
|
||||
bots have changed since version 0.5; see above for details.
|
||||
@ -793,7 +817,7 @@ This section is a catch-all for site-wide variables.
|
||||
|
||||
name: the name of your site, like 'YourCompany Microblog'.
|
||||
server: the server part of your site's URLs, like 'example.net'.
|
||||
path: The path part of your site's URLs, like 'mublog' or '/'
|
||||
path: The path part of your site's URLs, like 'mublog' or ''
|
||||
(installed in root).
|
||||
fancy: whether or not your site uses fancy URLs (see Fancy URLs
|
||||
section above). Default is false.
|
||||
@ -837,6 +861,20 @@ notice: A plain string that will appear on every page. A good place
|
||||
to put introductory information about your service, or info about
|
||||
upgrades and outages, or other community info. Any HTML will
|
||||
be escaped.
|
||||
dupelimit: Time in which it's not OK for the same person to post the
|
||||
same notice; default = 60 seconds.
|
||||
logo: URL of an image file to use as the logo for the site. Overrides
|
||||
the logo in the theme, if any.
|
||||
ssl: Whether to use SSL and https:// URLs for some or all pages.
|
||||
Possible values are 'always' (use it for all pages), 'never'
|
||||
(don't use it for any pages), or 'sometimes' (use it for
|
||||
sensitive pages that include passwords like login and registration,
|
||||
but not for regular pages). Default to 'never'.
|
||||
sslserver: use an alternate server name for SSL URLs, like
|
||||
'secure.example.org'. You should be careful to set cookie
|
||||
parameters correctly so that both the SSL server and the
|
||||
"normal" server can access the session cookie and
|
||||
preferably other cookies as well.
|
||||
|
||||
db
|
||||
--
|
||||
@ -1081,6 +1119,23 @@ banned: an array of usernames and/or profile IDs of 'banned' profiles.
|
||||
not be accepted at all. (Compare with blacklisted users above,
|
||||
whose posts just won't show up in the public stream.)
|
||||
|
||||
newuser
|
||||
-------
|
||||
|
||||
Options with new users.
|
||||
|
||||
default: nickname of a user account to automatically subscribe new
|
||||
users to. Typically this would be system account for e.g.
|
||||
service updates or announcements. Users are able to unsub
|
||||
if they want. Default is null; no auto subscribe.
|
||||
welcome: nickname of a user account that sends welcome messages to new
|
||||
users. Can be the same as 'default' account, although on
|
||||
busy servers it may be a good idea to keep that one just for
|
||||
'urgent' messages. Default is null; no message.
|
||||
|
||||
If either of these special user accounts are specified, the users should
|
||||
be created before the configuration is updated.
|
||||
|
||||
Troubleshooting
|
||||
===============
|
||||
|
||||
@ -1093,7 +1148,7 @@ repository (see below), and you get a compilation error ("unexpected
|
||||
T_STRING") in the browser, check to see that you don't have any
|
||||
conflicts in your code.
|
||||
|
||||
If you upgraded to Laconica 0.7.1 without reading the "Notice inboxes"
|
||||
If you upgraded to Laconica 0.7.3 without reading the "Notice inboxes"
|
||||
section above, and all your users' 'Personal' tabs are empty, read the
|
||||
"Notice inboxes" section above.
|
||||
|
||||
@ -1179,6 +1234,11 @@ if anyone's been overlooked in error.
|
||||
* Ken Sheppardson (Trac server, man-about-town)
|
||||
* Tiago 'gouki' Faria (i18n managerx)
|
||||
* Sean Murphy
|
||||
* Leslie Michael Orchard
|
||||
* Eric Helgeson
|
||||
* Ken Sedgwick
|
||||
* Brian Hendrickson
|
||||
* Tobias Diekershoff
|
||||
|
||||
Thanks also to the developers of our upstream library code and to the
|
||||
thousands of people who have tried out Identi.ca, installed Laconi.ca,
|
||||
|
@ -59,7 +59,7 @@ class AccesstokenAction extends Action
|
||||
try {
|
||||
common_debug('getting request from env variables', __FILE__);
|
||||
common_remove_magic_from_request();
|
||||
$req = OAuthRequest::from_request();
|
||||
$req = OAuthRequest::from_request('POST', common_local_url('accesstoken'));
|
||||
common_debug('getting a server', __FILE__);
|
||||
$server = omb_oauth_server();
|
||||
common_debug('fetching the access token', __FILE__);
|
||||
|
@ -23,31 +23,13 @@ require_once INSTALLDIR.'/lib/personalgroupnav.php';
|
||||
require_once INSTALLDIR.'/lib/noticelist.php';
|
||||
require_once INSTALLDIR.'/lib/feedlist.php';
|
||||
|
||||
class AllAction extends Action
|
||||
class AllAction extends ProfileAction
|
||||
{
|
||||
var $user = null;
|
||||
var $page = null;
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
$nickname = common_canonical_nickname($this->arg('nickname'));
|
||||
$this->user = User::staticGet('nickname', $nickname);
|
||||
$this->page = $this->trimmed('page');
|
||||
if (!$this->page) {
|
||||
$this->page = 1;
|
||||
}
|
||||
|
||||
common_set_returnto($this->selfUrl());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
@ -77,22 +59,54 @@ class AllAction extends Action
|
||||
sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->user->nickname)),
|
||||
new Feed(Feed::RSS2,
|
||||
common_local_url('api', array('apiaction' => 'statuses',
|
||||
'method' => 'friends',
|
||||
'method' => 'friends_timeline',
|
||||
'argument' => $this->user->nickname.'.rss')),
|
||||
sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->user->nickname)),
|
||||
new Feed(Feed::ATOM,
|
||||
common_local_url('api', array('apiaction' => 'statuses',
|
||||
'method' => 'friends',
|
||||
'method' => 'friends_timeline',
|
||||
'argument' => $this->user->nickname.'.atom')),
|
||||
sprintf(_('Feed for friends of %s (Atom)'), $this->user->nickname)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Output document relationship links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showRelationshipLinks()
|
||||
{
|
||||
$this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME
|
||||
$this->page, 'all', array('nickname' => $this->user->nickname));
|
||||
}
|
||||
|
||||
function showLocalNav()
|
||||
{
|
||||
$nav = new PersonalGroupNav($this);
|
||||
$nav->show();
|
||||
}
|
||||
|
||||
function showEmptyListMessage()
|
||||
{
|
||||
$message = sprintf(_('This is the timeline for %s and friends but no one has posted anything yet.'), $this->user->nickname) . ' ';
|
||||
|
||||
if (common_logged_in()) {
|
||||
$current_user = common_current_user();
|
||||
if ($this->user->id === $current_user->id) {
|
||||
$message .= _('Try subscribing to more people, [join a group](%%action.groups%%) or post something yourself.');
|
||||
} else {
|
||||
$message .= sprintf(_('You can try to [nudge %s](../%s) from his profile or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname);
|
||||
}
|
||||
|
||||
$this->elementStart('div', 'guide');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function showContent()
|
||||
{
|
||||
$notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
|
||||
@ -101,6 +115,10 @@ class AllAction extends Action
|
||||
|
||||
$cnt = $nl->show();
|
||||
|
||||
if (0 == $cnt) {
|
||||
$this->showEmptyListMessage();
|
||||
}
|
||||
|
||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$this->page, 'all', array('nickname' => $this->user->nickname));
|
||||
}
|
||||
|
@ -54,6 +54,8 @@ class AllrssAction extends Rss10Action
|
||||
/**
|
||||
* Initialization.
|
||||
*
|
||||
* @param array $args Web and URL arguments
|
||||
*
|
||||
* @return boolean false if user doesn't exist
|
||||
*/
|
||||
function prepare($args)
|
||||
@ -81,6 +83,7 @@ class AllrssAction extends Rss10Action
|
||||
{
|
||||
$user = $this->user;
|
||||
$notice = $user->noticesWithFriends(0, $limit);
|
||||
$notices = array();
|
||||
|
||||
while ($notice->fetch()) {
|
||||
$notices[] = clone($notice);
|
||||
@ -104,7 +107,8 @@ class AllrssAction extends Rss10Action
|
||||
'link' => common_local_url('all',
|
||||
array('nickname' =>
|
||||
$user->nickname)),
|
||||
'description' => sprintf(_('Feed for friends of %s'), $user->nickname));
|
||||
'description' => sprintf(_('Feed for friends of %s'),
|
||||
$user->nickname));
|
||||
return $c;
|
||||
}
|
||||
|
||||
@ -123,10 +127,5 @@ class AllrssAction extends Rss10Action
|
||||
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||
return $avatar ? $avatar->url : null;
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,18 +127,21 @@ class ApiAction extends Action
|
||||
'laconica/wadl');
|
||||
|
||||
static $bareauth = array('statuses/user_timeline',
|
||||
'statuses/friends_timeline',
|
||||
'statuses/friends',
|
||||
'statuses/replies',
|
||||
'statuses/mentions',
|
||||
'statuses/followers',
|
||||
'favorites/favorites');
|
||||
|
||||
# If the site is "private", all API methods need authentication
|
||||
|
||||
if (common_config('site', 'private')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$fullname = "$this->api_action/$this->api_method";
|
||||
|
||||
// If the site is "private", all API methods except laconica/config
|
||||
// need authentication
|
||||
if (common_config('site', 'private')) {
|
||||
return $fullname != 'laconica/config' || false;
|
||||
}
|
||||
|
||||
if (in_array($fullname, $bareauth)) {
|
||||
# bareauth: only needs auth if without an argument
|
||||
if ($this->api_arg) {
|
||||
@ -178,11 +181,11 @@ class ApiAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
# NOTE: before handle(), can't use $this->arg
|
||||
$apiaction = $_REQUEST['apiaction'];
|
||||
$method = $_REQUEST['method'];
|
||||
$apiaction = $args['apiaction'];
|
||||
$method = $args['method'];
|
||||
|
||||
list($cmdtext, $fmt) = explode('.', $method);
|
||||
|
||||
static $write_methods = array(
|
||||
@ -205,5 +208,4 @@ class ApiAction extends Action
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
209
actions/attachment.php
Normal file
209
actions/attachment.php
Normal file
@ -0,0 +1,209 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* Show notice attachments
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* @category Personal
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @copyright 2008-2009 Control Yourself, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//require_once INSTALLDIR.'/lib/personalgroupnav.php';
|
||||
//require_once INSTALLDIR.'/lib/feedlist.php';
|
||||
require_once INSTALLDIR.'/lib/attachmentlist.php';
|
||||
|
||||
/**
|
||||
* Show notice attachments
|
||||
*
|
||||
* @category Personal
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
class AttachmentAction extends Action
|
||||
{
|
||||
/**
|
||||
* Attachment object to show
|
||||
*/
|
||||
|
||||
var $attachment = null;
|
||||
|
||||
/**
|
||||
* Load attributes based on database arguments
|
||||
*
|
||||
* Loads all the DB stuff
|
||||
*
|
||||
* @param array $args $_REQUEST array
|
||||
*
|
||||
* @return success flag
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$id = $this->arg('attachment');
|
||||
|
||||
$this->attachment = File::staticGet($id);
|
||||
|
||||
if (!$this->attachment) {
|
||||
$this->clientError(_('No such attachment.'), 404);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this action read-only?
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Title of the page
|
||||
*
|
||||
* @return string title of the page
|
||||
*/
|
||||
function title()
|
||||
{
|
||||
$a = new Attachment($this->attachment);
|
||||
return $a->title();
|
||||
}
|
||||
|
||||
/**
|
||||
* Last-modified date for page
|
||||
*
|
||||
* When was the content of this page last modified? Based on notice,
|
||||
* profile, avatar.
|
||||
*
|
||||
* @return int last-modified date as unix timestamp
|
||||
*/
|
||||
/*
|
||||
function lastModified()
|
||||
{
|
||||
return max(strtotime($this->notice->created),
|
||||
strtotime($this->profile->modified),
|
||||
($this->avatar) ? strtotime($this->avatar->modified) : 0);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* An entity tag for this page
|
||||
*
|
||||
* Shows the ETag for the page, based on the notice ID and timestamps
|
||||
* for the notice, profile, and avatar. It's weak, since we change
|
||||
* the date text "one hour ago", etc.
|
||||
*
|
||||
* @return string etag
|
||||
*/
|
||||
/*
|
||||
function etag()
|
||||
{
|
||||
$avtime = ($this->avatar) ?
|
||||
strtotime($this->avatar->modified) : 0;
|
||||
|
||||
return 'W/"' . implode(':', array($this->arg('action'),
|
||||
common_language(),
|
||||
$this->notice->id,
|
||||
strtotime($this->notice->created),
|
||||
strtotime($this->profile->modified),
|
||||
$avtime)) . '"';
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Handle input
|
||||
*
|
||||
* Only handles get, so just show the page.
|
||||
*
|
||||
* @param array $args $_REQUEST data (unused)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't show local navigation
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showLocalNavBlock()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the content area of the page
|
||||
*
|
||||
* Shows a single notice list item.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showContent()
|
||||
{
|
||||
$this->elementStart('ul', array('class' => 'attachments'));
|
||||
$ali = new Attachment($this->attachment, $this);
|
||||
$cnt = $ali->show();
|
||||
$this->elementEnd('ul');
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't show page notice
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showPageNoticeBlock()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Show aside: this attachments appears in what notices
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showSections() {
|
||||
$ns = new AttachmentNoticeSection($this);
|
||||
$ns->show();
|
||||
$atcs = new AttachmentTagCloudSection($this);
|
||||
$atcs->show();
|
||||
}
|
||||
}
|
||||
|
141
actions/attachment_ajax.php
Normal file
141
actions/attachment_ajax.php
Normal file
@ -0,0 +1,141 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* Show notice attachments
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* @category Personal
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @copyright 2008-2009 Control Yourself, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/actions/attachment.php';
|
||||
|
||||
/**
|
||||
* Show notice attachments
|
||||
*
|
||||
* @category Personal
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
class Attachment_ajaxAction extends AttachmentAction
|
||||
{
|
||||
/**
|
||||
* Load attributes based on database arguments
|
||||
*
|
||||
* Loads all the DB stuff
|
||||
*
|
||||
* @param array $args $_REQUEST array
|
||||
*
|
||||
* @return success flag
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
if (!$this->attachment) {
|
||||
$this->clientError(_('No such attachment.'), 404);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show page, a template method.
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
function showPage()
|
||||
{
|
||||
if (Event::handle('StartShowBody', array($this))) {
|
||||
$this->showCore();
|
||||
Event::handle('EndShowBody', array($this));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show core.
|
||||
*
|
||||
* Shows local navigation, content block and aside.
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
function showCore()
|
||||
{
|
||||
$this->elementStart('div', array('id' => 'core'));
|
||||
if (Event::handle('StartShowContentBlock', array($this))) {
|
||||
$this->showContentBlock();
|
||||
Event::handle('EndShowContentBlock', array($this));
|
||||
}
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Last-modified date for page
|
||||
*
|
||||
* When was the content of this page last modified? Based on notice,
|
||||
* profile, avatar.
|
||||
*
|
||||
* @return int last-modified date as unix timestamp
|
||||
*/
|
||||
/*
|
||||
function lastModified()
|
||||
{
|
||||
return max(strtotime($this->notice->created),
|
||||
strtotime($this->profile->modified),
|
||||
($this->avatar) ? strtotime($this->avatar->modified) : 0);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* An entity tag for this page
|
||||
*
|
||||
* Shows the ETag for the page, based on the notice ID and timestamps
|
||||
* for the notice, profile, and avatar. It's weak, since we change
|
||||
* the date text "one hour ago", etc.
|
||||
*
|
||||
* @return string etag
|
||||
*/
|
||||
/*
|
||||
function etag()
|
||||
{
|
||||
$avtime = ($this->avatar) ?
|
||||
strtotime($this->avatar->modified) : 0;
|
||||
|
||||
return 'W/"' . implode(':', array($this->arg('action'),
|
||||
common_language(),
|
||||
$this->notice->id,
|
||||
strtotime($this->notice->created),
|
||||
strtotime($this->profile->modified),
|
||||
$avtime)) . '"';
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
292
actions/attachments.php
Normal file
292
actions/attachments.php
Normal file
@ -0,0 +1,292 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* Show notice attachments
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* @category Personal
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @copyright 2008-2009 Control Yourself, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//require_once INSTALLDIR.'/lib/personalgroupnav.php';
|
||||
//require_once INSTALLDIR.'/lib/feedlist.php';
|
||||
require_once INSTALLDIR.'/lib/attachmentlist.php';
|
||||
|
||||
/**
|
||||
* Show notice attachments
|
||||
*
|
||||
* @category Personal
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
class AttachmentsAction extends Action
|
||||
{
|
||||
/**
|
||||
* Notice object to show
|
||||
*/
|
||||
|
||||
var $notice = null;
|
||||
|
||||
/**
|
||||
* Profile of the notice object
|
||||
*/
|
||||
|
||||
var $profile = null;
|
||||
|
||||
/**
|
||||
* Avatar of the profile of the notice object
|
||||
*/
|
||||
|
||||
var $avatar = null;
|
||||
|
||||
/**
|
||||
* Is this action read-only?
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Last-modified date for page
|
||||
*
|
||||
* When was the content of this page last modified? Based on notice,
|
||||
* profile, avatar.
|
||||
*
|
||||
* @return int last-modified date as unix timestamp
|
||||
*/
|
||||
|
||||
function lastModified()
|
||||
{
|
||||
return max(strtotime($this->notice->created),
|
||||
strtotime($this->profile->modified),
|
||||
($this->avatar) ? strtotime($this->avatar->modified) : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* An entity tag for this page
|
||||
*
|
||||
* Shows the ETag for the page, based on the notice ID and timestamps
|
||||
* for the notice, profile, and avatar. It's weak, since we change
|
||||
* the date text "one hour ago", etc.
|
||||
*
|
||||
* @return string etag
|
||||
*/
|
||||
|
||||
function etag()
|
||||
{
|
||||
$avtime = ($this->avatar) ?
|
||||
strtotime($this->avatar->modified) : 0;
|
||||
|
||||
return 'W/"' . implode(':', array($this->arg('action'),
|
||||
common_language(),
|
||||
$this->notice->id,
|
||||
strtotime($this->notice->created),
|
||||
strtotime($this->profile->modified),
|
||||
$avtime)) . '"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Title of the page
|
||||
*
|
||||
* @return string title of the page
|
||||
*/
|
||||
|
||||
function title()
|
||||
{
|
||||
return sprintf(_('%1$s\'s status on %2$s'),
|
||||
$this->profile->nickname,
|
||||
common_exact_date($this->notice->created));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load attributes based on database arguments
|
||||
*
|
||||
* Loads all the DB stuff
|
||||
*
|
||||
* @param array $args $_REQUEST array
|
||||
*
|
||||
* @return success flag
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$id = $this->arg('notice');
|
||||
|
||||
$this->notice = Notice::staticGet($id);
|
||||
|
||||
if (!$this->notice) {
|
||||
$this->clientError(_('No such notice.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// STOP if there are no attachments
|
||||
// maybe even redirect if there's a single one
|
||||
// RYM FIXME TODO
|
||||
$this->clientError(_('No such attachment.'), 404);
|
||||
return false;
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
$this->profile = $this->notice->getProfile();
|
||||
|
||||
if (!$this->profile) {
|
||||
$this->serverError(_('Notice has no profile'), 500);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Handle input
|
||||
*
|
||||
* Only handles get, so just show the page.
|
||||
*
|
||||
* @param array $args $_REQUEST data (unused)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if ($this->notice->is_local == 0) {
|
||||
if (!empty($this->notice->url)) {
|
||||
common_redirect($this->notice->url, 301);
|
||||
} else if (!empty($this->notice->uri) && preg_match('/^https?:/', $this->notice->uri)) {
|
||||
common_redirect($this->notice->uri, 301);
|
||||
}
|
||||
} else {
|
||||
$f2p = new File_to_post;
|
||||
$f2p->post_id = $this->notice->id;
|
||||
$file = new File;
|
||||
$file->joinAdd($f2p);
|
||||
$file->selectAdd();
|
||||
$file->selectAdd('file.id as id');
|
||||
$count = $file->find(true);
|
||||
if (!$count) return;
|
||||
if (1 === $count) {
|
||||
common_redirect(common_local_url('attachment', array('attachment' => $file->id)), 301);
|
||||
} else {
|
||||
$this->showPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't show local navigation
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showLocalNavBlock()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the content area of the page
|
||||
*
|
||||
* Shows a single notice list item.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showContent()
|
||||
{
|
||||
$al = new AttachmentList($this->notice, $this);
|
||||
$cnt = $al->show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't show page notice
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showPageNoticeBlock()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't show aside
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showAside() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra <head> content
|
||||
*
|
||||
* We show the microid(s) for the author, if any.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function extraHead()
|
||||
{
|
||||
$user = User::staticGet($this->profile->id);
|
||||
|
||||
if (!$user) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($user->emailmicroid && $user->email && $this->notice->uri) {
|
||||
$id = new Microid('mailto:'. $user->email,
|
||||
$this->notice->uri);
|
||||
$this->element('meta', array('name' => 'microid',
|
||||
'content' => $id->toString()));
|
||||
}
|
||||
|
||||
if ($user->jabbermicroid && $user->jabber && $this->notice->uri) {
|
||||
$id = new Microid('xmpp:', $user->jabber,
|
||||
$this->notice->uri);
|
||||
$this->element('meta', array('name' => 'microid',
|
||||
'content' => $id->toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
115
actions/attachments_ajax.php
Normal file
115
actions/attachments_ajax.php
Normal file
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* Show notice attachments
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* @category Personal
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @copyright 2008-2009 Control Yourself, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//require_once INSTALLDIR.'/lib/personalgroupnav.php';
|
||||
//require_once INSTALLDIR.'/lib/feedlist.php';
|
||||
require_once INSTALLDIR.'/actions/attachments.php';
|
||||
|
||||
/**
|
||||
* Show notice attachments
|
||||
*
|
||||
* @category Personal
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
class Attachments_ajaxAction extends AttachmentsAction
|
||||
{
|
||||
function showContent()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the content area of the page
|
||||
*
|
||||
* Shows a single notice list item.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showContentBlock()
|
||||
{
|
||||
$al = new AttachmentList($this->notice, $this);
|
||||
$cnt = $al->show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra <head> content
|
||||
*
|
||||
* We show the microid(s) for the author, if any.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function extraHead()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show page, a template method.
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
function showPage()
|
||||
{
|
||||
if (Event::handle('StartShowBody', array($this))) {
|
||||
$this->showCore();
|
||||
Event::handle('EndShowBody', array($this));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show core.
|
||||
*
|
||||
* Shows local navigation, content block and aside.
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
function showCore()
|
||||
{
|
||||
$this->elementStart('div', array('id' => 'core'));
|
||||
if (Event::handle('StartShowContentBlock', array($this))) {
|
||||
$this->showContentBlock();
|
||||
Event::handle('EndShowContentBlock', array($this));
|
||||
}
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ class AvatarbynicknameAction extends Action
|
||||
common_redirect($url, 302);
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -324,13 +324,14 @@ class AvatarsettingsAction extends AccountSettingsAction
|
||||
return;
|
||||
}
|
||||
|
||||
// If image is not being cropped assume pos & dimentions of original
|
||||
$file_d = ($filedata['width'] > $filedata['height'])
|
||||
? $filedata['height'] : $filedata['width'];
|
||||
|
||||
$dest_x = $this->arg('avatar_crop_x') ? $this->arg('avatar_crop_x'):0;
|
||||
$dest_y = $this->arg('avatar_crop_y') ? $this->arg('avatar_crop_y'):0;
|
||||
$dest_w = $this->arg('avatar_crop_w') ? $this->arg('avatar_crop_w'):$filedata['width'];
|
||||
$dest_h = $this->arg('avatar_crop_h') ? $this->arg('avatar_crop_h'):$filedata['height'];
|
||||
$size = min($dest_w, $dest_h);
|
||||
$size = ($size > MAX_ORIGINAL) ? MAX_ORIGINAL:$size;
|
||||
$dest_w = $this->arg('avatar_crop_w') ? $this->arg('avatar_crop_w'):$file_d;
|
||||
$dest_h = $this->arg('avatar_crop_h') ? $this->arg('avatar_crop_h'):$file_d;
|
||||
$size = min($dest_w, $dest_h, MAX_ORIGINAL);
|
||||
|
||||
$user = common_current_user();
|
||||
$profile = $user->getProfile();
|
||||
@ -343,6 +344,7 @@ class AvatarsettingsAction extends AccountSettingsAction
|
||||
unset($_SESSION['FILEDATA']);
|
||||
$this->mode = 'upload';
|
||||
$this->showForm(_('Avatar updated.'), true);
|
||||
common_broadcast_profile($profile);
|
||||
} else {
|
||||
$this->showForm(_('Failed updating avatar.'));
|
||||
}
|
||||
|
@ -93,7 +93,8 @@ class BlockAction extends Action
|
||||
if ($this->arg('no')) {
|
||||
$cur = common_current_user();
|
||||
$other = Profile::staticGet('id', $this->arg('blockto'));
|
||||
common_redirect(common_local_url('showstream', array('nickname' => $other->nickname)));
|
||||
common_redirect(common_local_url('showstream', array('nickname' => $other->nickname)),
|
||||
303);
|
||||
} elseif ($this->arg('yes')) {
|
||||
$this->blockProfile();
|
||||
} elseif ($this->arg('blockto')) {
|
||||
@ -102,7 +103,6 @@ class BlockAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function showContent() {
|
||||
$this->areYouSureForm();
|
||||
}
|
||||
@ -178,10 +178,11 @@ class BlockAction extends Action
|
||||
}
|
||||
|
||||
if ($action) {
|
||||
common_redirect(common_local_url($action, $args));
|
||||
common_redirect(common_local_url($action, $args), 303);
|
||||
} else {
|
||||
common_redirect(common_local_url('subscriptions',
|
||||
array('nickname' => $cur->nickname)));
|
||||
array('nickname' => $cur->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
107
actions/conversation.php
Normal file
107
actions/conversation.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
/**
|
||||
* Display a conversation in the browser
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Action
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://laconi.ca/
|
||||
*
|
||||
* Laconica - a distributed open-source microblogging tool
|
||||
* Copyright (C) 2008, Controlez-Vous, Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once(INSTALLDIR.'/lib/noticelist.php');
|
||||
|
||||
/**
|
||||
* Conversation tree in the browser
|
||||
*
|
||||
* @category Action
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
class ConversationAction extends Action
|
||||
{
|
||||
var $id = null;
|
||||
var $page = null;
|
||||
|
||||
/**
|
||||
* Initialization.
|
||||
*
|
||||
* @param array $args Web and URL arguments
|
||||
*
|
||||
* @return boolean false if id not passed in
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
$this->id = $this->trimmed('id');
|
||||
if (empty($this->id)) {
|
||||
return false;
|
||||
}
|
||||
$this->page = $this->trimmed('page');
|
||||
if (empty($this->page)) {
|
||||
$this->page = 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
return _("Conversation");
|
||||
}
|
||||
|
||||
function showContent()
|
||||
{
|
||||
// FIXME this needs to be a tree, not a list
|
||||
|
||||
$qry = 'SELECT * FROM notice WHERE conversation = %s ';
|
||||
|
||||
$offset = ($this->page-1)*NOTICES_PER_PAGE;
|
||||
$limit = NOTICES_PER_PAGE + 1;
|
||||
|
||||
$txt = sprintf($qry, $this->id);
|
||||
|
||||
$notices = Notice::getStream($txt,
|
||||
'notice:conversation:'.$this->id,
|
||||
$offset, $limit);
|
||||
|
||||
$nl = new NoticeList($notices, $this);
|
||||
|
||||
$cnt = $nl->show();
|
||||
|
||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$this->page, 'conversation', array('id' => $this->id));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -141,6 +141,6 @@ class DeletenoticeAction extends DeleteAction
|
||||
$url = common_local_url('public');
|
||||
}
|
||||
|
||||
common_redirect($url);
|
||||
common_redirect($url, 303);
|
||||
}
|
||||
}
|
||||
|
262
actions/designsettings.php
Normal file
262
actions/designsettings.php
Normal file
@ -0,0 +1,262 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* Change user password
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* @category Settings
|
||||
* @package Laconica
|
||||
* @author Sarven Capadisli <csarven@controlyourself.ca>
|
||||
* @copyright 2008-2009 Control Yourself, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/accountsettingsaction.php';
|
||||
|
||||
|
||||
|
||||
class DesignsettingsAction extends AccountSettingsAction
|
||||
{
|
||||
/**
|
||||
* Title of the page
|
||||
*
|
||||
* @return string Title of the page
|
||||
*/
|
||||
|
||||
function title()
|
||||
{
|
||||
return _('Profile design');
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructions for use
|
||||
*
|
||||
* @return instructions for use
|
||||
*/
|
||||
|
||||
function getInstructions()
|
||||
{
|
||||
return _('Customize the way your profile looks with a background image and a colour palette of your choice.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Content area of the page
|
||||
*
|
||||
* Shows a form for changing the password
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showContent()
|
||||
{
|
||||
$user = common_current_user();
|
||||
$this->elementStart('form', array('method' => 'POST',
|
||||
'id' => 'form_settings_design',
|
||||
'class' => 'form_settings',
|
||||
'action' =>
|
||||
common_local_url('designsettings')));
|
||||
$this->elementStart('fieldset');
|
||||
$this->hidden('token', common_session_token());
|
||||
|
||||
$this->elementStart('fieldset', array('id' => 'settings_design_background-image'));
|
||||
$this->element('legend', null, _('Change background image'));
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
$this->element('label', array('for' => 'design_ background-image_file'),
|
||||
_('Upload file'));
|
||||
$this->element('input', array('name' => 'design_background-image_file',
|
||||
'type' => 'file',
|
||||
'id' => 'design_background-image_file'));
|
||||
$this->element('p', 'form_guide', _('You can upload your personal background image. The maximum file size is 2Mb.'));
|
||||
$this->element('input', array('name' => 'MAX_FILE_SIZE',
|
||||
'type' => 'hidden',
|
||||
'id' => 'MAX_FILE_SIZE',
|
||||
'value' => ImageFile::maxFileSizeInt()));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
$this->elementEnd('fieldset');
|
||||
|
||||
$this->elementStart('fieldset', array('id' => 'settings_design_color'));
|
||||
$this->element('legend', null, _('Change colours'));
|
||||
$this->elementStart('ul', 'form_data');
|
||||
|
||||
//This is a JSON object in the DB field. Here for testing. Remove later.
|
||||
$userSwatch = '{"body":{"background-color":"#F0F2F5"},
|
||||
"#content":{"background-color":"#FFFFFF"},
|
||||
"#aside_primary":{"background-color":"#CEE1E9"},
|
||||
"html body":{"color":"#000000"},
|
||||
"a":{"color":"#002E6E"}}';
|
||||
|
||||
//Default theme swatch -- Where should this be stored?
|
||||
$defaultSwatch = array('body' => array('background-color' => '#F0F2F5'),
|
||||
'#content' => array('background-color' => '#FFFFFF'),
|
||||
'#aside_primary' => array('background-color' => '#CEE1E9'),
|
||||
'html body' => array('color' => '#000000'),
|
||||
'a' => array('color' => '#002E6E'));
|
||||
|
||||
$userSwatch = ($userSwatch) ? json_decode($userSwatch, true) : $defaultSwatch;
|
||||
|
||||
$s = 0;
|
||||
$labelSwatch = array('Background',
|
||||
'Content',
|
||||
'Sidebar',
|
||||
'Text',
|
||||
'Links');
|
||||
foreach($userSwatch as $propertyvalue => $value) {
|
||||
$foo = array_values($value);
|
||||
$this->elementStart('li');
|
||||
$this->element('label', array('for' => 'swatch-'.$s), _($labelSwatch[$s]));
|
||||
$this->element('input', array('name' => 'swatch-'.$s, //prefer swatch[$s] ?
|
||||
'type' => 'text',
|
||||
'id' => 'swatch-'.$s,
|
||||
'class' => 'swatch',
|
||||
'maxlength' => '7',
|
||||
'size' => '7',
|
||||
'value' => $foo[0]));
|
||||
$this->elementEnd('li');
|
||||
$s++;
|
||||
}
|
||||
|
||||
$this->elementEnd('ul');
|
||||
$this->elementEnd('fieldset');
|
||||
|
||||
$this->submit('save', _('Save'));
|
||||
$this->element('input', array('type' => 'reset',
|
||||
'value' => 'Reset',
|
||||
'class' => 'form_action-secondary'));
|
||||
|
||||
/*TODO: Check submitted form values:
|
||||
json_encode(form values)
|
||||
if submitted Swatch == DefaultSwatch, don't store in DB.
|
||||
else store in BD
|
||||
*/
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a post
|
||||
*
|
||||
* Validate input and save changes. Reload the form with a success
|
||||
* or error message.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handlePost()
|
||||
{
|
||||
/*
|
||||
// CSRF protection
|
||||
|
||||
$token = $this->trimmed('token');
|
||||
if (!$token || $token != common_session_token()) {
|
||||
$this->showForm(_('There was a problem with your session token. '.
|
||||
'Try again, please.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$user = common_current_user();
|
||||
assert(!is_null($user)); // should already be checked
|
||||
|
||||
// FIXME: scrub input
|
||||
|
||||
$newpassword = $this->arg('newpassword');
|
||||
$confirm = $this->arg('confirm');
|
||||
|
||||
# Some validation
|
||||
|
||||
if (strlen($newpassword) < 6) {
|
||||
$this->showForm(_('Password must be 6 or more characters.'));
|
||||
return;
|
||||
} else if (0 != strcmp($newpassword, $confirm)) {
|
||||
$this->showForm(_('Passwords don\'t match.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if ($user->password) {
|
||||
$oldpassword = $this->arg('oldpassword');
|
||||
|
||||
if (!common_check_user($user->nickname, $oldpassword)) {
|
||||
$this->showForm(_('Incorrect old password'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$original = clone($user);
|
||||
|
||||
$user->password = common_munge_password($newpassword, $user->id);
|
||||
|
||||
$val = $user->validate();
|
||||
if ($val !== true) {
|
||||
$this->showForm(_('Error saving user; invalid.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$user->update($original)) {
|
||||
$this->serverError(_('Can\'t save new password.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->showForm(_('Password saved.'), true);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the Farbtastic stylesheet
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showStylesheets()
|
||||
{
|
||||
parent::showStylesheets();
|
||||
$farbtasticStyle =
|
||||
common_path('theme/base/css/farbtastic.css?version='.LACONICA_VERSION);
|
||||
|
||||
$this->element('link', array('rel' => 'stylesheet',
|
||||
'type' => 'text/css',
|
||||
'href' => $farbtasticStyle,
|
||||
'media' => 'screen, projection, tv'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the Farbtastic scripts
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showScripts()
|
||||
{
|
||||
parent::showScripts();
|
||||
|
||||
$farbtasticPack = common_path('js/farbtastic/farbtastic.js');
|
||||
$farbtasticGo = common_path('js/farbtastic/farbtastic.go.js');
|
||||
|
||||
$this->element('script', array('type' => 'text/javascript',
|
||||
'src' => $farbtasticPack));
|
||||
$this->element('script', array('type' => 'text/javascript',
|
||||
'src' => $farbtasticGo));
|
||||
}
|
||||
}
|
@ -100,7 +100,8 @@ class DisfavorAction extends Action
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
common_redirect(common_local_url('showfavorites',
|
||||
array('nickname' => $user->nickname)));
|
||||
array('nickname' => $user->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ class DocAction extends Action
|
||||
return ucfirst($this->title);
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -166,7 +166,6 @@ class EditgroupAction extends Action
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$nickname = common_canonical_nickname($this->trimmed('nickname'));
|
||||
$fullname = $this->trimmed('fullname');
|
||||
$homepage = $this->trimmed('homepage');
|
||||
@ -221,7 +220,7 @@ class EditgroupAction extends Action
|
||||
if ($this->group->nickname != $orig->nickname) {
|
||||
common_redirect(common_local_url('editgroup',
|
||||
array('nickname' => $nickname)),
|
||||
307);
|
||||
303);
|
||||
} else {
|
||||
$this->showForm(_('Options saved.'));
|
||||
}
|
||||
|
@ -100,7 +100,8 @@ class FavorAction extends Action
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
common_redirect(common_local_url('showfavorites',
|
||||
array('nickname' => $user->nickname)));
|
||||
array('nickname' => $user->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ class FavoritedAction extends Action
|
||||
* @return boolean true
|
||||
*/
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -145,6 +145,22 @@ class FavoritedAction extends Action
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function showEmptyList()
|
||||
{
|
||||
$message = _('Favorite notices appear on this page but no one has favorited one yet.') . ' ';
|
||||
|
||||
if (common_logged_in()) {
|
||||
$message .= _('Be the first to add a notice to your favorites by clicking the fave button next to any notice you like.');
|
||||
}
|
||||
else {
|
||||
$message .= _('Why not [register an account](%%action.register%%) and be the first to add a notice to your favorites!');
|
||||
}
|
||||
|
||||
$this->elementStart('div', 'guide');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
/**
|
||||
* Local navigation
|
||||
*
|
||||
@ -169,10 +185,16 @@ class FavoritedAction extends Action
|
||||
|
||||
function showContent()
|
||||
{
|
||||
if (common_config('db', 'type') == 'pgsql') {
|
||||
$weightexpr='sum(exp(-extract(epoch from (now() - fave.modified)) / %s))';
|
||||
} else {
|
||||
$weightexpr='sum(exp(-(now() - fave.modified) / %s))';
|
||||
}
|
||||
|
||||
$qry = 'SELECT notice.*, '.
|
||||
'sum(exp(-(now() - fave.modified) / %s)) as weight ' .
|
||||
$weightexpr . ' as weight ' .
|
||||
'FROM notice JOIN fave ON notice.id = fave.notice_id ' .
|
||||
'GROUP BY fave.notice_id ' .
|
||||
'GROUP BY id,profile_id,uri,content,rendered,url,created,notice.modified,reply_to,is_local,source ' .
|
||||
'ORDER BY weight DESC';
|
||||
|
||||
$offset = ($this->page - 1) * NOTICES_PER_PAGE;
|
||||
@ -192,7 +214,22 @@ class FavoritedAction extends Action
|
||||
|
||||
$cnt = $nl->show();
|
||||
|
||||
if ($cnt == 0) {
|
||||
$this->showEmptyList();
|
||||
}
|
||||
|
||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$this->page, 'favorited');
|
||||
}
|
||||
|
||||
/**
|
||||
* Output document relationship links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showRelationshipLinks()
|
||||
{
|
||||
$this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME
|
||||
$this->page, 'favorited');
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ class FavoritesrssAction extends Rss10Action
|
||||
$c = array('url' => common_local_url('favoritesrss',
|
||||
array('nickname' =>
|
||||
$user->nickname)),
|
||||
'title' => sprintf(_("%s favorite notices"), $user->nickname),
|
||||
'title' => sprintf(_("%s's favorite notices"), $user->nickname),
|
||||
'link' => common_local_url('showfavorites',
|
||||
array('nickname' =>
|
||||
$user->nickname)),
|
||||
|
@ -50,7 +50,7 @@ class FeaturedAction extends Action
|
||||
{
|
||||
var $page = null;
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -107,6 +107,7 @@ class FeaturedAction extends Action
|
||||
|
||||
$featured_nicks = common_config('nickname', 'featured');
|
||||
|
||||
|
||||
if (count($featured_nicks) > 0) {
|
||||
|
||||
$quoted = array();
|
||||
@ -118,7 +119,7 @@ class FeaturedAction extends Action
|
||||
$user = new User;
|
||||
$user->whereAdd(sprintf('nickname IN (%s)', implode(',', $quoted)));
|
||||
$user->limit(($this->page - 1) * PROFILES_PER_PAGE, PROFILES_PER_PAGE + 1);
|
||||
$user->orderBy('user.nickname ASC');
|
||||
$user->orderBy(common_database_tablename('user') .'.nickname ASC');
|
||||
|
||||
$user->find();
|
||||
|
||||
|
@ -139,7 +139,7 @@ class FinishaddopenidAction extends Action
|
||||
|
||||
oid_set_last($display);
|
||||
|
||||
common_redirect(common_local_url('openidsettings'));
|
||||
common_redirect(common_local_url('openidsettings'), 303);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,9 +62,8 @@ class FinishopenidloginAction extends Action
|
||||
if ($this->error) {
|
||||
$this->element('div', array('class' => 'error'), $this->error);
|
||||
} else {
|
||||
global $config;
|
||||
$this->element('div', 'instructions',
|
||||
sprintf(_('This is the first time you\'ve logged into %s so we must connect your OpenID to a local account. You can either create a new account, or connect with your existing account, if you have one.'), $config['site']['name']));
|
||||
sprintf(_('This is the first time you\'ve logged into %s so we must connect your OpenID to a local account. You can either create a new account, or connect with your existing account, if you have one.'), common_config('site', 'name')));
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +82,7 @@ class FinishopenidloginAction extends Action
|
||||
|
||||
function showContent()
|
||||
{
|
||||
if ($this->message_text) {
|
||||
if (!empty($this->message_text)) {
|
||||
$this->element('p', null, $this->message);
|
||||
return;
|
||||
}
|
||||
@ -192,11 +191,28 @@ class FinishopenidloginAction extends Action
|
||||
{
|
||||
# FIXME: save invite code before redirect, and check here
|
||||
|
||||
if (common_config('site', 'closed') || common_config('site', 'inviteonly')) {
|
||||
if (common_config('site', 'closed')) {
|
||||
$this->clientError(_('Registration not allowed.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$invite = null;
|
||||
|
||||
if (common_config('site', 'inviteonly')) {
|
||||
$code = $_SESSION['invitecode'];
|
||||
if (empty($code)) {
|
||||
$this->clientError(_('Registration not allowed.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$invite = Invitation::staticGet($code);
|
||||
|
||||
if (empty($invite)) {
|
||||
$this->clientError(_('Not a valid invitation code.'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$nickname = $this->trimmed('newname');
|
||||
|
||||
if (!Validate::string($nickname, array('min_length' => 1,
|
||||
@ -232,7 +248,8 @@ class FinishopenidloginAction extends Action
|
||||
return;
|
||||
}
|
||||
|
||||
if ($sreg['country']) {
|
||||
$location = '';
|
||||
if (!empty($sreg['country'])) {
|
||||
if ($sreg['postcode']) {
|
||||
# XXX: use postcode to get city and region
|
||||
# XXX: also, store postcode somewhere -- it's valuable!
|
||||
@ -242,21 +259,31 @@ class FinishopenidloginAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
if ($sreg['fullname'] && mb_strlen($sreg['fullname']) <= 255) {
|
||||
if (!empty($sreg['fullname']) && mb_strlen($sreg['fullname']) <= 255) {
|
||||
$fullname = $sreg['fullname'];
|
||||
} else {
|
||||
$fullname = '';
|
||||
}
|
||||
|
||||
if ($sreg['email'] && Validate::email($sreg['email'], true)) {
|
||||
if (!empty($sreg['email']) && Validate::email($sreg['email'], true)) {
|
||||
$email = $sreg['email'];
|
||||
} else {
|
||||
$email = '';
|
||||
}
|
||||
|
||||
# XXX: add language
|
||||
# XXX: add timezone
|
||||
|
||||
$user = User::register(array('nickname' => $nickname,
|
||||
$args = array('nickname' => $nickname,
|
||||
'email' => $email,
|
||||
'fullname' => $fullname,
|
||||
'location' => $location));
|
||||
'location' => $location);
|
||||
|
||||
if (!empty($invite)) {
|
||||
$args['code'] = $invite->code;
|
||||
}
|
||||
|
||||
$user = User::register($args);
|
||||
|
||||
$result = oid_link_user($user->id, $canonical, $display);
|
||||
|
||||
@ -267,7 +294,8 @@ class FinishopenidloginAction extends Action
|
||||
common_rememberme($user);
|
||||
}
|
||||
unset($_SESSION['openid_rememberme']);
|
||||
common_redirect(common_local_url('showstream', array('nickname' => $user->nickname)));
|
||||
common_redirect(common_local_url('showstream', array('nickname' => $user->nickname)),
|
||||
303);
|
||||
}
|
||||
|
||||
function connectUser()
|
||||
@ -320,7 +348,7 @@ class FinishopenidloginAction extends Action
|
||||
array('nickname' =>
|
||||
$nickname));
|
||||
}
|
||||
common_redirect($url);
|
||||
common_redirect($url, 303);
|
||||
}
|
||||
|
||||
function bestNewNickname($display, $sreg)
|
||||
@ -328,7 +356,7 @@ class FinishopenidloginAction extends Action
|
||||
|
||||
# Try the passed-in nickname
|
||||
|
||||
if ($sreg['nickname']) {
|
||||
if (!empty($sreg['nickname'])) {
|
||||
$nickname = $this->nicknamize($sreg['nickname']);
|
||||
if ($this->isNewNickname($nickname)) {
|
||||
return $nickname;
|
||||
@ -337,7 +365,7 @@ class FinishopenidloginAction extends Action
|
||||
|
||||
# Try the full name
|
||||
|
||||
if ($sreg['fullname']) {
|
||||
if (!empty($sreg['fullname'])) {
|
||||
$fullname = $this->nicknamize($sreg['fullname']);
|
||||
if ($this->isNewNickname($fullname)) {
|
||||
return $fullname;
|
||||
|
@ -44,7 +44,7 @@ class FinishremotesubscribeAction extends Action
|
||||
common_debug('stored request: '.print_r($omb,true), __FILE__);
|
||||
|
||||
common_remove_magic_from_request();
|
||||
$req = OAuthRequest::from_request();
|
||||
$req = OAuthRequest::from_request('POST', common_local_url('finishuserauthorization'));
|
||||
|
||||
$token = $req->get_parameter('oauth_token');
|
||||
|
||||
@ -136,16 +136,16 @@ class FinishremotesubscribeAction extends Action
|
||||
$profile->nickname = $nickname;
|
||||
$profile->profileurl = $profile_url;
|
||||
|
||||
if ($fullname) {
|
||||
if (!is_null($fullname)) {
|
||||
$profile->fullname = $fullname;
|
||||
}
|
||||
if ($homepage) {
|
||||
if (!is_null($homepage)) {
|
||||
$profile->homepage = $homepage;
|
||||
}
|
||||
if ($bio) {
|
||||
if (!is_null($bio)) {
|
||||
$profile->bio = $bio;
|
||||
}
|
||||
if ($location) {
|
||||
if (!is_null($location)) {
|
||||
$profile->location = $location;
|
||||
}
|
||||
|
||||
@ -230,7 +230,8 @@ class FinishremotesubscribeAction extends Action
|
||||
# show up close to the top of the page
|
||||
|
||||
common_redirect(common_local_url('subscribers', array('nickname' =>
|
||||
$user->nickname)));
|
||||
$user->nickname)),
|
||||
303);
|
||||
}
|
||||
|
||||
function add_avatar($profile, $url)
|
||||
@ -283,7 +284,7 @@ class FinishremotesubscribeAction extends Action
|
||||
$fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
|
||||
$result = $fetcher->post($req->get_normalized_http_url(),
|
||||
$req->to_postdata(),
|
||||
array('User-Agent' => 'Laconica/' . LACONICA_VERSION));
|
||||
array('User-Agent: Laconica/' . LACONICA_VERSION));
|
||||
|
||||
common_debug('got result: "'.print_r($result,true).'"', __FILE__);
|
||||
|
||||
|
@ -25,7 +25,7 @@ define('BOTH', 0);
|
||||
|
||||
class FoafAction extends Action
|
||||
{
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -33,7 +33,24 @@ class FoafAction extends Action
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
$this->nickname = $this->trimmed('nickname');
|
||||
|
||||
$nickname_arg = $this->arg('nickname');
|
||||
|
||||
if (empty($nickname_arg)) {
|
||||
$this->clientError(_('No such user.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->nickname = common_canonical_nickname($nickname_arg);
|
||||
|
||||
// Permanent redirect on non-canonical nickname
|
||||
|
||||
if ($nickname_arg != $this->nickname) {
|
||||
common_redirect(common_local_url('foaf',
|
||||
array('nickname' => $this->nickname)),
|
||||
301);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->user = User::staticGet('nickname', $this->nickname);
|
||||
|
||||
@ -122,20 +139,30 @@ class FoafAction extends Action
|
||||
|
||||
if ($sub->find()) {
|
||||
while ($sub->fetch()) {
|
||||
if ($sub->token) {
|
||||
if (!empty($sub->token)) {
|
||||
$other = Remote_profile::staticGet('id', $sub->subscribed);
|
||||
} else {
|
||||
$other = User::staticGet('id', $sub->subscribed);
|
||||
}
|
||||
if (!$other) {
|
||||
if (empty($other)) {
|
||||
common_debug('Got a bad subscription: '.print_r($sub,true));
|
||||
continue;
|
||||
}
|
||||
$this->element('knows', array('rdf:resource' => $other->uri));
|
||||
$person[$other->uri] = array(LISTENEE, $other);
|
||||
$person[$other->uri] = array(LISTENEE,
|
||||
$other->id,
|
||||
$other->nickname,
|
||||
(empty($sub->token)) ? 'User' : 'Remote_profile');
|
||||
$other->free();
|
||||
$other = null;
|
||||
unset($other);
|
||||
}
|
||||
}
|
||||
|
||||
$sub->free();
|
||||
$sub = null;
|
||||
unset($sub);
|
||||
|
||||
// Get people who subscribe to user
|
||||
|
||||
$sub = new Subscription();
|
||||
@ -156,24 +183,35 @@ class FoafAction extends Action
|
||||
if (array_key_exists($other->uri, $person)) {
|
||||
$person[$other->uri][0] = BOTH;
|
||||
} else {
|
||||
$person[$other->uri] = array(LISTENER, $other);
|
||||
}
|
||||
$person[$other->uri] = array(LISTENER,
|
||||
$other->id,
|
||||
$other->nickname,
|
||||
(empty($sub->token)) ? 'User' : 'Remote_profile');
|
||||
}
|
||||
$other->free();
|
||||
$other = null;
|
||||
unset($other);
|
||||
}
|
||||
}
|
||||
|
||||
$sub->free();
|
||||
$sub = null;
|
||||
unset($sub);
|
||||
|
||||
$this->elementEnd('Person');
|
||||
|
||||
foreach ($person as $uri => $p) {
|
||||
$foaf_url = null;
|
||||
if ($p[1] instanceof User) {
|
||||
$foaf_url = common_local_url('foaf', array('nickname' => $p[1]->nickname));
|
||||
list($type, $id, $nickname, $cls) = $p;
|
||||
if ($cls == 'User') {
|
||||
$foaf_url = common_local_url('foaf', array('nickname' => $nickname));
|
||||
}
|
||||
$this->profile = Profile::staticGet($p[1]->id);
|
||||
$profile = Profile::staticGet($id);
|
||||
$this->elementStart('Person', array('rdf:about' => $uri));
|
||||
if ($p[0] == LISTENER || $p[0] == BOTH) {
|
||||
if ($type == LISTENER || $type == BOTH) {
|
||||
$this->element('knows', array('rdf:resource' => $this->user->uri));
|
||||
}
|
||||
$this->showMicrobloggingAccount($this->profile, ($p[1] instanceof User) ?
|
||||
$this->showMicrobloggingAccount($profile, ($cls == 'User') ?
|
||||
common_root_url() : null);
|
||||
if ($foaf_url) {
|
||||
$this->element('rdfs:seeAlso', array('rdf:resource' => $foaf_url));
|
||||
@ -182,6 +220,9 @@ class FoafAction extends Action
|
||||
if ($foaf_url) {
|
||||
$this->showPpd($foaf_url, $uri);
|
||||
}
|
||||
$profile->free();
|
||||
$profile = null;
|
||||
unset($profile);
|
||||
}
|
||||
|
||||
$this->elementEnd('rdf:RDF');
|
||||
|
@ -59,7 +59,7 @@ class GroupbyidAction extends Action
|
||||
* @return boolean true
|
||||
*/
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ class GrouplogoAction extends Action
|
||||
|
||||
if ($nickname_arg != $nickname) {
|
||||
$args = array('nickname' => $nickname);
|
||||
common_redirect(common_local_url('editgroup', $args), 301);
|
||||
common_redirect(common_local_url('grouplogo', $args), 301);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ class GroupmembersAction extends Action
|
||||
{
|
||||
var $page = null;
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -137,4 +137,15 @@ class GroupmembersAction extends Action
|
||||
$this->page, 'groupmembers',
|
||||
array('nickname' => $this->group->nickname));
|
||||
}
|
||||
|
||||
/**
|
||||
* Output document relationship links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showRelationshipLinks()
|
||||
{
|
||||
$this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME
|
||||
$this->page, 'groupmembers', array('nickname' => $this->group->nickname));
|
||||
}
|
||||
}
|
@ -34,7 +34,7 @@ if (!defined('LACONICA')) {
|
||||
|
||||
require_once INSTALLDIR.'/lib/rssaction.php';
|
||||
|
||||
define('MEMBERS_PER_SECTION', 81);
|
||||
define('MEMBERS_PER_SECTION', 27);
|
||||
|
||||
/**
|
||||
* Group RSS feed
|
||||
@ -57,7 +57,7 @@ class groupRssAction extends Rss10Action
|
||||
* @return boolean true
|
||||
*/
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -141,13 +141,4 @@ class groupRssAction extends Rss10Action
|
||||
{
|
||||
return $this->group->homepage_logo;
|
||||
}
|
||||
|
||||
# override parent to add X-SUP-ID URL
|
||||
|
||||
function initRss($limit=0)
|
||||
{
|
||||
$url = common_local_url('sup', null, $this->group->id);
|
||||
header('X-SUP-ID: '.$url);
|
||||
parent::initRss($limit);
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ class GroupsAction extends Action
|
||||
var $page = null;
|
||||
var $profile = null;
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -129,4 +129,15 @@ class GroupsAction extends Action
|
||||
$gbm = new GroupsByMembersSection($this);
|
||||
$gbm->show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output document relationship links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showRelationshipLinks()
|
||||
{
|
||||
$this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME
|
||||
$this->page, 'groups', array('nickname' => $this->group->nickname));
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,4 @@
|
||||
<?php
|
||||
|
||||
|
||||
// define('GROUPS_PER_PAGE', 20);
|
||||
|
||||
|
||||
/**
|
||||
* Group search action class.
|
||||
*
|
||||
@ -77,12 +72,23 @@ class GroupsearchAction extends SearchAction
|
||||
$terms = preg_split('/[\s,]+/', $q);
|
||||
$results = new GroupSearchResults($user_group, $terms, $this);
|
||||
$results->show();
|
||||
} else {
|
||||
$this->element('p', 'error', _('No results'));
|
||||
}
|
||||
$user_group->free();
|
||||
$this->pagination($page > 1, $cnt > GROUPS_PER_PAGE,
|
||||
$page, 'groupsearch', array('q' => $q));
|
||||
} else {
|
||||
$this->element('p', 'error', _('No results.'));
|
||||
$this->searchSuggestions($q);
|
||||
if (common_logged_in()) {
|
||||
$message = _('If you can\'t find the group you\'re looking for, you can [create it](%%action.newgroup%%) yourself.');
|
||||
}
|
||||
else {
|
||||
$message = _('Why not [register an account](%%action.register%%) and [create the group](%%action.newgroup%%) yourself!');
|
||||
}
|
||||
$this->elementStart('div', 'guide');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
$this->elementEnd('div');
|
||||
$user_group->free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,10 +109,5 @@ class GroupSearchResults extends GroupList
|
||||
{
|
||||
return preg_replace($this->pattern, '<strong>\\1</strong>', htmlspecialchars($text));
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,17 @@ class InboxAction extends MailboxAction
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output document relationship links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showRelationshipLinks()
|
||||
{
|
||||
$this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME
|
||||
$this->page, 'inbox', array('nickname' => $this->user->nickname));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the messages for this user and this page
|
||||
*
|
||||
|
@ -27,7 +27,7 @@ class InviteAction extends Action
|
||||
var $subbed = null;
|
||||
var $sent = null;
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ class JoingroupAction extends Action
|
||||
|
||||
if ($nickname_arg != $nickname) {
|
||||
$args = array('nickname' => $nickname);
|
||||
common_redirect(common_local_url('editgroup', $args), 301);
|
||||
common_redirect(common_local_url('joingroup', $args), 301);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -143,7 +143,8 @@ class JoingroupAction extends Action
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
common_redirect(common_local_url('groupmembers', array('nickname' =>
|
||||
$this->group->nickname)));
|
||||
$this->group->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
@ -73,7 +73,7 @@ class LeavegroupAction extends Action
|
||||
|
||||
if ($nickname_arg != $nickname) {
|
||||
$args = array('nickname' => $nickname);
|
||||
common_redirect(common_local_url('editgroup', $args), 301);
|
||||
common_redirect(common_local_url('leavegroup', $args), 301);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -96,12 +96,6 @@ class LeavegroupAction extends Action
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($cur->isAdmin($this->group)) {
|
||||
$this->clientError(_('You may not leave a group while you are its administrator.'), 403);
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -153,7 +147,8 @@ class LeavegroupAction extends Action
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
common_redirect(common_local_url('groupmembers', array('nickname' =>
|
||||
$this->group->nickname)));
|
||||
$this->group->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ class LoginAction extends Action
|
||||
* @return boolean false
|
||||
*/
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -108,13 +108,15 @@ class LoginAction extends Action
|
||||
$nickname = common_canonical_nickname($this->trimmed('nickname'));
|
||||
$password = $this->arg('password');
|
||||
|
||||
if (!common_check_user($nickname, $password)) {
|
||||
$user = common_check_user($nickname, $password);
|
||||
|
||||
if (!$user) {
|
||||
$this->showForm(_('Incorrect username or password.'));
|
||||
return;
|
||||
}
|
||||
|
||||
// success!
|
||||
if (!common_set_user($nickname)) {
|
||||
if (!common_set_user($user)) {
|
||||
$this->serverError(_('Error setting user.'));
|
||||
return;
|
||||
}
|
||||
@ -136,7 +138,7 @@ class LoginAction extends Action
|
||||
$nickname));
|
||||
}
|
||||
|
||||
common_redirect($url);
|
||||
common_redirect($url, 303);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,7 +52,7 @@ class LogoutAction extends Action
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -70,10 +70,20 @@ class LogoutAction extends Action
|
||||
if (!common_logged_in()) {
|
||||
$this->clientError(_('Not logged in.'));
|
||||
} else {
|
||||
if (Event::handle('StartLogout', array($this))) {
|
||||
$this->logout();
|
||||
}
|
||||
Event::handle('EndLogout', array($this));
|
||||
|
||||
common_redirect(common_local_url('public'), 303);
|
||||
}
|
||||
}
|
||||
|
||||
function logout()
|
||||
{
|
||||
common_set_user(null);
|
||||
common_real_login(false); // not logged in
|
||||
common_forgetme(); // don't log back in!
|
||||
common_redirect(common_local_url('public'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ class MicrosummaryAction extends Action
|
||||
print $user->nickname . ': ' . $notice->content;
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ class NewgroupAction extends Action
|
||||
|
||||
$group->query('COMMIT');
|
||||
|
||||
common_redirect($group->homeUrl(), 307);
|
||||
common_redirect($group->homeUrl(), 303);
|
||||
}
|
||||
|
||||
function nicknameExists($nickname)
|
||||
|
@ -172,15 +172,54 @@ class NewmessageAction extends Action
|
||||
|
||||
$this->notify($user, $this->other, $message);
|
||||
|
||||
$url = common_local_url('outbox', array('nickname' => $user->nickname));
|
||||
|
||||
if ($this->boolean('ajax')) {
|
||||
$this->startHTML('text/xml;charset=utf-8');
|
||||
$this->elementStart('head');
|
||||
$this->element('title', null, _('Message sent'));
|
||||
$this->elementEnd('head');
|
||||
$this->elementStart('body');
|
||||
$this->element('p', array('id' => 'command_result'),
|
||||
sprintf(_('Direct message to %s sent'),
|
||||
$this->other->nickname));
|
||||
$this->elementEnd('body');
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
$url = common_local_url('outbox',
|
||||
array('nickname' => $user->nickname));
|
||||
common_redirect($url, 303);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an Ajax-y error message
|
||||
*
|
||||
* Goes back to the browser, where it's shown in a popup.
|
||||
*
|
||||
* @param string $msg Message to show
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function ajaxErrorMsg($msg)
|
||||
{
|
||||
$this->startHTML('text/xml;charset=utf-8', true);
|
||||
$this->elementStart('head');
|
||||
$this->element('title', null, _('Ajax Error'));
|
||||
$this->elementEnd('head');
|
||||
$this->elementStart('body');
|
||||
$this->element('p', array('id' => 'error'), $msg);
|
||||
$this->elementEnd('body');
|
||||
$this->elementEnd('html');
|
||||
}
|
||||
|
||||
function showForm($msg = null)
|
||||
{
|
||||
$this->msg = $msg;
|
||||
if ($msg && $this->boolean('ajax')) {
|
||||
$this->ajaxErrorMsg($msg);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->msg = $msg;
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
|
@ -152,8 +152,14 @@ class NewnoticeAction extends Action
|
||||
}
|
||||
|
||||
$replyto = $this->trimmed('inreplyto');
|
||||
#If an ID of 0 is wrongly passed here, it will cause a database error,
|
||||
#so override it...
|
||||
if ($replyto == 0) {
|
||||
$replyto = 'false';
|
||||
}
|
||||
|
||||
$notice = Notice::saveNew($user->id, $content, 'web', 1,
|
||||
// $notice = Notice::saveNew($user->id, $content_shortened, 'web', 1,
|
||||
$notice = Notice::saveNew($user->id, $content_shortened, 'web', 1,
|
||||
($replyto == 'false') ? null : $replyto);
|
||||
|
||||
if (is_string($notice)) {
|
||||
@ -161,6 +167,8 @@ class NewnoticeAction extends Action
|
||||
return;
|
||||
}
|
||||
|
||||
$this->saveUrls($notice);
|
||||
|
||||
common_broadcast_notice($notice);
|
||||
|
||||
if ($this->boolean('ajax')) {
|
||||
@ -186,6 +194,24 @@ class NewnoticeAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
/** save all urls in the notice to the db
|
||||
*
|
||||
* follow redirects and save all available file information
|
||||
* (mimetype, date, size, oembed, etc.)
|
||||
*
|
||||
* @param class $notice Notice to pull URLs from
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function saveUrls($notice) {
|
||||
common_replace_urls_callback($notice->content, array($this, 'saveUrl'), $notice->id);
|
||||
}
|
||||
|
||||
function saveUrl($data) {
|
||||
list($url, $notice_id) = $data;
|
||||
$zzz = File::processNew($url, $notice_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an Ajax-y error message
|
||||
*
|
||||
@ -253,7 +279,7 @@ class NewnoticeAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
$notice_form = new NoticeForm($this, $content);
|
||||
$notice_form = new NoticeForm($this, '', $content);
|
||||
$notice_form->show();
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ class NoticesearchAction extends SearchAction
|
||||
function showResults($q, $page)
|
||||
{
|
||||
$notice = new Notice();
|
||||
$q = strtolower($q);
|
||||
|
||||
$search_engine = $notice->getSearchEngine('identica_notices');
|
||||
$search_engine->set_sort_mode('chron');
|
||||
// Ask for an extra to see if there's more.
|
||||
@ -113,123 +113,64 @@ class NoticesearchAction extends SearchAction
|
||||
} else {
|
||||
$cnt = $notice->find();
|
||||
}
|
||||
if ($cnt > 0) {
|
||||
$terms = preg_split('/[\s,]+/', $q);
|
||||
$this->elementStart('ul', array('class' => 'notices'));
|
||||
for ($i = 0; $i < min($cnt, NOTICES_PER_PAGE); $i++) {
|
||||
if ($notice->fetch()) {
|
||||
$this->showNotice($notice, $terms);
|
||||
} else {
|
||||
// shouldn't happen!
|
||||
break;
|
||||
if ($cnt === 0) {
|
||||
$this->element('p', 'error', _('No results.'));
|
||||
|
||||
$this->searchSuggestions($q);
|
||||
if (common_logged_in()) {
|
||||
$message = sprintf(_('Be the first to [post on this topic](%%%%action.newnotice%%%%?status_textarea=%s)!'), urlencode($q));
|
||||
}
|
||||
}
|
||||
$this->elementEnd('ul');
|
||||
} else {
|
||||
$this->element('p', 'error', _('No results'));
|
||||
else {
|
||||
$message = sprintf(_('Why not [register an account](%%%%action.register%%%%) and be the first to [post on this topic](%%%%action.newnotice%%%%?status_textarea=%s)!'), urlencode($q));
|
||||
}
|
||||
|
||||
$this->elementStart('div', 'guide');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
$this->elementEnd('div');
|
||||
return;
|
||||
}
|
||||
$terms = preg_split('/[\s,]+/', $q);
|
||||
$nl = new SearchNoticeList($notice, $this, $terms);
|
||||
$cnt = $nl->show();
|
||||
$this->pagination($page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$page, 'noticesearch', array('q' => $q));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show notice
|
||||
*
|
||||
* @param class $notice notice
|
||||
* @param array $terms terms to highlight
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @todo refactor and combine with StreamAction::showNotice()
|
||||
*/
|
||||
function showNotice($notice, $terms)
|
||||
class SearchNoticeList extends NoticeList {
|
||||
function __construct($notice, $out=null, $terms)
|
||||
{
|
||||
$profile = $notice->getProfile();
|
||||
if (!$profile) {
|
||||
common_log_db_error($notice, 'SELECT', __FILE__);
|
||||
$this->serverError(_('Notice without matching profile'));
|
||||
return;
|
||||
parent::__construct($notice, $out);
|
||||
$this->terms = $terms;
|
||||
}
|
||||
// XXX: RDFa
|
||||
$this->elementStart('li', array('class' => 'hentry notice',
|
||||
'id' => 'notice-' . $notice->id));
|
||||
|
||||
$this->elementStart('div', 'entry-title');
|
||||
$this->elementStart('span', 'vcard author');
|
||||
$avatar = $profile->getAvatar(AVATAR_STREAM_SIZE);
|
||||
$this->elementStart('a', array('href' => $profile->profileurl,
|
||||
'class' => 'url'));
|
||||
$this->element('img', array('src' => ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_STREAM_SIZE),
|
||||
'class' => 'avatar photo',
|
||||
'width' => AVATAR_STREAM_SIZE,
|
||||
'height' => AVATAR_STREAM_SIZE,
|
||||
'alt' =>
|
||||
($profile->fullname) ? $profile->fullname :
|
||||
$profile->nickname));
|
||||
$this->element('span', 'nickname fn', $profile->nickname);
|
||||
$this->elementEnd('a');
|
||||
$this->elementEnd('span');
|
||||
function newListItem($notice)
|
||||
{
|
||||
return new SearchNoticeListItem($notice, $this->out, $this->terms);
|
||||
}
|
||||
}
|
||||
|
||||
class SearchNoticeListItem extends NoticeListItem {
|
||||
function __construct($notice, $out=null, $terms)
|
||||
{
|
||||
parent::__construct($notice, $out);
|
||||
$this->terms = $terms;
|
||||
}
|
||||
|
||||
function showContent()
|
||||
{
|
||||
// FIXME: URL, image, video, audio
|
||||
$this->elementStart('p', array('class' => 'entry-content'));
|
||||
if ($notice->rendered) {
|
||||
$this->raw($this->highlight($notice->rendered, $terms));
|
||||
$this->out->elementStart('p', array('class' => 'entry-content'));
|
||||
if ($this->notice->rendered) {
|
||||
$this->out->raw($this->highlight($this->notice->rendered, $this->terms));
|
||||
} else {
|
||||
// XXX: may be some uncooked notices in the DB,
|
||||
// we cook them right now. This should probably disappear in future
|
||||
// versions (>> 0.4.x)
|
||||
$this->raw($this->highlight(common_render_content($notice->content, $notice), $terms));
|
||||
$this->out->raw($this->highlight(common_render_content($this->notice->content, $this->notice), $this->terms));
|
||||
}
|
||||
$this->elementEnd('p');
|
||||
$this->elementEnd('div');
|
||||
$this->out->elementEnd('p');
|
||||
|
||||
$noticeurl = common_local_url('shownotice', array('notice' => $notice->id));
|
||||
$this->elementStart('div', 'entry-content');
|
||||
$this->elementStart('dl', 'timestamp');
|
||||
$this->element('dt', null, _('Published'));
|
||||
$this->elementStart('dd', null);
|
||||
$this->elementStart('a', array('rel' => 'bookmark',
|
||||
'href' => $noticeurl));
|
||||
$dt = common_date_iso8601($notice->created);
|
||||
$this->element('abbr', array('class' => 'published',
|
||||
'title' => $dt),
|
||||
common_date_string($notice->created));
|
||||
$this->elementEnd('a');
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
|
||||
if ($notice->reply_to) {
|
||||
$replyurl = common_local_url('shownotice',
|
||||
array('notice' => $this->notice->reply_to));
|
||||
$this->elementStart('dl', 'response');
|
||||
$this->element('dt', null, _('To'));
|
||||
$this->elementStart('dd');
|
||||
$this->element('a', array('href' => $replyurl,
|
||||
'rel' => 'in-reply-to'),
|
||||
_('in reply to'));
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
}
|
||||
$this->elementEnd('div');
|
||||
|
||||
$this->elementStart('div', 'notice-options');
|
||||
|
||||
$reply_url = common_local_url('newnotice',
|
||||
array('replyto' => $profile->nickname));
|
||||
|
||||
$this->elementStart('dl', 'notice_reply');
|
||||
$this->element('dt', null, _('Reply to this notice'));
|
||||
$this->elementStart('dd');
|
||||
$this->elementStart('a', array('href' => $reply_url,
|
||||
'title' => _('Reply to this notice')));
|
||||
$this->text(_('Reply'));
|
||||
$this->element('span', 'notice_id', $notice->id);
|
||||
$this->elementEnd('a');
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
$this->elementEnd('div');
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -242,21 +183,18 @@ class NoticesearchAction extends SearchAction
|
||||
*/
|
||||
function highlight($text, $terms)
|
||||
{
|
||||
/* Highligh serach terms */
|
||||
$pattern = '/('.implode('|', array_map('htmlspecialchars', $terms)).')/i';
|
||||
/* Highligh search terms */
|
||||
$options = implode('|', array_map('preg_quote', array_map('htmlspecialchars', $terms),
|
||||
array_fill(0, sizeof($terms), '/')));
|
||||
$pattern = "/($options)/i";
|
||||
$result = preg_replace($pattern, '<strong>\\1</strong>', $text);
|
||||
|
||||
/* Remove highlighting from inside links, loop incase multiple highlights in links */
|
||||
$pattern = '/(href="[^"]*)<strong>('.implode('|', array_map('htmlspecialchars', $terms)).')<\/strong>([^"]*")/iU';
|
||||
$pattern = '/(href="[^"]*)<strong>('.$options.')<\/strong>([^"]*")/iU';
|
||||
do {
|
||||
$result = preg_replace($pattern, '\\1\\2\\3', $result, -1, $count);
|
||||
} while ($count);
|
||||
return $result;
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,9 +62,6 @@ class NoticesearchrssAction extends Rss10Action
|
||||
|
||||
$notice = new Notice();
|
||||
|
||||
# lcase it for comparison
|
||||
$q = strtolower($q);
|
||||
|
||||
$search_engine = $notice->getSearchEngine('identica_notices');
|
||||
$search_engine->set_sort_mode('chron');
|
||||
|
||||
@ -82,10 +79,9 @@ class NoticesearchrssAction extends Rss10Action
|
||||
|
||||
function getChannel()
|
||||
{
|
||||
global $config;
|
||||
$q = $this->trimmed('q');
|
||||
$c = array('url' => common_local_url('noticesearchrss', array('q' => $q)),
|
||||
'title' => $config['site']['name'] . sprintf(_(' Search Stream for "%s"'), $q),
|
||||
'title' => common_config('site', 'name') . sprintf(_(' Search Stream for "%s"'), $q),
|
||||
'link' => common_local_url('noticesearch', array('q' => $q)),
|
||||
'description' => sprintf(_('All updates matching search term "%s"'), $q));
|
||||
return $c;
|
||||
@ -96,7 +92,7 @@ class NoticesearchrssAction extends Rss10Action
|
||||
return null;
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -100,7 +100,8 @@ class NudgeAction extends Action
|
||||
} else {
|
||||
// display a confirmation to the user
|
||||
common_redirect(common_local_url('showstream',
|
||||
array('nickname' => $other->nickname)));
|
||||
array('nickname' => $other->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,7 +124,7 @@ class NudgeAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -67,8 +67,8 @@ class OpenidsettingsAction extends AccountSettingsAction
|
||||
|
||||
function getInstructions()
|
||||
{
|
||||
return _('[OpenID](%%doc.openid%%) lets you log into many sites ' .
|
||||
' with the same user account. '.
|
||||
return _('[OpenID](%%doc.openid%%) lets you log into many sites' .
|
||||
' with the same user account.'.
|
||||
' Manage your associated OpenIDs from here.');
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ class OpensearchAction extends Action
|
||||
$this->endXML();
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -62,6 +62,17 @@ class OutboxAction extends MailboxAction
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output document relationship links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showRelationshipLinks()
|
||||
{
|
||||
$this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME
|
||||
$this->page, 'outbox', array('nickname' => $this->user->nickname));
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve the messages for this user and this page
|
||||
*
|
||||
|
@ -60,16 +60,10 @@ class PeoplesearchAction extends SearchAction
|
||||
|
||||
function showResults($q, $page)
|
||||
{
|
||||
|
||||
$profile = new Profile();
|
||||
|
||||
# lcase it for comparison
|
||||
$q = strtolower($q);
|
||||
|
||||
$search_engine = $profile->getSearchEngine('identica_people');
|
||||
|
||||
$search_engine->set_sort_mode('chron');
|
||||
# Ask for an extra to see if there's more.
|
||||
// Ask for an extra to see if there's more.
|
||||
$search_engine->limit((($page-1)*PROFILES_PER_PAGE), PROFILES_PER_PAGE + 1);
|
||||
if (false === $search_engine->query($q)) {
|
||||
$cnt = 0;
|
||||
@ -81,38 +75,15 @@ class PeoplesearchAction extends SearchAction
|
||||
$terms = preg_split('/[\s,]+/', $q);
|
||||
$results = new PeopleSearchResults($profile, $terms, $this);
|
||||
$results->show();
|
||||
} else {
|
||||
$this->element('p', 'error', _('No results'));
|
||||
}
|
||||
|
||||
$profile->free();
|
||||
|
||||
$this->pagination($page > 1, $cnt > PROFILES_PER_PAGE,
|
||||
$page, 'peoplesearch', array('q' => $q));
|
||||
}
|
||||
}
|
||||
|
||||
class PeopleSearchResults extends ProfileList
|
||||
{
|
||||
var $terms = null;
|
||||
var $pattern = null;
|
||||
|
||||
function __construct($profile, $terms, $action)
|
||||
{
|
||||
parent::__construct($profile, $terms, $action);
|
||||
$this->terms = array_map('preg_quote',
|
||||
array_map('htmlspecialchars', $terms));
|
||||
$this->pattern = '/('.implode('|',$terms).')/i';
|
||||
}
|
||||
|
||||
function highlight($text)
|
||||
{
|
||||
return preg_replace($this->pattern, '<strong>\\1</strong>', htmlspecialchars($text));
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
{
|
||||
return true;
|
||||
|
||||
} else {
|
||||
$this->element('p', 'error', _('No results.'));
|
||||
$this->searchSuggestions($q);
|
||||
$profile->free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ class PeopletagAction extends Action
|
||||
'FROM profile JOIN profile_tag ' .
|
||||
'ON profile.id = profile_tag.tagger ' .
|
||||
'WHERE profile_tag.tagger = profile_tag.tagged ' .
|
||||
'AND tag = "%s" ' .
|
||||
"AND tag = '%s' " .
|
||||
'ORDER BY profile_tag.modified DESC%s';
|
||||
|
||||
$profile->query(sprintf($qry, $this->tag, $lim));
|
||||
|
@ -28,7 +28,7 @@ class PostnoticeAction extends Action
|
||||
parent::handle($args);
|
||||
try {
|
||||
common_remove_magic_from_request();
|
||||
$req = OAuthRequest::from_request();
|
||||
$req = OAuthRequest::from_request('POST', common_local_url('postnotice'));
|
||||
# Note: server-to-server function!
|
||||
$server = omb_oauth_server();
|
||||
list($consumer, $token) = $server->verify_request($req);
|
||||
@ -79,7 +79,7 @@ class PostnoticeAction extends Action
|
||||
}
|
||||
$notice = Notice::staticGet('uri', $notice_uri);
|
||||
if (!$notice) {
|
||||
$notice = Notice::saveNew($remote_profile->id, $content, 'omb', false, 0, $notice_uri);
|
||||
$notice = Notice::saveNew($remote_profile->id, $content, 'omb', false, null, $notice_uri);
|
||||
if (is_string($notice)) {
|
||||
common_server_serror($notice, 500);
|
||||
return false;
|
||||
|
@ -91,9 +91,9 @@ class ProfilesettingsAction extends AccountSettingsAction
|
||||
$this->element('legend', null, _('Profile information'));
|
||||
$this->hidden('token', common_session_token());
|
||||
|
||||
# too much common patterns here... abstractable?
|
||||
|
||||
// too much common patterns here... abstractable?
|
||||
$this->elementStart('ul', 'form_data');
|
||||
if (Event::handle('StartProfileFormData', array($this))) {
|
||||
$this->elementStart('li');
|
||||
$this->input('nickname', _('Nickname'),
|
||||
($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname,
|
||||
@ -118,6 +118,7 @@ class ProfilesettingsAction extends AccountSettingsAction
|
||||
($this->arg('location')) ? $this->arg('location') : $profile->location,
|
||||
_('Where you are, like "City, State (or Region), Country"'));
|
||||
$this->elementEnd('li');
|
||||
Event::handle('EndProfileFormData', array($this));
|
||||
$this->elementStart('li');
|
||||
$this->input('tags', _('Tags'),
|
||||
($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()),
|
||||
@ -127,7 +128,7 @@ class ProfilesettingsAction extends AccountSettingsAction
|
||||
$language = common_language();
|
||||
$this->dropdown('language', _('Language'),
|
||||
get_nice_language_list(), _('Preferred language'),
|
||||
true, $language);
|
||||
false, $language);
|
||||
$this->elementEnd('li');
|
||||
$timezone = common_timezone();
|
||||
$timezones = array();
|
||||
@ -146,12 +147,12 @@ class ProfilesettingsAction extends AccountSettingsAction
|
||||
($this->arg('autosubscribe')) ?
|
||||
$this->boolean('autosubscribe') : $user->autosubscribe);
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
$this->elementEnd('ul');
|
||||
$this->submit('save', _('Save'));
|
||||
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -165,8 +166,7 @@ class ProfilesettingsAction extends AccountSettingsAction
|
||||
|
||||
function handlePost()
|
||||
{
|
||||
# CSRF protection
|
||||
|
||||
// CSRF protection
|
||||
$token = $this->trimmed('token');
|
||||
if (!$token || $token != common_session_token()) {
|
||||
$this->showForm(_('There was a problem with your session token. '.
|
||||
@ -174,6 +174,8 @@ class ProfilesettingsAction extends AccountSettingsAction
|
||||
return;
|
||||
}
|
||||
|
||||
if (Event::handle('StartProfileSaveForm', array($this))) {
|
||||
|
||||
$nickname = $this->trimmed('nickname');
|
||||
$fullname = $this->trimmed('fullname');
|
||||
$homepage = $this->trimmed('homepage');
|
||||
@ -184,8 +186,7 @@ class ProfilesettingsAction extends AccountSettingsAction
|
||||
$timezone = $this->trimmed('timezone');
|
||||
$tagstring = $this->trimmed('tags');
|
||||
|
||||
# Some validation
|
||||
|
||||
// Some validation
|
||||
if (!Validate::string($nickname, array('min_length' => 1,
|
||||
'max_length' => 64,
|
||||
'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
|
||||
@ -259,13 +260,12 @@ class ProfilesettingsAction extends AccountSettingsAction
|
||||
$this->serverError(_('Couldn\'t update user.'));
|
||||
return;
|
||||
} else {
|
||||
# Re-initialize language environment if it changed
|
||||
// Re-initialize language environment if it changed
|
||||
common_init_language();
|
||||
}
|
||||
}
|
||||
|
||||
# XXX: XOR
|
||||
|
||||
// XXX: XOR
|
||||
if ($user->autosubscribe ^ $autosubscribe) {
|
||||
|
||||
$original = clone($user);
|
||||
@ -303,8 +303,7 @@ class ProfilesettingsAction extends AccountSettingsAction
|
||||
return;
|
||||
}
|
||||
|
||||
# Set the user tags
|
||||
|
||||
// Set the user tags
|
||||
$result = $user->setSelfTags($tags);
|
||||
|
||||
if (!$result) {
|
||||
@ -313,10 +312,12 @@ class ProfilesettingsAction extends AccountSettingsAction
|
||||
}
|
||||
|
||||
$user->query('COMMIT');
|
||||
|
||||
Event::handle('EndProfileSaveForm', array($this));
|
||||
common_broadcast_profile($profile);
|
||||
|
||||
$this->showForm(_('Settings saved.'), true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function nicknameExists($nickname)
|
||||
|
@ -56,7 +56,7 @@ class PublicAction extends Action
|
||||
|
||||
var $page = null;
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -135,6 +135,17 @@ class PublicAction extends Action
|
||||
_('Public Stream Feed (Atom)')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Output document relationship links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showRelationshipLinks()
|
||||
{
|
||||
$this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME
|
||||
$this->page, 'public');
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra head elements
|
||||
*
|
||||
@ -166,6 +177,22 @@ class PublicAction extends Action
|
||||
$nav->show();
|
||||
}
|
||||
|
||||
function showEmptyList()
|
||||
{
|
||||
$message = _('This is the public timeline for %%site.name%% but no one has posted anything yet.') . ' ';
|
||||
|
||||
if (common_logged_in()) {
|
||||
$message .= _('Be the first to post!');
|
||||
}
|
||||
else {
|
||||
$message .= _('Why not [register an account](%%action.register%%) and be the first to post!');
|
||||
}
|
||||
|
||||
$this->elementStart('div', 'guide');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the content area
|
||||
*
|
||||
@ -189,6 +216,10 @@ class PublicAction extends Action
|
||||
|
||||
$cnt = $nl->show();
|
||||
|
||||
if ($cnt == 0) {
|
||||
$this->showEmptyList();
|
||||
}
|
||||
|
||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$this->page, 'public');
|
||||
}
|
||||
@ -207,9 +238,14 @@ class PublicAction extends Action
|
||||
|
||||
function showAnonymousMessage()
|
||||
{
|
||||
if (! (common_config('site','closed') || common_config('site','inviteonly'))) {
|
||||
$m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
||||
'based on the Free Software [Laconica](http://laconi.ca/) tool. ' .
|
||||
'[Join now](%%action.register%%) to share notices about yourself with friends, family, and colleagues! ([Read more](%%doc.help%%))');
|
||||
} else {
|
||||
$m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
||||
'based on the Free Software [Laconica](http://laconi.ca/) tool.');
|
||||
}
|
||||
$this->elementStart('div', array('id' => 'anon_notice'));
|
||||
$this->raw(common_markup_to_html($m));
|
||||
$this->elementEnd('div');
|
||||
|
@ -84,12 +84,11 @@ class PublicrssAction extends Rss10Action
|
||||
*/
|
||||
function getChannel()
|
||||
{
|
||||
global $config;
|
||||
$c = array(
|
||||
'url' => common_local_url('publicrss')
|
||||
, 'title' => sprintf(_('%s Public Stream'), $config['site']['name'])
|
||||
, 'title' => sprintf(_('%s Public Stream'), common_config('site', 'name'))
|
||||
, 'link' => common_local_url('public')
|
||||
, 'description' => sprintf(_('All updates for %s'), $config['site']['name']));
|
||||
, 'description' => sprintf(_('All updates for %s'), common_config('site', 'name')));
|
||||
return $c;
|
||||
}
|
||||
|
||||
@ -103,7 +102,7 @@ class PublicrssAction extends Rss10Action
|
||||
// nop
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ define('TAGS_PER_PAGE', 100);
|
||||
|
||||
class PublictagcloudAction extends Action
|
||||
{
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -64,6 +64,22 @@ class PublictagcloudAction extends Action
|
||||
common_config('site', 'name')));
|
||||
}
|
||||
|
||||
function showEmptyList()
|
||||
{
|
||||
$message = _('No one has posted a notice with a [hashtag](%%doc.tags%%) yet.') . ' ';
|
||||
|
||||
if (common_logged_in()) {
|
||||
$message .= _('Be the first to post one!');
|
||||
}
|
||||
else {
|
||||
$message .= _('Why not [register an account](%%action.register%%) and be the first to post one!');
|
||||
}
|
||||
|
||||
$this->elementStart('div', 'guide');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function showLocalNav()
|
||||
{
|
||||
$nav = new PublicGroupNav($this);
|
||||
@ -126,6 +142,8 @@ class PublictagcloudAction extends Action
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
$this->elementEnd('div');
|
||||
} else {
|
||||
$this->showEmptyList();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ class PublicxrdsAction extends Action
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -70,19 +70,19 @@ class PublicxrdsAction extends Action
|
||||
{
|
||||
parent::handle($args);
|
||||
header('Content-Type: application/xrds+xml');
|
||||
common_start_xml();
|
||||
$this->startXML();
|
||||
$this->elementStart('XRDS', array('xmlns' => 'xri://$xrds'));
|
||||
$this->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
|
||||
'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
|
||||
'version' => '2.0'));
|
||||
$this->element('Type', null, 'xri://$xrds*simple');
|
||||
foreach (array('finishopenidlogin', 'finishaddopenid', 'finishimmediate') as $finish) {
|
||||
foreach (array('finishopenidlogin', 'finishaddopenid') as $finish) {
|
||||
$this->showService(Auth_OpenID_RP_RETURN_TO_URL_TYPE,
|
||||
common_local_url($finish));
|
||||
}
|
||||
$this->elementEnd('XRD');
|
||||
$this->elementEnd('XRDS');
|
||||
common_end_xml();
|
||||
$this->endXML();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,11 +151,11 @@ class RecoverpasswordAction extends Action
|
||||
$this->element('p', null,
|
||||
_('If you\'ve forgotten or lost your' .
|
||||
' password, you can get a new one sent to' .
|
||||
' the email address you have stored ' .
|
||||
' the email address you have stored' .
|
||||
' in your account.'));
|
||||
} else if ($this->mode == 'reset') {
|
||||
$this->element('p', null,
|
||||
_('You\'ve been identified. Enter a ' .
|
||||
_('You\'ve been identified. Enter a' .
|
||||
' new password below. '));
|
||||
}
|
||||
$this->elementEnd('div');
|
||||
@ -181,13 +181,21 @@ class RecoverpasswordAction extends Action
|
||||
function showRecoverForm()
|
||||
{
|
||||
$this->elementStart('form', array('method' => 'post',
|
||||
'id' => 'recoverpassword',
|
||||
'id' => 'form_password_recover',
|
||||
'class' => 'form_settings',
|
||||
'action' => common_local_url('recoverpassword')));
|
||||
$this->elementStart('fieldset');
|
||||
$this->element('legend', null, _('Password recover'));
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
$this->input('nicknameoremail', _('Nickname or email'),
|
||||
$this->trimmed('nicknameoremail'),
|
||||
_('Your nickname on this server, ' .
|
||||
'or your registered email address.'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
$this->submit('recover', _('Recover'));
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
}
|
||||
|
||||
@ -213,14 +221,24 @@ class RecoverpasswordAction extends Action
|
||||
function showResetForm()
|
||||
{
|
||||
$this->elementStart('form', array('method' => 'post',
|
||||
'id' => 'recoverpassword',
|
||||
'id' => 'form_password_change',
|
||||
'class' => 'form_settings',
|
||||
'action' => common_local_url('recoverpassword')));
|
||||
$this->elementStart('fieldset');
|
||||
$this->element('legend', null, _('Password change'));
|
||||
$this->hidden('token', common_session_token());
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
$this->password('newpassword', _('New password'),
|
||||
_('6 or more characters, and don\'t forget it!'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li');
|
||||
$this->password('confirm', _('Confirm'),
|
||||
_('Same as password above'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
$this->submit('reset', _('Reset'));
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,45 @@ class RegisterAction extends Action
|
||||
|
||||
var $registered = false;
|
||||
|
||||
/**
|
||||
* Prepare page to run
|
||||
*
|
||||
*
|
||||
* @param $args
|
||||
* @return string title
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
$this->code = $this->trimmed('code');
|
||||
|
||||
if (empty($this->code)) {
|
||||
common_ensure_session();
|
||||
if (array_key_exists('invitecode', $_SESSION)) {
|
||||
$this->code = $_SESSION['invitecode'];
|
||||
}
|
||||
}
|
||||
|
||||
if (common_config('site', 'inviteonly') && empty($this->code)) {
|
||||
$this->clientError(_('Sorry, only invited people can register.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($this->code)) {
|
||||
$this->invite = Invitation::staticGet('code', $this->code);
|
||||
if (empty($this->invite)) {
|
||||
$this->clientError(_('Sorry, invalid invitation code.'));
|
||||
return false;
|
||||
}
|
||||
// Store this in case we need it
|
||||
common_ensure_session();
|
||||
$_SESSION['invitecode'] = $this->code;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Title of the page
|
||||
*
|
||||
@ -108,6 +147,7 @@ class RegisterAction extends Action
|
||||
|
||||
function tryRegister()
|
||||
{
|
||||
if (Event::handle('StartRegistrationTry', array($this))) {
|
||||
$token = $this->trimmed('token');
|
||||
if (!$token || $token != common_session_token()) {
|
||||
$this->showForm(_('There was a problem with your session token. '.
|
||||
@ -123,12 +163,10 @@ class RegisterAction extends Action
|
||||
$location = $this->trimmed('location');
|
||||
|
||||
// We don't trim these... whitespace is OK in a password!
|
||||
|
||||
$password = $this->arg('password');
|
||||
$confirm = $this->arg('confirm');
|
||||
|
||||
// invitation code, if any
|
||||
|
||||
$code = $this->trimmed('code');
|
||||
|
||||
if ($code) {
|
||||
@ -141,7 +179,6 @@ class RegisterAction extends Action
|
||||
}
|
||||
|
||||
// Input scrubbing
|
||||
|
||||
$nickname = common_canonical_nickname($nickname);
|
||||
$email = common_canonical_email($email);
|
||||
|
||||
@ -204,6 +241,9 @@ class RegisterAction extends Action
|
||||
common_debug('Adding rememberme cookie for ' . $nickname);
|
||||
common_rememberme($user);
|
||||
}
|
||||
|
||||
Event::handle('EndRegistrationTry', array($this));
|
||||
|
||||
// Re-init language env in case it changed (not yet, but soon)
|
||||
common_init_language();
|
||||
$this->showSuccess();
|
||||
@ -211,6 +251,7 @@ class RegisterAction extends Action
|
||||
$this->showForm(_('Invalid username or password.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the given nickname already exist?
|
||||
@ -250,8 +291,10 @@ class RegisterAction extends Action
|
||||
|
||||
// overrrided to add entry-title class
|
||||
function showPageTitle() {
|
||||
if (Event::handle('StartShowPageTitle', array($this))) {
|
||||
$this->element('h1', array('class' => 'entry-title'), $this->title());
|
||||
}
|
||||
}
|
||||
|
||||
// overrided to add hentry, and content-inner class
|
||||
function showContentBlock()
|
||||
@ -341,6 +384,8 @@ class RegisterAction extends Action
|
||||
{
|
||||
$code = $this->trimmed('code');
|
||||
|
||||
$invite = null;
|
||||
|
||||
if ($code) {
|
||||
$invite = Invitation::staticGet($code);
|
||||
}
|
||||
@ -358,11 +403,12 @@ class RegisterAction extends Action
|
||||
$this->element('legend', null, 'Account settings');
|
||||
$this->hidden('token', common_session_token());
|
||||
|
||||
if ($code) {
|
||||
$this->hidden('code', $code);
|
||||
if ($this->code) {
|
||||
$this->hidden('code', $this->code);
|
||||
}
|
||||
|
||||
$this->elementStart('ul', 'form_data');
|
||||
if (Event::handle('StartRegistrationFormData', array($this))) {
|
||||
$this->elementStart('li');
|
||||
$this->input('nickname', _('Nickname'), $this->trimmed('nickname'),
|
||||
_('1-64 lowercase letters or numbers, '.
|
||||
@ -377,8 +423,8 @@ class RegisterAction extends Action
|
||||
_('Same as password above. Required.'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li');
|
||||
if ($invite && $invite->address_type == 'email') {
|
||||
$this->input('email', _('Email'), $invite->address,
|
||||
if ($this->invite && $this->invite->address_type == 'email') {
|
||||
$this->input('email', _('Email'), $this->invite->address,
|
||||
_('Used only for updates, announcements, '.
|
||||
'and password recovery'));
|
||||
} else {
|
||||
@ -410,6 +456,7 @@ class RegisterAction extends Action
|
||||
_('Where you are, like "City, '.
|
||||
'State (or Region), Country"'));
|
||||
$this->elementEnd('li');
|
||||
Event::handle('EndRegistrationFormData', array($this));
|
||||
$this->elementStart('li', array('id' => 'settings_rememberme'));
|
||||
$this->checkbox('rememberme', _('Remember me'),
|
||||
$this->boolean('rememberme'),
|
||||
@ -434,6 +481,7 @@ class RegisterAction extends Action
|
||||
'email address, IM address, and phone number.'));
|
||||
$this->elementEnd('label');
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
$this->elementEnd('ul');
|
||||
$this->submit('submit', _('Register'));
|
||||
$this->elementEnd('fieldset');
|
||||
@ -515,3 +563,4 @@ class RegisterAction extends Action
|
||||
$nav->show();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ class RemotesubscribeAction extends Action
|
||||
'class' => 'form_settings',
|
||||
'action' => common_local_url('remotesubscribe')));
|
||||
$this->elementStart('fieldset');
|
||||
$this->element('legend', 'Subscribe to a remote user');
|
||||
$this->element('legend', _('Subscribe to a remote user'));
|
||||
$this->hidden('token', common_session_token());
|
||||
|
||||
$this->elementStart('ul', 'form_data');
|
||||
@ -321,8 +321,7 @@ class RemotesubscribeAction extends Action
|
||||
|
||||
$result = $fetcher->post($req->get_normalized_http_url(),
|
||||
$req->to_postdata(),
|
||||
array('User-Agent' => 'Laconica/' . LACONICA_VERSION));
|
||||
|
||||
array('User-Agent: Laconica/' . LACONICA_VERSION));
|
||||
if ($result->status != 200) {
|
||||
return null;
|
||||
}
|
||||
@ -334,8 +333,6 @@ class RemotesubscribeAction extends Action
|
||||
|
||||
function requestAuthorization($user, $omb, $token, $secret)
|
||||
{
|
||||
global $config; # for license URL
|
||||
|
||||
$con = omb_oauth_consumer();
|
||||
$tok = new OAuthToken($token, $secret);
|
||||
|
||||
@ -359,7 +356,7 @@ class RemotesubscribeAction extends Action
|
||||
$req->set_parameter('omb_listenee', $user->uri);
|
||||
$req->set_parameter('omb_listenee_profile', common_profile_url($user->nickname));
|
||||
$req->set_parameter('omb_listenee_nickname', $user->nickname);
|
||||
$req->set_parameter('omb_listenee_license', $config['license']['url']);
|
||||
$req->set_parameter('omb_listenee_license', common_config('license', 'url'));
|
||||
|
||||
$profile = $user->getProfile();
|
||||
if (!$profile) {
|
||||
@ -368,16 +365,16 @@ class RemotesubscribeAction extends Action
|
||||
return;
|
||||
}
|
||||
|
||||
if ($profile->fullname) {
|
||||
if (!is_null($profile->fullname)) {
|
||||
$req->set_parameter('omb_listenee_fullname', $profile->fullname);
|
||||
}
|
||||
if ($profile->homepage) {
|
||||
if (!is_null($profile->homepage)) {
|
||||
$req->set_parameter('omb_listenee_homepage', $profile->homepage);
|
||||
}
|
||||
if ($profile->bio) {
|
||||
if (!is_null($profile->bio)) {
|
||||
$req->set_parameter('omb_listenee_bio', $profile->bio);
|
||||
}
|
||||
if ($profile->location) {
|
||||
if (!is_null($profile->location)) {
|
||||
$req->set_parameter('omb_listenee_location', $profile->location);
|
||||
}
|
||||
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||
@ -410,7 +407,7 @@ class RemotesubscribeAction extends Action
|
||||
|
||||
# Redirect to authorization service
|
||||
|
||||
common_redirect($req->to_url());
|
||||
common_redirect($req->to_url(), 303);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +138,17 @@ class RepliesAction extends Action
|
||||
return array(new Feed(Feed::RSS1, $rssurl, $rsstitle));
|
||||
}
|
||||
|
||||
/**
|
||||
* Output document relationship links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showRelationshipLinks()
|
||||
{
|
||||
$this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME
|
||||
$this->page, 'replies', array('nickname' => $this->user->nickname));
|
||||
}
|
||||
|
||||
/**
|
||||
* show the personal group nav
|
||||
*
|
||||
@ -166,13 +177,37 @@ class RepliesAction extends Action
|
||||
$nl = new NoticeList($notice, $this);
|
||||
|
||||
$cnt = $nl->show();
|
||||
if (0 === $cnt) {
|
||||
$this->showEmptyListMessage();
|
||||
}
|
||||
|
||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$this->page, 'replies',
|
||||
array('nickname' => $this->user->nickname));
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function showEmptyListMessage()
|
||||
{
|
||||
$message = sprintf(_('This is the timeline showing replies to %s but %s hasn\'t received a notice to his attention yet.'), $this->user->nickname, $this->user->nickname) . ' ';
|
||||
|
||||
if (common_logged_in()) {
|
||||
$current_user = common_current_user();
|
||||
if ($this->user->id === $current_user->id) {
|
||||
$message .= _('You can engage other users in a conversation, subscribe to more people or [join groups](%%action.groups%%).');
|
||||
} else {
|
||||
$message .= sprintf(_('You can try to [nudge %s](../%s) or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname);
|
||||
}
|
||||
|
||||
$this->elementStart('div', 'guide');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ class RepliesrssAction extends Rss10Action
|
||||
return ($avatar) ? $avatar->url : null;
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class RequesttokenAction extends Action
|
||||
*
|
||||
* @return boolean false
|
||||
*/
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -69,7 +69,7 @@ class RequesttokenAction extends Action
|
||||
parent::handle($args);
|
||||
try {
|
||||
common_remove_magic_from_request();
|
||||
$req = OAuthRequest::from_request();
|
||||
$req = OAuthRequest::from_request('POST', common_local_url('requesttoken'));
|
||||
$server = omb_oauth_server();
|
||||
$token = $server->fetch_request_token($req);
|
||||
print $token;
|
||||
|
@ -58,7 +58,7 @@ class ShowfavoritesAction extends Action
|
||||
* @return boolean true
|
||||
*/
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -74,9 +74,9 @@ class ShowfavoritesAction extends Action
|
||||
function title()
|
||||
{
|
||||
if ($this->page == 1) {
|
||||
return sprintf(_("%s favorite notices"), $this->user->nickname);
|
||||
return sprintf(_("%s's favorite notices"), $this->user->nickname);
|
||||
} else {
|
||||
return sprintf(_("%s favorite notices, page %d"),
|
||||
return sprintf(_("%s's favorite notices, page %d"),
|
||||
$this->user->nickname,
|
||||
$this->page);
|
||||
}
|
||||
@ -150,6 +150,18 @@ class ShowfavoritesAction extends Action
|
||||
return array(new Feed(Feed::RSS1, $feedurl, $feedtitle));
|
||||
}
|
||||
|
||||
/**
|
||||
* Output document relationship links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showRelationshipLinks()
|
||||
{
|
||||
$this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME
|
||||
$this->page, 'showfavorites', array('nickname' => $this->user->nickname));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* show the personal group nav
|
||||
*
|
||||
@ -162,6 +174,25 @@ class ShowfavoritesAction extends Action
|
||||
$nav->show();
|
||||
}
|
||||
|
||||
function showEmptyListMessage()
|
||||
{
|
||||
if (common_logged_in()) {
|
||||
$current_user = common_current_user();
|
||||
if ($this->user->id === $current_user->id) {
|
||||
$message = _('You haven\'t chosen any favorite notices yet. Click the fave button on notices you like to bookmark them for later or shed a spotlight on them.');
|
||||
} else {
|
||||
$message = sprintf(_('%s hasn\'t added any notices to his favorites yet. Post something interesting they would add to their favorites :)'), $this->user->nickname);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$message = sprintf(_('%s hasn\'t added any notices to his favorites yet. Why not [register an account](%%%%action.register%%%%) and then post something interesting they would add to thier favorites :)'), $this->user->nickname);
|
||||
}
|
||||
|
||||
$this->elementStart('div', 'guide');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the content
|
||||
*
|
||||
@ -183,9 +214,17 @@ class ShowfavoritesAction extends Action
|
||||
$nl = new NoticeList($notice, $this);
|
||||
|
||||
$cnt = $nl->show();
|
||||
if (0 == $cnt) {
|
||||
$this->showEmptyListMessage();
|
||||
}
|
||||
|
||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$this->page, 'showfavorites',
|
||||
array('nickname' => $this->user->nickname));
|
||||
}
|
||||
|
||||
function showPageNotice() {
|
||||
$this->element('p', 'instructions', _('This is a way to share what you like.'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ if (!defined('LACONICA')) {
|
||||
require_once INSTALLDIR.'/lib/noticelist.php';
|
||||
require_once INSTALLDIR.'/lib/feedlist.php';
|
||||
|
||||
define('MEMBERS_PER_SECTION', 81);
|
||||
define('MEMBERS_PER_SECTION', 27);
|
||||
|
||||
/**
|
||||
* Group main page
|
||||
@ -60,7 +60,7 @@ class ShowgroupAction extends Action
|
||||
* @return boolean true
|
||||
*/
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -73,11 +73,17 @@ class ShowgroupAction extends Action
|
||||
|
||||
function title()
|
||||
{
|
||||
if (!empty($this->group->fullname)) {
|
||||
$base = $this->group->fullname . ' (' . $this->group->nickname . ')';
|
||||
} else {
|
||||
$base = $this->group->nickname;
|
||||
}
|
||||
|
||||
if ($this->page == 1) {
|
||||
return sprintf(_("%s group"), $this->group->nickname);
|
||||
return sprintf(_("%s group"), $base);
|
||||
} else {
|
||||
return sprintf(_("%s group, page %d"),
|
||||
$this->group->nickname,
|
||||
$base,
|
||||
$this->page);
|
||||
}
|
||||
}
|
||||
@ -275,10 +281,8 @@ class ShowgroupAction extends Action
|
||||
$cur = common_current_user();
|
||||
if ($cur) {
|
||||
if ($cur->isMember($this->group)) {
|
||||
if (!$cur->isAdmin($this->group)) {
|
||||
$lf = new LeaveForm($this, $this->group);
|
||||
$lf->show();
|
||||
}
|
||||
} else {
|
||||
$jf = new JoinForm($this, $this->group);
|
||||
$jf->show();
|
||||
@ -307,6 +311,17 @@ class ShowgroupAction extends Action
|
||||
$this->group->nickname)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Output document relationship links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showRelationshipLinks()
|
||||
{
|
||||
$this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME
|
||||
$this->page, 'showgroup', array('nickname' => $this->group->nickname));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill in the sidebar.
|
||||
*
|
||||
@ -346,7 +361,7 @@ class ShowgroupAction extends Action
|
||||
$this->element('p', null, _('(None)'));
|
||||
}
|
||||
|
||||
if ($cnt == MEMBERS_PER_SECTION) {
|
||||
if ($cnt > MEMBERS_PER_SECTION) {
|
||||
$this->element('a', array('href' => common_local_url('groupmembers',
|
||||
array('nickname' => $this->group->nickname))),
|
||||
_('All members'));
|
||||
@ -392,11 +407,18 @@ class ShowgroupAction extends Action
|
||||
|
||||
function showAnonymousMessage()
|
||||
{
|
||||
if (!(common_config('site','closed') || common_config('site','inviteonly'))) {
|
||||
$m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
||||
'based on the Free Software [Laconica](http://laconi.ca/) tool. Its members share ' .
|
||||
'short messages about their life and interests. '.
|
||||
'[Join now](%%%%action.register%%%%) to become part of this group and many more! ([Read more](%%%%doc.help%%%%))'),
|
||||
$this->group->nickname);
|
||||
} else {
|
||||
$m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
||||
'based on the Free Software [Laconica](http://laconi.ca/) tool. Its members share ' .
|
||||
'short messages about their life and interests. '),
|
||||
$this->group->nickname);
|
||||
}
|
||||
$this->elementStart('div', array('id' => 'anon_notice'));
|
||||
$this->raw(common_markup_to_html($m));
|
||||
$this->elementEnd('div');
|
||||
|
@ -177,7 +177,7 @@ class ShowmessageAction extends MailboxAction
|
||||
return '';
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ class ShownoticeAction extends Action
|
||||
* @return boolean true
|
||||
*/
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -177,9 +177,16 @@ class ShownoticeAction extends Action
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if ($this->notice->is_local == 0) {
|
||||
if (!empty($this->notice->url)) {
|
||||
common_redirect($this->notice->url, 301);
|
||||
} else if (!empty($this->notice->uri) && preg_match('/^https?:/', $this->notice->uri)) {
|
||||
common_redirect($this->notice->uri, 301);
|
||||
}
|
||||
} else {
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't show local navigation
|
||||
@ -191,7 +198,6 @@ class ShownoticeAction extends Action
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fill the content area of the page
|
||||
*
|
||||
@ -208,8 +214,6 @@ class ShownoticeAction extends Action
|
||||
$this->elementEnd('ul');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Don't show page notice
|
||||
*
|
||||
@ -220,7 +224,6 @@ class ShownoticeAction extends Action
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Don't show aside
|
||||
*
|
||||
@ -230,7 +233,6 @@ class ShownoticeAction extends Action
|
||||
function showAside() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extra <head> content
|
||||
*
|
||||
|
@ -54,67 +54,33 @@ require_once INSTALLDIR.'/lib/feedlist.php';
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
class ShowstreamAction extends Action
|
||||
class ShowstreamAction extends ProfileAction
|
||||
{
|
||||
var $user = null;
|
||||
var $page = null;
|
||||
var $profile = null;
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
if (!empty($this->profile->fullname)) {
|
||||
$base = $this->profile->fullname . ' (' . $this->user->nickname . ') ';
|
||||
} else {
|
||||
$base = $this->user->nickname;
|
||||
}
|
||||
if (!empty($this->tag)) {
|
||||
$base .= sprintf(_(' tagged %s'), $this->tag);
|
||||
}
|
||||
|
||||
if ($this->page == 1) {
|
||||
return $this->user->nickname;
|
||||
return $base;
|
||||
} else {
|
||||
return sprintf(_("%s, page %d"),
|
||||
$this->user->nickname,
|
||||
$base,
|
||||
$this->page);
|
||||
}
|
||||
}
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$nickname_arg = $this->arg('nickname');
|
||||
$nickname = common_canonical_nickname($nickname_arg);
|
||||
|
||||
// Permanent redirect on non-canonical nickname
|
||||
|
||||
if ($nickname_arg != $nickname) {
|
||||
$args = array('nickname' => $nickname);
|
||||
if ($this->arg('page') && $this->arg('page') != 1) {
|
||||
$args['page'] = $this->arg['page'];
|
||||
}
|
||||
common_redirect(common_local_url('showstream', $args), 301);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->user = User::staticGet('nickname', $nickname);
|
||||
|
||||
if (!$this->user) {
|
||||
$this->clientError(_('No such user.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->profile = $this->user->getProfile();
|
||||
|
||||
if (!$this->profile) {
|
||||
$this->serverError(_('User has no profile.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
||||
|
||||
common_set_returnto($this->selfUrl());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
|
||||
@ -140,16 +106,6 @@ class ShowstreamAction extends Action
|
||||
$nav->show();
|
||||
}
|
||||
|
||||
function showPageTitle()
|
||||
{
|
||||
$user =& common_current_user();
|
||||
if ($user && ($user->id == $this->profile->id)) {
|
||||
$this->element('h1', NULL, _("Your profile"));
|
||||
} else {
|
||||
$this->element('h1', NULL, sprintf(_('%s\'s profile'), $this->profile->nickname));
|
||||
}
|
||||
}
|
||||
|
||||
function showPageNoticeBlock()
|
||||
{
|
||||
return;
|
||||
@ -157,6 +113,15 @@ class ShowstreamAction extends Action
|
||||
|
||||
function getFeeds()
|
||||
{
|
||||
if (!empty($this->tag)) {
|
||||
return array(new Feed(Feed::RSS1,
|
||||
common_local_url('userrss',
|
||||
array('nickname' => $this->user->nickname,
|
||||
'tag' => $this->tag)),
|
||||
sprintf(_('Notice feed for %s tagged %s (RSS 1.0)'),
|
||||
$this->user->nickname, $this->tag)));
|
||||
}
|
||||
|
||||
return array(new Feed(Feed::RSS1,
|
||||
common_local_url('userrss',
|
||||
array('nickname' => $this->user->nickname)),
|
||||
@ -182,6 +147,17 @@ class ShowstreamAction extends Action
|
||||
sprintf(_('FOAF for %s'), $this->user->nickname)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Output document relationship links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showRelationshipLinks()
|
||||
{
|
||||
$this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME
|
||||
$this->page, 'showstream', array('nickname' => $this->user->nickname));
|
||||
}
|
||||
|
||||
function extraHead()
|
||||
{
|
||||
// for remote subscriptions etc.
|
||||
@ -292,11 +268,11 @@ class ShowstreamAction extends Action
|
||||
$this->elementStart('ul', 'tags xoxo');
|
||||
foreach ($tags as $tag) {
|
||||
$this->elementStart('li');
|
||||
$this->element('span', 'mark_hash', '#');
|
||||
$this->element('a', array('rel' => 'tag',
|
||||
'href' => common_local_url('peopletag',
|
||||
array('tag' => $tag))),
|
||||
$tag);
|
||||
// Avoid space by using raw output.
|
||||
$pt = '<span class="mark_hash">#</span><a rel="tag" href="' .
|
||||
common_local_url('peopletag', array('tag' => $tag)) .
|
||||
'">' . $tag . '</a>';
|
||||
$this->raw($pt);
|
||||
$this->elementEnd('li');
|
||||
}
|
||||
$this->elementEnd('ul');
|
||||
@ -376,178 +352,66 @@ class ShowstreamAction extends Action
|
||||
_('Subscribe'));
|
||||
}
|
||||
|
||||
function showEmptyListMessage()
|
||||
{
|
||||
$message = sprintf(_('This is the timeline for %s but %s hasn\'t posted anything yet.'), $this->user->nickname, $this->user->nickname) . ' ';
|
||||
|
||||
if (common_logged_in()) {
|
||||
$current_user = common_current_user();
|
||||
if ($this->user->id === $current_user->id) {
|
||||
$message .= _('Seen anything interesting recently? You haven\'t posted any notices yet, now would be a good time to start :)');
|
||||
} else {
|
||||
$message .= sprintf(_('You can try to nudge %s or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%s).'), $this->user->nickname, '@' . $this->user->nickname);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname);
|
||||
}
|
||||
|
||||
$this->elementStart('div', 'guide');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function showNotices()
|
||||
{
|
||||
$notice = $this->user->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
|
||||
$notice = empty($this->tag)
|
||||
? $this->user->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1)
|
||||
: $this->user->getTaggedNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1, 0, 0, null, $this->tag);
|
||||
|
||||
$pnl = new ProfileNoticeList($notice, $this);
|
||||
$cnt = $pnl->show();
|
||||
if (0 == $cnt) {
|
||||
$this->showEmptyListMessage();
|
||||
}
|
||||
|
||||
$this->pagination($this->page>1, $cnt>NOTICES_PER_PAGE, $this->page,
|
||||
'showstream', array('nickname' => $this->user->nickname));
|
||||
}
|
||||
|
||||
function showSections()
|
||||
{
|
||||
$this->showSubscriptions();
|
||||
$this->showSubscribers();
|
||||
$this->showGroups();
|
||||
$this->showStatistics();
|
||||
$cloud = new PersonalTagCloudSection($this, $this->user);
|
||||
$cloud->show();
|
||||
}
|
||||
|
||||
function showSubscriptions()
|
||||
{
|
||||
$profile = $this->user->getSubscriptions(0, PROFILES_PER_MINILIST + 1);
|
||||
|
||||
$this->elementStart('div', array('id' => 'entity_subscriptions',
|
||||
'class' => 'section'));
|
||||
|
||||
$this->element('h2', null, _('Subscriptions'));
|
||||
|
||||
if ($profile) {
|
||||
$pml = new ProfileMiniList($profile, $this->user, $this);
|
||||
$cnt = $pml->show();
|
||||
if ($cnt == 0) {
|
||||
$this->element('p', null, _('(None)'));
|
||||
}
|
||||
}
|
||||
|
||||
if ($cnt > PROFILES_PER_MINILIST) {
|
||||
$this->elementStart('p');
|
||||
$this->element('a', array('href' => common_local_url('subscriptions',
|
||||
array('nickname' => $this->profile->nickname)),
|
||||
'class' => 'more'),
|
||||
_('All subscriptions'));
|
||||
$this->elementEnd('p');
|
||||
}
|
||||
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function showSubscribers()
|
||||
{
|
||||
$profile = $this->user->getSubscribers(0, PROFILES_PER_MINILIST + 1);
|
||||
|
||||
$this->elementStart('div', array('id' => 'entity_subscribers',
|
||||
'class' => 'section'));
|
||||
|
||||
$this->element('h2', null, _('Subscribers'));
|
||||
|
||||
if ($profile) {
|
||||
$pml = new ProfileMiniList($profile, $this->user, $this);
|
||||
$cnt = $pml->show();
|
||||
if ($cnt == 0) {
|
||||
$this->element('p', null, _('(None)'));
|
||||
}
|
||||
}
|
||||
|
||||
if ($cnt > PROFILES_PER_MINILIST) {
|
||||
$this->elementStart('p');
|
||||
$this->element('a', array('href' => common_local_url('subscribers',
|
||||
array('nickname' => $this->profile->nickname)),
|
||||
'class' => 'more'),
|
||||
_('All subscribers'));
|
||||
$this->elementEnd('p');
|
||||
}
|
||||
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function showStatistics()
|
||||
{
|
||||
// XXX: WORM cache this
|
||||
$subs = new Subscription();
|
||||
$subs->subscriber = $this->profile->id;
|
||||
$subs_count = (int) $subs->count() - 1;
|
||||
|
||||
$subbed = new Subscription();
|
||||
$subbed->subscribed = $this->profile->id;
|
||||
$subbed_count = (int) $subbed->count() - 1;
|
||||
|
||||
$notices = new Notice();
|
||||
$notices->profile_id = $this->profile->id;
|
||||
$notice_count = (int) $notices->count();
|
||||
|
||||
$this->elementStart('div', array('id' => 'entity_statistics',
|
||||
'class' => 'section'));
|
||||
|
||||
$this->element('h2', null, _('Statistics'));
|
||||
|
||||
// Other stats...?
|
||||
$this->elementStart('dl', 'entity_member-since');
|
||||
$this->element('dt', null, _('Member since'));
|
||||
$this->element('dd', null, date('j M Y',
|
||||
strtotime($this->profile->created)));
|
||||
$this->elementEnd('dl');
|
||||
|
||||
$this->elementStart('dl', 'entity_subscriptions');
|
||||
$this->elementStart('dt');
|
||||
$this->element('a', array('href' => common_local_url('subscriptions',
|
||||
array('nickname' => $this->profile->nickname))),
|
||||
_('Subscriptions'));
|
||||
$this->elementEnd('dt');
|
||||
$this->element('dd', null, (is_int($subs_count)) ? $subs_count : '0');
|
||||
$this->elementEnd('dl');
|
||||
|
||||
$this->elementStart('dl', 'entity_subscribers');
|
||||
$this->elementStart('dt');
|
||||
$this->element('a', array('href' => common_local_url('subscribers',
|
||||
array('nickname' => $this->profile->nickname))),
|
||||
_('Subscribers'));
|
||||
$this->elementEnd('dt');
|
||||
$this->element('dd', 'subscribers', (is_int($subbed_count)) ? $subbed_count : '0');
|
||||
$this->elementEnd('dl');
|
||||
|
||||
$this->elementStart('dl', 'entity_notices');
|
||||
$this->element('dt', null, _('Notices'));
|
||||
$this->element('dd', null, (is_int($notice_count)) ? $notice_count : '0');
|
||||
$this->elementEnd('dl');
|
||||
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function showGroups()
|
||||
{
|
||||
$groups = $this->user->getGroups(0, GROUPS_PER_MINILIST + 1);
|
||||
|
||||
$this->elementStart('div', array('id' => 'entity_groups',
|
||||
'class' => 'section'));
|
||||
|
||||
$this->element('h2', null, _('Groups'));
|
||||
|
||||
if ($groups) {
|
||||
$gml = new GroupMiniList($groups, $this->user, $this);
|
||||
$cnt = $gml->show();
|
||||
if ($cnt == 0) {
|
||||
$this->element('p', null, _('(None)'));
|
||||
}
|
||||
}
|
||||
|
||||
if ($cnt > GROUPS_PER_MINILIST) {
|
||||
$this->elementStart('p');
|
||||
$this->element('a', array('href' => common_local_url('usergroups',
|
||||
array('nickname' => $this->profile->nickname)),
|
||||
'class' => 'more'),
|
||||
_('All groups'));
|
||||
$this->elementEnd('p');
|
||||
}
|
||||
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function showAnonymousMessage()
|
||||
{
|
||||
if (!(common_config('site','closed') || common_config('site','inviteonly'))) {
|
||||
$m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
||||
'based on the Free Software [Laconica](http://laconi.ca/) tool. ' .
|
||||
'[Join now](%%%%action.register%%%%) to follow **%s**\'s notices and many more! ([Read more](%%%%doc.help%%%%))'),
|
||||
$this->user->nickname, $this->user->nickname);
|
||||
} else {
|
||||
$m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
||||
'based on the Free Software [Laconica](http://laconi.ca/) tool. '),
|
||||
$this->user->nickname, $this->user->nickname);
|
||||
}
|
||||
$this->elementStart('div', array('id' => 'anon_notice'));
|
||||
$this->raw(common_markup_to_html($m));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function showSections()
|
||||
{
|
||||
parent::showSections();
|
||||
$cloud = new PersonalTagCloudSection($this, $this->user);
|
||||
$cloud->show();
|
||||
}
|
||||
}
|
||||
|
||||
// We don't show the author for a profile, since we already know who it is!
|
||||
|
@ -488,7 +488,8 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
}
|
||||
|
||||
common_redirect(common_local_url('confirmaddress',
|
||||
array('code' => $code)));
|
||||
array('code' => $code)),
|
||||
303);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,7 +85,8 @@ class SubeditAction extends Action
|
||||
}
|
||||
|
||||
common_redirect(common_local_url('subscriptions',
|
||||
array('nickname' => $cur->nickname)));
|
||||
array('nickname' => $cur->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,8 @@ class SubscribeAction extends Action
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
common_redirect(common_local_url('subscriptions', array('nickname' =>
|
||||
$user->nickname)));
|
||||
$user->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,6 +88,9 @@ class SubscribersAction extends GalleryAction
|
||||
if ($subscribers) {
|
||||
$subscribers_list = new SubscribersList($subscribers, $this->user, $this);
|
||||
$cnt = $subscribers_list->show();
|
||||
if (0 == $cnt) {
|
||||
$this->showEmptyListMessage();
|
||||
}
|
||||
}
|
||||
|
||||
$subscribers->free();
|
||||
@ -96,6 +99,35 @@ class SubscribersAction extends GalleryAction
|
||||
$this->page, 'subscribers',
|
||||
array('nickname' => $this->user->nickname));
|
||||
}
|
||||
|
||||
function showEmptyListMessage()
|
||||
{
|
||||
if (common_logged_in()) {
|
||||
$current_user = common_current_user();
|
||||
if ($this->user->id === $current_user->id) {
|
||||
$message = _('You have no subscribers. Try subscribing to people you know and they might return the favor');
|
||||
} else {
|
||||
$message = sprintf(_('%s has no subscribers. Want to be the first?'), $this->user->nickname);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$message = sprintf(_('%s has no subscribers. Why not [register an account](%%%%action.register%%%%) and be the first?'), $this->user->nickname);
|
||||
}
|
||||
|
||||
$this->elementStart('div', 'guide');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function showSections()
|
||||
{
|
||||
parent::showSections();
|
||||
$cloud = new SubscribersPeopleTagCloudSection($this);
|
||||
$cloud->show();
|
||||
|
||||
$cloud2 = new SubscribersPeopleSelfTagCloudSection($this);
|
||||
$cloud2->show();
|
||||
}
|
||||
}
|
||||
|
||||
class SubscribersList extends ProfileList
|
||||
@ -108,7 +140,7 @@ class SubscribersList extends ProfileList
|
||||
$bf->show();
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -95,6 +95,9 @@ class SubscriptionsAction extends GalleryAction
|
||||
if ($subscriptions) {
|
||||
$subscriptions_list = new SubscriptionsList($subscriptions, $this->user, $this);
|
||||
$cnt = $subscriptions_list->show();
|
||||
if (0 == $cnt) {
|
||||
$this->showEmptyListMessage();
|
||||
}
|
||||
}
|
||||
|
||||
$subscriptions->free();
|
||||
@ -103,6 +106,35 @@ class SubscriptionsAction extends GalleryAction
|
||||
$this->page, 'subscriptions',
|
||||
array('nickname' => $this->user->nickname));
|
||||
}
|
||||
|
||||
function showEmptyListMessage()
|
||||
{
|
||||
if (common_logged_in()) {
|
||||
$current_user = common_current_user();
|
||||
if ($this->user->id === $current_user->id) {
|
||||
$message = _('You\'re not listening to anyone\'s notices right now, try subscribing to people you know. Try [people search](%%action.peoplesearch%%), look for members in groups you\'re interested in and in our [featured users](%%action.featured%%). If you\'re a [Twitter user](%%action.twittersettings%%), you can automatically subscribe to people you already follow there.');
|
||||
} else {
|
||||
$message = sprintf(_('%s is not listening to anyone.'), $this->user->nickname);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$message = sprintf(_('%s is not listening to anyone.'), $this->user->nickname);
|
||||
}
|
||||
|
||||
$this->elementStart('div', 'guide');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function showSections()
|
||||
{
|
||||
parent::showSections();
|
||||
$cloud = new SubscriptionsPeopleTagCloudSection($this);
|
||||
$cloud->show();
|
||||
|
||||
$cloud2 = new SubscriptionsPeopleSelfTagCloudSection($this);
|
||||
$cloud2->show();
|
||||
}
|
||||
}
|
||||
|
||||
class SubscriptionsList extends ProfileList
|
||||
@ -117,7 +149,7 @@ class SubscriptionsList extends ProfileList
|
||||
|
||||
$this->out->elementStart('form', array('id' => 'subedit-' . $profile->id,
|
||||
'method' => 'post',
|
||||
'class' => 'form_subcription_edit',
|
||||
'class' => 'form_subscription_edit',
|
||||
'action' => common_local_url('subedit')));
|
||||
$this->out->hidden('token', common_session_token());
|
||||
$this->out->hidden('profile', $profile->id);
|
||||
|
@ -65,7 +65,9 @@ class SupAction extends Action
|
||||
|
||||
$notice->query('SELECT profile_id, max(id) AS max_id ' .
|
||||
'FROM notice ' .
|
||||
'WHERE created > (now() - ' . $seconds . ') ' .
|
||||
((common_config('db','type') == 'pgsql') ?
|
||||
'WHERE extract(epoch from created) > (extract(epoch from now()) - ' . $seconds . ') ' :
|
||||
'WHERE created > (now() - ' . $seconds . ') ' ) .
|
||||
'GROUP BY profile_id');
|
||||
|
||||
$updates = array();
|
||||
@ -77,7 +79,7 @@ class SupAction extends Action
|
||||
return $updates;
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -33,7 +33,9 @@ class TagAction extends Action
|
||||
}
|
||||
|
||||
if ($this->tag != $taginput) {
|
||||
common_redirect(common_local_url('tag', array('tag' => $this->tag)));
|
||||
common_redirect(common_local_url('tag', array('tag' => $this->tag)),
|
||||
301);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
||||
@ -43,6 +45,14 @@ class TagAction extends Action
|
||||
return true;
|
||||
}
|
||||
|
||||
function showSections()
|
||||
{
|
||||
$pop = new PopularNoticeSection($this);
|
||||
$pop->show();
|
||||
$freqatt = new FrequentAttachmentSection($this);
|
||||
$freqatt->show();
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
if ($this->page == 1) {
|
||||
@ -68,6 +78,17 @@ class TagAction extends Action
|
||||
sprintf(_('Feed for tag %s'), $this->tag)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Output document relationship links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showRelationshipLinks()
|
||||
{
|
||||
$this->sequenceRelationships($this->page > 1, $this->count > NOTICES_PER_PAGE, // FIXME
|
||||
$this->page, 'tag', array('tag' => $this->tag));
|
||||
}
|
||||
|
||||
function showPageNotice()
|
||||
{
|
||||
return sprintf(_('Messages tagged "%s", most recent first'), $this->tag);
|
||||
@ -84,4 +105,9 @@ class TagAction extends Action
|
||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$this->page, 'tag', array('tag' => $this->tag));
|
||||
}
|
||||
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +135,8 @@ class TagotherAction extends Action
|
||||
'id' => 'form_tag_user',
|
||||
'class' => 'form_settings',
|
||||
'name' => 'tagother',
|
||||
'action' => $this->selfUrl()));
|
||||
'action' => common_local_url('tagother', array('id' => $this->profile->id))));
|
||||
|
||||
$this->elementStart('fieldset');
|
||||
$this->element('legend', null, _('Tag user'));
|
||||
$this->hidden('token', common_session_token());
|
||||
@ -220,7 +221,8 @@ class TagotherAction extends Action
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
common_redirect(common_local_url($action, array('nickname' =>
|
||||
$user->nickname)));
|
||||
$user->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ class TagrssAction extends Rss10Action
|
||||
return $c;
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -23,20 +23,21 @@ require_once(INSTALLDIR.'/lib/twitterapi.php');
|
||||
|
||||
class TwitapiaccountAction extends TwitterapiAction
|
||||
{
|
||||
|
||||
function verify_credentials($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
if ($apidata['content-type'] == 'xml') {
|
||||
header('Content-Type: application/xml; charset=utf-8');
|
||||
print '<authorized>true</authorized>';
|
||||
} elseif ($apidata['content-type'] == 'json') {
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
print '{"authorized":true}';
|
||||
} else {
|
||||
common_user_error(_('API method not found!'), $code=404);
|
||||
switch ($apidata['content-type']) {
|
||||
case 'xml':
|
||||
case 'json':
|
||||
$action_obj = new TwitapiusersAction();
|
||||
$action_obj->prepare($args);
|
||||
call_user_func(array($action_obj, 'show'), $args, $apidata);
|
||||
break;
|
||||
default:
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
print 'Authorized';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function end_session($args, $apidata)
|
||||
|
@ -38,7 +38,6 @@ class Twitapidirect_messagesAction extends TwitterapiAction
|
||||
|
||||
function show_messages($args, $apidata, $type)
|
||||
{
|
||||
|
||||
$user = $apidata['user'];
|
||||
|
||||
$count = $this->arg('count');
|
||||
@ -102,7 +101,17 @@ class Twitapidirect_messagesAction extends TwitterapiAction
|
||||
$this->show_rss_dmsgs($message, $title, $link, $subtitle);
|
||||
break;
|
||||
case 'atom':
|
||||
$this->show_atom_dmsgs($message, $title, $link, $subtitle);
|
||||
$selfuri = common_root_url() . 'api/direct_messages';
|
||||
$selfuri .= ($type == 'received') ? '.atom' : '/sent.atom';
|
||||
$taguribase = common_config('integration', 'taguri');
|
||||
|
||||
if ($type == 'sent') {
|
||||
$id = "tag:$taguribase:SentDirectMessages:" . $user->id;
|
||||
} else {
|
||||
$id = "tag:$taguribase:DirectMessages:" . $user->id;
|
||||
}
|
||||
|
||||
$this->show_atom_dmsgs($message, $title, $link, $subtitle, $selfuri, $id);
|
||||
break;
|
||||
case 'json':
|
||||
$this->show_json_dmsgs($message);
|
||||
@ -190,7 +199,7 @@ class Twitapidirect_messagesAction extends TwitterapiAction
|
||||
$this->init_document('xml');
|
||||
$this->elementStart('direct-messages', array('type' => 'array'));
|
||||
|
||||
if (is_array($messages)) {
|
||||
if (is_array($message)) {
|
||||
foreach ($message as $m) {
|
||||
$twitter_dm = $this->twitter_dmsg_array($m);
|
||||
$this->show_twitter_xml_dmsg($twitter_dm);
|
||||
@ -261,16 +270,17 @@ class Twitapidirect_messagesAction extends TwitterapiAction
|
||||
|
||||
}
|
||||
|
||||
function show_atom_dmsgs($message, $title, $link, $subtitle)
|
||||
function show_atom_dmsgs($message, $title, $link, $subtitle, $selfuri, $id)
|
||||
{
|
||||
|
||||
$this->init_document('atom');
|
||||
|
||||
$this->element('title', null, $title);
|
||||
$siteserver = common_config('site', 'server');
|
||||
$this->element('id', null, "tag:$siteserver,2008:DirectMessage");
|
||||
$this->element('id', null, $id);
|
||||
$this->element('link', array('href' => $link, 'rel' => 'alternate', 'type' => 'text/html'), null);
|
||||
$this->element('updated', null, common_date_iso8601(strftime('%c')));
|
||||
$this->element('link', array('href' => $selfuri, 'rel' => 'self',
|
||||
'type' => 'application/atom+xml'), null);
|
||||
$this->element('updated', null, common_date_iso8601('now'));
|
||||
$this->element('subtitle', null, $subtitle);
|
||||
|
||||
if (is_array($message)) {
|
||||
|
@ -61,10 +61,9 @@ class TwitapifavoritesAction extends TwitterapiAction
|
||||
}
|
||||
|
||||
$sitename = common_config('site', 'name');
|
||||
$siteserver = common_config('site', 'server');
|
||||
|
||||
$title = sprintf(_('%s / Favorites from %s'), $sitename, $user->nickname);
|
||||
$id = "tag:$siteserver:favorites:".$user->id;
|
||||
$taguribase = common_config('integration', 'taguri');
|
||||
$id = "tag:$taguribase:Favorites:".$user->id;
|
||||
$link = common_local_url('favorites', array('nickname' => $user->nickname));
|
||||
$subtitle = sprintf(_('%s updates favorited by %s / %s.'), $sitename, $profile->getBestName(), $user->nickname);
|
||||
|
||||
@ -76,7 +75,14 @@ class TwitapifavoritesAction extends TwitterapiAction
|
||||
$this->show_rss_timeline($notice, $title, $link, $subtitle);
|
||||
break;
|
||||
case 'atom':
|
||||
$this->show_atom_timeline($notice, $title, $id, $link, $subtitle);
|
||||
if (isset($apidata['api_arg'])) {
|
||||
$selfuri = $selfuri = common_root_url() .
|
||||
'api/favorites/' . $apidata['api_arg'] . '.atom';
|
||||
} else {
|
||||
$selfuri = $selfuri = common_root_url() .
|
||||
'api/favorites.atom';
|
||||
}
|
||||
$this->show_atom_timeline($notice, $title, $id, $link, $subtitle, null, $selfuri);
|
||||
break;
|
||||
case 'json':
|
||||
$this->show_json_timeline($notice);
|
||||
|
@ -133,11 +133,7 @@ class TwitapifriendshipsAction extends TwitterapiAction
|
||||
return;
|
||||
}
|
||||
|
||||
if ($user_a->isSubscribed($user_b)) {
|
||||
$result = 'true';
|
||||
} else {
|
||||
$result = 'false';
|
||||
}
|
||||
$result = $user_a->isSubscribed($user_b);
|
||||
|
||||
switch ($apidata['content-type']) {
|
||||
case 'xml':
|
||||
|
377
actions/twitapisearchatom.php
Normal file
377
actions/twitapisearchatom.php
Normal file
@ -0,0 +1,377 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* Action for showing Twitter-like Atom search results
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* @category Search
|
||||
* @package Laconica
|
||||
* @author Zach Copley <zach@controlyourself.ca>
|
||||
* @copyright 2008-2009 Control Yourself, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/twitterapi.php';
|
||||
|
||||
/**
|
||||
* Action for outputting search results in Twitter compatible Atom
|
||||
* format.
|
||||
*
|
||||
* TODO: abstract Atom stuff into a ruseable base class like
|
||||
* RSS10Action.
|
||||
*
|
||||
* @category Search
|
||||
* @package Laconica
|
||||
* @author Zach Copley <zach@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*
|
||||
* @see TwitterapiAction
|
||||
*/
|
||||
|
||||
class TwitapisearchatomAction extends TwitterapiAction
|
||||
{
|
||||
|
||||
var $cnt;
|
||||
var $query;
|
||||
var $lang;
|
||||
var $rpp;
|
||||
var $page;
|
||||
var $since_id;
|
||||
var $geocode;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Just wraps the Action constructor.
|
||||
*
|
||||
* @param string $output URI to output to, default = stdout
|
||||
* @param boolean $indent Whether to indent output, default true
|
||||
*
|
||||
* @see Action::__construct
|
||||
*/
|
||||
|
||||
function __construct($output='php://output', $indent=true)
|
||||
{
|
||||
parent::__construct($output, $indent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we need to write to the database?
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
|
||||
function isReadonly()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read arguments and initialize members
|
||||
*
|
||||
* @param array $args Arguments from $_REQUEST
|
||||
*
|
||||
* @return boolean success
|
||||
*
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->query = $this->trimmed('q');
|
||||
$this->lang = $this->trimmed('lang');
|
||||
$this->rpp = $this->trimmed('rpp');
|
||||
|
||||
if (!$this->rpp) {
|
||||
$this->rpp = 15;
|
||||
}
|
||||
|
||||
if ($this->rpp > 100) {
|
||||
$this->rpp = 100;
|
||||
}
|
||||
|
||||
$this->page = $this->trimmed('page');
|
||||
|
||||
if (!$this->page) {
|
||||
$this->page = 1;
|
||||
}
|
||||
|
||||
// TODO: Suppport since_id -- we need to tweak the backend
|
||||
// Search classes to support it.
|
||||
|
||||
$this->since_id = $this->trimmed('since_id');
|
||||
$this->geocode = $this->trimmed('geocode');
|
||||
|
||||
// TODO: Also, language and geocode
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request
|
||||
*
|
||||
* @param array $args Arguments from $_REQUEST
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
$this->showAtom();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notices to output as results. This also sets some class
|
||||
* attrs so we can use them to calculate pagination, and output
|
||||
* since_id and max_id.
|
||||
*
|
||||
* @return array an array of Notice objects sorted in reverse chron
|
||||
*/
|
||||
|
||||
function getNotices()
|
||||
{
|
||||
// TODO: Support search operators like from: and to:, boolean, etc.
|
||||
|
||||
$notices = array();
|
||||
$notice = new Notice();
|
||||
|
||||
// lcase it for comparison
|
||||
$q = strtolower($this->query);
|
||||
|
||||
$search_engine = $notice->getSearchEngine('identica_notices');
|
||||
$search_engine->set_sort_mode('chron');
|
||||
$search_engine->limit(($this->page - 1) * $this->rpp,
|
||||
$this->rpp + 1, true);
|
||||
$search_engine->query($q);
|
||||
$this->cnt = $notice->find();
|
||||
|
||||
$cnt = 0;
|
||||
|
||||
while ($notice->fetch()) {
|
||||
|
||||
++$cnt;
|
||||
|
||||
if (!$this->max_id) {
|
||||
$this->max_id = $notice->id;
|
||||
}
|
||||
|
||||
if ($cnt > $this->rpp) {
|
||||
break;
|
||||
}
|
||||
|
||||
$notices[] = clone($notice);
|
||||
}
|
||||
|
||||
return $notices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output search results as an Atom feed
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showAtom()
|
||||
{
|
||||
$notices = $this->getNotices();
|
||||
|
||||
$this->initAtom();
|
||||
$this->showFeed();
|
||||
|
||||
foreach ($notices as $n) {
|
||||
$this->showEntry($n);
|
||||
}
|
||||
|
||||
$this->endAtom();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show feed specific Atom elements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showFeed()
|
||||
{
|
||||
// TODO: A9 OpenSearch stuff like search.twitter.com?
|
||||
|
||||
$server = common_config('site', 'server');
|
||||
$sitename = common_config('site', 'name');
|
||||
|
||||
// XXX: Use xmlns:laconica instead?
|
||||
|
||||
$this->elementStart('feed',
|
||||
array('xmlns' => 'http://www.w3.org/2005/Atom',
|
||||
|
||||
// XXX: xmlns:twitter causes Atom validation to fail
|
||||
// It's used for the source attr on notices
|
||||
|
||||
'xmlns:twitter' => 'http://api.twitter.com/',
|
||||
'xml:lang' => 'en-US')); // XXX Other locales ?
|
||||
|
||||
$taguribase = common_config('integration', 'taguri');
|
||||
$this->element('id', null, "tag:$taguribase:search/$server");
|
||||
|
||||
$site_uri = common_path(false);
|
||||
|
||||
$search_uri = $site_uri . 'api/search.atom?q=' . urlencode($this->query);
|
||||
|
||||
if ($this->rpp != 15) {
|
||||
$search_uri .= '&rpp=' . $this->rpp;
|
||||
}
|
||||
|
||||
// FIXME: this alternate link is not quite right because our
|
||||
// web-based notice search doesn't support a rpp (responses per
|
||||
// page) param yet
|
||||
|
||||
$this->element('link', array('type' => 'text/html',
|
||||
'rel' => 'alternate',
|
||||
'href' => $site_uri . 'search/notice?q=' .
|
||||
urlencode($this->query)));
|
||||
|
||||
// self link
|
||||
|
||||
$self_uri = $search_uri;
|
||||
$self_uri .= ($this->page > 1) ? '&page=' . $this->page : '';
|
||||
|
||||
$this->element('link', array('type' => 'application/atom+xml',
|
||||
'rel' => 'self',
|
||||
'href' => $self_uri));
|
||||
|
||||
$this->element('title', null, "$this->query - $sitename Search");
|
||||
$this->element('updated', null, common_date_iso8601('now'));
|
||||
|
||||
// XXX: The below "rel" links are not valid Atom, but it's what
|
||||
// Twitter does...
|
||||
|
||||
// refresh link
|
||||
|
||||
$refresh_uri = $search_uri . "&since_id=" . $this->max_id;
|
||||
|
||||
$this->element('link', array('type' => 'application/atom+xml',
|
||||
'rel' => 'refresh',
|
||||
'href' => $refresh_uri));
|
||||
|
||||
// pagination links
|
||||
|
||||
if ($this->cnt > $this->rpp) {
|
||||
|
||||
$next_uri = $search_uri . "&max_id=" . $this->max_id .
|
||||
'&page=' . ($this->page + 1);
|
||||
|
||||
$this->element('link', array('type' => 'application/atom+xml',
|
||||
'rel' => 'next',
|
||||
'href' => $next_uri));
|
||||
}
|
||||
|
||||
if ($this->page > 1) {
|
||||
|
||||
$previous_uri = $search_uri . "&max_id=" . $this->max_id .
|
||||
'&page=' . ($this->page - 1);
|
||||
|
||||
$this->element('link', array('type' => 'application/atom+xml',
|
||||
'rel' => 'previous',
|
||||
'href' => $previous_uri));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an Atom entry similar to search.twitter.com's based on
|
||||
* a given notice
|
||||
*
|
||||
* @param Notice $notice the notice to use
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showEntry($notice)
|
||||
{
|
||||
$server = common_config('site', 'server');
|
||||
$profile = $notice->getProfile();
|
||||
$nurl = common_local_url('shownotice', array('notice' => $notice->id));
|
||||
|
||||
$this->elementStart('entry');
|
||||
|
||||
$taguribase = common_config('integration', 'taguri');
|
||||
|
||||
$this->element('id', null, "tag:$taguribase:$notice->id");
|
||||
$this->element('published', null, common_date_w3dtf($notice->created));
|
||||
$this->element('link', array('type' => 'text/html',
|
||||
'rel' => 'alternate',
|
||||
'href' => $nurl));
|
||||
$this->element('title', null, common_xml_safe_str(trim($notice->content)));
|
||||
$this->element('content', array('type' => 'html'), $notice->rendered);
|
||||
$this->element('updated', null, common_date_w3dtf($notice->created));
|
||||
$this->element('link', array('type' => 'image/png',
|
||||
// XXX: Twitter uses rel="image" (not valid)
|
||||
'rel' => 'related',
|
||||
'href' => $profile->avatarUrl()));
|
||||
|
||||
// TODO: Here is where we'd put in a link to an atom feed for threads
|
||||
|
||||
$this->element("twitter:source", null,
|
||||
htmlentities($this->source_link($notice->source)));
|
||||
|
||||
$this->elementStart('author');
|
||||
|
||||
$name = $profile->nickname;
|
||||
|
||||
if ($profile->fullname) {
|
||||
$name .= ' (' . $profile->fullname . ')';
|
||||
}
|
||||
|
||||
$this->element('name', null, $name);
|
||||
$this->element('uri', null, common_profile_uri($profile));
|
||||
$this->elementEnd('author');
|
||||
|
||||
$this->elementEnd('entry');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Atom output, send headers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function initAtom()
|
||||
{
|
||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||
$this->startXml();
|
||||
}
|
||||
|
||||
/**
|
||||
* End the Atom feed
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function endAtom()
|
||||
{
|
||||
$this->elementEnd('feed');
|
||||
}
|
||||
|
||||
}
|
149
actions/twitapisearchjson.php
Normal file
149
actions/twitapisearchjson.php
Normal file
@ -0,0 +1,149 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* Action for showing Twitter-like JSON search results
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* @category Search
|
||||
* @package Laconica
|
||||
* @author Zach Copley <zach@controlyourself.ca>
|
||||
* @copyright 2008-2009 Control Yourself, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/twitterapi.php';
|
||||
require_once INSTALLDIR.'/lib/jsonsearchresultslist.php';
|
||||
|
||||
/**
|
||||
* Action handler for Twitter-compatible API search
|
||||
*
|
||||
* @category Search
|
||||
* @package Laconica
|
||||
* @author Zach Copley <zach@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
* @see TwitterapiAction
|
||||
*/
|
||||
|
||||
class TwitapisearchjsonAction extends TwitterapiAction
|
||||
{
|
||||
var $query;
|
||||
var $lang;
|
||||
var $rpp;
|
||||
var $page;
|
||||
var $since_id;
|
||||
var $limit;
|
||||
var $geocode;
|
||||
|
||||
/**
|
||||
* Initialization.
|
||||
*
|
||||
* @param array $args Web and URL arguments
|
||||
*
|
||||
* @return boolean true if nothing goes wrong
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->query = $this->trimmed('q');
|
||||
$this->lang = $this->trimmed('lang');
|
||||
$this->rpp = $this->trimmed('rpp');
|
||||
|
||||
if (!$this->rpp) {
|
||||
$this->rpp = 15;
|
||||
}
|
||||
|
||||
if ($this->rpp > 100) {
|
||||
$this->rpp = 100;
|
||||
}
|
||||
|
||||
$this->page = $this->trimmed('page');
|
||||
|
||||
if (!$this->page) {
|
||||
$this->page = 1;
|
||||
}
|
||||
|
||||
$this->since_id = $this->trimmed('since_id');
|
||||
$this->geocode = $this->trimmed('geocode');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request
|
||||
*
|
||||
* @param array $args Arguments from $_REQUEST
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
$this->showResults();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show search results
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showResults()
|
||||
{
|
||||
|
||||
// TODO: Support search operators like from: and to:, boolean, etc.
|
||||
|
||||
$notice = new Notice();
|
||||
|
||||
// lcase it for comparison
|
||||
$q = strtolower($this->query);
|
||||
|
||||
$search_engine = $notice->getSearchEngine('identica_notices');
|
||||
$search_engine->set_sort_mode('chron');
|
||||
$search_engine->limit(($this->page - 1) * $this->rpp, $this->rpp + 1, true);
|
||||
$search_engine->query($q);
|
||||
$cnt = $notice->find();
|
||||
|
||||
// TODO: since_id, lang, geocode
|
||||
|
||||
$results = new JSONSearchResultsList($notice, $q, $this->rpp, $this->page);
|
||||
|
||||
$this->init_document('json');
|
||||
$results->show();
|
||||
$this->end_document('json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we need to write to the database?
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
@ -29,10 +29,12 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
parent::handle($args);
|
||||
|
||||
$sitename = common_config('site', 'name');
|
||||
$siteserver = common_config('site', 'server');
|
||||
$title = sprintf(_("%s public timeline"), $sitename);
|
||||
$id = "tag:$siteserver:Statuses";
|
||||
|
||||
$taguribase = common_config('integration', 'taguri');
|
||||
$id = "tag:$taguribase:PublicTimeline";
|
||||
$link = common_root_url();
|
||||
|
||||
$subtitle = sprintf(_("%s updates from everyone!"), $sitename);
|
||||
|
||||
// Number of public statuses to return by default -- Twitter sends 20
|
||||
@ -70,7 +72,8 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$this->show_rss_timeline($notice, $title, $link, $subtitle);
|
||||
break;
|
||||
case 'atom':
|
||||
$this->show_atom_timeline($notice, $title, $id, $link, $subtitle);
|
||||
$selfuri = common_root_url() . 'api/statuses/public_timeline.atom';
|
||||
$this->show_atom_timeline($notice, $title, $id, $link, $subtitle, null, $selfuri);
|
||||
break;
|
||||
case 'json':
|
||||
$this->show_json_timeline($notice);
|
||||
@ -114,17 +117,19 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
}
|
||||
|
||||
$since = strtotime($this->arg('since'));
|
||||
|
||||
$user = $this->get_user(null, $apidata);
|
||||
$user = $this->get_user($apidata['api_arg'], $apidata);
|
||||
$this->auth_user = $user;
|
||||
|
||||
if (empty($user)) {
|
||||
$this->clientError(_('No such user!'), 404, $apidata['content-type']);
|
||||
return;
|
||||
}
|
||||
|
||||
$profile = $user->getProfile();
|
||||
|
||||
$sitename = common_config('site', 'name');
|
||||
$siteserver = common_config('site', 'server');
|
||||
|
||||
$title = sprintf(_("%s and friends"), $user->nickname);
|
||||
$id = "tag:$siteserver:friends:" . $user->id;
|
||||
$taguribase = common_config('integration', 'taguri');
|
||||
$id = "tag:$taguribase:FriendsTimeline:" . $user->id;
|
||||
$link = common_local_url('all', array('nickname' => $user->nickname));
|
||||
$subtitle = sprintf(_('Updates from %1$s and friends on %2$s!'), $user->nickname, $sitename);
|
||||
|
||||
@ -138,7 +143,14 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$this->show_rss_timeline($notice, $title, $link, $subtitle);
|
||||
break;
|
||||
case 'atom':
|
||||
$this->show_atom_timeline($notice, $title, $id, $link, $subtitle);
|
||||
if (isset($apidata['api_arg'])) {
|
||||
$selfuri = common_root_url() .
|
||||
'api/statuses/friends_timeline/' . $apidata['api_arg'] . '.atom';
|
||||
} else {
|
||||
$selfuri = common_root_url() .
|
||||
'api/statuses/friends_timeline.atom';
|
||||
}
|
||||
$this->show_atom_timeline($notice, $title, $id, $link, $subtitle, null, $selfuri);
|
||||
break;
|
||||
case 'json':
|
||||
$this->show_json_timeline($notice);
|
||||
@ -194,17 +206,16 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$since = strtotime($this->arg('since'));
|
||||
|
||||
$sitename = common_config('site', 'name');
|
||||
$siteserver = common_config('site', 'server');
|
||||
|
||||
$title = sprintf(_("%s timeline"), $user->nickname);
|
||||
$id = "tag:$siteserver:user:".$user->id;
|
||||
$taguribase = common_config('integration', 'taguri');
|
||||
$id = "tag:$taguribase:UserTimeline:".$user->id;
|
||||
$link = common_local_url('showstream', array('nickname' => $user->nickname));
|
||||
$subtitle = sprintf(_('Updates from %1$s on %2$s!'), $user->nickname, $sitename);
|
||||
|
||||
# FriendFeed's SUP protocol
|
||||
# Also added RSS and Atom feeds
|
||||
|
||||
$suplink = common_local_url('sup', null, $user->id);
|
||||
$suplink = common_local_url('sup', null, null, $user->id);
|
||||
header('X-SUP-ID: '.$suplink);
|
||||
|
||||
# XXX: since
|
||||
@ -219,7 +230,14 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$this->show_rss_timeline($notice, $title, $link, $subtitle, $suplink);
|
||||
break;
|
||||
case 'atom':
|
||||
$this->show_atom_timeline($notice, $title, $id, $link, $subtitle, $suplink);
|
||||
if (isset($apidata['api_arg'])) {
|
||||
$selfuri = common_root_url() .
|
||||
'api/statuses/user_timeline/' . $apidata['api_arg'] . '.atom';
|
||||
} else {
|
||||
$selfuri = common_root_url() .
|
||||
'api/statuses/user_timeline.atom';
|
||||
}
|
||||
$this->show_atom_timeline($notice, $title, $id, $link, $subtitle, $suplink, $selfuri);
|
||||
break;
|
||||
case 'json':
|
||||
$this->show_json_timeline($notice);
|
||||
@ -326,7 +344,7 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$this->show($args, $apidata);
|
||||
}
|
||||
|
||||
function replies($args, $apidata)
|
||||
function mentions($args, $apidata)
|
||||
{
|
||||
|
||||
parent::handle($args);
|
||||
@ -337,17 +355,18 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$since_id = $this->arg('since_id');
|
||||
$before_id = $this->arg('before_id');
|
||||
|
||||
$user = $this->get_user($apidata['api_arg'], $apidata);
|
||||
$this->auth_user = $apidata['user'];
|
||||
$user = $this->auth_user;
|
||||
$profile = $user->getProfile();
|
||||
|
||||
$sitename = common_config('site', 'name');
|
||||
$siteserver = common_config('site', 'server');
|
||||
|
||||
$title = sprintf(_('%1$s / Updates replying to %2$s'), $sitename, $user->nickname);
|
||||
$id = "tag:$siteserver:replies:".$user->id;
|
||||
$title = sprintf(_('%1$s / Updates mentioning %2$s'),
|
||||
$sitename, $user->nickname);
|
||||
$taguribase = common_config('integration', 'taguri');
|
||||
$id = "tag:$taguribase:Mentions:".$user->id;
|
||||
$link = common_local_url('replies', array('nickname' => $user->nickname));
|
||||
$subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'), $sitename, $user->nickname, $profile->getBestName());
|
||||
$subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'),
|
||||
$sitename, $user->nickname, $profile->getBestName());
|
||||
|
||||
if (!$page) {
|
||||
$page = 1;
|
||||
@ -368,7 +387,8 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
|
||||
$since = strtotime($this->arg('since'));
|
||||
|
||||
$notice = $user->getReplies((($page-1)*20), $count, $since_id, $before_id, $since);
|
||||
$notice = $user->getReplies((($page-1)*20),
|
||||
$count, $since_id, $before_id, $since);
|
||||
$notices = array();
|
||||
|
||||
while ($notice->fetch()) {
|
||||
@ -383,7 +403,10 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$this->show_rss_timeline($notices, $title, $link, $subtitle);
|
||||
break;
|
||||
case 'atom':
|
||||
$this->show_atom_timeline($notices, $title, $id, $link, $subtitle);
|
||||
$selfuri = common_root_url() .
|
||||
ltrim($_SERVER['QUERY_STRING'], 'p=');
|
||||
$this->show_atom_timeline($notices, $title, $id, $link, $subtitle,
|
||||
null, $selfuri);
|
||||
break;
|
||||
case 'json':
|
||||
$this->show_json_timeline($notices);
|
||||
@ -394,6 +417,11 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
|
||||
}
|
||||
|
||||
function replies($args, $apidata)
|
||||
{
|
||||
call_user_func(array($this, 'mentions'), $args, $apidata);
|
||||
}
|
||||
|
||||
function show($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
@ -470,19 +498,28 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
return $this->subscriptions($apidata, 'subscribed', 'subscriber');
|
||||
}
|
||||
|
||||
function friendsIDs($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
return $this->subscriptions($apidata, 'subscribed', 'subscriber', true);
|
||||
}
|
||||
|
||||
function followers($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
||||
return $this->subscriptions($apidata, 'subscriber', 'subscribed');
|
||||
}
|
||||
|
||||
function subscriptions($apidata, $other_attr, $user_attr)
|
||||
function followersIDs($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
return $this->subscriptions($apidata, 'subscriber', 'subscribed', true);
|
||||
}
|
||||
|
||||
function subscriptions($apidata, $other_attr, $user_attr, $onlyIDs=false)
|
||||
{
|
||||
|
||||
# XXX: lite
|
||||
|
||||
$this->auth_user = $apidate['user'];
|
||||
$this->auth_user = $apidata['user'];
|
||||
$user = $this->get_user($apidata['api_arg'], $apidata);
|
||||
|
||||
if (!$user) {
|
||||
@ -514,7 +551,10 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
}
|
||||
|
||||
$sub->orderBy('created DESC');
|
||||
|
||||
if (!$onlyIDs) {
|
||||
$sub->limit(($page-1)*100, 100);
|
||||
}
|
||||
|
||||
$others = array();
|
||||
|
||||
@ -529,7 +569,13 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
$type = $apidata['content-type'];
|
||||
|
||||
$this->init_document($type);
|
||||
|
||||
if ($onlyIDs) {
|
||||
$this->showIDs($others, $type);
|
||||
} else {
|
||||
$this->show_profiles($others, $type);
|
||||
}
|
||||
|
||||
$this->end_document($type);
|
||||
}
|
||||
|
||||
@ -555,6 +601,28 @@ class TwitapistatusesAction extends TwitterapiAction
|
||||
}
|
||||
}
|
||||
|
||||
function showIDs($profiles, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'xml':
|
||||
$this->elementStart('ids');
|
||||
foreach ($profiles as $profile) {
|
||||
$this->element('id', null, $profile->id);
|
||||
}
|
||||
$this->elementEnd('ids');
|
||||
break;
|
||||
case 'json':
|
||||
$ids = array();
|
||||
foreach ($profiles as $profile) {
|
||||
$ids[] = (int)$profile->id;
|
||||
}
|
||||
print json_encode($ids);
|
||||
break;
|
||||
default:
|
||||
$this->clientError(_('unsupported file type'));
|
||||
}
|
||||
}
|
||||
|
||||
function featured($args, $apidata)
|
||||
{
|
||||
parent::handle($args);
|
||||
|
90
actions/twitapitrends.php
Normal file
90
actions/twitapitrends.php
Normal file
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* List of replies
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* @category Search
|
||||
* @package Laconica
|
||||
* @author Zach Copley <zach@controlyourself.ca>
|
||||
* @copyright 2008-2009 Control Yourself, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/twitterapi.php';
|
||||
|
||||
/**
|
||||
* Returns the top ten queries that are currently trending
|
||||
*
|
||||
* @category Search
|
||||
* @package Laconica
|
||||
* @author Zach Copley <zach@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*
|
||||
* @see TwitterapiAction
|
||||
*/
|
||||
|
||||
class TwitapitrendsAction extends TwitterapiAction
|
||||
{
|
||||
|
||||
var $callback;
|
||||
|
||||
/**
|
||||
* Initialization.
|
||||
*
|
||||
* @param array $args Web and URL arguments
|
||||
*
|
||||
* @return boolean false if user doesn't exist
|
||||
*/
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request
|
||||
*
|
||||
* @param array $args Arguments from $_REQUEST
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
$this->showTrends();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the trends
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showTrends()
|
||||
{
|
||||
$this->serverError(_('API method under construction.'), $code = 501);
|
||||
}
|
||||
|
||||
}
|
@ -33,14 +33,18 @@ class TwitapiusersAction extends TwitterapiAction
|
||||
return;
|
||||
}
|
||||
|
||||
$this->auth_user = $apidata['user'];
|
||||
$user = null;
|
||||
$email = $this->arg('email');
|
||||
$user_id = $this->arg('user_id');
|
||||
|
||||
if ($email) {
|
||||
$user = User::staticGet('email', $email);
|
||||
} elseif ($user_id) {
|
||||
$user = $this->get_user($user_id);
|
||||
} elseif (isset($apidata['api_arg'])) {
|
||||
$user = $this->get_user($apidata['api_arg']);
|
||||
} elseif (isset($apidata['user'])) {
|
||||
$user = $apidata['user'];
|
||||
}
|
||||
|
||||
if (!$user) {
|
||||
@ -74,9 +78,12 @@ class TwitapiusersAction extends TwitterapiAction
|
||||
|
||||
// Other fields Twitter sends...
|
||||
$twitter_user['profile_background_color'] = '';
|
||||
$twitter_user['profile_background_image_url'] = '';
|
||||
$twitter_user['profile_text_color'] = '';
|
||||
$twitter_user['profile_link_color'] = '';
|
||||
$twitter_user['profile_sidebar_fill_color'] = '';
|
||||
$twitter_user['profile_sidebar_border_color'] = '';
|
||||
$twitter_user['profile_background_tile'] = false;
|
||||
|
||||
$faves = DB_DataObject::factory('fave');
|
||||
$faves->user_id = $user->id;
|
||||
@ -94,16 +101,17 @@ class TwitapiusersAction extends TwitterapiAction
|
||||
$twitter_user['utc_offset'] = $t->format('Z');
|
||||
$twitter_user['time_zone'] = $timezone;
|
||||
|
||||
if (isset($this->auth_user)) {
|
||||
if (isset($apidata['user'])) {
|
||||
|
||||
if ($this->auth_user->isSubscribed($profile)) {
|
||||
$twitter_user['following'] = 'true';
|
||||
} else {
|
||||
$twitter_user['following'] = 'false';
|
||||
$twitter_user['following'] = $apidata['user']->isSubscribed($profile);
|
||||
|
||||
// Notifications on?
|
||||
$sub = Subscription::pkeyGet(array('subscriber' =>
|
||||
$apidata['user']->id, 'subscribed' => $profile->id));
|
||||
|
||||
if ($sub) {
|
||||
$twitter_user['notifications'] = ($sub->jabber || $sub->sms);
|
||||
}
|
||||
|
||||
// Not implemented yet
|
||||
$twitter_user['notifications'] = 'false';
|
||||
}
|
||||
|
||||
if ($apidata['content-type'] == 'xml') {
|
||||
@ -114,6 +122,12 @@ class TwitapiusersAction extends TwitterapiAction
|
||||
$this->init_document('json');
|
||||
$this->show_json_objects($twitter_user);
|
||||
$this->end_document('json');
|
||||
} else {
|
||||
|
||||
// This is in case 'show' was called via /account/verify_credentials
|
||||
// without a format (xml or json).
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
print 'Authorized';
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ class TwittersettingsAction extends ConnectSettingsAction
|
||||
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('noticesync',
|
||||
$this->checkbox('noticesend',
|
||||
_('Automatically send my notices to Twitter.'),
|
||||
($flink) ?
|
||||
($flink->noticesync & FOREIGN_NOTICE_SEND) :
|
||||
@ -158,6 +158,22 @@ class TwittersettingsAction extends ConnectSettingsAction
|
||||
($flink->friendsync & FOREIGN_FRIEND_RECV) :
|
||||
false);
|
||||
$this->elementEnd('li');
|
||||
|
||||
if (common_config('twitterbridge','enabled')) {
|
||||
$this->elementStart('li');
|
||||
$this->checkbox('noticerecv',
|
||||
_('Import my Friends Timeline.'),
|
||||
($flink) ?
|
||||
($flink->noticesync & FOREIGN_NOTICE_RECV) :
|
||||
false);
|
||||
$this->elementEnd('li');
|
||||
} else {
|
||||
// preserve setting even if bidrection bridge toggled off
|
||||
if ($flink && ($flink->noticesync & FOREIGN_NOTICE_RECV)) {
|
||||
$this->hidden('noticerecv', true, 'noticerecv');
|
||||
}
|
||||
}
|
||||
|
||||
$this->elementEnd('ul');
|
||||
|
||||
if ($flink) {
|
||||
@ -186,12 +202,12 @@ class TwittersettingsAction extends ConnectSettingsAction
|
||||
|
||||
$current_user = common_current_user();
|
||||
|
||||
$qry = 'SELECT user.* ' .
|
||||
$qry = 'SELECT "user".* ' .
|
||||
'FROM subscription ' .
|
||||
'JOIN user ON subscription.subscribed = user.id ' .
|
||||
'JOIN foreign_link ON foreign_link.user_id = user.id ' .
|
||||
'JOIN "user" ON subscription.subscribed = "user".id ' .
|
||||
'JOIN foreign_link ON foreign_link.user_id = "user".id ' .
|
||||
'WHERE subscriber = %d ' .
|
||||
'ORDER BY user.nickname';
|
||||
'ORDER BY "user".nickname';
|
||||
|
||||
$user = new User();
|
||||
|
||||
@ -320,7 +336,8 @@ class TwittersettingsAction extends ConnectSettingsAction
|
||||
{
|
||||
$screen_name = $this->trimmed('twitter_username');
|
||||
$password = $this->trimmed('twitter_password');
|
||||
$noticesync = $this->boolean('noticesync');
|
||||
$noticesend = $this->boolean('noticesend');
|
||||
$noticerecv = $this->boolean('noticerecv');
|
||||
$replysync = $this->boolean('replysync');
|
||||
$friendsync = $this->boolean('friendsync');
|
||||
|
||||
@ -363,7 +380,7 @@ class TwittersettingsAction extends ConnectSettingsAction
|
||||
$flink->credentials = $password;
|
||||
$flink->created = common_sql_now();
|
||||
|
||||
$flink->set_flags($noticesync, $replysync, $friendsync);
|
||||
$flink->set_flags($noticesend, $noticerecv, $replysync, $friendsync);
|
||||
|
||||
$flink_id = $flink->insert();
|
||||
|
||||
@ -375,6 +392,8 @@ class TwittersettingsAction extends ConnectSettingsAction
|
||||
|
||||
if ($friendsync) {
|
||||
save_twitter_friends($user, $twit_user->id, $screen_name, $password);
|
||||
$flink->last_friendsync = common_sql_now();
|
||||
$flink->update();
|
||||
}
|
||||
|
||||
$this->showForm(_('Twitter settings saved.'), true);
|
||||
@ -419,7 +438,8 @@ class TwittersettingsAction extends ConnectSettingsAction
|
||||
|
||||
function savePreferences()
|
||||
{
|
||||
$noticesync = $this->boolean('noticesync');
|
||||
$noticesend = $this->boolean('noticesend');
|
||||
$noticerecv = $this->boolean('noticerecv');
|
||||
$friendsync = $this->boolean('friendsync');
|
||||
$replysync = $this->boolean('replysync');
|
||||
|
||||
@ -448,7 +468,7 @@ class TwittersettingsAction extends ConnectSettingsAction
|
||||
|
||||
$original = clone($flink);
|
||||
|
||||
$flink->set_flags($noticesync, $replysync, $friendsync);
|
||||
$flink->set_flags($noticesend, $noticerecv, $replysync, $friendsync);
|
||||
|
||||
$result = $flink->update($original);
|
||||
|
||||
|
@ -116,10 +116,11 @@ class UnblockAction extends Action
|
||||
}
|
||||
}
|
||||
if ($action) {
|
||||
common_redirect(common_local_url($action, $args));
|
||||
common_redirect(common_local_url($action, $args), 303);
|
||||
} else {
|
||||
common_redirect(common_local_url('subscriptions',
|
||||
array('nickname' => $cur->nickname)));
|
||||
array('nickname' => $cur->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +77,8 @@ class UnsubscribeAction extends Action
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
common_redirect(common_local_url('subscriptions', array('nickname' =>
|
||||
$user->nickname)));
|
||||
$user->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,11 +29,13 @@ class UpdateprofileAction extends Action
|
||||
parent::handle($args);
|
||||
try {
|
||||
common_remove_magic_from_request();
|
||||
$req = OAuthRequest::from_request();
|
||||
$req = OAuthRequest::from_request('POST', common_local_url('updateprofile'));
|
||||
# Note: server-to-server function!
|
||||
$server = omb_oauth_server();
|
||||
list($consumer, $token) = $server->verify_request($req);
|
||||
if ($this->update_profile($req, $consumer, $token)) {
|
||||
header('HTTP/1.1 200 OK');
|
||||
header('Content-type: text/plain');
|
||||
print "omb_version=".OMB_VERSION_01;
|
||||
}
|
||||
} catch (OAuthException $e) {
|
||||
@ -136,22 +138,24 @@ class UpdateprofileAction extends Action
|
||||
|
||||
$orig_profile = clone($profile);
|
||||
|
||||
if ($nickname) {
|
||||
/* Use values even if they are an empty string. Parsing an empty string in
|
||||
updateProfile is the specified way of clearing a parameter in OMB. */
|
||||
if (!is_null($nickname)) {
|
||||
$profile->nickname = $nickname;
|
||||
}
|
||||
if ($profile_url) {
|
||||
if (!is_null($profile_url)) {
|
||||
$profile->profileurl = $profile_url;
|
||||
}
|
||||
if ($fullname) {
|
||||
if (!is_null($fullname)) {
|
||||
$profile->fullname = $fullname;
|
||||
}
|
||||
if ($homepage) {
|
||||
if (!is_null($homepage)) {
|
||||
$profile->homepage = $homepage;
|
||||
}
|
||||
if ($bio) {
|
||||
if (!is_null($bio)) {
|
||||
$profile->bio = $bio;
|
||||
}
|
||||
if ($location) {
|
||||
if (!is_null($location)) {
|
||||
$profile->location = $location;
|
||||
}
|
||||
|
||||
@ -162,15 +166,17 @@ class UpdateprofileAction extends Action
|
||||
if ($avatar) {
|
||||
$temp_filename = tempnam(sys_get_temp_dir(), 'listenee_avatar');
|
||||
copy($avatar, $temp_filename);
|
||||
if (!$profile->setOriginal($temp_filename)) {
|
||||
$imagefile = new ImageFile($profile->id, $temp_filename);
|
||||
$filename = Avatar::filename($profile->id,
|
||||
image_type_to_extension($imagefile->type),
|
||||
null,
|
||||
common_timestamp());
|
||||
rename($temp_filename, Avatar::path($filename));
|
||||
if (!$profile->setOriginal($filename)) {
|
||||
$this->serverError(_('Could not save avatar info'), 500);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
header('HTTP/1.1 200 OK');
|
||||
header('Content-type: text/plain');
|
||||
print 'Updated profile';
|
||||
print "\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ define('TIMESTAMP_THRESHOLD', 300);
|
||||
class UserauthorizationAction extends Action
|
||||
{
|
||||
var $error;
|
||||
var $req;
|
||||
var $params;
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
@ -35,8 +35,8 @@ class UserauthorizationAction extends Action
|
||||
# CSRF protection
|
||||
$token = $this->trimmed('token');
|
||||
if (!$token || $token != common_session_token()) {
|
||||
$req = $this->getStoredRequest();
|
||||
$this->showForm($req, _('There was a problem with your session token. '.
|
||||
$params = $this->getStoredParams();
|
||||
$this->showForm($params, _('There was a problem with your session token. '.
|
||||
'Try again, please.'));
|
||||
return;
|
||||
}
|
||||
@ -50,18 +50,13 @@ class UserauthorizationAction extends Action
|
||||
common_redirect(common_local_url('login'));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
# this must be a new request
|
||||
$req = $this->getNewRequest();
|
||||
if (!$req) {
|
||||
$this->clientError(_('No request found!'));
|
||||
}
|
||||
# XXX: only validate new requests, since nonce is one-time use
|
||||
$this->validateRequest($req);
|
||||
$this->storeRequest($req);
|
||||
$this->showForm($req);
|
||||
$this->validateRequest();
|
||||
$this->storeParams($_GET);
|
||||
$this->showForm($_GET);
|
||||
} catch (OAuthException $e) {
|
||||
$this->clearRequest();
|
||||
$this->clearParams();
|
||||
$this->clientError($e->getMessage());
|
||||
return;
|
||||
}
|
||||
@ -69,9 +64,9 @@ class UserauthorizationAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
function showForm($req, $error=null)
|
||||
function showForm($params, $error=null)
|
||||
{
|
||||
$this->req = $req;
|
||||
$this->params = $params;
|
||||
$this->error = $error;
|
||||
$this->showPage();
|
||||
}
|
||||
@ -91,113 +86,157 @@ class UserauthorizationAction extends Action
|
||||
|
||||
function showContent()
|
||||
{
|
||||
$req = $this->req;
|
||||
$params = $this->params;
|
||||
|
||||
$nickname = $req->get_parameter('omb_listenee_nickname');
|
||||
$profile = $req->get_parameter('omb_listenee_profile');
|
||||
$license = $req->get_parameter('omb_listenee_license');
|
||||
$fullname = $req->get_parameter('omb_listenee_fullname');
|
||||
$homepage = $req->get_parameter('omb_listenee_homepage');
|
||||
$bio = $req->get_parameter('omb_listenee_bio');
|
||||
$location = $req->get_parameter('omb_listenee_location');
|
||||
$avatar = $req->get_parameter('omb_listenee_avatar');
|
||||
$nickname = $params['omb_listenee_nickname'];
|
||||
$profile = $params['omb_listenee_profile'];
|
||||
$license = $params['omb_listenee_license'];
|
||||
$fullname = $params['omb_listenee_fullname'];
|
||||
$homepage = $params['omb_listenee_homepage'];
|
||||
$bio = $params['omb_listenee_bio'];
|
||||
$location = $params['omb_listenee_location'];
|
||||
$avatar = $params['omb_listenee_avatar'];
|
||||
|
||||
$this->elementStart('div', 'profile');
|
||||
$this->elementStart('div', array('class' => 'profile'));
|
||||
$this->elementStart('div', 'entity_profile vcard');
|
||||
$this->elementStart('a', array('href' => $profile,
|
||||
'class' => 'url'));
|
||||
if ($avatar) {
|
||||
$this->element('img', array('src' => $avatar,
|
||||
'class' => 'avatar profile',
|
||||
'class' => 'photo avatar',
|
||||
'width' => AVATAR_PROFILE_SIZE,
|
||||
'height' => AVATAR_PROFILE_SIZE,
|
||||
'alt' => $nickname));
|
||||
}
|
||||
$this->element('a', array('href' => $profile,
|
||||
'class' => 'external profile nickname'),
|
||||
$nickname);
|
||||
if ($fullname) {
|
||||
$this->elementStart('div', 'fullname');
|
||||
if ($homepage) {
|
||||
$this->element('a', array('href' => $homepage),
|
||||
$fullname);
|
||||
} else {
|
||||
$this->text($fullname);
|
||||
$hasFN = ($fullname !== '') ? 'nickname' : 'fn nickname';
|
||||
$this->elementStart('span', $hasFN);
|
||||
$this->raw($nickname);
|
||||
$this->elementEnd('span');
|
||||
$this->elementEnd('a');
|
||||
|
||||
if (!is_null($fullname)) {
|
||||
$this->elementStart('dl', 'entity_fn');
|
||||
$this->elementStart('dd');
|
||||
$this->elementStart('span', 'fn');
|
||||
$this->raw($fullname);
|
||||
$this->elementEnd('span');
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
}
|
||||
$this->elementEnd('div');
|
||||
if (!is_null($location)) {
|
||||
$this->elementStart('dl', 'entity_location');
|
||||
$this->element('dt', null, _('Location'));
|
||||
$this->elementStart('dd', 'label');
|
||||
$this->raw($location);
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
}
|
||||
if ($location) {
|
||||
$this->element('div', 'location', $location);
|
||||
|
||||
if (!is_null($homepage)) {
|
||||
$this->elementStart('dl', 'entity_url');
|
||||
$this->element('dt', null, _('URL'));
|
||||
$this->elementStart('dd');
|
||||
$this->elementStart('a', array('href' => $homepage,
|
||||
'class' => 'url'));
|
||||
$this->raw($homepage);
|
||||
$this->elementEnd('a');
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
}
|
||||
if ($bio) {
|
||||
$this->element('div', 'bio', $bio);
|
||||
|
||||
if (!is_null($bio)) {
|
||||
$this->elementStart('dl', 'entity_note');
|
||||
$this->element('dt', null, _('Note'));
|
||||
$this->elementStart('dd', 'note');
|
||||
$this->raw($bio);
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
}
|
||||
$this->elementStart('div', 'license');
|
||||
|
||||
if (!is_null($license)) {
|
||||
$this->elementStart('dl', 'entity_license');
|
||||
$this->element('dt', null, _('License'));
|
||||
$this->elementStart('dd', 'license');
|
||||
$this->element('a', array('href' => $license,
|
||||
'class' => 'license'),
|
||||
$license);
|
||||
$this->elementEnd('dd');
|
||||
$this->elementEnd('dl');
|
||||
}
|
||||
$this->elementEnd('div');
|
||||
$this->elementEnd('div');
|
||||
|
||||
$this->elementStart('div', 'entity_actions');
|
||||
$this->elementStart('ul');
|
||||
$this->elementStart('li', 'entity_subscribe');
|
||||
$this->elementStart('form', array('method' => 'post',
|
||||
'id' => 'userauthorization',
|
||||
'class' => 'form_user_authorization',
|
||||
'name' => 'userauthorization',
|
||||
'action' => common_local_url('userauthorization')));
|
||||
$this->hidden('token', common_session_token());
|
||||
$this->submit('accept', _('Accept'));
|
||||
$this->submit('reject', _('Reject'));
|
||||
|
||||
$this->submit('accept', _('Accept'), 'submit accept', null, _('Subscribe to this user'));
|
||||
$this->submit('reject', _('Reject'), 'submit reject', null, _('Reject this subscription'));
|
||||
$this->elementEnd('form');
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
$this->elementEnd('div');
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function sendAuthorization()
|
||||
{
|
||||
$req = $this->getStoredRequest();
|
||||
$params = $this->getStoredParams();
|
||||
|
||||
if (!$req) {
|
||||
if (!$params) {
|
||||
$this->clientError(_('No authorization request!'));
|
||||
return;
|
||||
}
|
||||
|
||||
$callback = $req->get_parameter('oauth_callback');
|
||||
$callback = $params['oauth_callback'];
|
||||
|
||||
if ($this->arg('accept')) {
|
||||
if (!$this->authorizeToken($req)) {
|
||||
if (!$this->authorizeToken($params)) {
|
||||
$this->clientError(_('Error authorizing token'));
|
||||
}
|
||||
if (!$this->saveRemoteProfile($req)) {
|
||||
if (!$this->saveRemoteProfile($params)) {
|
||||
$this->clientError(_('Error saving remote profile'));
|
||||
}
|
||||
if (!$callback) {
|
||||
$this->showAcceptMessage($req->get_parameter('oauth_token'));
|
||||
$this->showAcceptMessage($params['oauth_token']);
|
||||
} else {
|
||||
$params = array();
|
||||
$params['oauth_token'] = $req->get_parameter('oauth_token');
|
||||
$params['omb_version'] = OMB_VERSION_01;
|
||||
$user = User::staticGet('uri', $req->get_parameter('omb_listener'));
|
||||
$newparams = array();
|
||||
$newparams['oauth_token'] = $params['oauth_token'];
|
||||
$newparams['omb_version'] = OMB_VERSION_01;
|
||||
$user = User::staticGet('uri', $params['omb_listener']);
|
||||
$profile = $user->getProfile();
|
||||
if (!$profile) {
|
||||
common_log_db_error($user, 'SELECT', __FILE__);
|
||||
$this->serverError(_('User without matching profile'));
|
||||
return;
|
||||
}
|
||||
$params['omb_listener_nickname'] = $user->nickname;
|
||||
$params['omb_listener_profile'] = common_local_url('showstream',
|
||||
$newparams['omb_listener_nickname'] = $user->nickname;
|
||||
$newparams['omb_listener_profile'] = common_local_url('showstream',
|
||||
array('nickname' => $user->nickname));
|
||||
if ($profile->fullname) {
|
||||
$params['omb_listener_fullname'] = $profile->fullname;
|
||||
if (!is_null($profile->fullname)) {
|
||||
$newparams['omb_listener_fullname'] = $profile->fullname;
|
||||
}
|
||||
if ($profile->homepage) {
|
||||
$params['omb_listener_homepage'] = $profile->homepage;
|
||||
if (!is_null($profile->homepage)) {
|
||||
$newparams['omb_listener_homepage'] = $profile->homepage;
|
||||
}
|
||||
if ($profile->bio) {
|
||||
$params['omb_listener_bio'] = $profile->bio;
|
||||
if (!is_null($profile->bio)) {
|
||||
$newparams['omb_listener_bio'] = $profile->bio;
|
||||
}
|
||||
if ($profile->location) {
|
||||
$params['omb_listener_location'] = $profile->location;
|
||||
if (!is_null($profile->location)) {
|
||||
$newparams['omb_listener_location'] = $profile->location;
|
||||
}
|
||||
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||
if ($avatar) {
|
||||
$params['omb_listener_avatar'] = $avatar->url;
|
||||
$newparams['omb_listener_avatar'] = $avatar->url;
|
||||
}
|
||||
$parts = array();
|
||||
foreach ($params as $k => $v) {
|
||||
$parts[] = $k . '=' . OAuthUtil::urlencodeRFC3986($v);
|
||||
foreach ($newparams as $k => $v) {
|
||||
$parts[] = $k . '=' . OAuthUtil::urlencode_rfc3986($v);
|
||||
}
|
||||
$query_string = implode('&', $parts);
|
||||
$parsed = parse_url($callback);
|
||||
@ -214,12 +253,10 @@ class UserauthorizationAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
function authorizeToken(&$req)
|
||||
function authorizeToken(&$params)
|
||||
{
|
||||
$consumer_key = $req->get_parameter('oauth_consumer_key');
|
||||
$token_field = $req->get_parameter('oauth_token');
|
||||
$token_field = $params['oauth_token'];
|
||||
$rt = new Token();
|
||||
$rt->consumer_key = $consumer_key;
|
||||
$rt->tok = $token_field;
|
||||
$rt->type = 0;
|
||||
$rt->state = 0;
|
||||
@ -235,21 +272,21 @@ class UserauthorizationAction extends Action
|
||||
|
||||
# XXX: refactor with similar code in finishremotesubscribe.php
|
||||
|
||||
function saveRemoteProfile(&$req)
|
||||
function saveRemoteProfile(&$params)
|
||||
{
|
||||
# FIXME: we should really do this when the consumer comes
|
||||
# back for an access token. If they never do, we've got stuff in a
|
||||
# weird state.
|
||||
|
||||
$nickname = $req->get_parameter('omb_listenee_nickname');
|
||||
$fullname = $req->get_parameter('omb_listenee_fullname');
|
||||
$profile_url = $req->get_parameter('omb_listenee_profile');
|
||||
$homepage = $req->get_parameter('omb_listenee_homepage');
|
||||
$bio = $req->get_parameter('omb_listenee_bio');
|
||||
$location = $req->get_parameter('omb_listenee_location');
|
||||
$avatar_url = $req->get_parameter('omb_listenee_avatar');
|
||||
$nickname = $params['omb_listenee_nickname'];
|
||||
$fullname = $params['omb_listenee_fullname'];
|
||||
$profile_url = $params['omb_listenee_profile'];
|
||||
$homepage = $params['omb_listenee_homepage'];
|
||||
$bio = $params['omb_listenee_bio'];
|
||||
$location = $params['omb_listenee_location'];
|
||||
$avatar_url = $params['omb_listenee_avatar'];
|
||||
|
||||
$listenee = $req->get_parameter('omb_listenee');
|
||||
$listenee = $params['omb_listenee'];
|
||||
$remote = Remote_profile::staticGet('uri', $listenee);
|
||||
|
||||
if ($remote) {
|
||||
@ -267,16 +304,16 @@ class UserauthorizationAction extends Action
|
||||
$profile->nickname = $nickname;
|
||||
$profile->profileurl = $profile_url;
|
||||
|
||||
if ($fullname) {
|
||||
if (!is_null($fullname)) {
|
||||
$profile->fullname = $fullname;
|
||||
}
|
||||
if ($homepage) {
|
||||
if (!is_null($homepage)) {
|
||||
$profile->homepage = $homepage;
|
||||
}
|
||||
if ($bio) {
|
||||
if (!is_null($bio)) {
|
||||
$profile->bio = $bio;
|
||||
}
|
||||
if ($location) {
|
||||
if (!is_null($location)) {
|
||||
$profile->location = $location;
|
||||
}
|
||||
|
||||
@ -309,14 +346,11 @@ class UserauthorizationAction extends Action
|
||||
}
|
||||
|
||||
$user = common_current_user();
|
||||
$datastore = omb_oauth_datastore();
|
||||
$consumer = $this->getConsumer($datastore, $req);
|
||||
$token = $this->getToken($datastore, $req, $consumer);
|
||||
|
||||
$sub = new Subscription();
|
||||
$sub->subscriber = $user->id;
|
||||
$sub->subscribed = $remote->id;
|
||||
$sub->token = $token->key; # NOTE: request token, not valid for use!
|
||||
$sub->token = $params['oauth_token']; # NOTE: request token, not valid for use!
|
||||
$sub->created = DB_DataObject_Cast::dateTime(); # current time
|
||||
|
||||
if (!$sub->insert()) {
|
||||
@ -360,65 +394,59 @@ class UserauthorizationAction extends Action
|
||||
common_show_footer();
|
||||
}
|
||||
|
||||
function storeRequest($req)
|
||||
function storeParams($params)
|
||||
{
|
||||
common_ensure_session();
|
||||
$_SESSION['userauthorizationrequest'] = $req;
|
||||
$_SESSION['userauthorizationparams'] = $params;
|
||||
}
|
||||
|
||||
function clearRequest()
|
||||
function clearParams()
|
||||
{
|
||||
common_ensure_session();
|
||||
unset($_SESSION['userauthorizationrequest']);
|
||||
unset($_SESSION['userauthorizationparams']);
|
||||
}
|
||||
|
||||
function getStoredRequest()
|
||||
function getStoredParams()
|
||||
{
|
||||
common_ensure_session();
|
||||
$req = $_SESSION['userauthorizationrequest'];
|
||||
return $req;
|
||||
}
|
||||
|
||||
function getNewRequest()
|
||||
{
|
||||
common_remove_magic_from_request();
|
||||
$req = OAuthRequest::from_request();
|
||||
return $req;
|
||||
$params = $_SESSION['userauthorizationparams'];
|
||||
return $params;
|
||||
}
|
||||
|
||||
# Throws an OAuthException if anything goes wrong
|
||||
|
||||
function validateRequest(&$req)
|
||||
function validateRequest()
|
||||
{
|
||||
# OAuth stuff -- have to copy from OAuth.php since they're
|
||||
# all private methods, and there's no user-authentication method
|
||||
$this->checkVersion($req);
|
||||
$datastore = omb_oauth_datastore();
|
||||
$consumer = $this->getConsumer($datastore, $req);
|
||||
$token = $this->getToken($datastore, $req, $consumer);
|
||||
$this->checkTimestamp($req);
|
||||
$this->checkNonce($datastore, $req, $consumer, $token);
|
||||
$this->checkSignature($req, $consumer, $token);
|
||||
$this->validateOmb($req);
|
||||
/* Find token.
|
||||
TODO: If no token is passed the user should get a prompt to enter it
|
||||
according to OAuth Core 1.0 */
|
||||
$t = new Token();
|
||||
$t->tok = $_GET['oauth_token'];
|
||||
$t->type = 0;
|
||||
if (!$t->find(true)) {
|
||||
throw new OAuthException("Invalid request token: " . $_GET['oauth_token']);
|
||||
}
|
||||
|
||||
$this->validateOmb();
|
||||
return true;
|
||||
}
|
||||
|
||||
function validateOmb(&$req)
|
||||
function validateOmb()
|
||||
{
|
||||
foreach (array('omb_version', 'omb_listener', 'omb_listenee',
|
||||
'omb_listenee_profile', 'omb_listenee_nickname',
|
||||
'omb_listenee_license') as $param)
|
||||
{
|
||||
if (!$req->get_parameter($param)) {
|
||||
if (!isset($_GET[$param]) || is_null($_GET[$param])) {
|
||||
throw new OAuthException("Required parameter '$param' not found");
|
||||
}
|
||||
}
|
||||
# Now, OMB stuff
|
||||
$version = $req->get_parameter('omb_version');
|
||||
$version = $_GET['omb_version'];
|
||||
if ($version != OMB_VERSION_01) {
|
||||
throw new OAuthException("OpenMicroBlogging version '$version' not supported");
|
||||
}
|
||||
$listener = $req->get_parameter('omb_listener');
|
||||
$listener = $_GET['omb_listener'];
|
||||
$user = User::staticGet('uri', $listener);
|
||||
if (!$user) {
|
||||
throw new OAuthException("Listener URI '$listener' not found here");
|
||||
@ -427,7 +455,7 @@ class UserauthorizationAction extends Action
|
||||
if ($cur->id != $user->id) {
|
||||
throw new OAuthException("Can't add for another user!");
|
||||
}
|
||||
$listenee = $req->get_parameter('omb_listenee');
|
||||
$listenee = $_GET['omb_listenee'];
|
||||
if (!Validate::uri($listenee) &&
|
||||
!common_valid_tag($listenee)) {
|
||||
throw new OAuthException("Listenee URI '$listenee' not a recognizable URI");
|
||||
@ -450,13 +478,13 @@ class UserauthorizationAction extends Action
|
||||
throw new OAuthException("Already subscribed to user!");
|
||||
}
|
||||
}
|
||||
$nickname = $req->get_parameter('omb_listenee_nickname');
|
||||
$nickname = $_GET['omb_listenee_nickname'];
|
||||
if (!Validate::string($nickname, array('min_length' => 1,
|
||||
'max_length' => 64,
|
||||
'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
|
||||
throw new OAuthException('Nickname must have only letters and numbers and no spaces.');
|
||||
}
|
||||
$profile = $req->get_parameter('omb_listenee_profile');
|
||||
$profile = $_GET['omb_listenee_profile'];
|
||||
if (!common_valid_http_url($profile)) {
|
||||
throw new OAuthException("Invalid profile URL '$profile'.");
|
||||
}
|
||||
@ -465,7 +493,7 @@ class UserauthorizationAction extends Action
|
||||
throw new OAuthException("Profile URL '$profile' is for a local user.");
|
||||
}
|
||||
|
||||
$license = $req->get_parameter('omb_listenee_license');
|
||||
$license = $_GET['omb_listenee_license'];
|
||||
if (!common_valid_http_url($license)) {
|
||||
throw new OAuthException("Invalid license URL '$license'.");
|
||||
}
|
||||
@ -474,23 +502,23 @@ class UserauthorizationAction extends Action
|
||||
throw new OAuthException("Listenee stream license '$license' not compatible with site license '$site_license'.");
|
||||
}
|
||||
# optional stuff
|
||||
$fullname = $req->get_parameter('omb_listenee_fullname');
|
||||
$fullname = $_GET['omb_listenee_fullname'];
|
||||
if ($fullname && mb_strlen($fullname) > 255) {
|
||||
throw new OAuthException("Full name '$fullname' too long.");
|
||||
}
|
||||
$homepage = $req->get_parameter('omb_listenee_homepage');
|
||||
$homepage = $_GET['omb_listenee_homepage'];
|
||||
if ($homepage && (!common_valid_http_url($homepage) || mb_strlen($homepage) > 255)) {
|
||||
throw new OAuthException("Invalid homepage '$homepage'");
|
||||
}
|
||||
$bio = $req->get_parameter('omb_listenee_bio');
|
||||
$bio = $_GET['omb_listenee_bio'];
|
||||
if ($bio && mb_strlen($bio) > 140) {
|
||||
throw new OAuthException("Bio too long '$bio'");
|
||||
}
|
||||
$location = $req->get_parameter('omb_listenee_location');
|
||||
$location = $_GET['omb_listenee_location'];
|
||||
if ($location && mb_strlen($location) > 255) {
|
||||
throw new OAuthException("Location too long '$location'");
|
||||
}
|
||||
$avatar = $req->get_parameter('omb_listenee_avatar');
|
||||
$avatar = $_GET['omb_listenee_avatar'];
|
||||
if ($avatar) {
|
||||
if (!common_valid_http_url($avatar) || strlen($avatar) > 255) {
|
||||
throw new OAuthException("Invalid avatar URL '$avatar'");
|
||||
@ -507,7 +535,7 @@ class UserauthorizationAction extends Action
|
||||
throw new OAuthException("Wrong image type for '$avatar'");
|
||||
}
|
||||
}
|
||||
$callback = $req->get_parameter('oauth_callback');
|
||||
$callback = $_GET['oauth_callback'];
|
||||
if ($callback && !common_valid_http_url($callback)) {
|
||||
throw new OAuthException("Invalid callback URL '$callback'");
|
||||
}
|
||||
@ -515,92 +543,4 @@ class UserauthorizationAction extends Action
|
||||
throw new OAuthException("Callback URL '$callback' is for local site.");
|
||||
}
|
||||
}
|
||||
|
||||
# Snagged from OAuthServer
|
||||
|
||||
function checkVersion(&$req)
|
||||
{
|
||||
$version = $req->get_parameter("oauth_version");
|
||||
if (!$version) {
|
||||
$version = 1.0;
|
||||
}
|
||||
if ($version != 1.0) {
|
||||
throw new OAuthException("OAuth version '$version' not supported");
|
||||
}
|
||||
return $version;
|
||||
}
|
||||
|
||||
# Snagged from OAuthServer
|
||||
|
||||
function getConsumer($datastore, $req)
|
||||
{
|
||||
$consumer_key = @$req->get_parameter("oauth_consumer_key");
|
||||
if (!$consumer_key) {
|
||||
throw new OAuthException("Invalid consumer key");
|
||||
}
|
||||
|
||||
$consumer = $datastore->lookup_consumer($consumer_key);
|
||||
if (!$consumer) {
|
||||
throw new OAuthException("Invalid consumer");
|
||||
}
|
||||
return $consumer;
|
||||
}
|
||||
|
||||
# Mostly cadged from OAuthServer
|
||||
|
||||
function getToken($datastore, &$req, $consumer)
|
||||
{/*{{{*/
|
||||
$token_field = @$req->get_parameter('oauth_token');
|
||||
$token = $datastore->lookup_token($consumer, 'request', $token_field);
|
||||
if (!$token) {
|
||||
throw new OAuthException("Invalid $token_type token: $token_field");
|
||||
}
|
||||
return $token;
|
||||
}
|
||||
|
||||
function checkTimestamp(&$req)
|
||||
{
|
||||
$timestamp = @$req->get_parameter('oauth_timestamp');
|
||||
$now = time();
|
||||
if ($now - $timestamp > TIMESTAMP_THRESHOLD) {
|
||||
throw new OAuthException("Expired timestamp, yours $timestamp, ours $now");
|
||||
}
|
||||
}
|
||||
|
||||
# NOTE: don't call twice on the same request; will fail!
|
||||
function checkNonce(&$datastore, &$req, $consumer, $token)
|
||||
{
|
||||
$timestamp = @$req->get_parameter('oauth_timestamp');
|
||||
$nonce = @$req->get_parameter('oauth_nonce');
|
||||
$found = $datastore->lookup_nonce($consumer, $token, $nonce, $timestamp);
|
||||
if ($found) {
|
||||
throw new OAuthException("Nonce already used");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function checkSignature(&$req, $consumer, $token)
|
||||
{
|
||||
$signature_method = $this->getSignatureMethod($req);
|
||||
$signature = $req->get_parameter('oauth_signature');
|
||||
$valid_sig = $signature_method->check_signature($req,
|
||||
$consumer,
|
||||
$token,
|
||||
$signature);
|
||||
if (!$valid_sig) {
|
||||
throw new OAuthException("Invalid signature");
|
||||
}
|
||||
}
|
||||
|
||||
function getSignatureMethod(&$req)
|
||||
{
|
||||
$signature_method = @$req->get_parameter("oauth_signature_method");
|
||||
if (!$signature_method) {
|
||||
$signature_method = "PLAINTEXT";
|
||||
}
|
||||
if ($signature_method != 'HMAC-SHA1') {
|
||||
throw new OAuthException("Signature method '$signature_method' not supported.");
|
||||
}
|
||||
return omb_hmac_sha1();
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ class UserbyidAction extends Action
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class UsergroupsAction extends Action
|
||||
var $page = null;
|
||||
var $profile = null;
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -139,10 +139,28 @@ class UsergroupsAction extends Action
|
||||
if ($groups) {
|
||||
$gl = new GroupList($groups, $this->user, $this);
|
||||
$cnt = $gl->show();
|
||||
if (0 == $cnt) {
|
||||
$this->showEmptyListMessage();
|
||||
}
|
||||
}
|
||||
|
||||
$this->pagination($this->page > 1, $cnt > GROUPS_PER_PAGE,
|
||||
$this->page, 'usergroups',
|
||||
array('nickname' => $this->user->nickname));
|
||||
}
|
||||
|
||||
function showEmptyListMessage()
|
||||
{
|
||||
$message = sprintf(_('%s is not a member of any group.'), $this->user->nickname) . ' ';
|
||||
|
||||
if (common_logged_in()) {
|
||||
$current_user = common_current_user();
|
||||
if ($this->user->id === $current_user->id) {
|
||||
$message .= _('Try [searching for groups](%%action.groupsearch%%) and joining them.');
|
||||
}
|
||||
}
|
||||
$this->elementStart('div', 'guide');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
}
|
||||
|
@ -25,14 +25,15 @@ require_once(INSTALLDIR.'/lib/rssaction.php');
|
||||
|
||||
class UserrssAction extends Rss10Action
|
||||
{
|
||||
|
||||
var $user = null;
|
||||
var $tag = null;
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
$nickname = $this->trimmed('nickname');
|
||||
$this->user = User::staticGet('nickname', $nickname);
|
||||
$this->tag = $this->trimmed('tag');
|
||||
|
||||
if (!$this->user) {
|
||||
$this->clientError(_('No such user.'));
|
||||
@ -42,6 +43,25 @@ class UserrssAction extends Rss10Action
|
||||
}
|
||||
}
|
||||
|
||||
function getTaggedNotices($tag = null, $limit=0)
|
||||
{
|
||||
$user = $this->user;
|
||||
|
||||
if (is_null($user)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$notice = $user->getTaggedNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit, 0, 0, null, $tag);
|
||||
|
||||
$notices = array();
|
||||
while ($notice->fetch()) {
|
||||
$notices[] = clone($notice);
|
||||
}
|
||||
|
||||
return $notices;
|
||||
}
|
||||
|
||||
|
||||
function getNotices($limit=0)
|
||||
{
|
||||
|
||||
@ -53,6 +73,7 @@ class UserrssAction extends Rss10Action
|
||||
|
||||
$notice = $user->getNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit);
|
||||
|
||||
$notices = array();
|
||||
while ($notice->fetch()) {
|
||||
$notices[] = clone($notice);
|
||||
}
|
||||
@ -90,14 +111,13 @@ class UserrssAction extends Rss10Action
|
||||
|
||||
function initRss($limit=0)
|
||||
{
|
||||
$url = common_local_url('sup', null, $this->user->id);
|
||||
$url = common_local_url('sup', null, null, $this->user->id);
|
||||
header('X-SUP-ID: '.$url);
|
||||
parent::initRss($limit);
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ class XrdsAction extends Action
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
function isReadOnly()
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
BIN
apple-touch-icon.png
Normal file
BIN
apple-touch-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user