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/*
|
avatar/*
|
||||||
files/*
|
files/*
|
||||||
_darcs/*
|
_darcs/*
|
||||||
|
logs/*
|
||||||
config.php
|
config.php
|
||||||
.htaccess
|
.htaccess
|
||||||
|
httpd.conf
|
||||||
*.tmproj
|
*.tmproj
|
||||||
dataobject.ini
|
dataobject.ini
|
||||||
*~
|
*~
|
||||||
@ -10,3 +12,7 @@ dataobject.ini
|
|||||||
*.orig
|
*.orig
|
||||||
*.rej
|
*.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
|
EndNoticeSave: after inserting a notice and related code
|
||||||
- $notice: notice that was saved (with ID and URI)
|
- $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
|
||||||
|
286
README
286
README
@ -2,8 +2,8 @@
|
|||||||
README
|
README
|
||||||
------
|
------
|
||||||
|
|
||||||
Laconica 0.7.1 ("West of the Fields")
|
Laconica 0.7.3 ("You Are The Everything")
|
||||||
6 February 2009
|
7 April 2009
|
||||||
|
|
||||||
This is the README file for Laconica, the Open Source microblogging
|
This is the README file for Laconica, the Open Source microblogging
|
||||||
platform. It includes installation instructions, descriptions of
|
platform. It includes installation instructions, descriptions of
|
||||||
@ -71,54 +71,29 @@ for additional terms.
|
|||||||
New this version
|
New this version
|
||||||
================
|
================
|
||||||
|
|
||||||
This is a minor bug-fix release since version 0.7.0, released Jan 29
|
This is a minor bug-fix and feature release since version 0.7.2.1,
|
||||||
2009. Notable changes this version:
|
released Mar 11 2009. Notable changes this version:
|
||||||
|
|
||||||
- Vast improvement in auto-linking to URLs.
|
- A plugin to allow a templating language for customization
|
||||||
- Link to group search from user's group page
|
- A plugin for Piwik Analytics engine
|
||||||
- Improved interface in Facebook application
|
- A bookmarklet for posting a notice about a Web page you're reading
|
||||||
- Fix bad redirects in delete notice
|
- A welcome notice ('welcomebot') and default subscription for new users
|
||||||
- Updated PostgreSQL database creation script
|
- Support for SSL for some or all pages on the site
|
||||||
- Show filesize in avatar/logo upload
|
- Better handling of empty notice lists on many pages
|
||||||
- Vastly improved avatar/logo upload
|
- Major improvements to the Twitter friend-sync offline processing
|
||||||
- Allow re-authentication with OpenID
|
- subscribers, subscriptions, groups are listed on the Personal page.
|
||||||
- Correctly link hashtabs inside parens and brackets
|
- "Invite" link restored to main menu
|
||||||
- Group and avatar image transparency works
|
- Better memory handling in FOAF output
|
||||||
- Better handling of commands through the Web and Ajax channels
|
- Fix for SUP support (FriendFeed)
|
||||||
- Fix links for profile page feeds
|
- Correct and intelligent redirect HTTP status codes
|
||||||
- Fixed destroy method in API
|
- Fix DB collations for search and sort
|
||||||
- Fix endpoint of Connect menu when XMPP disabled
|
- Better H1s and Titles using user full names
|
||||||
- Show number of group members
|
- Fixes to make the linkback plugin operational
|
||||||
- Enable configuration files in /etc/laconica/
|
- Better indication that a notice is being published by Ajax (spinner)
|
||||||
|
- Better and unified Atom output
|
||||||
Changes in version 0.7.0:
|
- Hiding "register" and "join now" messages when site is closed
|
||||||
|
- ping, twitter and facebook queuehandlers working better
|
||||||
- Support for groups. Users can join groups and send themed notices
|
- Updated RPM spec
|
||||||
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
|
|
||||||
|
|
||||||
Prerequisites
|
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
|
1. Unpack the tarball you downloaded on your Web server. Usually a
|
||||||
command like this will work:
|
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
|
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
|
may have to unpack the tarball on your local computer and FTP the
|
||||||
files to the server.)
|
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
|
2. Move the tarball to a directory of your choosing in your Web root
|
||||||
directory. Usually something like this will work:
|
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
|
This will make your Laconica instance available in the mublog path of
|
||||||
your server, like "http://example.net/mublog". "microblog" or
|
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
|
configure virtual hosts on your web server, you can try setting up
|
||||||
"http://micro.example.net/" or the like.
|
"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:
|
writeable by the Web server. An insecure way to do this is:
|
||||||
|
|
||||||
chmod a+w /var/www/mublog/avatar
|
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
|
5. Create a database to hold your microblog data. Something like this
|
||||||
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
|
|
||||||
should work:
|
should work:
|
||||||
|
|
||||||
mysqladmin -u "username" --password="password" create laconica
|
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
|
a tool like PHPAdmin to create a database. Check your hosting
|
||||||
service's documentation for how to create a new MySQL database.)
|
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
|
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
|
database. If you have shell access, this will probably work from the
|
||||||
MySQL shell:
|
MySQL shell:
|
||||||
|
|
||||||
GRANT SELECT,INSERT,DELETE,UPDATE on laconica.*
|
GRANT ALL on laconica.*
|
||||||
TO 'lacuser'@'localhost'
|
TO 'lacuser'@'localhost'
|
||||||
IDENTIFIED BY 'lacpassword';
|
IDENTIFIED BY 'lacpassword';
|
||||||
|
|
||||||
You should change 'lacuser' and 'lacpassword' to your preferred new
|
You should change 'lacuser' and 'lacpassword' to your preferred new
|
||||||
username and password. You may want to test logging in as this new
|
username and password. You may want to test logging in to MySQL as
|
||||||
user and testing that you can SELECT from some of the tables in the
|
this new user.
|
||||||
DB (use SHOW TABLES to see which ones are there).
|
|
||||||
|
|
||||||
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.
|
http://yourserver.example.com/mublog/install.php
|
||||||
(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.
|
|
||||||
|
|
||||||
9. At this point, you should be able to navigate in a browser to your
|
Enter the database connection information and your site name. The
|
||||||
microblog's main directory and see the "Public Timeline", which
|
install program will configure your site and install the initial,
|
||||||
will be empty. If not, magic has happened! You can now register a
|
almost-empty database.
|
||||||
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
|
8. You should now be able to navigate to your microblog's main directory
|
||||||
"fancy URLs" (see below), since some URLs are stored in the database.
|
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
|
Fancy URLs
|
||||||
----------
|
----------
|
||||||
|
|
||||||
By default, Laconica will have big long sloppy URLs that are hard for
|
By default, Laconica will use URLs that include the main PHP program's
|
||||||
people to remember or use. For example, a user's home profile might be
|
name in them. For example, a user's home profile might be
|
||||||
found at:
|
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:
|
It's possible to configure the software so it looks like this instead:
|
||||||
|
|
||||||
http://example.org/mublog/fred
|
http://example.org/mublog/fred
|
||||||
|
|
||||||
These "fancy URLs" are more readable and memorable for users. To use
|
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
|
fancy URLs, you must either have Apache 2.x with .htaccess enabled and
|
||||||
and mod_redirect enabled, -OR- know how to configure "url redirection"
|
mod_redirect enabled, -OR- know how to configure "url redirection" in
|
||||||
in your server.
|
your server.
|
||||||
|
|
||||||
1. Copy the htaccess.sample file to .htaccess in your Laconica
|
1. Copy the htaccess.sample file to .htaccess in your Laconica
|
||||||
directory. Note: if you have control of your server's httpd.conf or
|
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
|
If you changed your HTTP server configuration, you may need to restart
|
||||||
the server first.
|
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
|
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
|
needs as a parameter the install path; if you run it from the
|
||||||
Laconica dir, "." should suffice.
|
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
|
* xmppdaemon.php - listens for new XMPP messages from users and stores
|
||||||
them as notices in the database.
|
them as notices in the database.
|
||||||
@ -525,6 +495,10 @@ This will run six (for now) queue handlers:
|
|||||||
of registered users.
|
of registered users.
|
||||||
* xmppconfirmhandler.php - sends confirmation messages to registered
|
* xmppconfirmhandler.php - sends confirmation messages to registered
|
||||||
users.
|
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
|
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
|
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
|
# Update Twitter friends subscriptions every half hour
|
||||||
0,30 * * * * /path/to/php /path/to/laconica/scripts/synctwitterfriends.php>&/dev/null
|
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
|
Sitemaps
|
||||||
--------
|
--------
|
||||||
|
|
||||||
@ -597,7 +618,7 @@ to these resources.
|
|||||||
Themes
|
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
|
which is what the Identi.ca site uses, and "default", which is a good
|
||||||
basis for other sites.
|
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
|
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
|
tracking the "git" version of the software, you will probably want
|
||||||
to upgrade and keep your existing data. There is no automated upgrade
|
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.
|
to the end first before trying them.
|
||||||
|
|
||||||
0. Download Laconica and set up all the prerequisites as if you were
|
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.
|
directory to your new directory.
|
||||||
9. Copy htaccess.sample to .htaccess in the new directory. Change the
|
9. Copy htaccess.sample to .htaccess in the new directory. Change the
|
||||||
RewriteBase to use the correct path.
|
RewriteBase to use the correct path.
|
||||||
10. Rebuild the database. Go to your Laconica directory and run the
|
10. Rebuild the database. For MySQL, go to your Laconica directory and
|
||||||
rebuilddb.sh script like this:
|
run the rebuilddb.sh script like this:
|
||||||
|
|
||||||
./scripts/rebuilddb.sh rootuser rootpassword database db/laconica.sql
|
./scripts/rebuilddb.sh rootuser rootpassword database db/laconica.sql
|
||||||
|
|
||||||
Here, rootuser and rootpassword are the username and password for a
|
Here, rootuser and rootpassword are the username and password for a
|
||||||
user who can drop and create databases as well as tables; typically
|
user who can drop and create databases as well as tables; typically
|
||||||
that's _not_ the user Laconica runs as.
|
that's _not_ the user Laconica runs as.
|
||||||
11. Use mysql client to log into your database and make sure that the
|
For PostgreSQL databases there is an equivalent, rebuilddb_psql.sh,
|
||||||
notice, user, profile, subscription etc. tables are non-empty.
|
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.
|
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
|
13. Turn back on XMPP bots and email maildaemon. Note that the XMPP
|
||||||
bots have changed since version 0.5; see above for details.
|
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'.
|
name: the name of your site, like 'YourCompany Microblog'.
|
||||||
server: the server part of your site's URLs, like 'example.net'.
|
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).
|
(installed in root).
|
||||||
fancy: whether or not your site uses fancy URLs (see Fancy URLs
|
fancy: whether or not your site uses fancy URLs (see Fancy URLs
|
||||||
section above). Default is false.
|
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
|
to put introductory information about your service, or info about
|
||||||
upgrades and outages, or other community info. Any HTML will
|
upgrades and outages, or other community info. Any HTML will
|
||||||
be escaped.
|
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
|
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,
|
not be accepted at all. (Compare with blacklisted users above,
|
||||||
whose posts just won't show up in the public stream.)
|
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
|
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
|
T_STRING") in the browser, check to see that you don't have any
|
||||||
conflicts in your code.
|
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
|
section above, and all your users' 'Personal' tabs are empty, read the
|
||||||
"Notice inboxes" section above.
|
"Notice inboxes" section above.
|
||||||
|
|
||||||
@ -1179,6 +1234,11 @@ if anyone's been overlooked in error.
|
|||||||
* Ken Sheppardson (Trac server, man-about-town)
|
* Ken Sheppardson (Trac server, man-about-town)
|
||||||
* Tiago 'gouki' Faria (i18n managerx)
|
* Tiago 'gouki' Faria (i18n managerx)
|
||||||
* Sean Murphy
|
* 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
|
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,
|
thousands of people who have tried out Identi.ca, installed Laconi.ca,
|
||||||
|
@ -59,7 +59,7 @@ class AccesstokenAction extends Action
|
|||||||
try {
|
try {
|
||||||
common_debug('getting request from env variables', __FILE__);
|
common_debug('getting request from env variables', __FILE__);
|
||||||
common_remove_magic_from_request();
|
common_remove_magic_from_request();
|
||||||
$req = OAuthRequest::from_request();
|
$req = OAuthRequest::from_request('POST', common_local_url('accesstoken'));
|
||||||
common_debug('getting a server', __FILE__);
|
common_debug('getting a server', __FILE__);
|
||||||
$server = omb_oauth_server();
|
$server = omb_oauth_server();
|
||||||
common_debug('fetching the access token', __FILE__);
|
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/noticelist.php';
|
||||||
require_once INSTALLDIR.'/lib/feedlist.php';
|
require_once INSTALLDIR.'/lib/feedlist.php';
|
||||||
|
|
||||||
class AllAction extends Action
|
class AllAction extends ProfileAction
|
||||||
{
|
{
|
||||||
var $user = null;
|
function isReadOnly($args)
|
||||||
var $page = null;
|
|
||||||
|
|
||||||
function isReadOnly()
|
|
||||||
{
|
{
|
||||||
return true;
|
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)
|
function handle($args)
|
||||||
{
|
{
|
||||||
parent::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)),
|
sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->user->nickname)),
|
||||||
new Feed(Feed::RSS2,
|
new Feed(Feed::RSS2,
|
||||||
common_local_url('api', array('apiaction' => 'statuses',
|
common_local_url('api', array('apiaction' => 'statuses',
|
||||||
'method' => 'friends',
|
'method' => 'friends_timeline',
|
||||||
'argument' => $this->user->nickname.'.rss')),
|
'argument' => $this->user->nickname.'.rss')),
|
||||||
sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->user->nickname)),
|
sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->user->nickname)),
|
||||||
new Feed(Feed::ATOM,
|
new Feed(Feed::ATOM,
|
||||||
common_local_url('api', array('apiaction' => 'statuses',
|
common_local_url('api', array('apiaction' => 'statuses',
|
||||||
'method' => 'friends',
|
'method' => 'friends_timeline',
|
||||||
'argument' => $this->user->nickname.'.atom')),
|
'argument' => $this->user->nickname.'.atom')),
|
||||||
sprintf(_('Feed for friends of %s (Atom)'), $this->user->nickname)));
|
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()
|
function showLocalNav()
|
||||||
{
|
{
|
||||||
$nav = new PersonalGroupNav($this);
|
$nav = new PersonalGroupNav($this);
|
||||||
$nav->show();
|
$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()
|
function showContent()
|
||||||
{
|
{
|
||||||
$notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
|
$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();
|
$cnt = $nl->show();
|
||||||
|
|
||||||
|
if (0 == $cnt) {
|
||||||
|
$this->showEmptyListMessage();
|
||||||
|
}
|
||||||
|
|
||||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||||
$this->page, 'all', array('nickname' => $this->user->nickname));
|
$this->page, 'all', array('nickname' => $this->user->nickname));
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,9 @@ class AllrssAction extends Rss10Action
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialization.
|
* Initialization.
|
||||||
*
|
*
|
||||||
|
* @param array $args Web and URL arguments
|
||||||
|
*
|
||||||
* @return boolean false if user doesn't exist
|
* @return boolean false if user doesn't exist
|
||||||
*/
|
*/
|
||||||
function prepare($args)
|
function prepare($args)
|
||||||
@ -79,9 +81,10 @@ class AllrssAction extends Rss10Action
|
|||||||
*/
|
*/
|
||||||
function getNotices($limit=0)
|
function getNotices($limit=0)
|
||||||
{
|
{
|
||||||
$user = $this->user;
|
$user = $this->user;
|
||||||
$notice = $user->noticesWithFriends(0, $limit);
|
$notice = $user->noticesWithFriends(0, $limit);
|
||||||
|
$notices = array();
|
||||||
|
|
||||||
while ($notice->fetch()) {
|
while ($notice->fetch()) {
|
||||||
$notices[] = clone($notice);
|
$notices[] = clone($notice);
|
||||||
}
|
}
|
||||||
@ -104,7 +107,8 @@ class AllrssAction extends Rss10Action
|
|||||||
'link' => common_local_url('all',
|
'link' => common_local_url('all',
|
||||||
array('nickname' =>
|
array('nickname' =>
|
||||||
$user->nickname)),
|
$user->nickname)),
|
||||||
'description' => sprintf(_('Feed for friends of %s'), $user->nickname));
|
'description' => sprintf(_('Feed for friends of %s'),
|
||||||
|
$user->nickname));
|
||||||
return $c;
|
return $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,10 +127,5 @@ class AllrssAction extends Rss10Action
|
|||||||
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||||
return $avatar ? $avatar->url : null;
|
return $avatar ? $avatar->url : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReadOnly()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,18 +127,21 @@ class ApiAction extends Action
|
|||||||
'laconica/wadl');
|
'laconica/wadl');
|
||||||
|
|
||||||
static $bareauth = array('statuses/user_timeline',
|
static $bareauth = array('statuses/user_timeline',
|
||||||
|
'statuses/friends_timeline',
|
||||||
'statuses/friends',
|
'statuses/friends',
|
||||||
|
'statuses/replies',
|
||||||
|
'statuses/mentions',
|
||||||
'statuses/followers',
|
'statuses/followers',
|
||||||
'favorites/favorites');
|
'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";
|
$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)) {
|
if (in_array($fullname, $bareauth)) {
|
||||||
# bareauth: only needs auth if without an argument
|
# bareauth: only needs auth if without an argument
|
||||||
if ($this->api_arg) {
|
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 = $args['apiaction'];
|
||||||
$apiaction = $_REQUEST['apiaction'];
|
$method = $args['method'];
|
||||||
$method = $_REQUEST['method'];
|
|
||||||
list($cmdtext, $fmt) = explode('.', $method);
|
list($cmdtext, $fmt) = explode('.', $method);
|
||||||
|
|
||||||
static $write_methods = array(
|
static $write_methods = array(
|
||||||
@ -205,5 +208,4 @@ class ApiAction extends Action
|
|||||||
|
|
||||||
return false;
|
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);
|
common_redirect($url, 302);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -324,13 +324,14 @@ class AvatarsettingsAction extends AccountSettingsAction
|
|||||||
return;
|
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_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_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_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'):$filedata['height'];
|
$dest_h = $this->arg('avatar_crop_h') ? $this->arg('avatar_crop_h'):$file_d;
|
||||||
$size = min($dest_w, $dest_h);
|
$size = min($dest_w, $dest_h, MAX_ORIGINAL);
|
||||||
$size = ($size > MAX_ORIGINAL) ? MAX_ORIGINAL:$size;
|
|
||||||
|
|
||||||
$user = common_current_user();
|
$user = common_current_user();
|
||||||
$profile = $user->getProfile();
|
$profile = $user->getProfile();
|
||||||
@ -343,6 +344,7 @@ class AvatarsettingsAction extends AccountSettingsAction
|
|||||||
unset($_SESSION['FILEDATA']);
|
unset($_SESSION['FILEDATA']);
|
||||||
$this->mode = 'upload';
|
$this->mode = 'upload';
|
||||||
$this->showForm(_('Avatar updated.'), true);
|
$this->showForm(_('Avatar updated.'), true);
|
||||||
|
common_broadcast_profile($profile);
|
||||||
} else {
|
} else {
|
||||||
$this->showForm(_('Failed updating avatar.'));
|
$this->showForm(_('Failed updating avatar.'));
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,8 @@ class BlockAction extends Action
|
|||||||
if ($this->arg('no')) {
|
if ($this->arg('no')) {
|
||||||
$cur = common_current_user();
|
$cur = common_current_user();
|
||||||
$other = Profile::staticGet('id', $this->arg('blockto'));
|
$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')) {
|
} elseif ($this->arg('yes')) {
|
||||||
$this->blockProfile();
|
$this->blockProfile();
|
||||||
} elseif ($this->arg('blockto')) {
|
} elseif ($this->arg('blockto')) {
|
||||||
@ -102,7 +103,6 @@ class BlockAction extends Action
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function showContent() {
|
function showContent() {
|
||||||
$this->areYouSureForm();
|
$this->areYouSureForm();
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ class BlockAction extends Action
|
|||||||
function title() {
|
function title() {
|
||||||
return _('Block user');
|
return _('Block user');
|
||||||
}
|
}
|
||||||
|
|
||||||
function showNoticeForm() {
|
function showNoticeForm() {
|
||||||
// nop
|
// nop
|
||||||
}
|
}
|
||||||
@ -178,10 +178,11 @@ class BlockAction extends Action
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($action) {
|
if ($action) {
|
||||||
common_redirect(common_local_url($action, $args));
|
common_redirect(common_local_url($action, $args), 303);
|
||||||
} else {
|
} else {
|
||||||
common_redirect(common_local_url('subscriptions',
|
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');
|
$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));
|
||||||
|
}
|
||||||
|
}
|
@ -49,7 +49,7 @@ class DisfavorAction extends Action
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Class handler.
|
* Class handler.
|
||||||
*
|
*
|
||||||
* @param array $args query arguments
|
* @param array $args query arguments
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
@ -100,7 +100,8 @@ class DisfavorAction extends Action
|
|||||||
$this->elementEnd('html');
|
$this->elementEnd('html');
|
||||||
} else {
|
} else {
|
||||||
common_redirect(common_local_url('showfavorites',
|
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);
|
return ucfirst($this->title);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,6 @@ class EditgroupAction extends Action
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$nickname = common_canonical_nickname($this->trimmed('nickname'));
|
$nickname = common_canonical_nickname($this->trimmed('nickname'));
|
||||||
$fullname = $this->trimmed('fullname');
|
$fullname = $this->trimmed('fullname');
|
||||||
$homepage = $this->trimmed('homepage');
|
$homepage = $this->trimmed('homepage');
|
||||||
@ -221,7 +220,7 @@ class EditgroupAction extends Action
|
|||||||
if ($this->group->nickname != $orig->nickname) {
|
if ($this->group->nickname != $orig->nickname) {
|
||||||
common_redirect(common_local_url('editgroup',
|
common_redirect(common_local_url('editgroup',
|
||||||
array('nickname' => $nickname)),
|
array('nickname' => $nickname)),
|
||||||
307);
|
303);
|
||||||
} else {
|
} else {
|
||||||
$this->showForm(_('Options saved.'));
|
$this->showForm(_('Options saved.'));
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ class FavorAction extends Action
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Class handler.
|
* Class handler.
|
||||||
*
|
*
|
||||||
* @param array $args query arguments
|
* @param array $args query arguments
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
@ -100,13 +100,14 @@ class FavorAction extends Action
|
|||||||
$this->elementEnd('html');
|
$this->elementEnd('html');
|
||||||
} else {
|
} else {
|
||||||
common_redirect(common_local_url('showfavorites',
|
common_redirect(common_local_url('showfavorites',
|
||||||
array('nickname' => $user->nickname)));
|
array('nickname' => $user->nickname)),
|
||||||
|
303);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies a user when his notice is favorited.
|
* Notifies a user when his notice is favorited.
|
||||||
*
|
*
|
||||||
* @param class $notice favorited notice
|
* @param class $notice favorited notice
|
||||||
* @param class $user user declaring a favorite
|
* @param class $user user declaring a favorite
|
||||||
*
|
*
|
||||||
|
@ -85,7 +85,7 @@ class FavoritedAction extends Action
|
|||||||
* @return boolean true
|
* @return boolean true
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -104,9 +104,9 @@ class FavoritedAction extends Action
|
|||||||
{
|
{
|
||||||
parent::prepare($args);
|
parent::prepare($args);
|
||||||
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
||||||
|
|
||||||
common_set_returnto($this->selfUrl());
|
common_set_returnto($this->selfUrl());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,6 +145,22 @@ class FavoritedAction extends Action
|
|||||||
$this->elementEnd('div');
|
$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
|
* Local navigation
|
||||||
*
|
*
|
||||||
@ -169,10 +185,16 @@ class FavoritedAction extends Action
|
|||||||
|
|
||||||
function showContent()
|
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.*, '.
|
$qry = 'SELECT notice.*, '.
|
||||||
'sum(exp(-(now() - fave.modified) / %s)) as weight ' .
|
$weightexpr . ' as weight ' .
|
||||||
'FROM notice JOIN fave ON notice.id = fave.notice_id ' .
|
'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';
|
'ORDER BY weight DESC';
|
||||||
|
|
||||||
$offset = ($this->page - 1) * NOTICES_PER_PAGE;
|
$offset = ($this->page - 1) * NOTICES_PER_PAGE;
|
||||||
@ -192,7 +214,22 @@ class FavoritedAction extends Action
|
|||||||
|
|
||||||
$cnt = $nl->show();
|
$cnt = $nl->show();
|
||||||
|
|
||||||
|
if ($cnt == 0) {
|
||||||
|
$this->showEmptyList();
|
||||||
|
}
|
||||||
|
|
||||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||||
$this->page, 'favorited');
|
$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',
|
$c = array('url' => common_local_url('favoritesrss',
|
||||||
array('nickname' =>
|
array('nickname' =>
|
||||||
$user->nickname)),
|
$user->nickname)),
|
||||||
'title' => sprintf(_("%s favorite notices"), $user->nickname),
|
'title' => sprintf(_("%s's favorite notices"), $user->nickname),
|
||||||
'link' => common_local_url('showfavorites',
|
'link' => common_local_url('showfavorites',
|
||||||
array('nickname' =>
|
array('nickname' =>
|
||||||
$user->nickname)),
|
$user->nickname)),
|
||||||
|
@ -50,7 +50,7 @@ class FeaturedAction extends Action
|
|||||||
{
|
{
|
||||||
var $page = null;
|
var $page = null;
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -107,6 +107,7 @@ class FeaturedAction extends Action
|
|||||||
|
|
||||||
$featured_nicks = common_config('nickname', 'featured');
|
$featured_nicks = common_config('nickname', 'featured');
|
||||||
|
|
||||||
|
|
||||||
if (count($featured_nicks) > 0) {
|
if (count($featured_nicks) > 0) {
|
||||||
|
|
||||||
$quoted = array();
|
$quoted = array();
|
||||||
@ -118,7 +119,7 @@ class FeaturedAction extends Action
|
|||||||
$user = new User;
|
$user = new User;
|
||||||
$user->whereAdd(sprintf('nickname IN (%s)', implode(',', $quoted)));
|
$user->whereAdd(sprintf('nickname IN (%s)', implode(',', $quoted)));
|
||||||
$user->limit(($this->page - 1) * PROFILES_PER_PAGE, PROFILES_PER_PAGE + 1);
|
$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();
|
$user->find();
|
||||||
|
|
||||||
@ -145,4 +146,4 @@ class FeaturedAction extends Action
|
|||||||
$this->page, 'featured');
|
$this->page, 'featured');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ class FinishaddopenidAction extends Action
|
|||||||
|
|
||||||
oid_set_last($display);
|
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) {
|
if ($this->error) {
|
||||||
$this->element('div', array('class' => 'error'), $this->error);
|
$this->element('div', array('class' => 'error'), $this->error);
|
||||||
} else {
|
} else {
|
||||||
global $config;
|
|
||||||
$this->element('div', 'instructions',
|
$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()
|
function showContent()
|
||||||
{
|
{
|
||||||
if ($this->message_text) {
|
if (!empty($this->message_text)) {
|
||||||
$this->element('p', null, $this->message);
|
$this->element('p', null, $this->message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -192,11 +191,28 @@ class FinishopenidloginAction extends Action
|
|||||||
{
|
{
|
||||||
# FIXME: save invite code before redirect, and check here
|
# 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.'));
|
$this->clientError(_('Registration not allowed.'));
|
||||||
return;
|
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');
|
$nickname = $this->trimmed('newname');
|
||||||
|
|
||||||
if (!Validate::string($nickname, array('min_length' => 1,
|
if (!Validate::string($nickname, array('min_length' => 1,
|
||||||
@ -232,7 +248,8 @@ class FinishopenidloginAction extends Action
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($sreg['country']) {
|
$location = '';
|
||||||
|
if (!empty($sreg['country'])) {
|
||||||
if ($sreg['postcode']) {
|
if ($sreg['postcode']) {
|
||||||
# XXX: use postcode to get city and region
|
# XXX: use postcode to get city and region
|
||||||
# XXX: also, store postcode somewhere -- it's valuable!
|
# 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'];
|
$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'];
|
$email = $sreg['email'];
|
||||||
|
} else {
|
||||||
|
$email = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
# XXX: add language
|
# XXX: add language
|
||||||
# XXX: add timezone
|
# XXX: add timezone
|
||||||
|
|
||||||
$user = User::register(array('nickname' => $nickname,
|
$args = array('nickname' => $nickname,
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
'fullname' => $fullname,
|
'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);
|
$result = oid_link_user($user->id, $canonical, $display);
|
||||||
|
|
||||||
@ -267,7 +294,8 @@ class FinishopenidloginAction extends Action
|
|||||||
common_rememberme($user);
|
common_rememberme($user);
|
||||||
}
|
}
|
||||||
unset($_SESSION['openid_rememberme']);
|
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()
|
function connectUser()
|
||||||
@ -320,7 +348,7 @@ class FinishopenidloginAction extends Action
|
|||||||
array('nickname' =>
|
array('nickname' =>
|
||||||
$nickname));
|
$nickname));
|
||||||
}
|
}
|
||||||
common_redirect($url);
|
common_redirect($url, 303);
|
||||||
}
|
}
|
||||||
|
|
||||||
function bestNewNickname($display, $sreg)
|
function bestNewNickname($display, $sreg)
|
||||||
@ -328,7 +356,7 @@ class FinishopenidloginAction extends Action
|
|||||||
|
|
||||||
# Try the passed-in nickname
|
# Try the passed-in nickname
|
||||||
|
|
||||||
if ($sreg['nickname']) {
|
if (!empty($sreg['nickname'])) {
|
||||||
$nickname = $this->nicknamize($sreg['nickname']);
|
$nickname = $this->nicknamize($sreg['nickname']);
|
||||||
if ($this->isNewNickname($nickname)) {
|
if ($this->isNewNickname($nickname)) {
|
||||||
return $nickname;
|
return $nickname;
|
||||||
@ -337,7 +365,7 @@ class FinishopenidloginAction extends Action
|
|||||||
|
|
||||||
# Try the full name
|
# Try the full name
|
||||||
|
|
||||||
if ($sreg['fullname']) {
|
if (!empty($sreg['fullname'])) {
|
||||||
$fullname = $this->nicknamize($sreg['fullname']);
|
$fullname = $this->nicknamize($sreg['fullname']);
|
||||||
if ($this->isNewNickname($fullname)) {
|
if ($this->isNewNickname($fullname)) {
|
||||||
return $fullname;
|
return $fullname;
|
||||||
|
@ -44,7 +44,7 @@ class FinishremotesubscribeAction extends Action
|
|||||||
common_debug('stored request: '.print_r($omb,true), __FILE__);
|
common_debug('stored request: '.print_r($omb,true), __FILE__);
|
||||||
|
|
||||||
common_remove_magic_from_request();
|
common_remove_magic_from_request();
|
||||||
$req = OAuthRequest::from_request();
|
$req = OAuthRequest::from_request('POST', common_local_url('finishuserauthorization'));
|
||||||
|
|
||||||
$token = $req->get_parameter('oauth_token');
|
$token = $req->get_parameter('oauth_token');
|
||||||
|
|
||||||
@ -136,16 +136,16 @@ class FinishremotesubscribeAction extends Action
|
|||||||
$profile->nickname = $nickname;
|
$profile->nickname = $nickname;
|
||||||
$profile->profileurl = $profile_url;
|
$profile->profileurl = $profile_url;
|
||||||
|
|
||||||
if ($fullname) {
|
if (!is_null($fullname)) {
|
||||||
$profile->fullname = $fullname;
|
$profile->fullname = $fullname;
|
||||||
}
|
}
|
||||||
if ($homepage) {
|
if (!is_null($homepage)) {
|
||||||
$profile->homepage = $homepage;
|
$profile->homepage = $homepage;
|
||||||
}
|
}
|
||||||
if ($bio) {
|
if (!is_null($bio)) {
|
||||||
$profile->bio = $bio;
|
$profile->bio = $bio;
|
||||||
}
|
}
|
||||||
if ($location) {
|
if (!is_null($location)) {
|
||||||
$profile->location = $location;
|
$profile->location = $location;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +230,8 @@ class FinishremotesubscribeAction extends Action
|
|||||||
# show up close to the top of the page
|
# show up close to the top of the page
|
||||||
|
|
||||||
common_redirect(common_local_url('subscribers', array('nickname' =>
|
common_redirect(common_local_url('subscribers', array('nickname' =>
|
||||||
$user->nickname)));
|
$user->nickname)),
|
||||||
|
303);
|
||||||
}
|
}
|
||||||
|
|
||||||
function add_avatar($profile, $url)
|
function add_avatar($profile, $url)
|
||||||
@ -283,7 +284,7 @@ class FinishremotesubscribeAction extends Action
|
|||||||
$fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
|
$fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
|
||||||
$result = $fetcher->post($req->get_normalized_http_url(),
|
$result = $fetcher->post($req->get_normalized_http_url(),
|
||||||
$req->to_postdata(),
|
$req->to_postdata(),
|
||||||
array('User-Agent' => 'Laconica/' . LACONICA_VERSION));
|
array('User-Agent: Laconica/' . LACONICA_VERSION));
|
||||||
|
|
||||||
common_debug('got result: "'.print_r($result,true).'"', __FILE__);
|
common_debug('got result: "'.print_r($result,true).'"', __FILE__);
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ define('BOTH', 0);
|
|||||||
|
|
||||||
class FoafAction extends Action
|
class FoafAction extends Action
|
||||||
{
|
{
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -33,7 +33,24 @@ class FoafAction extends Action
|
|||||||
function prepare($args)
|
function prepare($args)
|
||||||
{
|
{
|
||||||
parent::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);
|
$this->user = User::staticGet('nickname', $this->nickname);
|
||||||
|
|
||||||
@ -122,20 +139,30 @@ class FoafAction extends Action
|
|||||||
|
|
||||||
if ($sub->find()) {
|
if ($sub->find()) {
|
||||||
while ($sub->fetch()) {
|
while ($sub->fetch()) {
|
||||||
if ($sub->token) {
|
if (!empty($sub->token)) {
|
||||||
$other = Remote_profile::staticGet('id', $sub->subscribed);
|
$other = Remote_profile::staticGet('id', $sub->subscribed);
|
||||||
} else {
|
} else {
|
||||||
$other = User::staticGet('id', $sub->subscribed);
|
$other = User::staticGet('id', $sub->subscribed);
|
||||||
}
|
}
|
||||||
if (!$other) {
|
if (empty($other)) {
|
||||||
common_debug('Got a bad subscription: '.print_r($sub,true));
|
common_debug('Got a bad subscription: '.print_r($sub,true));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$this->element('knows', array('rdf:resource' => $other->uri));
|
$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
|
// Get people who subscribe to user
|
||||||
|
|
||||||
$sub = new Subscription();
|
$sub = new Subscription();
|
||||||
@ -156,25 +183,36 @@ class FoafAction extends Action
|
|||||||
if (array_key_exists($other->uri, $person)) {
|
if (array_key_exists($other->uri, $person)) {
|
||||||
$person[$other->uri][0] = BOTH;
|
$person[$other->uri][0] = BOTH;
|
||||||
} else {
|
} 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');
|
$this->elementEnd('Person');
|
||||||
|
|
||||||
foreach ($person as $uri => $p) {
|
foreach ($person as $uri => $p) {
|
||||||
$foaf_url = null;
|
$foaf_url = null;
|
||||||
if ($p[1] instanceof User) {
|
list($type, $id, $nickname, $cls) = $p;
|
||||||
$foaf_url = common_local_url('foaf', array('nickname' => $p[1]->nickname));
|
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));
|
$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->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);
|
common_root_url() : null);
|
||||||
if ($foaf_url) {
|
if ($foaf_url) {
|
||||||
$this->element('rdfs:seeAlso', array('rdf:resource' => $foaf_url));
|
$this->element('rdfs:seeAlso', array('rdf:resource' => $foaf_url));
|
||||||
}
|
}
|
||||||
@ -182,6 +220,9 @@ class FoafAction extends Action
|
|||||||
if ($foaf_url) {
|
if ($foaf_url) {
|
||||||
$this->showPpd($foaf_url, $uri);
|
$this->showPpd($foaf_url, $uri);
|
||||||
}
|
}
|
||||||
|
$profile->free();
|
||||||
|
$profile = null;
|
||||||
|
unset($profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->elementEnd('rdf:RDF');
|
$this->elementEnd('rdf:RDF');
|
||||||
|
@ -59,7 +59,7 @@ class GroupbyidAction extends Action
|
|||||||
* @return boolean true
|
* @return boolean true
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ class GrouplogoAction extends Action
|
|||||||
|
|
||||||
if ($nickname_arg != $nickname) {
|
if ($nickname_arg != $nickname) {
|
||||||
$args = array('nickname' => $nickname);
|
$args = array('nickname' => $nickname);
|
||||||
common_redirect(common_local_url('editgroup', $args), 301);
|
common_redirect(common_local_url('grouplogo', $args), 301);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ class GroupmembersAction extends Action
|
|||||||
{
|
{
|
||||||
var $page = null;
|
var $page = null;
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -137,4 +137,15 @@ class GroupmembersAction extends Action
|
|||||||
$this->page, 'groupmembers',
|
$this->page, 'groupmembers',
|
||||||
array('nickname' => $this->group->nickname));
|
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';
|
require_once INSTALLDIR.'/lib/rssaction.php';
|
||||||
|
|
||||||
define('MEMBERS_PER_SECTION', 81);
|
define('MEMBERS_PER_SECTION', 27);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Group RSS feed
|
* Group RSS feed
|
||||||
@ -57,7 +57,7 @@ class groupRssAction extends Rss10Action
|
|||||||
* @return boolean true
|
* @return boolean true
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -111,13 +111,13 @@ class groupRssAction extends Rss10Action
|
|||||||
{
|
{
|
||||||
|
|
||||||
$group = $this->group;
|
$group = $this->group;
|
||||||
|
|
||||||
if (is_null($group)) {
|
if (is_null($group)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$notice = $group->getNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit);
|
$notice = $group->getNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit);
|
||||||
|
|
||||||
while ($notice->fetch()) {
|
while ($notice->fetch()) {
|
||||||
$notices[] = clone($notice);
|
$notices[] = clone($notice);
|
||||||
}
|
}
|
||||||
@ -141,13 +141,4 @@ class groupRssAction extends Rss10Action
|
|||||||
{
|
{
|
||||||
return $this->group->homepage_logo;
|
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 $page = null;
|
||||||
var $profile = null;
|
var $profile = null;
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -129,4 +129,15 @@ class GroupsAction extends Action
|
|||||||
$gbm = new GroupsByMembersSection($this);
|
$gbm = new GroupsByMembersSection($this);
|
||||||
$gbm->show();
|
$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
|
<?php
|
||||||
|
|
||||||
|
|
||||||
// define('GROUPS_PER_PAGE', 20);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Group search action class.
|
* Group search action class.
|
||||||
*
|
*
|
||||||
@ -77,12 +72,23 @@ class GroupsearchAction extends SearchAction
|
|||||||
$terms = preg_split('/[\s,]+/', $q);
|
$terms = preg_split('/[\s,]+/', $q);
|
||||||
$results = new GroupSearchResults($user_group, $terms, $this);
|
$results = new GroupSearchResults($user_group, $terms, $this);
|
||||||
$results->show();
|
$results->show();
|
||||||
} else {
|
$user_group->free();
|
||||||
$this->element('p', 'error', _('No results'));
|
$this->pagination($page > 1, $cnt > GROUPS_PER_PAGE,
|
||||||
}
|
|
||||||
$user_group->free();
|
|
||||||
$this->pagination($page > 1, $cnt > GROUPS_PER_PAGE,
|
|
||||||
$page, 'groupsearch', array('q' => $q));
|
$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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,23 +96,18 @@ class GroupSearchResults extends GroupList
|
|||||||
{
|
{
|
||||||
var $terms = null;
|
var $terms = null;
|
||||||
var $pattern = null;
|
var $pattern = null;
|
||||||
|
|
||||||
function __construct($user_group, $terms, $action)
|
function __construct($user_group, $terms, $action)
|
||||||
{
|
{
|
||||||
parent::__construct($user_group, $terms, $action);
|
parent::__construct($user_group, $terms, $action);
|
||||||
$this->terms = array_map('preg_quote',
|
$this->terms = array_map('preg_quote',
|
||||||
array_map('htmlspecialchars', $terms));
|
array_map('htmlspecialchars', $terms));
|
||||||
$this->pattern = '/('.implode('|',$terms).')/i';
|
$this->pattern = '/('.implode('|',$terms).')/i';
|
||||||
}
|
}
|
||||||
|
|
||||||
function highlight($text)
|
function highlight($text)
|
||||||
{
|
{
|
||||||
return preg_replace($this->pattern, '<strong>\\1</strong>', htmlspecialchars($text));
|
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
|
* Retrieve the messages for this user and this page
|
||||||
*
|
*
|
||||||
|
@ -27,7 +27,7 @@ class InviteAction extends Action
|
|||||||
var $subbed = null;
|
var $subbed = null;
|
||||||
var $sent = null;
|
var $sent = null;
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ class JoingroupAction extends Action
|
|||||||
|
|
||||||
if ($nickname_arg != $nickname) {
|
if ($nickname_arg != $nickname) {
|
||||||
$args = array('nickname' => $nickname);
|
$args = array('nickname' => $nickname);
|
||||||
common_redirect(common_local_url('editgroup', $args), 301);
|
common_redirect(common_local_url('joingroup', $args), 301);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +143,8 @@ class JoingroupAction extends Action
|
|||||||
$this->elementEnd('html');
|
$this->elementEnd('html');
|
||||||
} else {
|
} else {
|
||||||
common_redirect(common_local_url('groupmembers', array('nickname' =>
|
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) {
|
if ($nickname_arg != $nickname) {
|
||||||
$args = array('nickname' => $nickname);
|
$args = array('nickname' => $nickname);
|
||||||
common_redirect(common_local_url('editgroup', $args), 301);
|
common_redirect(common_local_url('leavegroup', $args), 301);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,12 +96,6 @@ class LeavegroupAction extends Action
|
|||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +147,8 @@ class LeavegroupAction extends Action
|
|||||||
$this->elementEnd('html');
|
$this->elementEnd('html');
|
||||||
} else {
|
} else {
|
||||||
common_redirect(common_local_url('groupmembers', array('nickname' =>
|
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
|
* @return boolean false
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -108,13 +108,15 @@ class LoginAction extends Action
|
|||||||
$nickname = common_canonical_nickname($this->trimmed('nickname'));
|
$nickname = common_canonical_nickname($this->trimmed('nickname'));
|
||||||
$password = $this->arg('password');
|
$password = $this->arg('password');
|
||||||
|
|
||||||
if (!common_check_user($nickname, $password)) {
|
$user = common_check_user($nickname, $password);
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
$this->showForm(_('Incorrect username or password.'));
|
$this->showForm(_('Incorrect username or password.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// success!
|
// success!
|
||||||
if (!common_set_user($nickname)) {
|
if (!common_set_user($user)) {
|
||||||
$this->serverError(_('Error setting user.'));
|
$this->serverError(_('Error setting user.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -136,7 +138,7 @@ class LoginAction extends Action
|
|||||||
$nickname));
|
$nickname));
|
||||||
}
|
}
|
||||||
|
|
||||||
common_redirect($url);
|
common_redirect($url, 303);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,20 +46,20 @@ require_once INSTALLDIR.'/lib/openid.php';
|
|||||||
*/
|
*/
|
||||||
class LogoutAction extends Action
|
class LogoutAction extends Action
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is read only.
|
* This is read only.
|
||||||
*
|
*
|
||||||
* @return boolean true
|
* @return boolean true
|
||||||
*/
|
*/
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class handler.
|
* Class handler.
|
||||||
*
|
*
|
||||||
* @param array $args array of arguments
|
* @param array $args array of arguments
|
||||||
*
|
*
|
||||||
* @return nothing
|
* @return nothing
|
||||||
@ -70,10 +70,20 @@ class LogoutAction extends Action
|
|||||||
if (!common_logged_in()) {
|
if (!common_logged_in()) {
|
||||||
$this->clientError(_('Not logged in.'));
|
$this->clientError(_('Not logged in.'));
|
||||||
} else {
|
} else {
|
||||||
common_set_user(null);
|
if (Event::handle('StartLogout', array($this))) {
|
||||||
common_real_login(false); // not logged in
|
$this->logout();
|
||||||
common_forgetme(); // don't log back in!
|
}
|
||||||
common_redirect(common_local_url('public'));
|
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!
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ class MicrosummaryAction extends Action
|
|||||||
print $user->nickname . ': ' . $notice->content;
|
print $user->nickname . ': ' . $notice->content;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,7 @@ class NewgroupAction extends Action
|
|||||||
|
|
||||||
$group->query('COMMIT');
|
$group->query('COMMIT');
|
||||||
|
|
||||||
common_redirect($group->homeUrl(), 307);
|
common_redirect($group->homeUrl(), 303);
|
||||||
}
|
}
|
||||||
|
|
||||||
function nicknameExists($nickname)
|
function nicknameExists($nickname)
|
||||||
|
@ -172,15 +172,54 @@ class NewmessageAction extends Action
|
|||||||
|
|
||||||
$this->notify($user, $this->other, $message);
|
$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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
function showForm($msg = null)
|
||||||
{
|
{
|
||||||
$this->msg = $msg;
|
if ($msg && $this->boolean('ajax')) {
|
||||||
|
$this->ajaxErrorMsg($msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->msg = $msg;
|
||||||
$this->showPage();
|
$this->showPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,8 +152,14 @@ class NewnoticeAction extends Action
|
|||||||
}
|
}
|
||||||
|
|
||||||
$replyto = $this->trimmed('inreplyto');
|
$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);
|
($replyto == 'false') ? null : $replyto);
|
||||||
|
|
||||||
if (is_string($notice)) {
|
if (is_string($notice)) {
|
||||||
@ -161,6 +167,8 @@ class NewnoticeAction extends Action
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->saveUrls($notice);
|
||||||
|
|
||||||
common_broadcast_notice($notice);
|
common_broadcast_notice($notice);
|
||||||
|
|
||||||
if ($this->boolean('ajax')) {
|
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
|
* 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();
|
$notice_form->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ class NoticesearchAction extends SearchAction
|
|||||||
function showResults($q, $page)
|
function showResults($q, $page)
|
||||||
{
|
{
|
||||||
$notice = new Notice();
|
$notice = new Notice();
|
||||||
$q = strtolower($q);
|
|
||||||
$search_engine = $notice->getSearchEngine('identica_notices');
|
$search_engine = $notice->getSearchEngine('identica_notices');
|
||||||
$search_engine->set_sort_mode('chron');
|
$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.
|
||||||
@ -113,123 +113,64 @@ class NoticesearchAction extends SearchAction
|
|||||||
} else {
|
} else {
|
||||||
$cnt = $notice->find();
|
$cnt = $notice->find();
|
||||||
}
|
}
|
||||||
if ($cnt > 0) {
|
if ($cnt === 0) {
|
||||||
$terms = preg_split('/[\s,]+/', $q);
|
$this->element('p', 'error', _('No results.'));
|
||||||
$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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->elementEnd('ul');
|
|
||||||
} else {
|
|
||||||
$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));
|
||||||
|
}
|
||||||
|
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,
|
$this->pagination($page > 1, $cnt > NOTICES_PER_PAGE,
|
||||||
$page, 'noticesearch', array('q' => $q));
|
$page, 'noticesearch', array('q' => $q));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
class SearchNoticeList extends NoticeList {
|
||||||
* Show notice
|
function __construct($notice, $out=null, $terms)
|
||||||
*
|
|
||||||
* @param class $notice notice
|
|
||||||
* @param array $terms terms to highlight
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @todo refactor and combine with StreamAction::showNotice()
|
|
||||||
*/
|
|
||||||
function showNotice($notice, $terms)
|
|
||||||
{
|
{
|
||||||
$profile = $notice->getProfile();
|
parent::__construct($notice, $out);
|
||||||
if (!$profile) {
|
$this->terms = $terms;
|
||||||
common_log_db_error($notice, 'SELECT', __FILE__);
|
}
|
||||||
$this->serverError(_('Notice without matching profile'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// XXX: RDFa
|
|
||||||
$this->elementStart('li', array('class' => 'hentry notice',
|
|
||||||
'id' => 'notice-' . $notice->id));
|
|
||||||
|
|
||||||
$this->elementStart('div', 'entry-title');
|
function newListItem($notice)
|
||||||
$this->elementStart('span', 'vcard author');
|
{
|
||||||
$avatar = $profile->getAvatar(AVATAR_STREAM_SIZE);
|
return new SearchNoticeListItem($notice, $this->out, $this->terms);
|
||||||
$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');
|
|
||||||
|
|
||||||
|
class SearchNoticeListItem extends NoticeListItem {
|
||||||
|
function __construct($notice, $out=null, $terms)
|
||||||
|
{
|
||||||
|
parent::__construct($notice, $out);
|
||||||
|
$this->terms = $terms;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showContent()
|
||||||
|
{
|
||||||
// FIXME: URL, image, video, audio
|
// FIXME: URL, image, video, audio
|
||||||
$this->elementStart('p', array('class' => 'entry-content'));
|
$this->out->elementStart('p', array('class' => 'entry-content'));
|
||||||
if ($notice->rendered) {
|
if ($this->notice->rendered) {
|
||||||
$this->raw($this->highlight($notice->rendered, $terms));
|
$this->out->raw($this->highlight($this->notice->rendered, $this->terms));
|
||||||
} else {
|
} else {
|
||||||
// XXX: may be some uncooked notices in the DB,
|
// XXX: may be some uncooked notices in the DB,
|
||||||
// we cook them right now. This should probably disappear in future
|
// we cook them right now. This should probably disappear in future
|
||||||
// versions (>> 0.4.x)
|
// 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->out->elementEnd('p');
|
||||||
$this->elementEnd('div');
|
|
||||||
|
|
||||||
$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)
|
function highlight($text, $terms)
|
||||||
{
|
{
|
||||||
/* Highligh serach terms */
|
/* Highligh search terms */
|
||||||
$pattern = '/('.implode('|', array_map('htmlspecialchars', $terms)).')/i';
|
$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);
|
$result = preg_replace($pattern, '<strong>\\1</strong>', $text);
|
||||||
|
|
||||||
/* Remove highlighting from inside links, loop incase multiple highlights in links */
|
/* 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 {
|
do {
|
||||||
$result = preg_replace($pattern, '\\1\\2\\3', $result, -1, $count);
|
$result = preg_replace($pattern, '\\1\\2\\3', $result, -1, $count);
|
||||||
} while ($count);
|
} while ($count);
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReadOnly()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,9 +62,6 @@ class NoticesearchrssAction extends Rss10Action
|
|||||||
|
|
||||||
$notice = new Notice();
|
$notice = new Notice();
|
||||||
|
|
||||||
# lcase it for comparison
|
|
||||||
$q = strtolower($q);
|
|
||||||
|
|
||||||
$search_engine = $notice->getSearchEngine('identica_notices');
|
$search_engine = $notice->getSearchEngine('identica_notices');
|
||||||
$search_engine->set_sort_mode('chron');
|
$search_engine->set_sort_mode('chron');
|
||||||
|
|
||||||
@ -82,10 +79,9 @@ class NoticesearchrssAction extends Rss10Action
|
|||||||
|
|
||||||
function getChannel()
|
function getChannel()
|
||||||
{
|
{
|
||||||
global $config;
|
|
||||||
$q = $this->trimmed('q');
|
$q = $this->trimmed('q');
|
||||||
$c = array('url' => common_local_url('noticesearchrss', array('q' => $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)),
|
'link' => common_local_url('noticesearch', array('q' => $q)),
|
||||||
'description' => sprintf(_('All updates matching search term "%s"'), $q));
|
'description' => sprintf(_('All updates matching search term "%s"'), $q));
|
||||||
return $c;
|
return $c;
|
||||||
@ -96,7 +92,7 @@ class NoticesearchrssAction extends Rss10Action
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ class NudgeAction extends Action
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Class handler.
|
* Class handler.
|
||||||
*
|
*
|
||||||
* @param array $args array of arguments
|
* @param array $args array of arguments
|
||||||
*
|
*
|
||||||
* @return nothing
|
* @return nothing
|
||||||
@ -75,7 +75,7 @@ class NudgeAction extends Action
|
|||||||
|
|
||||||
// CSRF protection
|
// CSRF protection
|
||||||
$token = $this->trimmed('token');
|
$token = $this->trimmed('token');
|
||||||
|
|
||||||
if (!$token || $token != common_session_token()) {
|
if (!$token || $token != common_session_token()) {
|
||||||
$this->clientError(_('There was a problem with your session token. Try again, please.'));
|
$this->clientError(_('There was a problem with your session token. Try again, please.'));
|
||||||
return;
|
return;
|
||||||
@ -100,7 +100,8 @@ class NudgeAction extends Action
|
|||||||
} else {
|
} else {
|
||||||
// display a confirmation to the user
|
// display a confirmation to the user
|
||||||
common_redirect(common_local_url('showstream',
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -67,8 +67,8 @@ class OpenidsettingsAction extends AccountSettingsAction
|
|||||||
|
|
||||||
function getInstructions()
|
function getInstructions()
|
||||||
{
|
{
|
||||||
return _('[OpenID](%%doc.openid%%) lets you log into many sites ' .
|
return _('[OpenID](%%doc.openid%%) lets you log into many sites' .
|
||||||
' with the same user account. '.
|
' with the same user account.'.
|
||||||
' Manage your associated OpenIDs from here.');
|
' Manage your associated OpenIDs from here.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ class OpensearchAction extends Action
|
|||||||
$this->endXML();
|
$this->endXML();
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
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
|
* retrieve the messages for this user and this page
|
||||||
*
|
*
|
||||||
|
@ -60,16 +60,10 @@ class PeoplesearchAction extends SearchAction
|
|||||||
|
|
||||||
function showResults($q, $page)
|
function showResults($q, $page)
|
||||||
{
|
{
|
||||||
|
|
||||||
$profile = new Profile();
|
$profile = new Profile();
|
||||||
|
|
||||||
# lcase it for comparison
|
|
||||||
$q = strtolower($q);
|
|
||||||
|
|
||||||
$search_engine = $profile->getSearchEngine('identica_people');
|
$search_engine = $profile->getSearchEngine('identica_people');
|
||||||
|
|
||||||
$search_engine->set_sort_mode('chron');
|
$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);
|
$search_engine->limit((($page-1)*PROFILES_PER_PAGE), PROFILES_PER_PAGE + 1);
|
||||||
if (false === $search_engine->query($q)) {
|
if (false === $search_engine->query($q)) {
|
||||||
$cnt = 0;
|
$cnt = 0;
|
||||||
@ -81,38 +75,15 @@ class PeoplesearchAction extends SearchAction
|
|||||||
$terms = preg_split('/[\s,]+/', $q);
|
$terms = preg_split('/[\s,]+/', $q);
|
||||||
$results = new PeopleSearchResults($profile, $terms, $this);
|
$results = new PeopleSearchResults($profile, $terms, $this);
|
||||||
$results->show();
|
$results->show();
|
||||||
} else {
|
$profile->free();
|
||||||
$this->element('p', 'error', _('No results'));
|
$this->pagination($page > 1, $cnt > PROFILES_PER_PAGE,
|
||||||
}
|
|
||||||
|
|
||||||
$profile->free();
|
|
||||||
|
|
||||||
$this->pagination($page > 1, $cnt > PROFILES_PER_PAGE,
|
|
||||||
$page, 'peoplesearch', array('q' => $q));
|
$page, 'peoplesearch', array('q' => $q));
|
||||||
}
|
|
||||||
}
|
} else {
|
||||||
|
$this->element('p', 'error', _('No results.'));
|
||||||
class PeopleSearchResults extends ProfileList
|
$this->searchSuggestions($q);
|
||||||
{
|
$profile->free();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ class PeopletagAction extends Action
|
|||||||
'FROM profile JOIN profile_tag ' .
|
'FROM profile JOIN profile_tag ' .
|
||||||
'ON profile.id = profile_tag.tagger ' .
|
'ON profile.id = profile_tag.tagger ' .
|
||||||
'WHERE profile_tag.tagger = profile_tag.tagged ' .
|
'WHERE profile_tag.tagger = profile_tag.tagged ' .
|
||||||
'AND tag = "%s" ' .
|
"AND tag = '%s' " .
|
||||||
'ORDER BY profile_tag.modified DESC%s';
|
'ORDER BY profile_tag.modified DESC%s';
|
||||||
|
|
||||||
$profile->query(sprintf($qry, $this->tag, $lim));
|
$profile->query(sprintf($qry, $this->tag, $lim));
|
||||||
|
@ -28,7 +28,7 @@ class PostnoticeAction extends Action
|
|||||||
parent::handle($args);
|
parent::handle($args);
|
||||||
try {
|
try {
|
||||||
common_remove_magic_from_request();
|
common_remove_magic_from_request();
|
||||||
$req = OAuthRequest::from_request();
|
$req = OAuthRequest::from_request('POST', common_local_url('postnotice'));
|
||||||
# Note: server-to-server function!
|
# Note: server-to-server function!
|
||||||
$server = omb_oauth_server();
|
$server = omb_oauth_server();
|
||||||
list($consumer, $token) = $server->verify_request($req);
|
list($consumer, $token) = $server->verify_request($req);
|
||||||
@ -79,7 +79,7 @@ class PostnoticeAction extends Action
|
|||||||
}
|
}
|
||||||
$notice = Notice::staticGet('uri', $notice_uri);
|
$notice = Notice::staticGet('uri', $notice_uri);
|
||||||
if (!$notice) {
|
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)) {
|
if (is_string($notice)) {
|
||||||
common_server_serror($notice, 500);
|
common_server_serror($notice, 500);
|
||||||
return false;
|
return false;
|
||||||
|
@ -91,67 +91,68 @@ class ProfilesettingsAction extends AccountSettingsAction
|
|||||||
$this->element('legend', null, _('Profile information'));
|
$this->element('legend', null, _('Profile information'));
|
||||||
$this->hidden('token', common_session_token());
|
$this->hidden('token', common_session_token());
|
||||||
|
|
||||||
# too much common patterns here... abstractable?
|
// too much common patterns here... abstractable?
|
||||||
|
|
||||||
$this->elementStart('ul', 'form_data');
|
$this->elementStart('ul', 'form_data');
|
||||||
$this->elementStart('li');
|
if (Event::handle('StartProfileFormData', array($this))) {
|
||||||
$this->input('nickname', _('Nickname'),
|
$this->elementStart('li');
|
||||||
($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname,
|
$this->input('nickname', _('Nickname'),
|
||||||
_('1-64 lowercase letters or numbers, no punctuation or spaces'));
|
($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname,
|
||||||
$this->elementEnd('li');
|
_('1-64 lowercase letters or numbers, no punctuation or spaces'));
|
||||||
$this->elementStart('li');
|
$this->elementEnd('li');
|
||||||
$this->input('fullname', _('Full name'),
|
$this->elementStart('li');
|
||||||
($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname);
|
$this->input('fullname', _('Full name'),
|
||||||
$this->elementEnd('li');
|
($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname);
|
||||||
$this->elementStart('li');
|
$this->elementEnd('li');
|
||||||
$this->input('homepage', _('Homepage'),
|
$this->elementStart('li');
|
||||||
($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage,
|
$this->input('homepage', _('Homepage'),
|
||||||
_('URL of your homepage, blog, or profile on another site'));
|
($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage,
|
||||||
$this->elementEnd('li');
|
_('URL of your homepage, blog, or profile on another site'));
|
||||||
$this->elementStart('li');
|
$this->elementEnd('li');
|
||||||
$this->textarea('bio', _('Bio'),
|
$this->elementStart('li');
|
||||||
($this->arg('bio')) ? $this->arg('bio') : $profile->bio,
|
$this->textarea('bio', _('Bio'),
|
||||||
_('Describe yourself and your interests in 140 chars'));
|
($this->arg('bio')) ? $this->arg('bio') : $profile->bio,
|
||||||
$this->elementEnd('li');
|
_('Describe yourself and your interests in 140 chars'));
|
||||||
$this->elementStart('li');
|
$this->elementEnd('li');
|
||||||
$this->input('location', _('Location'),
|
$this->elementStart('li');
|
||||||
($this->arg('location')) ? $this->arg('location') : $profile->location,
|
$this->input('location', _('Location'),
|
||||||
_('Where you are, like "City, State (or Region), Country"'));
|
($this->arg('location')) ? $this->arg('location') : $profile->location,
|
||||||
$this->elementEnd('li');
|
_('Where you are, like "City, State (or Region), Country"'));
|
||||||
$this->elementStart('li');
|
$this->elementEnd('li');
|
||||||
$this->input('tags', _('Tags'),
|
Event::handle('EndProfileFormData', array($this));
|
||||||
($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()),
|
$this->elementStart('li');
|
||||||
_('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated'));
|
$this->input('tags', _('Tags'),
|
||||||
$this->elementEnd('li');
|
($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()),
|
||||||
$this->elementStart('li');
|
_('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated'));
|
||||||
$language = common_language();
|
$this->elementEnd('li');
|
||||||
$this->dropdown('language', _('Language'),
|
$this->elementStart('li');
|
||||||
get_nice_language_list(), _('Preferred language'),
|
$language = common_language();
|
||||||
true, $language);
|
$this->dropdown('language', _('Language'),
|
||||||
$this->elementEnd('li');
|
get_nice_language_list(), _('Preferred language'),
|
||||||
$timezone = common_timezone();
|
false, $language);
|
||||||
$timezones = array();
|
$this->elementEnd('li');
|
||||||
foreach(DateTimeZone::listIdentifiers() as $k => $v) {
|
$timezone = common_timezone();
|
||||||
$timezones[$v] = $v;
|
$timezones = array();
|
||||||
|
foreach(DateTimeZone::listIdentifiers() as $k => $v) {
|
||||||
|
$timezones[$v] = $v;
|
||||||
|
}
|
||||||
|
$this->elementStart('li');
|
||||||
|
$this->dropdown('timezone', _('Timezone'),
|
||||||
|
$timezones, _('What timezone are you normally in?'),
|
||||||
|
true, $timezone);
|
||||||
|
$this->elementEnd('li');
|
||||||
|
$this->elementStart('li');
|
||||||
|
$this->checkbox('autosubscribe',
|
||||||
|
_('Automatically subscribe to whoever '.
|
||||||
|
'subscribes to me (best for non-humans)'),
|
||||||
|
($this->arg('autosubscribe')) ?
|
||||||
|
$this->boolean('autosubscribe') : $user->autosubscribe);
|
||||||
|
$this->elementEnd('li');
|
||||||
}
|
}
|
||||||
$this->elementStart('li');
|
|
||||||
$this->dropdown('timezone', _('Timezone'),
|
|
||||||
$timezones, _('What timezone are you normally in?'),
|
|
||||||
true, $timezone);
|
|
||||||
$this->elementEnd('li');
|
|
||||||
$this->elementStart('li');
|
|
||||||
$this->checkbox('autosubscribe',
|
|
||||||
_('Automatically subscribe to whoever '.
|
|
||||||
'subscribes to me (best for non-humans)'),
|
|
||||||
($this->arg('autosubscribe')) ?
|
|
||||||
$this->boolean('autosubscribe') : $user->autosubscribe);
|
|
||||||
$this->elementEnd('li');
|
|
||||||
$this->elementEnd('ul');
|
$this->elementEnd('ul');
|
||||||
$this->submit('save', _('Save'));
|
$this->submit('save', _('Save'));
|
||||||
|
|
||||||
$this->elementEnd('fieldset');
|
$this->elementEnd('fieldset');
|
||||||
$this->elementEnd('form');
|
$this->elementEnd('form');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -165,158 +166,158 @@ class ProfilesettingsAction extends AccountSettingsAction
|
|||||||
|
|
||||||
function handlePost()
|
function handlePost()
|
||||||
{
|
{
|
||||||
# CSRF protection
|
// CSRF protection
|
||||||
|
|
||||||
$token = $this->trimmed('token');
|
$token = $this->trimmed('token');
|
||||||
if (!$token || $token != common_session_token()) {
|
if (!$token || $token != common_session_token()) {
|
||||||
$this->showForm(_('There was a problem with your session token. '.
|
$this->showForm(_('There was a problem with your session token. '.
|
||||||
'Try again, please.'));
|
'Try again, please.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$nickname = $this->trimmed('nickname');
|
if (Event::handle('StartProfileSaveForm', array($this))) {
|
||||||
$fullname = $this->trimmed('fullname');
|
|
||||||
$homepage = $this->trimmed('homepage');
|
|
||||||
$bio = $this->trimmed('bio');
|
|
||||||
$location = $this->trimmed('location');
|
|
||||||
$autosubscribe = $this->boolean('autosubscribe');
|
|
||||||
$language = $this->trimmed('language');
|
|
||||||
$timezone = $this->trimmed('timezone');
|
|
||||||
$tagstring = $this->trimmed('tags');
|
|
||||||
|
|
||||||
# Some validation
|
$nickname = $this->trimmed('nickname');
|
||||||
|
$fullname = $this->trimmed('fullname');
|
||||||
|
$homepage = $this->trimmed('homepage');
|
||||||
|
$bio = $this->trimmed('bio');
|
||||||
|
$location = $this->trimmed('location');
|
||||||
|
$autosubscribe = $this->boolean('autosubscribe');
|
||||||
|
$language = $this->trimmed('language');
|
||||||
|
$timezone = $this->trimmed('timezone');
|
||||||
|
$tagstring = $this->trimmed('tags');
|
||||||
|
|
||||||
if (!Validate::string($nickname, array('min_length' => 1,
|
// Some validation
|
||||||
'max_length' => 64,
|
if (!Validate::string($nickname, array('min_length' => 1,
|
||||||
'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
|
'max_length' => 64,
|
||||||
$this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.'));
|
'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
|
||||||
return;
|
$this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.'));
|
||||||
} else if (!User::allowed_nickname($nickname)) {
|
return;
|
||||||
$this->showForm(_('Not a valid nickname.'));
|
} else if (!User::allowed_nickname($nickname)) {
|
||||||
return;
|
$this->showForm(_('Not a valid nickname.'));
|
||||||
} else if (!is_null($homepage) && (strlen($homepage) > 0) &&
|
return;
|
||||||
!Validate::uri($homepage, array('allowed_schemes' => array('http', 'https')))) {
|
} else if (!is_null($homepage) && (strlen($homepage) > 0) &&
|
||||||
$this->showForm(_('Homepage is not a valid URL.'));
|
!Validate::uri($homepage, array('allowed_schemes' => array('http', 'https')))) {
|
||||||
return;
|
$this->showForm(_('Homepage is not a valid URL.'));
|
||||||
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
|
return;
|
||||||
$this->showForm(_('Full name is too long (max 255 chars).'));
|
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
|
||||||
return;
|
$this->showForm(_('Full name is too long (max 255 chars).'));
|
||||||
} else if (!is_null($bio) && mb_strlen($bio) > 140) {
|
return;
|
||||||
$this->showForm(_('Bio is too long (max 140 chars).'));
|
} else if (!is_null($bio) && mb_strlen($bio) > 140) {
|
||||||
return;
|
$this->showForm(_('Bio is too long (max 140 chars).'));
|
||||||
} else if (!is_null($location) && mb_strlen($location) > 255) {
|
return;
|
||||||
$this->showForm(_('Location is too long (max 255 chars).'));
|
} else if (!is_null($location) && mb_strlen($location) > 255) {
|
||||||
return;
|
$this->showForm(_('Location is too long (max 255 chars).'));
|
||||||
} else if (is_null($timezone) || !in_array($timezone, DateTimeZone::listIdentifiers())) {
|
return;
|
||||||
$this->showForm(_('Timezone not selected.'));
|
} else if (is_null($timezone) || !in_array($timezone, DateTimeZone::listIdentifiers())) {
|
||||||
return;
|
$this->showForm(_('Timezone not selected.'));
|
||||||
} else if ($this->nicknameExists($nickname)) {
|
return;
|
||||||
$this->showForm(_('Nickname already in use. Try another one.'));
|
} else if ($this->nicknameExists($nickname)) {
|
||||||
return;
|
$this->showForm(_('Nickname already in use. Try another one.'));
|
||||||
} else if (!is_null($language) && strlen($language) > 50) {
|
return;
|
||||||
$this->showForm(_('Language is too long (max 50 chars).'));
|
} else if (!is_null($language) && strlen($language) > 50) {
|
||||||
return;
|
$this->showForm(_('Language is too long (max 50 chars).'));
|
||||||
}
|
|
||||||
|
|
||||||
if ($tagstring) {
|
|
||||||
$tags = array_map('common_canonical_tag', preg_split('/[\s,]+/', $tagstring));
|
|
||||||
} else {
|
|
||||||
$tags = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($tags as $tag) {
|
|
||||||
if (!common_valid_profile_tag($tag)) {
|
|
||||||
$this->showForm(sprintf(_('Invalid tag: "%s"'), $tag));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$user = common_current_user();
|
if ($tagstring) {
|
||||||
|
$tags = array_map('common_canonical_tag', preg_split('/[\s,]+/', $tagstring));
|
||||||
$user->query('BEGIN');
|
|
||||||
|
|
||||||
if ($user->nickname != $nickname ||
|
|
||||||
$user->language != $language ||
|
|
||||||
$user->timezone != $timezone) {
|
|
||||||
|
|
||||||
common_debug('Updating user nickname from ' . $user->nickname . ' to ' . $nickname,
|
|
||||||
__FILE__);
|
|
||||||
common_debug('Updating user language from ' . $user->language . ' to ' . $language,
|
|
||||||
__FILE__);
|
|
||||||
common_debug('Updating user timezone from ' . $user->timezone . ' to ' . $timezone,
|
|
||||||
__FILE__);
|
|
||||||
|
|
||||||
$original = clone($user);
|
|
||||||
|
|
||||||
$user->nickname = $nickname;
|
|
||||||
$user->language = $language;
|
|
||||||
$user->timezone = $timezone;
|
|
||||||
|
|
||||||
$result = $user->updateKeys($original);
|
|
||||||
|
|
||||||
if ($result === false) {
|
|
||||||
common_log_db_error($user, 'UPDATE', __FILE__);
|
|
||||||
$this->serverError(_('Couldn\'t update user.'));
|
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
# Re-initialize language environment if it changed
|
$tags = array();
|
||||||
common_init_language();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
# XXX: XOR
|
foreach ($tags as $tag) {
|
||||||
|
if (!common_valid_profile_tag($tag)) {
|
||||||
|
$this->showForm(sprintf(_('Invalid tag: "%s"'), $tag));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($user->autosubscribe ^ $autosubscribe) {
|
$user = common_current_user();
|
||||||
|
|
||||||
$original = clone($user);
|
$user->query('BEGIN');
|
||||||
|
|
||||||
$user->autosubscribe = $autosubscribe;
|
if ($user->nickname != $nickname ||
|
||||||
|
$user->language != $language ||
|
||||||
|
$user->timezone != $timezone) {
|
||||||
|
|
||||||
$result = $user->update($original);
|
common_debug('Updating user nickname from ' . $user->nickname . ' to ' . $nickname,
|
||||||
|
__FILE__);
|
||||||
|
common_debug('Updating user language from ' . $user->language . ' to ' . $language,
|
||||||
|
__FILE__);
|
||||||
|
common_debug('Updating user timezone from ' . $user->timezone . ' to ' . $timezone,
|
||||||
|
__FILE__);
|
||||||
|
|
||||||
if ($result === false) {
|
$original = clone($user);
|
||||||
common_log_db_error($user, 'UPDATE', __FILE__);
|
|
||||||
$this->serverError(_('Couldn\'t update user for autosubscribe.'));
|
$user->nickname = $nickname;
|
||||||
|
$user->language = $language;
|
||||||
|
$user->timezone = $timezone;
|
||||||
|
|
||||||
|
$result = $user->updateKeys($original);
|
||||||
|
|
||||||
|
if ($result === false) {
|
||||||
|
common_log_db_error($user, 'UPDATE', __FILE__);
|
||||||
|
$this->serverError(_('Couldn\'t update user.'));
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Re-initialize language environment if it changed
|
||||||
|
common_init_language();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: XOR
|
||||||
|
if ($user->autosubscribe ^ $autosubscribe) {
|
||||||
|
|
||||||
|
$original = clone($user);
|
||||||
|
|
||||||
|
$user->autosubscribe = $autosubscribe;
|
||||||
|
|
||||||
|
$result = $user->update($original);
|
||||||
|
|
||||||
|
if ($result === false) {
|
||||||
|
common_log_db_error($user, 'UPDATE', __FILE__);
|
||||||
|
$this->serverError(_('Couldn\'t update user for autosubscribe.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$profile = $user->getProfile();
|
||||||
|
|
||||||
|
$orig_profile = clone($profile);
|
||||||
|
|
||||||
|
$profile->nickname = $user->nickname;
|
||||||
|
$profile->fullname = $fullname;
|
||||||
|
$profile->homepage = $homepage;
|
||||||
|
$profile->bio = $bio;
|
||||||
|
$profile->location = $location;
|
||||||
|
$profile->profileurl = common_profile_url($nickname);
|
||||||
|
|
||||||
|
common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__);
|
||||||
|
common_debug('New profile: ' . common_log_objstring($profile), __FILE__);
|
||||||
|
|
||||||
|
$result = $profile->update($orig_profile);
|
||||||
|
|
||||||
|
if (!$result) {
|
||||||
|
common_log_db_error($profile, 'UPDATE', __FILE__);
|
||||||
|
$this->serverError(_('Couldn\'t save profile.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the user tags
|
||||||
|
$result = $user->setSelfTags($tags);
|
||||||
|
|
||||||
|
if (!$result) {
|
||||||
|
$this->serverError(_('Couldn\'t save tags.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->query('COMMIT');
|
||||||
|
Event::handle('EndProfileSaveForm', array($this));
|
||||||
|
common_broadcast_profile($profile);
|
||||||
|
|
||||||
|
$this->showForm(_('Settings saved.'), true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$profile = $user->getProfile();
|
|
||||||
|
|
||||||
$orig_profile = clone($profile);
|
|
||||||
|
|
||||||
$profile->nickname = $user->nickname;
|
|
||||||
$profile->fullname = $fullname;
|
|
||||||
$profile->homepage = $homepage;
|
|
||||||
$profile->bio = $bio;
|
|
||||||
$profile->location = $location;
|
|
||||||
$profile->profileurl = common_profile_url($nickname);
|
|
||||||
|
|
||||||
common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__);
|
|
||||||
common_debug('New profile: ' . common_log_objstring($profile), __FILE__);
|
|
||||||
|
|
||||||
$result = $profile->update($orig_profile);
|
|
||||||
|
|
||||||
if (!$result) {
|
|
||||||
common_log_db_error($profile, 'UPDATE', __FILE__);
|
|
||||||
$this->serverError(_('Couldn\'t save profile.'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Set the user tags
|
|
||||||
|
|
||||||
$result = $user->setSelfTags($tags);
|
|
||||||
|
|
||||||
if (!$result) {
|
|
||||||
$this->serverError(_('Couldn\'t save tags.'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$user->query('COMMIT');
|
|
||||||
|
|
||||||
common_broadcast_profile($profile);
|
|
||||||
|
|
||||||
$this->showForm(_('Settings saved.'), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function nicknameExists($nickname)
|
function nicknameExists($nickname)
|
||||||
|
@ -56,7 +56,7 @@ class PublicAction extends Action
|
|||||||
|
|
||||||
var $page = null;
|
var $page = null;
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -135,6 +135,17 @@ class PublicAction extends Action
|
|||||||
_('Public Stream Feed (Atom)')));
|
_('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
|
* Extra head elements
|
||||||
*
|
*
|
||||||
@ -166,6 +177,22 @@ class PublicAction extends Action
|
|||||||
$nav->show();
|
$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
|
* Fill the content area
|
||||||
*
|
*
|
||||||
@ -189,6 +216,10 @@ class PublicAction extends Action
|
|||||||
|
|
||||||
$cnt = $nl->show();
|
$cnt = $nl->show();
|
||||||
|
|
||||||
|
if ($cnt == 0) {
|
||||||
|
$this->showEmptyList();
|
||||||
|
}
|
||||||
|
|
||||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||||
$this->page, 'public');
|
$this->page, 'public');
|
||||||
}
|
}
|
||||||
@ -207,9 +238,14 @@ class PublicAction extends Action
|
|||||||
|
|
||||||
function showAnonymousMessage()
|
function showAnonymousMessage()
|
||||||
{
|
{
|
||||||
$m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
if (! (common_config('site','closed') || common_config('site','inviteonly'))) {
|
||||||
'based on the Free Software [Laconica](http://laconi.ca/) tool. ' .
|
$m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
||||||
'[Join now](%%action.register%%) to share notices about yourself with friends, family, and colleagues! ([Read more](%%doc.help%%))');
|
'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->elementStart('div', array('id' => 'anon_notice'));
|
||||||
$this->raw(common_markup_to_html($m));
|
$this->raw(common_markup_to_html($m));
|
||||||
$this->elementEnd('div');
|
$this->elementEnd('div');
|
||||||
|
@ -84,12 +84,11 @@ class PublicrssAction extends Rss10Action
|
|||||||
*/
|
*/
|
||||||
function getChannel()
|
function getChannel()
|
||||||
{
|
{
|
||||||
global $config;
|
|
||||||
$c = array(
|
$c = array(
|
||||||
'url' => common_local_url('publicrss')
|
'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')
|
, '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;
|
return $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +102,7 @@ class PublicrssAction extends Rss10Action
|
|||||||
// nop
|
// nop
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ define('TAGS_PER_PAGE', 100);
|
|||||||
|
|
||||||
class PublictagcloudAction extends Action
|
class PublictagcloudAction extends Action
|
||||||
{
|
{
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -64,6 +64,22 @@ class PublictagcloudAction extends Action
|
|||||||
common_config('site', 'name')));
|
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()
|
function showLocalNav()
|
||||||
{
|
{
|
||||||
$nav = new PublicGroupNav($this);
|
$nav = new PublicGroupNav($this);
|
||||||
@ -126,6 +142,8 @@ class PublictagcloudAction extends Action
|
|||||||
$this->elementEnd('dd');
|
$this->elementEnd('dd');
|
||||||
$this->elementEnd('dl');
|
$this->elementEnd('dl');
|
||||||
$this->elementEnd('div');
|
$this->elementEnd('div');
|
||||||
|
} else {
|
||||||
|
$this->showEmptyList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,17 +51,17 @@ class PublicxrdsAction extends Action
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Is read only?
|
* Is read only?
|
||||||
*
|
*
|
||||||
* @return boolean true
|
* @return boolean true
|
||||||
*/
|
*/
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class handler.
|
* Class handler.
|
||||||
*
|
*
|
||||||
* @param array $args array of arguments
|
* @param array $args array of arguments
|
||||||
*
|
*
|
||||||
* @return nothing
|
* @return nothing
|
||||||
@ -70,24 +70,24 @@ class PublicxrdsAction extends Action
|
|||||||
{
|
{
|
||||||
parent::handle($args);
|
parent::handle($args);
|
||||||
header('Content-Type: application/xrds+xml');
|
header('Content-Type: application/xrds+xml');
|
||||||
common_start_xml();
|
$this->startXML();
|
||||||
$this->elementStart('XRDS', array('xmlns' => 'xri://$xrds'));
|
$this->elementStart('XRDS', array('xmlns' => 'xri://$xrds'));
|
||||||
$this->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
|
$this->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
|
||||||
'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
|
'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
|
||||||
'version' => '2.0'));
|
'version' => '2.0'));
|
||||||
$this->element('Type', null, 'xri://$xrds*simple');
|
$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,
|
$this->showService(Auth_OpenID_RP_RETURN_TO_URL_TYPE,
|
||||||
common_local_url($finish));
|
common_local_url($finish));
|
||||||
}
|
}
|
||||||
$this->elementEnd('XRD');
|
$this->elementEnd('XRD');
|
||||||
$this->elementEnd('XRDS');
|
$this->elementEnd('XRDS');
|
||||||
common_end_xml();
|
$this->endXML();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show service.
|
* Show service.
|
||||||
*
|
*
|
||||||
* @param string $type XRDS type
|
* @param string $type XRDS type
|
||||||
* @param string $uri URI
|
* @param string $uri URI
|
||||||
* @param array $params type parameters, null by default
|
* @param array $params type parameters, null by default
|
||||||
|
@ -151,11 +151,11 @@ class RecoverpasswordAction extends Action
|
|||||||
$this->element('p', null,
|
$this->element('p', null,
|
||||||
_('If you\'ve forgotten or lost your' .
|
_('If you\'ve forgotten or lost your' .
|
||||||
' password, you can get a new one sent to' .
|
' password, you can get a new one sent to' .
|
||||||
' the email address you have stored ' .
|
' the email address you have stored' .
|
||||||
' in your account.'));
|
' in your account.'));
|
||||||
} else if ($this->mode == 'reset') {
|
} else if ($this->mode == 'reset') {
|
||||||
$this->element('p', null,
|
$this->element('p', null,
|
||||||
_('You\'ve been identified. Enter a ' .
|
_('You\'ve been identified. Enter a' .
|
||||||
' new password below. '));
|
' new password below. '));
|
||||||
}
|
}
|
||||||
$this->elementEnd('div');
|
$this->elementEnd('div');
|
||||||
@ -181,13 +181,21 @@ class RecoverpasswordAction extends Action
|
|||||||
function showRecoverForm()
|
function showRecoverForm()
|
||||||
{
|
{
|
||||||
$this->elementStart('form', array('method' => 'post',
|
$this->elementStart('form', array('method' => 'post',
|
||||||
'id' => 'recoverpassword',
|
'id' => 'form_password_recover',
|
||||||
|
'class' => 'form_settings',
|
||||||
'action' => common_local_url('recoverpassword')));
|
'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->input('nicknameoremail', _('Nickname or email'),
|
||||||
$this->trimmed('nicknameoremail'),
|
$this->trimmed('nicknameoremail'),
|
||||||
_('Your nickname on this server, ' .
|
_('Your nickname on this server, ' .
|
||||||
'or your registered email address.'));
|
'or your registered email address.'));
|
||||||
|
$this->elementEnd('li');
|
||||||
|
$this->elementEnd('ul');
|
||||||
$this->submit('recover', _('Recover'));
|
$this->submit('recover', _('Recover'));
|
||||||
|
$this->elementEnd('fieldset');
|
||||||
$this->elementEnd('form');
|
$this->elementEnd('form');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,14 +221,24 @@ class RecoverpasswordAction extends Action
|
|||||||
function showResetForm()
|
function showResetForm()
|
||||||
{
|
{
|
||||||
$this->elementStart('form', array('method' => 'post',
|
$this->elementStart('form', array('method' => 'post',
|
||||||
'id' => 'recoverpassword',
|
'id' => 'form_password_change',
|
||||||
|
'class' => 'form_settings',
|
||||||
'action' => common_local_url('recoverpassword')));
|
'action' => common_local_url('recoverpassword')));
|
||||||
|
$this->elementStart('fieldset');
|
||||||
|
$this->element('legend', null, _('Password change'));
|
||||||
$this->hidden('token', common_session_token());
|
$this->hidden('token', common_session_token());
|
||||||
|
$this->elementStart('ul', 'form_data');
|
||||||
|
$this->elementStart('li');
|
||||||
$this->password('newpassword', _('New password'),
|
$this->password('newpassword', _('New password'),
|
||||||
_('6 or more characters, and don\'t forget it!'));
|
_('6 or more characters, and don\'t forget it!'));
|
||||||
|
$this->elementEnd('li');
|
||||||
|
$this->elementStart('li');
|
||||||
$this->password('confirm', _('Confirm'),
|
$this->password('confirm', _('Confirm'),
|
||||||
_('Same as password above'));
|
_('Same as password above'));
|
||||||
|
$this->elementEnd('li');
|
||||||
|
$this->elementEnd('ul');
|
||||||
$this->submit('reset', _('Reset'));
|
$this->submit('reset', _('Reset'));
|
||||||
|
$this->elementEnd('fieldset');
|
||||||
$this->elementEnd('form');
|
$this->elementEnd('form');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,45 @@ class RegisterAction extends Action
|
|||||||
|
|
||||||
var $registered = false;
|
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
|
* Title of the page
|
||||||
*
|
*
|
||||||
@ -108,107 +147,109 @@ class RegisterAction extends Action
|
|||||||
|
|
||||||
function tryRegister()
|
function tryRegister()
|
||||||
{
|
{
|
||||||
$token = $this->trimmed('token');
|
if (Event::handle('StartRegistrationTry', array($this))) {
|
||||||
if (!$token || $token != common_session_token()) {
|
$token = $this->trimmed('token');
|
||||||
$this->showForm(_('There was a problem with your session token. '.
|
if (!$token || $token != common_session_token()) {
|
||||||
'Try again, please.'));
|
$this->showForm(_('There was a problem with your session token. '.
|
||||||
return;
|
'Try again, please.'));
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$nickname = $this->trimmed('nickname');
|
$nickname = $this->trimmed('nickname');
|
||||||
$email = $this->trimmed('email');
|
$email = $this->trimmed('email');
|
||||||
$fullname = $this->trimmed('fullname');
|
$fullname = $this->trimmed('fullname');
|
||||||
$homepage = $this->trimmed('homepage');
|
$homepage = $this->trimmed('homepage');
|
||||||
$bio = $this->trimmed('bio');
|
$bio = $this->trimmed('bio');
|
||||||
$location = $this->trimmed('location');
|
$location = $this->trimmed('location');
|
||||||
|
|
||||||
// We don't trim these... whitespace is OK in a password!
|
// We don't trim these... whitespace is OK in a password!
|
||||||
|
$password = $this->arg('password');
|
||||||
|
$confirm = $this->arg('confirm');
|
||||||
|
|
||||||
$password = $this->arg('password');
|
// invitation code, if any
|
||||||
$confirm = $this->arg('confirm');
|
$code = $this->trimmed('code');
|
||||||
|
|
||||||
// invitation code, if any
|
if ($code) {
|
||||||
|
$invite = Invitation::staticGet($code);
|
||||||
|
}
|
||||||
|
|
||||||
$code = $this->trimmed('code');
|
if (common_config('site', 'inviteonly') && !($code && $invite)) {
|
||||||
|
$this->clientError(_('Sorry, only invited people can register.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ($code) {
|
// Input scrubbing
|
||||||
$invite = Invitation::staticGet($code);
|
$nickname = common_canonical_nickname($nickname);
|
||||||
}
|
$email = common_canonical_email($email);
|
||||||
|
|
||||||
if (common_config('site', 'inviteonly') && !($code && $invite)) {
|
if (!$this->boolean('license')) {
|
||||||
$this->clientError(_('Sorry, only invited people can register.'));
|
$this->showForm(_('You can\'t register if you don\'t '.
|
||||||
return;
|
'agree to the license.'));
|
||||||
}
|
} else if ($email && !Validate::email($email, true)) {
|
||||||
|
$this->showForm(_('Not a valid email address.'));
|
||||||
|
} else if (!Validate::string($nickname, array('min_length' => 1,
|
||||||
|
'max_length' => 64,
|
||||||
|
'format' => NICKNAME_FMT))) {
|
||||||
|
$this->showForm(_('Nickname must have only lowercase letters '.
|
||||||
|
'and numbers and no spaces.'));
|
||||||
|
} else if ($this->nicknameExists($nickname)) {
|
||||||
|
$this->showForm(_('Nickname already in use. Try another one.'));
|
||||||
|
} else if (!User::allowed_nickname($nickname)) {
|
||||||
|
$this->showForm(_('Not a valid nickname.'));
|
||||||
|
} else if ($this->emailExists($email)) {
|
||||||
|
$this->showForm(_('Email address already exists.'));
|
||||||
|
} else if (!is_null($homepage) && (strlen($homepage) > 0) &&
|
||||||
|
!Validate::uri($homepage,
|
||||||
|
array('allowed_schemes' =>
|
||||||
|
array('http', 'https')))) {
|
||||||
|
$this->showForm(_('Homepage is not a valid URL.'));
|
||||||
|
return;
|
||||||
|
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
|
||||||
|
$this->showForm(_('Full name is too long (max 255 chars).'));
|
||||||
|
return;
|
||||||
|
} else if (!is_null($bio) && mb_strlen($bio) > 140) {
|
||||||
|
$this->showForm(_('Bio is too long (max 140 chars).'));
|
||||||
|
return;
|
||||||
|
} else if (!is_null($location) && mb_strlen($location) > 255) {
|
||||||
|
$this->showForm(_('Location is too long (max 255 chars).'));
|
||||||
|
return;
|
||||||
|
} else if (strlen($password) < 6) {
|
||||||
|
$this->showForm(_('Password must be 6 or more characters.'));
|
||||||
|
return;
|
||||||
|
} else if ($password != $confirm) {
|
||||||
|
$this->showForm(_('Passwords don\'t match.'));
|
||||||
|
} else if ($user = User::register(array('nickname' => $nickname,
|
||||||
|
'password' => $password,
|
||||||
|
'email' => $email,
|
||||||
|
'fullname' => $fullname,
|
||||||
|
'homepage' => $homepage,
|
||||||
|
'bio' => $bio,
|
||||||
|
'location' => $location,
|
||||||
|
'code' => $code))) {
|
||||||
|
if (!$user) {
|
||||||
|
$this->showForm(_('Invalid username or password.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// success!
|
||||||
|
if (!common_set_user($user)) {
|
||||||
|
$this->serverError(_('Error setting user.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// this is a real login
|
||||||
|
common_real_login(true);
|
||||||
|
if ($this->boolean('rememberme')) {
|
||||||
|
common_debug('Adding rememberme cookie for ' . $nickname);
|
||||||
|
common_rememberme($user);
|
||||||
|
}
|
||||||
|
|
||||||
// Input scrubbing
|
Event::handle('EndRegistrationTry', array($this));
|
||||||
|
|
||||||
$nickname = common_canonical_nickname($nickname);
|
// Re-init language env in case it changed (not yet, but soon)
|
||||||
$email = common_canonical_email($email);
|
common_init_language();
|
||||||
|
$this->showSuccess();
|
||||||
if (!$this->boolean('license')) {
|
} else {
|
||||||
$this->showForm(_('You can\'t register if you don\'t '.
|
|
||||||
'agree to the license.'));
|
|
||||||
} else if ($email && !Validate::email($email, true)) {
|
|
||||||
$this->showForm(_('Not a valid email address.'));
|
|
||||||
} else if (!Validate::string($nickname, array('min_length' => 1,
|
|
||||||
'max_length' => 64,
|
|
||||||
'format' => NICKNAME_FMT))) {
|
|
||||||
$this->showForm(_('Nickname must have only lowercase letters '.
|
|
||||||
'and numbers and no spaces.'));
|
|
||||||
} else if ($this->nicknameExists($nickname)) {
|
|
||||||
$this->showForm(_('Nickname already in use. Try another one.'));
|
|
||||||
} else if (!User::allowed_nickname($nickname)) {
|
|
||||||
$this->showForm(_('Not a valid nickname.'));
|
|
||||||
} else if ($this->emailExists($email)) {
|
|
||||||
$this->showForm(_('Email address already exists.'));
|
|
||||||
} else if (!is_null($homepage) && (strlen($homepage) > 0) &&
|
|
||||||
!Validate::uri($homepage,
|
|
||||||
array('allowed_schemes' =>
|
|
||||||
array('http', 'https')))) {
|
|
||||||
$this->showForm(_('Homepage is not a valid URL.'));
|
|
||||||
return;
|
|
||||||
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
|
|
||||||
$this->showForm(_('Full name is too long (max 255 chars).'));
|
|
||||||
return;
|
|
||||||
} else if (!is_null($bio) && mb_strlen($bio) > 140) {
|
|
||||||
$this->showForm(_('Bio is too long (max 140 chars).'));
|
|
||||||
return;
|
|
||||||
} else if (!is_null($location) && mb_strlen($location) > 255) {
|
|
||||||
$this->showForm(_('Location is too long (max 255 chars).'));
|
|
||||||
return;
|
|
||||||
} else if (strlen($password) < 6) {
|
|
||||||
$this->showForm(_('Password must be 6 or more characters.'));
|
|
||||||
return;
|
|
||||||
} else if ($password != $confirm) {
|
|
||||||
$this->showForm(_('Passwords don\'t match.'));
|
|
||||||
} else if ($user = User::register(array('nickname' => $nickname,
|
|
||||||
'password' => $password,
|
|
||||||
'email' => $email,
|
|
||||||
'fullname' => $fullname,
|
|
||||||
'homepage' => $homepage,
|
|
||||||
'bio' => $bio,
|
|
||||||
'location' => $location,
|
|
||||||
'code' => $code))) {
|
|
||||||
if (!$user) {
|
|
||||||
$this->showForm(_('Invalid username or password.'));
|
$this->showForm(_('Invalid username or password.'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// success!
|
|
||||||
if (!common_set_user($user)) {
|
|
||||||
$this->serverError(_('Error setting user.'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// this is a real login
|
|
||||||
common_real_login(true);
|
|
||||||
if ($this->boolean('rememberme')) {
|
|
||||||
common_debug('Adding rememberme cookie for ' . $nickname);
|
|
||||||
common_rememberme($user);
|
|
||||||
}
|
|
||||||
// Re-init language env in case it changed (not yet, but soon)
|
|
||||||
common_init_language();
|
|
||||||
$this->showSuccess();
|
|
||||||
} else {
|
|
||||||
$this->showForm(_('Invalid username or password.'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,22 +291,24 @@ class RegisterAction extends Action
|
|||||||
|
|
||||||
// overrrided to add entry-title class
|
// overrrided to add entry-title class
|
||||||
function showPageTitle() {
|
function showPageTitle() {
|
||||||
$this->element('h1', array('class' => 'entry-title'), $this->title());
|
if (Event::handle('StartShowPageTitle', array($this))) {
|
||||||
|
$this->element('h1', array('class' => 'entry-title'), $this->title());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// overrided to add hentry, and content-inner class
|
// overrided to add hentry, and content-inner class
|
||||||
function showContentBlock()
|
function showContentBlock()
|
||||||
{
|
{
|
||||||
$this->elementStart('div', array('id' => 'content', 'class' => 'hentry'));
|
$this->elementStart('div', array('id' => 'content', 'class' => 'hentry'));
|
||||||
$this->showPageTitle();
|
$this->showPageTitle();
|
||||||
$this->showPageNoticeBlock();
|
$this->showPageNoticeBlock();
|
||||||
$this->elementStart('div', array('id' => 'content_inner',
|
$this->elementStart('div', array('id' => 'content_inner',
|
||||||
'class' => 'entry-content'));
|
'class' => 'entry-content'));
|
||||||
// show the actual content (forms, lists, whatever)
|
// show the actual content (forms, lists, whatever)
|
||||||
$this->showContent();
|
$this->showContent();
|
||||||
$this->elementEnd('div');
|
$this->elementEnd('div');
|
||||||
$this->elementEnd('div');
|
$this->elementEnd('div');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instructions or a notice for the page
|
* Instructions or a notice for the page
|
||||||
@ -341,6 +384,8 @@ class RegisterAction extends Action
|
|||||||
{
|
{
|
||||||
$code = $this->trimmed('code');
|
$code = $this->trimmed('code');
|
||||||
|
|
||||||
|
$invite = null;
|
||||||
|
|
||||||
if ($code) {
|
if ($code) {
|
||||||
$invite = Invitation::staticGet($code);
|
$invite = Invitation::staticGet($code);
|
||||||
}
|
}
|
||||||
@ -358,82 +403,85 @@ class RegisterAction extends Action
|
|||||||
$this->element('legend', null, 'Account settings');
|
$this->element('legend', null, 'Account settings');
|
||||||
$this->hidden('token', common_session_token());
|
$this->hidden('token', common_session_token());
|
||||||
|
|
||||||
if ($code) {
|
if ($this->code) {
|
||||||
$this->hidden('code', $code);
|
$this->hidden('code', $this->code);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->elementStart('ul', 'form_data');
|
$this->elementStart('ul', 'form_data');
|
||||||
$this->elementStart('li');
|
if (Event::handle('StartRegistrationFormData', array($this))) {
|
||||||
$this->input('nickname', _('Nickname'), $this->trimmed('nickname'),
|
$this->elementStart('li');
|
||||||
_('1-64 lowercase letters or numbers, '.
|
$this->input('nickname', _('Nickname'), $this->trimmed('nickname'),
|
||||||
'no punctuation or spaces. Required.'));
|
_('1-64 lowercase letters or numbers, '.
|
||||||
$this->elementEnd('li');
|
'no punctuation or spaces. Required.'));
|
||||||
$this->elementStart('li');
|
$this->elementEnd('li');
|
||||||
$this->password('password', _('Password'),
|
$this->elementStart('li');
|
||||||
_('6 or more characters. Required.'));
|
$this->password('password', _('Password'),
|
||||||
$this->elementEnd('li');
|
_('6 or more characters. Required.'));
|
||||||
$this->elementStart('li');
|
$this->elementEnd('li');
|
||||||
$this->password('confirm', _('Confirm'),
|
$this->elementStart('li');
|
||||||
_('Same as password above. Required.'));
|
$this->password('confirm', _('Confirm'),
|
||||||
$this->elementEnd('li');
|
_('Same as password above. Required.'));
|
||||||
$this->elementStart('li');
|
$this->elementEnd('li');
|
||||||
if ($invite && $invite->address_type == 'email') {
|
$this->elementStart('li');
|
||||||
$this->input('email', _('Email'), $invite->address,
|
if ($this->invite && $this->invite->address_type == 'email') {
|
||||||
_('Used only for updates, announcements, '.
|
$this->input('email', _('Email'), $this->invite->address,
|
||||||
'and password recovery'));
|
_('Used only for updates, announcements, '.
|
||||||
} else {
|
'and password recovery'));
|
||||||
$this->input('email', _('Email'), $this->trimmed('email'),
|
} else {
|
||||||
_('Used only for updates, announcements, '.
|
$this->input('email', _('Email'), $this->trimmed('email'),
|
||||||
'and password recovery'));
|
_('Used only for updates, announcements, '.
|
||||||
|
'and password recovery'));
|
||||||
|
}
|
||||||
|
$this->elementEnd('li');
|
||||||
|
$this->elementStart('li');
|
||||||
|
$this->input('fullname', _('Full name'),
|
||||||
|
$this->trimmed('fullname'),
|
||||||
|
_('Longer name, preferably your "real" name'));
|
||||||
|
$this->elementEnd('li');
|
||||||
|
$this->elementStart('li');
|
||||||
|
$this->input('homepage', _('Homepage'),
|
||||||
|
$this->trimmed('homepage'),
|
||||||
|
_('URL of your homepage, blog, '.
|
||||||
|
'or profile on another site'));
|
||||||
|
$this->elementEnd('li');
|
||||||
|
$this->elementStart('li');
|
||||||
|
$this->textarea('bio', _('Bio'),
|
||||||
|
$this->trimmed('bio'),
|
||||||
|
_('Describe yourself and your '.
|
||||||
|
'interests in 140 chars'));
|
||||||
|
$this->elementEnd('li');
|
||||||
|
$this->elementStart('li');
|
||||||
|
$this->input('location', _('Location'),
|
||||||
|
$this->trimmed('location'),
|
||||||
|
_('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'),
|
||||||
|
_('Automatically login in the future; '.
|
||||||
|
'not for shared computers!'));
|
||||||
|
$this->elementEnd('li');
|
||||||
|
$attrs = array('type' => 'checkbox',
|
||||||
|
'id' => 'license',
|
||||||
|
'class' => 'checkbox',
|
||||||
|
'name' => 'license',
|
||||||
|
'value' => 'true');
|
||||||
|
if ($this->boolean('license')) {
|
||||||
|
$attrs['checked'] = 'checked';
|
||||||
|
}
|
||||||
|
$this->elementStart('li');
|
||||||
|
$this->element('input', $attrs);
|
||||||
|
$this->elementStart('label', array('class' => 'checkbox', 'for' => 'license'));
|
||||||
|
$this->text(_('My text and files are available under '));
|
||||||
|
$this->element('a', array('href' => common_config('license', 'url')),
|
||||||
|
common_config('license', 'title'), _("Creative Commons Attribution 3.0"));
|
||||||
|
$this->text(_(' except this private data: password, '.
|
||||||
|
'email address, IM address, and phone number.'));
|
||||||
|
$this->elementEnd('label');
|
||||||
|
$this->elementEnd('li');
|
||||||
}
|
}
|
||||||
$this->elementEnd('li');
|
|
||||||
$this->elementStart('li');
|
|
||||||
$this->input('fullname', _('Full name'),
|
|
||||||
$this->trimmed('fullname'),
|
|
||||||
_('Longer name, preferably your "real" name'));
|
|
||||||
$this->elementEnd('li');
|
|
||||||
$this->elementStart('li');
|
|
||||||
$this->input('homepage', _('Homepage'),
|
|
||||||
$this->trimmed('homepage'),
|
|
||||||
_('URL of your homepage, blog, '.
|
|
||||||
'or profile on another site'));
|
|
||||||
$this->elementEnd('li');
|
|
||||||
$this->elementStart('li');
|
|
||||||
$this->textarea('bio', _('Bio'),
|
|
||||||
$this->trimmed('bio'),
|
|
||||||
_('Describe yourself and your '.
|
|
||||||
'interests in 140 chars'));
|
|
||||||
$this->elementEnd('li');
|
|
||||||
$this->elementStart('li');
|
|
||||||
$this->input('location', _('Location'),
|
|
||||||
$this->trimmed('location'),
|
|
||||||
_('Where you are, like "City, '.
|
|
||||||
'State (or Region), Country"'));
|
|
||||||
$this->elementEnd('li');
|
|
||||||
$this->elementStart('li', array('id' => 'settings_rememberme'));
|
|
||||||
$this->checkbox('rememberme', _('Remember me'),
|
|
||||||
$this->boolean('rememberme'),
|
|
||||||
_('Automatically login in the future; '.
|
|
||||||
'not for shared computers!'));
|
|
||||||
$this->elementEnd('li');
|
|
||||||
$attrs = array('type' => 'checkbox',
|
|
||||||
'id' => 'license',
|
|
||||||
'class' => 'checkbox',
|
|
||||||
'name' => 'license',
|
|
||||||
'value' => 'true');
|
|
||||||
if ($this->boolean('license')) {
|
|
||||||
$attrs['checked'] = 'checked';
|
|
||||||
}
|
|
||||||
$this->elementStart('li');
|
|
||||||
$this->element('input', $attrs);
|
|
||||||
$this->elementStart('label', array('class' => 'checkbox', 'for' => 'license'));
|
|
||||||
$this->text(_('My text and files are available under '));
|
|
||||||
$this->element('a', array('href' => common_config('license', 'url')),
|
|
||||||
common_config('license', 'title'), _("Creative Commons Attribution 3.0"));
|
|
||||||
$this->text(_(' except this private data: password, '.
|
|
||||||
'email address, IM address, and phone number.'));
|
|
||||||
$this->elementEnd('label');
|
|
||||||
$this->elementEnd('li');
|
|
||||||
$this->elementEnd('ul');
|
$this->elementEnd('ul');
|
||||||
$this->submit('submit', _('Register'));
|
$this->submit('submit', _('Register'));
|
||||||
$this->elementEnd('fieldset');
|
$this->elementEnd('fieldset');
|
||||||
@ -515,3 +563,4 @@ class RegisterAction extends Action
|
|||||||
$nav->show();
|
$nav->show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,9 +97,9 @@ class RemotesubscribeAction extends Action
|
|||||||
'class' => 'form_settings',
|
'class' => 'form_settings',
|
||||||
'action' => common_local_url('remotesubscribe')));
|
'action' => common_local_url('remotesubscribe')));
|
||||||
$this->elementStart('fieldset');
|
$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->hidden('token', common_session_token());
|
||||||
|
|
||||||
$this->elementStart('ul', 'form_data');
|
$this->elementStart('ul', 'form_data');
|
||||||
$this->elementStart('li');
|
$this->elementStart('li');
|
||||||
$this->input('nickname', _('User nickname'), $this->nickname,
|
$this->input('nickname', _('User nickname'), $this->nickname,
|
||||||
@ -321,8 +321,7 @@ class RemotesubscribeAction extends Action
|
|||||||
|
|
||||||
$result = $fetcher->post($req->get_normalized_http_url(),
|
$result = $fetcher->post($req->get_normalized_http_url(),
|
||||||
$req->to_postdata(),
|
$req->to_postdata(),
|
||||||
array('User-Agent' => 'Laconica/' . LACONICA_VERSION));
|
array('User-Agent: Laconica/' . LACONICA_VERSION));
|
||||||
|
|
||||||
if ($result->status != 200) {
|
if ($result->status != 200) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -334,8 +333,6 @@ class RemotesubscribeAction extends Action
|
|||||||
|
|
||||||
function requestAuthorization($user, $omb, $token, $secret)
|
function requestAuthorization($user, $omb, $token, $secret)
|
||||||
{
|
{
|
||||||
global $config; # for license URL
|
|
||||||
|
|
||||||
$con = omb_oauth_consumer();
|
$con = omb_oauth_consumer();
|
||||||
$tok = new OAuthToken($token, $secret);
|
$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', $user->uri);
|
||||||
$req->set_parameter('omb_listenee_profile', common_profile_url($user->nickname));
|
$req->set_parameter('omb_listenee_profile', common_profile_url($user->nickname));
|
||||||
$req->set_parameter('omb_listenee_nickname', $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();
|
$profile = $user->getProfile();
|
||||||
if (!$profile) {
|
if (!$profile) {
|
||||||
@ -368,16 +365,16 @@ class RemotesubscribeAction extends Action
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($profile->fullname) {
|
if (!is_null($profile->fullname)) {
|
||||||
$req->set_parameter('omb_listenee_fullname', $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);
|
$req->set_parameter('omb_listenee_homepage', $profile->homepage);
|
||||||
}
|
}
|
||||||
if ($profile->bio) {
|
if (!is_null($profile->bio)) {
|
||||||
$req->set_parameter('omb_listenee_bio', $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);
|
$req->set_parameter('omb_listenee_location', $profile->location);
|
||||||
}
|
}
|
||||||
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||||
@ -410,7 +407,7 @@ class RemotesubscribeAction extends Action
|
|||||||
|
|
||||||
# Redirect to authorization service
|
# Redirect to authorization service
|
||||||
|
|
||||||
common_redirect($req->to_url());
|
common_redirect($req->to_url(), 303);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,6 +138,17 @@ class RepliesAction extends Action
|
|||||||
return array(new Feed(Feed::RSS1, $rssurl, $rsstitle));
|
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
|
* show the personal group nav
|
||||||
*
|
*
|
||||||
@ -166,13 +177,37 @@ class RepliesAction extends Action
|
|||||||
$nl = new NoticeList($notice, $this);
|
$nl = new NoticeList($notice, $this);
|
||||||
|
|
||||||
$cnt = $nl->show();
|
$cnt = $nl->show();
|
||||||
|
if (0 === $cnt) {
|
||||||
|
$this->showEmptyListMessage();
|
||||||
|
}
|
||||||
|
|
||||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||||
$this->page, 'replies',
|
$this->page, 'replies',
|
||||||
array('nickname' => $this->user->nickname));
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ class RepliesrssAction extends Rss10Action
|
|||||||
return ($avatar) ? $avatar->url : null;
|
return ($avatar) ? $avatar->url : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ class RequesttokenAction extends Action
|
|||||||
*
|
*
|
||||||
* @return boolean false
|
* @return boolean false
|
||||||
*/
|
*/
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ class RequesttokenAction extends Action
|
|||||||
parent::handle($args);
|
parent::handle($args);
|
||||||
try {
|
try {
|
||||||
common_remove_magic_from_request();
|
common_remove_magic_from_request();
|
||||||
$req = OAuthRequest::from_request();
|
$req = OAuthRequest::from_request('POST', common_local_url('requesttoken'));
|
||||||
$server = omb_oauth_server();
|
$server = omb_oauth_server();
|
||||||
$token = $server->fetch_request_token($req);
|
$token = $server->fetch_request_token($req);
|
||||||
print $token;
|
print $token;
|
||||||
|
@ -58,7 +58,7 @@ class ShowfavoritesAction extends Action
|
|||||||
* @return boolean true
|
* @return boolean true
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -74,9 +74,9 @@ class ShowfavoritesAction extends Action
|
|||||||
function title()
|
function title()
|
||||||
{
|
{
|
||||||
if ($this->page == 1) {
|
if ($this->page == 1) {
|
||||||
return sprintf(_("%s favorite notices"), $this->user->nickname);
|
return sprintf(_("%s's favorite notices"), $this->user->nickname);
|
||||||
} else {
|
} else {
|
||||||
return sprintf(_("%s favorite notices, page %d"),
|
return sprintf(_("%s's favorite notices, page %d"),
|
||||||
$this->user->nickname,
|
$this->user->nickname,
|
||||||
$this->page);
|
$this->page);
|
||||||
}
|
}
|
||||||
@ -150,6 +150,18 @@ class ShowfavoritesAction extends Action
|
|||||||
return array(new Feed(Feed::RSS1, $feedurl, $feedtitle));
|
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
|
* show the personal group nav
|
||||||
*
|
*
|
||||||
@ -162,6 +174,25 @@ class ShowfavoritesAction extends Action
|
|||||||
$nav->show();
|
$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
|
* Show the content
|
||||||
*
|
*
|
||||||
@ -183,9 +214,17 @@ class ShowfavoritesAction extends Action
|
|||||||
$nl = new NoticeList($notice, $this);
|
$nl = new NoticeList($notice, $this);
|
||||||
|
|
||||||
$cnt = $nl->show();
|
$cnt = $nl->show();
|
||||||
|
if (0 == $cnt) {
|
||||||
|
$this->showEmptyListMessage();
|
||||||
|
}
|
||||||
|
|
||||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||||
$this->page, 'showfavorites',
|
$this->page, 'showfavorites',
|
||||||
array('nickname' => $this->user->nickname));
|
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/noticelist.php';
|
||||||
require_once INSTALLDIR.'/lib/feedlist.php';
|
require_once INSTALLDIR.'/lib/feedlist.php';
|
||||||
|
|
||||||
define('MEMBERS_PER_SECTION', 81);
|
define('MEMBERS_PER_SECTION', 27);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Group main page
|
* Group main page
|
||||||
@ -60,7 +60,7 @@ class ShowgroupAction extends Action
|
|||||||
* @return boolean true
|
* @return boolean true
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -73,11 +73,17 @@ class ShowgroupAction extends Action
|
|||||||
|
|
||||||
function title()
|
function title()
|
||||||
{
|
{
|
||||||
|
if (!empty($this->group->fullname)) {
|
||||||
|
$base = $this->group->fullname . ' (' . $this->group->nickname . ')';
|
||||||
|
} else {
|
||||||
|
$base = $this->group->nickname;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->page == 1) {
|
if ($this->page == 1) {
|
||||||
return sprintf(_("%s group"), $this->group->nickname);
|
return sprintf(_("%s group"), $base);
|
||||||
} else {
|
} else {
|
||||||
return sprintf(_("%s group, page %d"),
|
return sprintf(_("%s group, page %d"),
|
||||||
$this->group->nickname,
|
$base,
|
||||||
$this->page);
|
$this->page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,10 +281,8 @@ class ShowgroupAction extends Action
|
|||||||
$cur = common_current_user();
|
$cur = common_current_user();
|
||||||
if ($cur) {
|
if ($cur) {
|
||||||
if ($cur->isMember($this->group)) {
|
if ($cur->isMember($this->group)) {
|
||||||
if (!$cur->isAdmin($this->group)) {
|
$lf = new LeaveForm($this, $this->group);
|
||||||
$lf = new LeaveForm($this, $this->group);
|
$lf->show();
|
||||||
$lf->show();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
$jf = new JoinForm($this, $this->group);
|
$jf = new JoinForm($this, $this->group);
|
||||||
$jf->show();
|
$jf->show();
|
||||||
@ -307,6 +311,17 @@ class ShowgroupAction extends Action
|
|||||||
$this->group->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, 'showgroup', array('nickname' => $this->group->nickname));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill in the sidebar.
|
* Fill in the sidebar.
|
||||||
*
|
*
|
||||||
@ -346,7 +361,7 @@ class ShowgroupAction extends Action
|
|||||||
$this->element('p', null, _('(None)'));
|
$this->element('p', null, _('(None)'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($cnt == MEMBERS_PER_SECTION) {
|
if ($cnt > MEMBERS_PER_SECTION) {
|
||||||
$this->element('a', array('href' => common_local_url('groupmembers',
|
$this->element('a', array('href' => common_local_url('groupmembers',
|
||||||
array('nickname' => $this->group->nickname))),
|
array('nickname' => $this->group->nickname))),
|
||||||
_('All members'));
|
_('All members'));
|
||||||
@ -392,11 +407,18 @@ class ShowgroupAction extends Action
|
|||||||
|
|
||||||
function showAnonymousMessage()
|
function showAnonymousMessage()
|
||||||
{
|
{
|
||||||
$m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
if (!(common_config('site','closed') || common_config('site','inviteonly'))) {
|
||||||
'based on the Free Software [Laconica](http://laconi.ca/) tool. Its members share ' .
|
$m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
||||||
'short messages about their life and interests. '.
|
'based on the Free Software [Laconica](http://laconi.ca/) tool. Its members share ' .
|
||||||
'[Join now](%%%%action.register%%%%) to become part of this group and many more! ([Read more](%%%%doc.help%%%%))'),
|
'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);
|
$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->elementStart('div', array('id' => 'anon_notice'));
|
||||||
$this->raw(common_markup_to_html($m));
|
$this->raw(common_markup_to_html($m));
|
||||||
$this->elementEnd('div');
|
$this->elementEnd('div');
|
||||||
|
@ -177,7 +177,7 @@ class ShowmessageAction extends MailboxAction
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ class ShownoticeAction extends Action
|
|||||||
* @return boolean true
|
* @return boolean true
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -177,10 +177,17 @@ class ShownoticeAction extends Action
|
|||||||
{
|
{
|
||||||
parent::handle($args);
|
parent::handle($args);
|
||||||
|
|
||||||
$this->showPage();
|
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
|
* Don't show local navigation
|
||||||
*
|
*
|
||||||
@ -191,7 +198,6 @@ class ShownoticeAction extends Action
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill the content area of the page
|
* Fill the content area of the page
|
||||||
*
|
*
|
||||||
@ -208,8 +214,6 @@ class ShownoticeAction extends Action
|
|||||||
$this->elementEnd('ul');
|
$this->elementEnd('ul');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Don't show page notice
|
* Don't show page notice
|
||||||
*
|
*
|
||||||
@ -220,7 +224,6 @@ class ShownoticeAction extends Action
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Don't show aside
|
* Don't show aside
|
||||||
*
|
*
|
||||||
@ -230,7 +233,6 @@ class ShownoticeAction extends Action
|
|||||||
function showAside() {
|
function showAside() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extra <head> content
|
* Extra <head> content
|
||||||
*
|
*
|
||||||
|
@ -54,67 +54,33 @@ require_once INSTALLDIR.'/lib/feedlist.php';
|
|||||||
* @link http://laconi.ca/
|
* @link http://laconi.ca/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ShowstreamAction extends Action
|
class ShowstreamAction extends ProfileAction
|
||||||
{
|
{
|
||||||
var $user = null;
|
function isReadOnly($args)
|
||||||
var $page = null;
|
|
||||||
var $profile = null;
|
|
||||||
|
|
||||||
function isReadOnly()
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function title()
|
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) {
|
if ($this->page == 1) {
|
||||||
return $this->user->nickname;
|
return $base;
|
||||||
} else {
|
} else {
|
||||||
return sprintf(_("%s, page %d"),
|
return sprintf(_("%s, page %d"),
|
||||||
$this->user->nickname,
|
$base,
|
||||||
$this->page);
|
$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)
|
function handle($args)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -140,16 +106,6 @@ class ShowstreamAction extends Action
|
|||||||
$nav->show();
|
$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()
|
function showPageNoticeBlock()
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -157,6 +113,15 @@ class ShowstreamAction extends Action
|
|||||||
|
|
||||||
function getFeeds()
|
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,
|
return array(new Feed(Feed::RSS1,
|
||||||
common_local_url('userrss',
|
common_local_url('userrss',
|
||||||
array('nickname' => $this->user->nickname)),
|
array('nickname' => $this->user->nickname)),
|
||||||
@ -182,6 +147,17 @@ class ShowstreamAction extends Action
|
|||||||
sprintf(_('FOAF for %s'), $this->user->nickname)));
|
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()
|
function extraHead()
|
||||||
{
|
{
|
||||||
// for remote subscriptions etc.
|
// for remote subscriptions etc.
|
||||||
@ -292,11 +268,11 @@ class ShowstreamAction extends Action
|
|||||||
$this->elementStart('ul', 'tags xoxo');
|
$this->elementStart('ul', 'tags xoxo');
|
||||||
foreach ($tags as $tag) {
|
foreach ($tags as $tag) {
|
||||||
$this->elementStart('li');
|
$this->elementStart('li');
|
||||||
$this->element('span', 'mark_hash', '#');
|
// Avoid space by using raw output.
|
||||||
$this->element('a', array('rel' => 'tag',
|
$pt = '<span class="mark_hash">#</span><a rel="tag" href="' .
|
||||||
'href' => common_local_url('peopletag',
|
common_local_url('peopletag', array('tag' => $tag)) .
|
||||||
array('tag' => $tag))),
|
'">' . $tag . '</a>';
|
||||||
$tag);
|
$this->raw($pt);
|
||||||
$this->elementEnd('li');
|
$this->elementEnd('li');
|
||||||
}
|
}
|
||||||
$this->elementEnd('ul');
|
$this->elementEnd('ul');
|
||||||
@ -376,178 +352,66 @@ class ShowstreamAction extends Action
|
|||||||
_('Subscribe'));
|
_('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()
|
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);
|
$pnl = new ProfileNoticeList($notice, $this);
|
||||||
$cnt = $pnl->show();
|
$cnt = $pnl->show();
|
||||||
|
if (0 == $cnt) {
|
||||||
|
$this->showEmptyListMessage();
|
||||||
|
}
|
||||||
|
|
||||||
$this->pagination($this->page>1, $cnt>NOTICES_PER_PAGE, $this->page,
|
$this->pagination($this->page>1, $cnt>NOTICES_PER_PAGE, $this->page,
|
||||||
'showstream', array('nickname' => $this->user->nickname));
|
'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()
|
function showAnonymousMessage()
|
||||||
{
|
{
|
||||||
$m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
if (!(common_config('site','closed') || common_config('site','inviteonly'))) {
|
||||||
'based on the Free Software [Laconica](http://laconi.ca/) tool. ' .
|
$m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
|
||||||
'[Join now](%%%%action.register%%%%) to follow **%s**\'s notices and many more! ([Read more](%%%%doc.help%%%%))'),
|
'based on the Free Software [Laconica](http://laconi.ca/) tool. ' .
|
||||||
$this->user->nickname, $this->user->nickname);
|
'[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->elementStart('div', array('id' => 'anon_notice'));
|
||||||
$this->raw(common_markup_to_html($m));
|
$this->raw(common_markup_to_html($m));
|
||||||
$this->elementEnd('div');
|
$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!
|
// 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',
|
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',
|
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');
|
$this->elementEnd('html');
|
||||||
} else {
|
} else {
|
||||||
common_redirect(common_local_url('subscriptions', array('nickname' =>
|
common_redirect(common_local_url('subscriptions', array('nickname' =>
|
||||||
$user->nickname)));
|
$user->nickname)),
|
||||||
|
303);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,9 @@ class SubscribersAction extends GalleryAction
|
|||||||
if ($subscribers) {
|
if ($subscribers) {
|
||||||
$subscribers_list = new SubscribersList($subscribers, $this->user, $this);
|
$subscribers_list = new SubscribersList($subscribers, $this->user, $this);
|
||||||
$cnt = $subscribers_list->show();
|
$cnt = $subscribers_list->show();
|
||||||
|
if (0 == $cnt) {
|
||||||
|
$this->showEmptyListMessage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$subscribers->free();
|
$subscribers->free();
|
||||||
@ -96,6 +99,35 @@ class SubscribersAction extends GalleryAction
|
|||||||
$this->page, 'subscribers',
|
$this->page, 'subscribers',
|
||||||
array('nickname' => $this->user->nickname));
|
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
|
class SubscribersList extends ProfileList
|
||||||
@ -108,7 +140,7 @@ class SubscribersList extends ProfileList
|
|||||||
$bf->show();
|
$bf->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,9 @@ class SubscriptionsAction extends GalleryAction
|
|||||||
if ($subscriptions) {
|
if ($subscriptions) {
|
||||||
$subscriptions_list = new SubscriptionsList($subscriptions, $this->user, $this);
|
$subscriptions_list = new SubscriptionsList($subscriptions, $this->user, $this);
|
||||||
$cnt = $subscriptions_list->show();
|
$cnt = $subscriptions_list->show();
|
||||||
|
if (0 == $cnt) {
|
||||||
|
$this->showEmptyListMessage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$subscriptions->free();
|
$subscriptions->free();
|
||||||
@ -103,6 +106,35 @@ class SubscriptionsAction extends GalleryAction
|
|||||||
$this->page, 'subscriptions',
|
$this->page, 'subscriptions',
|
||||||
array('nickname' => $this->user->nickname));
|
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
|
class SubscriptionsList extends ProfileList
|
||||||
@ -117,7 +149,7 @@ class SubscriptionsList extends ProfileList
|
|||||||
|
|
||||||
$this->out->elementStart('form', array('id' => 'subedit-' . $profile->id,
|
$this->out->elementStart('form', array('id' => 'subedit-' . $profile->id,
|
||||||
'method' => 'post',
|
'method' => 'post',
|
||||||
'class' => 'form_subcription_edit',
|
'class' => 'form_subscription_edit',
|
||||||
'action' => common_local_url('subedit')));
|
'action' => common_local_url('subedit')));
|
||||||
$this->out->hidden('token', common_session_token());
|
$this->out->hidden('token', common_session_token());
|
||||||
$this->out->hidden('profile', $profile->id);
|
$this->out->hidden('profile', $profile->id);
|
||||||
|
@ -45,7 +45,7 @@ class SupAction extends Action
|
|||||||
function availablePeriods()
|
function availablePeriods()
|
||||||
{
|
{
|
||||||
static $periods = array(86400, 43200, 21600, 7200,
|
static $periods = array(86400, 43200, 21600, 7200,
|
||||||
3600, 1800, 600, 300, 120,
|
3600, 1800, 600, 300, 120,
|
||||||
60, 30, 15);
|
60, 30, 15);
|
||||||
$available = array();
|
$available = array();
|
||||||
foreach ($periods as $period) {
|
foreach ($periods as $period) {
|
||||||
@ -65,7 +65,9 @@ class SupAction extends Action
|
|||||||
|
|
||||||
$notice->query('SELECT profile_id, max(id) AS max_id ' .
|
$notice->query('SELECT profile_id, max(id) AS max_id ' .
|
||||||
'FROM notice ' .
|
'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');
|
'GROUP BY profile_id');
|
||||||
|
|
||||||
$updates = array();
|
$updates = array();
|
||||||
@ -77,7 +79,7 @@ class SupAction extends Action
|
|||||||
return $updates;
|
return $updates;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,9 @@ class TagAction extends Action
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->tag != $taginput) {
|
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;
|
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
||||||
@ -43,6 +45,14 @@ class TagAction extends Action
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showSections()
|
||||||
|
{
|
||||||
|
$pop = new PopularNoticeSection($this);
|
||||||
|
$pop->show();
|
||||||
|
$freqatt = new FrequentAttachmentSection($this);
|
||||||
|
$freqatt->show();
|
||||||
|
}
|
||||||
|
|
||||||
function title()
|
function title()
|
||||||
{
|
{
|
||||||
if ($this->page == 1) {
|
if ($this->page == 1) {
|
||||||
@ -68,6 +78,17 @@ class TagAction extends Action
|
|||||||
sprintf(_('Feed for tag %s'), $this->tag)));
|
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()
|
function showPageNotice()
|
||||||
{
|
{
|
||||||
return sprintf(_('Messages tagged "%s", most recent first'), $this->tag);
|
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->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||||
$this->page, 'tag', array('tag' => $this->tag));
|
$this->page, 'tag', array('tag' => $this->tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,8 @@ class TagotherAction extends Action
|
|||||||
'id' => 'form_tag_user',
|
'id' => 'form_tag_user',
|
||||||
'class' => 'form_settings',
|
'class' => 'form_settings',
|
||||||
'name' => 'tagother',
|
'name' => 'tagother',
|
||||||
'action' => $this->selfUrl()));
|
'action' => common_local_url('tagother', array('id' => $this->profile->id))));
|
||||||
|
|
||||||
$this->elementStart('fieldset');
|
$this->elementStart('fieldset');
|
||||||
$this->element('legend', null, _('Tag user'));
|
$this->element('legend', null, _('Tag user'));
|
||||||
$this->hidden('token', common_session_token());
|
$this->hidden('token', common_session_token());
|
||||||
@ -220,7 +221,8 @@ class TagotherAction extends Action
|
|||||||
$this->elementEnd('html');
|
$this->elementEnd('html');
|
||||||
} else {
|
} else {
|
||||||
common_redirect(common_local_url($action, array('nickname' =>
|
common_redirect(common_local_url($action, array('nickname' =>
|
||||||
$user->nickname)));
|
$user->nickname)),
|
||||||
|
303);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ class TagrssAction extends Rss10Action
|
|||||||
return $c;
|
return $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -23,23 +23,24 @@ require_once(INSTALLDIR.'/lib/twitterapi.php');
|
|||||||
|
|
||||||
class TwitapiaccountAction extends TwitterapiAction
|
class TwitapiaccountAction extends TwitterapiAction
|
||||||
{
|
{
|
||||||
|
function verify_credentials($args, $apidata)
|
||||||
function verify_credentials($args, $apidata)
|
|
||||||
{
|
{
|
||||||
|
parent::handle($args);
|
||||||
|
|
||||||
if ($apidata['content-type'] == 'xml') {
|
switch ($apidata['content-type']) {
|
||||||
header('Content-Type: application/xml; charset=utf-8');
|
case 'xml':
|
||||||
print '<authorized>true</authorized>';
|
case 'json':
|
||||||
} elseif ($apidata['content-type'] == 'json') {
|
$action_obj = new TwitapiusersAction();
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
$action_obj->prepare($args);
|
||||||
print '{"authorized":true}';
|
call_user_func(array($action_obj, 'show'), $args, $apidata);
|
||||||
} else {
|
break;
|
||||||
common_user_error(_('API method not found!'), $code=404);
|
default:
|
||||||
}
|
header('Content-Type: text/html; charset=utf-8');
|
||||||
|
print 'Authorized';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
function end_session($args, $apidata)
|
||||||
|
|
||||||
function end_session($args, $apidata)
|
|
||||||
{
|
{
|
||||||
parent::handle($args);
|
parent::handle($args);
|
||||||
$this->serverError(_('API method under construction.'), $code=501);
|
$this->serverError(_('API method under construction.'), $code=501);
|
||||||
|
@ -38,7 +38,6 @@ class Twitapidirect_messagesAction extends TwitterapiAction
|
|||||||
|
|
||||||
function show_messages($args, $apidata, $type)
|
function show_messages($args, $apidata, $type)
|
||||||
{
|
{
|
||||||
|
|
||||||
$user = $apidata['user'];
|
$user = $apidata['user'];
|
||||||
|
|
||||||
$count = $this->arg('count');
|
$count = $this->arg('count');
|
||||||
@ -102,7 +101,17 @@ class Twitapidirect_messagesAction extends TwitterapiAction
|
|||||||
$this->show_rss_dmsgs($message, $title, $link, $subtitle);
|
$this->show_rss_dmsgs($message, $title, $link, $subtitle);
|
||||||
break;
|
break;
|
||||||
case 'atom':
|
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;
|
break;
|
||||||
case 'json':
|
case 'json':
|
||||||
$this->show_json_dmsgs($message);
|
$this->show_json_dmsgs($message);
|
||||||
@ -190,7 +199,7 @@ class Twitapidirect_messagesAction extends TwitterapiAction
|
|||||||
$this->init_document('xml');
|
$this->init_document('xml');
|
||||||
$this->elementStart('direct-messages', array('type' => 'array'));
|
$this->elementStart('direct-messages', array('type' => 'array'));
|
||||||
|
|
||||||
if (is_array($messages)) {
|
if (is_array($message)) {
|
||||||
foreach ($message as $m) {
|
foreach ($message as $m) {
|
||||||
$twitter_dm = $this->twitter_dmsg_array($m);
|
$twitter_dm = $this->twitter_dmsg_array($m);
|
||||||
$this->show_twitter_xml_dmsg($twitter_dm);
|
$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->init_document('atom');
|
||||||
|
|
||||||
$this->element('title', null, $title);
|
$this->element('title', null, $title);
|
||||||
$siteserver = common_config('site', 'server');
|
$this->element('id', null, $id);
|
||||||
$this->element('id', null, "tag:$siteserver,2008:DirectMessage");
|
|
||||||
$this->element('link', array('href' => $link, 'rel' => 'alternate', 'type' => 'text/html'), null);
|
$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);
|
$this->element('subtitle', null, $subtitle);
|
||||||
|
|
||||||
if (is_array($message)) {
|
if (is_array($message)) {
|
||||||
|
@ -61,10 +61,9 @@ class TwitapifavoritesAction extends TwitterapiAction
|
|||||||
}
|
}
|
||||||
|
|
||||||
$sitename = common_config('site', 'name');
|
$sitename = common_config('site', 'name');
|
||||||
$siteserver = common_config('site', 'server');
|
|
||||||
|
|
||||||
$title = sprintf(_('%s / Favorites from %s'), $sitename, $user->nickname);
|
$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));
|
$link = common_local_url('favorites', array('nickname' => $user->nickname));
|
||||||
$subtitle = sprintf(_('%s updates favorited by %s / %s.'), $sitename, $profile->getBestName(), $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);
|
$this->show_rss_timeline($notice, $title, $link, $subtitle);
|
||||||
break;
|
break;
|
||||||
case 'atom':
|
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;
|
break;
|
||||||
case 'json':
|
case 'json':
|
||||||
$this->show_json_timeline($notice);
|
$this->show_json_timeline($notice);
|
||||||
|
@ -133,11 +133,7 @@ class TwitapifriendshipsAction extends TwitterapiAction
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($user_a->isSubscribed($user_b)) {
|
$result = $user_a->isSubscribed($user_b);
|
||||||
$result = 'true';
|
|
||||||
} else {
|
|
||||||
$result = 'false';
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($apidata['content-type']) {
|
switch ($apidata['content-type']) {
|
||||||
case 'xml':
|
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);
|
parent::handle($args);
|
||||||
|
|
||||||
$sitename = common_config('site', 'name');
|
$sitename = common_config('site', 'name');
|
||||||
$siteserver = common_config('site', 'server');
|
|
||||||
$title = sprintf(_("%s public timeline"), $sitename);
|
$title = sprintf(_("%s public timeline"), $sitename);
|
||||||
$id = "tag:$siteserver:Statuses";
|
|
||||||
|
$taguribase = common_config('integration', 'taguri');
|
||||||
|
$id = "tag:$taguribase:PublicTimeline";
|
||||||
$link = common_root_url();
|
$link = common_root_url();
|
||||||
|
|
||||||
$subtitle = sprintf(_("%s updates from everyone!"), $sitename);
|
$subtitle = sprintf(_("%s updates from everyone!"), $sitename);
|
||||||
|
|
||||||
// Number of public statuses to return by default -- Twitter sends 20
|
// 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);
|
$this->show_rss_timeline($notice, $title, $link, $subtitle);
|
||||||
break;
|
break;
|
||||||
case 'atom':
|
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;
|
break;
|
||||||
case 'json':
|
case 'json':
|
||||||
$this->show_json_timeline($notice);
|
$this->show_json_timeline($notice);
|
||||||
@ -114,17 +117,19 @@ class TwitapistatusesAction extends TwitterapiAction
|
|||||||
}
|
}
|
||||||
|
|
||||||
$since = strtotime($this->arg('since'));
|
$since = strtotime($this->arg('since'));
|
||||||
|
$user = $this->get_user($apidata['api_arg'], $apidata);
|
||||||
$user = $this->get_user(null, $apidata);
|
|
||||||
$this->auth_user = $user;
|
$this->auth_user = $user;
|
||||||
|
|
||||||
|
if (empty($user)) {
|
||||||
|
$this->clientError(_('No such user!'), 404, $apidata['content-type']);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$profile = $user->getProfile();
|
$profile = $user->getProfile();
|
||||||
|
|
||||||
$sitename = common_config('site', 'name');
|
$sitename = common_config('site', 'name');
|
||||||
$siteserver = common_config('site', 'server');
|
|
||||||
|
|
||||||
$title = sprintf(_("%s and friends"), $user->nickname);
|
$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));
|
$link = common_local_url('all', array('nickname' => $user->nickname));
|
||||||
$subtitle = sprintf(_('Updates from %1$s and friends on %2$s!'), $user->nickname, $sitename);
|
$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);
|
$this->show_rss_timeline($notice, $title, $link, $subtitle);
|
||||||
break;
|
break;
|
||||||
case 'atom':
|
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;
|
break;
|
||||||
case 'json':
|
case 'json':
|
||||||
$this->show_json_timeline($notice);
|
$this->show_json_timeline($notice);
|
||||||
@ -194,17 +206,16 @@ class TwitapistatusesAction extends TwitterapiAction
|
|||||||
$since = strtotime($this->arg('since'));
|
$since = strtotime($this->arg('since'));
|
||||||
|
|
||||||
$sitename = common_config('site', 'name');
|
$sitename = common_config('site', 'name');
|
||||||
$siteserver = common_config('site', 'server');
|
|
||||||
|
|
||||||
$title = sprintf(_("%s timeline"), $user->nickname);
|
$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));
|
$link = common_local_url('showstream', array('nickname' => $user->nickname));
|
||||||
$subtitle = sprintf(_('Updates from %1$s on %2$s!'), $user->nickname, $sitename);
|
$subtitle = sprintf(_('Updates from %1$s on %2$s!'), $user->nickname, $sitename);
|
||||||
|
|
||||||
# FriendFeed's SUP protocol
|
# FriendFeed's SUP protocol
|
||||||
# Also added RSS and Atom feeds
|
# 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);
|
header('X-SUP-ID: '.$suplink);
|
||||||
|
|
||||||
# XXX: since
|
# XXX: since
|
||||||
@ -219,7 +230,14 @@ class TwitapistatusesAction extends TwitterapiAction
|
|||||||
$this->show_rss_timeline($notice, $title, $link, $subtitle, $suplink);
|
$this->show_rss_timeline($notice, $title, $link, $subtitle, $suplink);
|
||||||
break;
|
break;
|
||||||
case 'atom':
|
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;
|
break;
|
||||||
case 'json':
|
case 'json':
|
||||||
$this->show_json_timeline($notice);
|
$this->show_json_timeline($notice);
|
||||||
@ -326,7 +344,7 @@ class TwitapistatusesAction extends TwitterapiAction
|
|||||||
$this->show($args, $apidata);
|
$this->show($args, $apidata);
|
||||||
}
|
}
|
||||||
|
|
||||||
function replies($args, $apidata)
|
function mentions($args, $apidata)
|
||||||
{
|
{
|
||||||
|
|
||||||
parent::handle($args);
|
parent::handle($args);
|
||||||
@ -337,17 +355,18 @@ class TwitapistatusesAction extends TwitterapiAction
|
|||||||
$since_id = $this->arg('since_id');
|
$since_id = $this->arg('since_id');
|
||||||
$before_id = $this->arg('before_id');
|
$before_id = $this->arg('before_id');
|
||||||
|
|
||||||
|
$user = $this->get_user($apidata['api_arg'], $apidata);
|
||||||
$this->auth_user = $apidata['user'];
|
$this->auth_user = $apidata['user'];
|
||||||
$user = $this->auth_user;
|
|
||||||
$profile = $user->getProfile();
|
$profile = $user->getProfile();
|
||||||
|
|
||||||
$sitename = common_config('site', 'name');
|
$sitename = common_config('site', 'name');
|
||||||
$siteserver = common_config('site', 'server');
|
$title = sprintf(_('%1$s / Updates mentioning %2$s'),
|
||||||
|
$sitename, $user->nickname);
|
||||||
$title = sprintf(_('%1$s / Updates replying to %2$s'), $sitename, $user->nickname);
|
$taguribase = common_config('integration', 'taguri');
|
||||||
$id = "tag:$siteserver:replies:".$user->id;
|
$id = "tag:$taguribase:Mentions:".$user->id;
|
||||||
$link = common_local_url('replies', array('nickname' => $user->nickname));
|
$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) {
|
if (!$page) {
|
||||||
$page = 1;
|
$page = 1;
|
||||||
@ -368,7 +387,8 @@ class TwitapistatusesAction extends TwitterapiAction
|
|||||||
|
|
||||||
$since = strtotime($this->arg('since'));
|
$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();
|
$notices = array();
|
||||||
|
|
||||||
while ($notice->fetch()) {
|
while ($notice->fetch()) {
|
||||||
@ -383,7 +403,10 @@ class TwitapistatusesAction extends TwitterapiAction
|
|||||||
$this->show_rss_timeline($notices, $title, $link, $subtitle);
|
$this->show_rss_timeline($notices, $title, $link, $subtitle);
|
||||||
break;
|
break;
|
||||||
case 'atom':
|
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;
|
break;
|
||||||
case 'json':
|
case 'json':
|
||||||
$this->show_json_timeline($notices);
|
$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)
|
function show($args, $apidata)
|
||||||
{
|
{
|
||||||
parent::handle($args);
|
parent::handle($args);
|
||||||
@ -470,19 +498,28 @@ class TwitapistatusesAction extends TwitterapiAction
|
|||||||
return $this->subscriptions($apidata, 'subscribed', 'subscriber');
|
return $this->subscriptions($apidata, 'subscribed', 'subscriber');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function friendsIDs($args, $apidata)
|
||||||
|
{
|
||||||
|
parent::handle($args);
|
||||||
|
return $this->subscriptions($apidata, 'subscribed', 'subscriber', true);
|
||||||
|
}
|
||||||
|
|
||||||
function followers($args, $apidata)
|
function followers($args, $apidata)
|
||||||
{
|
{
|
||||||
parent::handle($args);
|
parent::handle($args);
|
||||||
|
|
||||||
return $this->subscriptions($apidata, 'subscriber', 'subscribed');
|
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 = $apidata['user'];
|
||||||
|
|
||||||
$this->auth_user = $apidate['user'];
|
|
||||||
$user = $this->get_user($apidata['api_arg'], $apidata);
|
$user = $this->get_user($apidata['api_arg'], $apidata);
|
||||||
|
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
@ -514,7 +551,10 @@ class TwitapistatusesAction extends TwitterapiAction
|
|||||||
}
|
}
|
||||||
|
|
||||||
$sub->orderBy('created DESC');
|
$sub->orderBy('created DESC');
|
||||||
$sub->limit(($page-1)*100, 100);
|
|
||||||
|
if (!$onlyIDs) {
|
||||||
|
$sub->limit(($page-1)*100, 100);
|
||||||
|
}
|
||||||
|
|
||||||
$others = array();
|
$others = array();
|
||||||
|
|
||||||
@ -529,7 +569,13 @@ class TwitapistatusesAction extends TwitterapiAction
|
|||||||
$type = $apidata['content-type'];
|
$type = $apidata['content-type'];
|
||||||
|
|
||||||
$this->init_document($type);
|
$this->init_document($type);
|
||||||
$this->show_profiles($others, $type);
|
|
||||||
|
if ($onlyIDs) {
|
||||||
|
$this->showIDs($others, $type);
|
||||||
|
} else {
|
||||||
|
$this->show_profiles($others, $type);
|
||||||
|
}
|
||||||
|
|
||||||
$this->end_document($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)
|
function featured($args, $apidata)
|
||||||
{
|
{
|
||||||
parent::handle($args);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -25,25 +25,29 @@ class TwitapiusersAction extends TwitterapiAction
|
|||||||
{
|
{
|
||||||
|
|
||||||
function show($args, $apidata)
|
function show($args, $apidata)
|
||||||
{
|
{
|
||||||
parent::handle($args);
|
parent::handle($args);
|
||||||
|
|
||||||
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
|
if (!in_array($apidata['content-type'], array('xml', 'json'))) {
|
||||||
$this->clientError(_('API method not found!'), $code = 404);
|
$this->clientError(_('API method not found!'), $code = 404);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->auth_user = $apidata['user'];
|
|
||||||
$user = null;
|
$user = null;
|
||||||
$email = $this->arg('email');
|
$email = $this->arg('email');
|
||||||
|
$user_id = $this->arg('user_id');
|
||||||
|
|
||||||
if ($email) {
|
if ($email) {
|
||||||
$user = User::staticGet('email', $email);
|
$user = User::staticGet('email', $email);
|
||||||
|
} elseif ($user_id) {
|
||||||
|
$user = $this->get_user($user_id);
|
||||||
} elseif (isset($apidata['api_arg'])) {
|
} elseif (isset($apidata['api_arg'])) {
|
||||||
$user = $this->get_user($apidata['api_arg']);
|
$user = $this->get_user($apidata['api_arg']);
|
||||||
}
|
} elseif (isset($apidata['user'])) {
|
||||||
|
$user = $apidata['user'];
|
||||||
if (!$user) {
|
}
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
// XXX: Twitter returns a random(?) user instead of throwing and err! -- Zach
|
// XXX: Twitter returns a random(?) user instead of throwing and err! -- Zach
|
||||||
$this->client_error(_('Not found.'), 404, $apidata['content-type']);
|
$this->client_error(_('Not found.'), 404, $apidata['content-type']);
|
||||||
return;
|
return;
|
||||||
@ -74,9 +78,12 @@ class TwitapiusersAction extends TwitterapiAction
|
|||||||
|
|
||||||
// Other fields Twitter sends...
|
// Other fields Twitter sends...
|
||||||
$twitter_user['profile_background_color'] = '';
|
$twitter_user['profile_background_color'] = '';
|
||||||
|
$twitter_user['profile_background_image_url'] = '';
|
||||||
$twitter_user['profile_text_color'] = '';
|
$twitter_user['profile_text_color'] = '';
|
||||||
$twitter_user['profile_link_color'] = '';
|
$twitter_user['profile_link_color'] = '';
|
||||||
$twitter_user['profile_sidebar_fill_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 = DB_DataObject::factory('fave');
|
||||||
$faves->user_id = $user->id;
|
$faves->user_id = $user->id;
|
||||||
@ -94,18 +101,19 @@ class TwitapiusersAction extends TwitterapiAction
|
|||||||
$twitter_user['utc_offset'] = $t->format('Z');
|
$twitter_user['utc_offset'] = $t->format('Z');
|
||||||
$twitter_user['time_zone'] = $timezone;
|
$twitter_user['time_zone'] = $timezone;
|
||||||
|
|
||||||
if (isset($this->auth_user)) {
|
if (isset($apidata['user'])) {
|
||||||
|
|
||||||
if ($this->auth_user->isSubscribed($profile)) {
|
$twitter_user['following'] = $apidata['user']->isSubscribed($profile);
|
||||||
$twitter_user['following'] = 'true';
|
|
||||||
} else {
|
// Notifications on?
|
||||||
$twitter_user['following'] = 'false';
|
$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') {
|
if ($apidata['content-type'] == 'xml') {
|
||||||
$this->init_document('xml');
|
$this->init_document('xml');
|
||||||
$this->show_twitter_xml_user($twitter_user);
|
$this->show_twitter_xml_user($twitter_user);
|
||||||
@ -114,7 +122,13 @@ class TwitapiusersAction extends TwitterapiAction
|
|||||||
$this->init_document('json');
|
$this->init_document('json');
|
||||||
$this->show_json_objects($twitter_user);
|
$this->show_json_objects($twitter_user);
|
||||||
$this->end_document('json');
|
$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('ul', 'form_data');
|
||||||
$this->elementStart('li');
|
$this->elementStart('li');
|
||||||
$this->checkbox('noticesync',
|
$this->checkbox('noticesend',
|
||||||
_('Automatically send my notices to Twitter.'),
|
_('Automatically send my notices to Twitter.'),
|
||||||
($flink) ?
|
($flink) ?
|
||||||
($flink->noticesync & FOREIGN_NOTICE_SEND) :
|
($flink->noticesync & FOREIGN_NOTICE_SEND) :
|
||||||
@ -158,6 +158,22 @@ class TwittersettingsAction extends ConnectSettingsAction
|
|||||||
($flink->friendsync & FOREIGN_FRIEND_RECV) :
|
($flink->friendsync & FOREIGN_FRIEND_RECV) :
|
||||||
false);
|
false);
|
||||||
$this->elementEnd('li');
|
$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');
|
$this->elementEnd('ul');
|
||||||
|
|
||||||
if ($flink) {
|
if ($flink) {
|
||||||
@ -186,12 +202,12 @@ class TwittersettingsAction extends ConnectSettingsAction
|
|||||||
|
|
||||||
$current_user = common_current_user();
|
$current_user = common_current_user();
|
||||||
|
|
||||||
$qry = 'SELECT user.* ' .
|
$qry = 'SELECT "user".* ' .
|
||||||
'FROM subscription ' .
|
'FROM subscription ' .
|
||||||
'JOIN user ON subscription.subscribed = user.id ' .
|
'JOIN "user" ON subscription.subscribed = "user".id ' .
|
||||||
'JOIN foreign_link ON foreign_link.user_id = user.id ' .
|
'JOIN foreign_link ON foreign_link.user_id = "user".id ' .
|
||||||
'WHERE subscriber = %d ' .
|
'WHERE subscriber = %d ' .
|
||||||
'ORDER BY user.nickname';
|
'ORDER BY "user".nickname';
|
||||||
|
|
||||||
$user = new User();
|
$user = new User();
|
||||||
|
|
||||||
@ -261,7 +277,7 @@ class TwittersettingsAction extends ConnectSettingsAction
|
|||||||
'alt' => ($other->fullname) ?
|
'alt' => ($other->fullname) ?
|
||||||
$other->fullname :
|
$other->fullname :
|
||||||
$other->nickname));
|
$other->nickname));
|
||||||
|
|
||||||
$this->element('span', 'fn nickname', $other->nickname);
|
$this->element('span', 'fn nickname', $other->nickname);
|
||||||
$this->elementEnd('a');
|
$this->elementEnd('a');
|
||||||
$this->elementEnd('li');
|
$this->elementEnd('li');
|
||||||
@ -320,7 +336,8 @@ class TwittersettingsAction extends ConnectSettingsAction
|
|||||||
{
|
{
|
||||||
$screen_name = $this->trimmed('twitter_username');
|
$screen_name = $this->trimmed('twitter_username');
|
||||||
$password = $this->trimmed('twitter_password');
|
$password = $this->trimmed('twitter_password');
|
||||||
$noticesync = $this->boolean('noticesync');
|
$noticesend = $this->boolean('noticesend');
|
||||||
|
$noticerecv = $this->boolean('noticerecv');
|
||||||
$replysync = $this->boolean('replysync');
|
$replysync = $this->boolean('replysync');
|
||||||
$friendsync = $this->boolean('friendsync');
|
$friendsync = $this->boolean('friendsync');
|
||||||
|
|
||||||
@ -363,7 +380,7 @@ class TwittersettingsAction extends ConnectSettingsAction
|
|||||||
$flink->credentials = $password;
|
$flink->credentials = $password;
|
||||||
$flink->created = common_sql_now();
|
$flink->created = common_sql_now();
|
||||||
|
|
||||||
$flink->set_flags($noticesync, $replysync, $friendsync);
|
$flink->set_flags($noticesend, $noticerecv, $replysync, $friendsync);
|
||||||
|
|
||||||
$flink_id = $flink->insert();
|
$flink_id = $flink->insert();
|
||||||
|
|
||||||
@ -375,6 +392,8 @@ class TwittersettingsAction extends ConnectSettingsAction
|
|||||||
|
|
||||||
if ($friendsync) {
|
if ($friendsync) {
|
||||||
save_twitter_friends($user, $twit_user->id, $screen_name, $password);
|
save_twitter_friends($user, $twit_user->id, $screen_name, $password);
|
||||||
|
$flink->last_friendsync = common_sql_now();
|
||||||
|
$flink->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->showForm(_('Twitter settings saved.'), true);
|
$this->showForm(_('Twitter settings saved.'), true);
|
||||||
@ -419,7 +438,8 @@ class TwittersettingsAction extends ConnectSettingsAction
|
|||||||
|
|
||||||
function savePreferences()
|
function savePreferences()
|
||||||
{
|
{
|
||||||
$noticesync = $this->boolean('noticesync');
|
$noticesend = $this->boolean('noticesend');
|
||||||
|
$noticerecv = $this->boolean('noticerecv');
|
||||||
$friendsync = $this->boolean('friendsync');
|
$friendsync = $this->boolean('friendsync');
|
||||||
$replysync = $this->boolean('replysync');
|
$replysync = $this->boolean('replysync');
|
||||||
|
|
||||||
@ -448,7 +468,7 @@ class TwittersettingsAction extends ConnectSettingsAction
|
|||||||
|
|
||||||
$original = clone($flink);
|
$original = clone($flink);
|
||||||
|
|
||||||
$flink->set_flags($noticesync, $replysync, $friendsync);
|
$flink->set_flags($noticesend, $noticerecv, $replysync, $friendsync);
|
||||||
|
|
||||||
$result = $flink->update($original);
|
$result = $flink->update($original);
|
||||||
|
|
||||||
|
@ -116,10 +116,11 @@ class UnblockAction extends Action
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($action) {
|
if ($action) {
|
||||||
common_redirect(common_local_url($action, $args));
|
common_redirect(common_local_url($action, $args), 303);
|
||||||
} else {
|
} else {
|
||||||
common_redirect(common_local_url('subscriptions',
|
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');
|
$this->elementEnd('html');
|
||||||
} else {
|
} else {
|
||||||
common_redirect(common_local_url('subscriptions', array('nickname' =>
|
common_redirect(common_local_url('subscriptions', array('nickname' =>
|
||||||
$user->nickname)));
|
$user->nickname)),
|
||||||
|
303);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,11 +29,13 @@ class UpdateprofileAction extends Action
|
|||||||
parent::handle($args);
|
parent::handle($args);
|
||||||
try {
|
try {
|
||||||
common_remove_magic_from_request();
|
common_remove_magic_from_request();
|
||||||
$req = OAuthRequest::from_request();
|
$req = OAuthRequest::from_request('POST', common_local_url('updateprofile'));
|
||||||
# Note: server-to-server function!
|
# Note: server-to-server function!
|
||||||
$server = omb_oauth_server();
|
$server = omb_oauth_server();
|
||||||
list($consumer, $token) = $server->verify_request($req);
|
list($consumer, $token) = $server->verify_request($req);
|
||||||
if ($this->update_profile($req, $consumer, $token)) {
|
if ($this->update_profile($req, $consumer, $token)) {
|
||||||
|
header('HTTP/1.1 200 OK');
|
||||||
|
header('Content-type: text/plain');
|
||||||
print "omb_version=".OMB_VERSION_01;
|
print "omb_version=".OMB_VERSION_01;
|
||||||
}
|
}
|
||||||
} catch (OAuthException $e) {
|
} catch (OAuthException $e) {
|
||||||
@ -136,22 +138,24 @@ class UpdateprofileAction extends Action
|
|||||||
|
|
||||||
$orig_profile = clone($profile);
|
$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;
|
$profile->nickname = $nickname;
|
||||||
}
|
}
|
||||||
if ($profile_url) {
|
if (!is_null($profile_url)) {
|
||||||
$profile->profileurl = $profile_url;
|
$profile->profileurl = $profile_url;
|
||||||
}
|
}
|
||||||
if ($fullname) {
|
if (!is_null($fullname)) {
|
||||||
$profile->fullname = $fullname;
|
$profile->fullname = $fullname;
|
||||||
}
|
}
|
||||||
if ($homepage) {
|
if (!is_null($homepage)) {
|
||||||
$profile->homepage = $homepage;
|
$profile->homepage = $homepage;
|
||||||
}
|
}
|
||||||
if ($bio) {
|
if (!is_null($bio)) {
|
||||||
$profile->bio = $bio;
|
$profile->bio = $bio;
|
||||||
}
|
}
|
||||||
if ($location) {
|
if (!is_null($location)) {
|
||||||
$profile->location = $location;
|
$profile->location = $location;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,15 +166,17 @@ class UpdateprofileAction extends Action
|
|||||||
if ($avatar) {
|
if ($avatar) {
|
||||||
$temp_filename = tempnam(sys_get_temp_dir(), 'listenee_avatar');
|
$temp_filename = tempnam(sys_get_temp_dir(), 'listenee_avatar');
|
||||||
copy($avatar, $temp_filename);
|
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);
|
$this->serverError(_('Could not save avatar info'), 500);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
header('HTTP/1.1 200 OK');
|
|
||||||
header('Content-type: text/plain');
|
|
||||||
print 'Updated profile';
|
|
||||||
print "\n";
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ define('TIMESTAMP_THRESHOLD', 300);
|
|||||||
class UserauthorizationAction extends Action
|
class UserauthorizationAction extends Action
|
||||||
{
|
{
|
||||||
var $error;
|
var $error;
|
||||||
var $req;
|
var $params;
|
||||||
|
|
||||||
function handle($args)
|
function handle($args)
|
||||||
{
|
{
|
||||||
@ -35,8 +35,8 @@ class UserauthorizationAction extends Action
|
|||||||
# CSRF protection
|
# CSRF protection
|
||||||
$token = $this->trimmed('token');
|
$token = $this->trimmed('token');
|
||||||
if (!$token || $token != common_session_token()) {
|
if (!$token || $token != common_session_token()) {
|
||||||
$req = $this->getStoredRequest();
|
$params = $this->getStoredParams();
|
||||||
$this->showForm($req, _('There was a problem with your session token. '.
|
$this->showForm($params, _('There was a problem with your session token. '.
|
||||||
'Try again, please.'));
|
'Try again, please.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -50,18 +50,13 @@ class UserauthorizationAction extends Action
|
|||||||
common_redirect(common_local_url('login'));
|
common_redirect(common_local_url('login'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
# this must be a new request
|
$this->validateRequest();
|
||||||
$req = $this->getNewRequest();
|
$this->storeParams($_GET);
|
||||||
if (!$req) {
|
$this->showForm($_GET);
|
||||||
$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);
|
|
||||||
} catch (OAuthException $e) {
|
} catch (OAuthException $e) {
|
||||||
$this->clearRequest();
|
$this->clearParams();
|
||||||
$this->clientError($e->getMessage());
|
$this->clientError($e->getMessage());
|
||||||
return;
|
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->error = $error;
|
||||||
$this->showPage();
|
$this->showPage();
|
||||||
}
|
}
|
||||||
@ -91,113 +86,157 @@ class UserauthorizationAction extends Action
|
|||||||
|
|
||||||
function showContent()
|
function showContent()
|
||||||
{
|
{
|
||||||
$req = $this->req;
|
$params = $this->params;
|
||||||
|
|
||||||
$nickname = $req->get_parameter('omb_listenee_nickname');
|
$nickname = $params['omb_listenee_nickname'];
|
||||||
$profile = $req->get_parameter('omb_listenee_profile');
|
$profile = $params['omb_listenee_profile'];
|
||||||
$license = $req->get_parameter('omb_listenee_license');
|
$license = $params['omb_listenee_license'];
|
||||||
$fullname = $req->get_parameter('omb_listenee_fullname');
|
$fullname = $params['omb_listenee_fullname'];
|
||||||
$homepage = $req->get_parameter('omb_listenee_homepage');
|
$homepage = $params['omb_listenee_homepage'];
|
||||||
$bio = $req->get_parameter('omb_listenee_bio');
|
$bio = $params['omb_listenee_bio'];
|
||||||
$location = $req->get_parameter('omb_listenee_location');
|
$location = $params['omb_listenee_location'];
|
||||||
$avatar = $req->get_parameter('omb_listenee_avatar');
|
$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) {
|
if ($avatar) {
|
||||||
$this->element('img', array('src' => $avatar,
|
$this->element('img', array('src' => $avatar,
|
||||||
'class' => 'avatar profile',
|
'class' => 'photo avatar',
|
||||||
'width' => AVATAR_PROFILE_SIZE,
|
'width' => AVATAR_PROFILE_SIZE,
|
||||||
'height' => AVATAR_PROFILE_SIZE,
|
'height' => AVATAR_PROFILE_SIZE,
|
||||||
'alt' => $nickname));
|
'alt' => $nickname));
|
||||||
}
|
}
|
||||||
$this->element('a', array('href' => $profile,
|
$hasFN = ($fullname !== '') ? 'nickname' : 'fn nickname';
|
||||||
'class' => 'external profile nickname'),
|
$this->elementStart('span', $hasFN);
|
||||||
$nickname);
|
$this->raw($nickname);
|
||||||
if ($fullname) {
|
$this->elementEnd('span');
|
||||||
$this->elementStart('div', 'fullname');
|
$this->elementEnd('a');
|
||||||
if ($homepage) {
|
|
||||||
$this->element('a', array('href' => $homepage),
|
if (!is_null($fullname)) {
|
||||||
$fullname);
|
$this->elementStart('dl', 'entity_fn');
|
||||||
} else {
|
$this->elementStart('dd');
|
||||||
$this->text($fullname);
|
$this->elementStart('span', 'fn');
|
||||||
}
|
$this->raw($fullname);
|
||||||
$this->elementEnd('div');
|
$this->elementEnd('span');
|
||||||
|
$this->elementEnd('dd');
|
||||||
|
$this->elementEnd('dl');
|
||||||
}
|
}
|
||||||
if ($location) {
|
if (!is_null($location)) {
|
||||||
$this->element('div', 'location', $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 ($bio) {
|
|
||||||
$this->element('div', 'bio', $bio);
|
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 (!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');
|
||||||
|
}
|
||||||
|
|
||||||
|
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->elementStart('div', 'license');
|
|
||||||
$this->element('a', array('href' => $license,
|
|
||||||
'class' => 'license'),
|
|
||||||
$license);
|
|
||||||
$this->elementEnd('div');
|
|
||||||
$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',
|
$this->elementStart('form', array('method' => 'post',
|
||||||
'id' => 'userauthorization',
|
'id' => 'userauthorization',
|
||||||
|
'class' => 'form_user_authorization',
|
||||||
'name' => 'userauthorization',
|
'name' => 'userauthorization',
|
||||||
'action' => common_local_url('userauthorization')));
|
'action' => common_local_url('userauthorization')));
|
||||||
$this->hidden('token', common_session_token());
|
$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('form');
|
||||||
|
$this->elementEnd('li');
|
||||||
|
$this->elementEnd('ul');
|
||||||
|
$this->elementEnd('div');
|
||||||
|
$this->elementEnd('div');
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendAuthorization()
|
function sendAuthorization()
|
||||||
{
|
{
|
||||||
$req = $this->getStoredRequest();
|
$params = $this->getStoredParams();
|
||||||
|
|
||||||
if (!$req) {
|
if (!$params) {
|
||||||
$this->clientError(_('No authorization request!'));
|
$this->clientError(_('No authorization request!'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$callback = $req->get_parameter('oauth_callback');
|
$callback = $params['oauth_callback'];
|
||||||
|
|
||||||
if ($this->arg('accept')) {
|
if ($this->arg('accept')) {
|
||||||
if (!$this->authorizeToken($req)) {
|
if (!$this->authorizeToken($params)) {
|
||||||
$this->clientError(_('Error authorizing token'));
|
$this->clientError(_('Error authorizing token'));
|
||||||
}
|
}
|
||||||
if (!$this->saveRemoteProfile($req)) {
|
if (!$this->saveRemoteProfile($params)) {
|
||||||
$this->clientError(_('Error saving remote profile'));
|
$this->clientError(_('Error saving remote profile'));
|
||||||
}
|
}
|
||||||
if (!$callback) {
|
if (!$callback) {
|
||||||
$this->showAcceptMessage($req->get_parameter('oauth_token'));
|
$this->showAcceptMessage($params['oauth_token']);
|
||||||
} else {
|
} else {
|
||||||
$params = array();
|
$newparams = array();
|
||||||
$params['oauth_token'] = $req->get_parameter('oauth_token');
|
$newparams['oauth_token'] = $params['oauth_token'];
|
||||||
$params['omb_version'] = OMB_VERSION_01;
|
$newparams['omb_version'] = OMB_VERSION_01;
|
||||||
$user = User::staticGet('uri', $req->get_parameter('omb_listener'));
|
$user = User::staticGet('uri', $params['omb_listener']);
|
||||||
$profile = $user->getProfile();
|
$profile = $user->getProfile();
|
||||||
if (!$profile) {
|
if (!$profile) {
|
||||||
common_log_db_error($user, 'SELECT', __FILE__);
|
common_log_db_error($user, 'SELECT', __FILE__);
|
||||||
$this->serverError(_('User without matching profile'));
|
$this->serverError(_('User without matching profile'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$params['omb_listener_nickname'] = $user->nickname;
|
$newparams['omb_listener_nickname'] = $user->nickname;
|
||||||
$params['omb_listener_profile'] = common_local_url('showstream',
|
$newparams['omb_listener_profile'] = common_local_url('showstream',
|
||||||
array('nickname' => $user->nickname));
|
array('nickname' => $user->nickname));
|
||||||
if ($profile->fullname) {
|
if (!is_null($profile->fullname)) {
|
||||||
$params['omb_listener_fullname'] = $profile->fullname;
|
$newparams['omb_listener_fullname'] = $profile->fullname;
|
||||||
}
|
}
|
||||||
if ($profile->homepage) {
|
if (!is_null($profile->homepage)) {
|
||||||
$params['omb_listener_homepage'] = $profile->homepage;
|
$newparams['omb_listener_homepage'] = $profile->homepage;
|
||||||
}
|
}
|
||||||
if ($profile->bio) {
|
if (!is_null($profile->bio)) {
|
||||||
$params['omb_listener_bio'] = $profile->bio;
|
$newparams['omb_listener_bio'] = $profile->bio;
|
||||||
}
|
}
|
||||||
if ($profile->location) {
|
if (!is_null($profile->location)) {
|
||||||
$params['omb_listener_location'] = $profile->location;
|
$newparams['omb_listener_location'] = $profile->location;
|
||||||
}
|
}
|
||||||
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||||
if ($avatar) {
|
if ($avatar) {
|
||||||
$params['omb_listener_avatar'] = $avatar->url;
|
$newparams['omb_listener_avatar'] = $avatar->url;
|
||||||
}
|
}
|
||||||
$parts = array();
|
$parts = array();
|
||||||
foreach ($params as $k => $v) {
|
foreach ($newparams as $k => $v) {
|
||||||
$parts[] = $k . '=' . OAuthUtil::urlencodeRFC3986($v);
|
$parts[] = $k . '=' . OAuthUtil::urlencode_rfc3986($v);
|
||||||
}
|
}
|
||||||
$query_string = implode('&', $parts);
|
$query_string = implode('&', $parts);
|
||||||
$parsed = parse_url($callback);
|
$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 = $params['oauth_token'];
|
||||||
$token_field = $req->get_parameter('oauth_token');
|
|
||||||
$rt = new Token();
|
$rt = new Token();
|
||||||
$rt->consumer_key = $consumer_key;
|
|
||||||
$rt->tok = $token_field;
|
$rt->tok = $token_field;
|
||||||
$rt->type = 0;
|
$rt->type = 0;
|
||||||
$rt->state = 0;
|
$rt->state = 0;
|
||||||
@ -235,21 +272,21 @@ class UserauthorizationAction extends Action
|
|||||||
|
|
||||||
# XXX: refactor with similar code in finishremotesubscribe.php
|
# XXX: refactor with similar code in finishremotesubscribe.php
|
||||||
|
|
||||||
function saveRemoteProfile(&$req)
|
function saveRemoteProfile(&$params)
|
||||||
{
|
{
|
||||||
# FIXME: we should really do this when the consumer comes
|
# 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
|
# back for an access token. If they never do, we've got stuff in a
|
||||||
# weird state.
|
# weird state.
|
||||||
|
|
||||||
$nickname = $req->get_parameter('omb_listenee_nickname');
|
$nickname = $params['omb_listenee_nickname'];
|
||||||
$fullname = $req->get_parameter('omb_listenee_fullname');
|
$fullname = $params['omb_listenee_fullname'];
|
||||||
$profile_url = $req->get_parameter('omb_listenee_profile');
|
$profile_url = $params['omb_listenee_profile'];
|
||||||
$homepage = $req->get_parameter('omb_listenee_homepage');
|
$homepage = $params['omb_listenee_homepage'];
|
||||||
$bio = $req->get_parameter('omb_listenee_bio');
|
$bio = $params['omb_listenee_bio'];
|
||||||
$location = $req->get_parameter('omb_listenee_location');
|
$location = $params['omb_listenee_location'];
|
||||||
$avatar_url = $req->get_parameter('omb_listenee_avatar');
|
$avatar_url = $params['omb_listenee_avatar'];
|
||||||
|
|
||||||
$listenee = $req->get_parameter('omb_listenee');
|
$listenee = $params['omb_listenee'];
|
||||||
$remote = Remote_profile::staticGet('uri', $listenee);
|
$remote = Remote_profile::staticGet('uri', $listenee);
|
||||||
|
|
||||||
if ($remote) {
|
if ($remote) {
|
||||||
@ -267,16 +304,16 @@ class UserauthorizationAction extends Action
|
|||||||
$profile->nickname = $nickname;
|
$profile->nickname = $nickname;
|
||||||
$profile->profileurl = $profile_url;
|
$profile->profileurl = $profile_url;
|
||||||
|
|
||||||
if ($fullname) {
|
if (!is_null($fullname)) {
|
||||||
$profile->fullname = $fullname;
|
$profile->fullname = $fullname;
|
||||||
}
|
}
|
||||||
if ($homepage) {
|
if (!is_null($homepage)) {
|
||||||
$profile->homepage = $homepage;
|
$profile->homepage = $homepage;
|
||||||
}
|
}
|
||||||
if ($bio) {
|
if (!is_null($bio)) {
|
||||||
$profile->bio = $bio;
|
$profile->bio = $bio;
|
||||||
}
|
}
|
||||||
if ($location) {
|
if (!is_null($location)) {
|
||||||
$profile->location = $location;
|
$profile->location = $location;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,14 +346,11 @@ class UserauthorizationAction extends Action
|
|||||||
}
|
}
|
||||||
|
|
||||||
$user = common_current_user();
|
$user = common_current_user();
|
||||||
$datastore = omb_oauth_datastore();
|
|
||||||
$consumer = $this->getConsumer($datastore, $req);
|
|
||||||
$token = $this->getToken($datastore, $req, $consumer);
|
|
||||||
|
|
||||||
$sub = new Subscription();
|
$sub = new Subscription();
|
||||||
$sub->subscriber = $user->id;
|
$sub->subscriber = $user->id;
|
||||||
$sub->subscribed = $remote->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
|
$sub->created = DB_DataObject_Cast::dateTime(); # current time
|
||||||
|
|
||||||
if (!$sub->insert()) {
|
if (!$sub->insert()) {
|
||||||
@ -360,65 +394,59 @@ class UserauthorizationAction extends Action
|
|||||||
common_show_footer();
|
common_show_footer();
|
||||||
}
|
}
|
||||||
|
|
||||||
function storeRequest($req)
|
function storeParams($params)
|
||||||
{
|
{
|
||||||
common_ensure_session();
|
common_ensure_session();
|
||||||
$_SESSION['userauthorizationrequest'] = $req;
|
$_SESSION['userauthorizationparams'] = $params;
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearRequest()
|
function clearParams()
|
||||||
{
|
{
|
||||||
common_ensure_session();
|
common_ensure_session();
|
||||||
unset($_SESSION['userauthorizationrequest']);
|
unset($_SESSION['userauthorizationparams']);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStoredRequest()
|
function getStoredParams()
|
||||||
{
|
{
|
||||||
common_ensure_session();
|
common_ensure_session();
|
||||||
$req = $_SESSION['userauthorizationrequest'];
|
$params = $_SESSION['userauthorizationparams'];
|
||||||
return $req;
|
return $params;
|
||||||
}
|
|
||||||
|
|
||||||
function getNewRequest()
|
|
||||||
{
|
|
||||||
common_remove_magic_from_request();
|
|
||||||
$req = OAuthRequest::from_request();
|
|
||||||
return $req;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Throws an OAuthException if anything goes wrong
|
# Throws an OAuthException if anything goes wrong
|
||||||
|
|
||||||
function validateRequest(&$req)
|
function validateRequest()
|
||||||
{
|
{
|
||||||
# OAuth stuff -- have to copy from OAuth.php since they're
|
/* Find token.
|
||||||
# all private methods, and there's no user-authentication method
|
TODO: If no token is passed the user should get a prompt to enter it
|
||||||
$this->checkVersion($req);
|
according to OAuth Core 1.0 */
|
||||||
$datastore = omb_oauth_datastore();
|
$t = new Token();
|
||||||
$consumer = $this->getConsumer($datastore, $req);
|
$t->tok = $_GET['oauth_token'];
|
||||||
$token = $this->getToken($datastore, $req, $consumer);
|
$t->type = 0;
|
||||||
$this->checkTimestamp($req);
|
if (!$t->find(true)) {
|
||||||
$this->checkNonce($datastore, $req, $consumer, $token);
|
throw new OAuthException("Invalid request token: " . $_GET['oauth_token']);
|
||||||
$this->checkSignature($req, $consumer, $token);
|
}
|
||||||
$this->validateOmb($req);
|
|
||||||
|
$this->validateOmb();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateOmb(&$req)
|
function validateOmb()
|
||||||
{
|
{
|
||||||
foreach (array('omb_version', 'omb_listener', 'omb_listenee',
|
foreach (array('omb_version', 'omb_listener', 'omb_listenee',
|
||||||
'omb_listenee_profile', 'omb_listenee_nickname',
|
'omb_listenee_profile', 'omb_listenee_nickname',
|
||||||
'omb_listenee_license') as $param)
|
'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");
|
throw new OAuthException("Required parameter '$param' not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# Now, OMB stuff
|
# Now, OMB stuff
|
||||||
$version = $req->get_parameter('omb_version');
|
$version = $_GET['omb_version'];
|
||||||
if ($version != OMB_VERSION_01) {
|
if ($version != OMB_VERSION_01) {
|
||||||
throw new OAuthException("OpenMicroBlogging version '$version' not supported");
|
throw new OAuthException("OpenMicroBlogging version '$version' not supported");
|
||||||
}
|
}
|
||||||
$listener = $req->get_parameter('omb_listener');
|
$listener = $_GET['omb_listener'];
|
||||||
$user = User::staticGet('uri', $listener);
|
$user = User::staticGet('uri', $listener);
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
throw new OAuthException("Listener URI '$listener' not found here");
|
throw new OAuthException("Listener URI '$listener' not found here");
|
||||||
@ -427,7 +455,7 @@ class UserauthorizationAction extends Action
|
|||||||
if ($cur->id != $user->id) {
|
if ($cur->id != $user->id) {
|
||||||
throw new OAuthException("Can't add for another user!");
|
throw new OAuthException("Can't add for another user!");
|
||||||
}
|
}
|
||||||
$listenee = $req->get_parameter('omb_listenee');
|
$listenee = $_GET['omb_listenee'];
|
||||||
if (!Validate::uri($listenee) &&
|
if (!Validate::uri($listenee) &&
|
||||||
!common_valid_tag($listenee)) {
|
!common_valid_tag($listenee)) {
|
||||||
throw new OAuthException("Listenee URI '$listenee' not a recognizable URI");
|
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!");
|
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,
|
if (!Validate::string($nickname, array('min_length' => 1,
|
||||||
'max_length' => 64,
|
'max_length' => 64,
|
||||||
'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
|
'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
|
||||||
throw new OAuthException('Nickname must have only letters and numbers and no spaces.');
|
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)) {
|
if (!common_valid_http_url($profile)) {
|
||||||
throw new OAuthException("Invalid profile 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.");
|
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)) {
|
if (!common_valid_http_url($license)) {
|
||||||
throw new OAuthException("Invalid license 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'.");
|
throw new OAuthException("Listenee stream license '$license' not compatible with site license '$site_license'.");
|
||||||
}
|
}
|
||||||
# optional stuff
|
# optional stuff
|
||||||
$fullname = $req->get_parameter('omb_listenee_fullname');
|
$fullname = $_GET['omb_listenee_fullname'];
|
||||||
if ($fullname && mb_strlen($fullname) > 255) {
|
if ($fullname && mb_strlen($fullname) > 255) {
|
||||||
throw new OAuthException("Full name '$fullname' too long.");
|
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)) {
|
if ($homepage && (!common_valid_http_url($homepage) || mb_strlen($homepage) > 255)) {
|
||||||
throw new OAuthException("Invalid homepage '$homepage'");
|
throw new OAuthException("Invalid homepage '$homepage'");
|
||||||
}
|
}
|
||||||
$bio = $req->get_parameter('omb_listenee_bio');
|
$bio = $_GET['omb_listenee_bio'];
|
||||||
if ($bio && mb_strlen($bio) > 140) {
|
if ($bio && mb_strlen($bio) > 140) {
|
||||||
throw new OAuthException("Bio too long '$bio'");
|
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) {
|
if ($location && mb_strlen($location) > 255) {
|
||||||
throw new OAuthException("Location too long '$location'");
|
throw new OAuthException("Location too long '$location'");
|
||||||
}
|
}
|
||||||
$avatar = $req->get_parameter('omb_listenee_avatar');
|
$avatar = $_GET['omb_listenee_avatar'];
|
||||||
if ($avatar) {
|
if ($avatar) {
|
||||||
if (!common_valid_http_url($avatar) || strlen($avatar) > 255) {
|
if (!common_valid_http_url($avatar) || strlen($avatar) > 255) {
|
||||||
throw new OAuthException("Invalid avatar URL '$avatar'");
|
throw new OAuthException("Invalid avatar URL '$avatar'");
|
||||||
@ -507,7 +535,7 @@ class UserauthorizationAction extends Action
|
|||||||
throw new OAuthException("Wrong image type for '$avatar'");
|
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)) {
|
if ($callback && !common_valid_http_url($callback)) {
|
||||||
throw new OAuthException("Invalid callback 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.");
|
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
|
* @return boolean true
|
||||||
*/
|
*/
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ class UsergroupsAction extends Action
|
|||||||
var $page = null;
|
var $page = null;
|
||||||
var $profile = null;
|
var $profile = null;
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -139,10 +139,28 @@ class UsergroupsAction extends Action
|
|||||||
if ($groups) {
|
if ($groups) {
|
||||||
$gl = new GroupList($groups, $this->user, $this);
|
$gl = new GroupList($groups, $this->user, $this);
|
||||||
$cnt = $gl->show();
|
$cnt = $gl->show();
|
||||||
|
if (0 == $cnt) {
|
||||||
|
$this->showEmptyListMessage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->pagination($this->page > 1, $cnt > GROUPS_PER_PAGE,
|
$this->pagination($this->page > 1, $cnt > GROUPS_PER_PAGE,
|
||||||
$this->page, 'usergroups',
|
$this->page, 'usergroups',
|
||||||
array('nickname' => $this->user->nickname));
|
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
|
class UserrssAction extends Rss10Action
|
||||||
{
|
{
|
||||||
|
|
||||||
var $user = null;
|
var $user = null;
|
||||||
|
var $tag = null;
|
||||||
|
|
||||||
function prepare($args)
|
function prepare($args)
|
||||||
{
|
{
|
||||||
parent::prepare($args);
|
parent::prepare($args);
|
||||||
$nickname = $this->trimmed('nickname');
|
$nickname = $this->trimmed('nickname');
|
||||||
$this->user = User::staticGet('nickname', $nickname);
|
$this->user = User::staticGet('nickname', $nickname);
|
||||||
|
$this->tag = $this->trimmed('tag');
|
||||||
|
|
||||||
if (!$this->user) {
|
if (!$this->user) {
|
||||||
$this->clientError(_('No such user.'));
|
$this->clientError(_('No such user.'));
|
||||||
@ -42,17 +43,37 @@ 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)
|
function getNotices($limit=0)
|
||||||
{
|
{
|
||||||
|
|
||||||
$user = $this->user;
|
$user = $this->user;
|
||||||
|
|
||||||
if (is_null($user)) {
|
if (is_null($user)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$notice = $user->getNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit);
|
$notice = $user->getNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit);
|
||||||
|
|
||||||
|
$notices = array();
|
||||||
while ($notice->fetch()) {
|
while ($notice->fetch()) {
|
||||||
$notices[] = clone($notice);
|
$notices[] = clone($notice);
|
||||||
}
|
}
|
||||||
@ -87,17 +108,16 @@ class UserrssAction extends Rss10Action
|
|||||||
}
|
}
|
||||||
|
|
||||||
# override parent to add X-SUP-ID URL
|
# override parent to add X-SUP-ID URL
|
||||||
|
|
||||||
function initRss($limit=0)
|
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);
|
header('X-SUP-ID: '.$url);
|
||||||
parent::initRss($limit);
|
parent::initRss($limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ class XrdsAction extends Action
|
|||||||
*
|
*
|
||||||
* @return boolean true
|
* @return boolean true
|
||||||
*/
|
*/
|
||||||
function isReadOnly()
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return true;
|
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