Merge branch '0.8.x' of git@gitorious.org:+laconica-developers/laconica/dev into upload

This commit is contained in:
Robin Millette 2009-05-26 23:46:37 -04:00
commit 37423b12d7
19 changed files with 531 additions and 280 deletions

26
README
View File

@ -1136,6 +1136,32 @@ welcome: nickname of a user account that sends welcome messages to new
If either of these special user accounts are specified, the users should
be created before the configuration is updated.
snapshot
--------
The software will, by default, send statistical snapshots about the
local installation to a stats server on the laconi.ca Web site. This
data is used by the developers to prioritize development decisions. No
identifying data about users or organizations is collected. The data
is available to the public for review. Participating in this survey
helps Laconica developers take your needs into account when updating
the software.
run: string indicating when to run the statistics. Values can be 'web'
(run occasionally at Web time), 'cron' (run from a cron script),
or 'never' (don't ever run). If you set it to 'cron', remember to
schedule the script to run on a regular basis.
frequency: if run value is 'web', how often to report statistics.
Measured in Web hits; depends on how active your site is.
Default is 10000 -- that is, one report every 10000 Web hits,
on average.
reporturl: URL to post statistics to. Defaults to Laconica developers'
report system, but if they go evil or disappear you may
need to update this to another value. Note: if you
don't want to report stats, it's much better to
set 'run' to 'never' than to set this value to something
nonsensical.
Troubleshooting
===============

View File

@ -115,7 +115,7 @@ class FacebookhomeAction extends FacebookAction
$flink->foreign_id = $this->fbuid;
$flink->service = FACEBOOK_SERVICE;
$flink->created = common_sql_now();
$flink->set_flags(true, false, false);
$flink->set_flags(true, false, false, false);
$flink_id = $flink->insert();
@ -138,9 +138,6 @@ class FacebookhomeAction extends FacebookAction
function setDefaults()
{
// A default prefix string for notices
$this->facebook->api_client->data_setUserPreference(
FACEBOOK_NOTICE_PREFIX, 'dented: ');
$this->facebook->api_client->data_setUserPreference(
FACEBOOK_PROMPTED_UPDATE_PREF, 'false');
}

View File

@ -17,7 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('LACONICA')) { exit(1); }
if (!defined('LACONICA')) {
exit(1);
}
require_once(INSTALLDIR.'/lib/facebookaction.php');
@ -67,7 +69,7 @@ class FacebookinviteAction extends FacebookAction
function showSuccessContent()
{
$this->element('h2', null, sprintf(_('Thanks for inviting your friends to use %s'),
$this->element('h2', null, sprintf(_('Thanks for inviting your friends to use %s'),
common_config('site', 'name')));
$this->element('p', null, _('Invitations have been sent to the following users:'));
@ -89,16 +91,6 @@ class FacebookinviteAction extends FacebookAction
function showFormContent()
{
// Get a list of users who are already using the app for exclusion
$exclude_ids = $this->facebook->api_client->friends_getAppUsers();
$exclude_ids_csv = null;
// fbml needs these as a csv string, not an array
if ($exclude_ids) {
$exclude_ids_csv = implode(',', $exclude_ids);
}
$content = sprintf(_('You have been invited to %s'), common_config('site', 'name')) .
htmlentities('<fb:req-choice url="' . $this->app_uri . '" label="Add"/>');
@ -109,36 +101,43 @@ class FacebookinviteAction extends FacebookAction
'content' => $content));
$this->hidden('invite', 'true');
$actiontext = sprintf(_('Invite your friends to use %s'), common_config('site', 'name'));
$multi_params = array('showborder' => 'false');
$multi_params = array('showborder' => 'false');
$multi_params['actiontext'] = $actiontext;
if ($exclude_ids_csv) {
$multi_params['bypass'] = 'cancel';
// Get a list of users who are already using the app for exclusion
$exclude_ids = $this->facebook->api_client->friends_getAppUsers();
$exclude_ids_csv = null;
// fbml needs these as a csv string, not an array
if ($exclude_ids) {
$exclude_ids_csv = implode(',', $exclude_ids);
$multi_params['exclude_ids'] = $exclude_ids_csv;
}
$multi_params['bypass'] = 'cancel';
$this->element('fb:multi-friend-selector', $multi_params);
$this->elementEnd('fb:request-form');
$this->element('h2', null, sprintf(_('Friends already using %s:'),
common_config('site', 'name')));
$this->elementStart('ul', array('id' => 'facebook-friends'));
foreach ($exclude_ids as $friend) {
$this->elementStart('li');
$this->element('fb:profile-pic', array('uid' => $friend, 'size' => 'square'));
$this->element('fb:name', array('uid' => $friend,
'capitalize' => 'true'));
$this->elementEnd('li');
}
if ($exclude_ids) {
$this->elementEnd("ul");
$this->element('h2', null, sprintf(_('Friends already using %s:'),
common_config('site', 'name')));
$this->elementStart('ul', array('id' => 'facebook-friends'));
foreach ($exclude_ids as $friend) {
$this->elementStart('li');
$this->element('fb:profile-pic', array('uid' => $friend, 'size' => 'square'));
$this->element('fb:name', array('uid' => $friend,
'capitalize' => 'true'));
$this->elementEnd('li');
}
$this->elementEnd("ul");
}
}
function title()
function title()
{
return sprintf(_('Send invitations'));
}

View File

@ -55,7 +55,7 @@ class FacebooksettingsAction extends FacebookAction
$prefix = $this->trimmed('prefix');
$original = clone($this->flink);
$this->flink->set_flags($noticesync, $replysync, false);
$this->flink->set_flags($noticesync, $replysync, false, false);
$result = $this->flink->update($original);
$this->facebook->api_client->data_setUserPreference(FACEBOOK_NOTICE_PREFIX,

0
classes/Group_inbox.php Executable file → Normal file
View File

0
classes/Group_member.php Executable file → Normal file
View File

0
classes/Related_group.php Executable file → Normal file
View File

0
classes/Status_network.php Executable file → Normal file
View File

0
classes/User_group.php Executable file → Normal file
View File

View File

@ -46,6 +46,64 @@ modified = 384
notice_id = K
user_id = K
[file]
id = 129
url = 2
mimetype = 2
size = 1
title = 2
date = 1
protected = 1
[file__keys]
id = N
[file_oembed]
id = 129
file_id = 1
version = 2
type = 2
provider = 2
provider_url = 2
width = 1
height = 1
html = 34
title = 2
author_name = 2
author_url = 2
url = 2
[file_oembed__keys]
id = N
[file_redirection]
id = 129
url = 2
file_id = 1
redirections = 1
httpcode = 1
[file_redirection__keys]
id = N
[file_thumbnail]
id = 129
file_id = 1
url = 2
width = 1
height = 1
[file_thumbnail__keys]
id = N
[file_to_post]
id = 129
file_id = 1
post_id = 1
[file_to_post__keys]
id = N
[foreign_link]
user_id = 129
foreign_id = 129
@ -392,63 +450,3 @@ modified = 384
[user_openid__keys]
canonical = K
display = U
[file]
id = 129
url = 2
mimetype = 2
size = 1
title = 2
date = 1
protected = 1
[file__keys]
id = N
[file_oembed]
id = 129
file_id = 129
version = 2
type = 2
provider = 2
provider_url = 2
width = 1
height = 1
html = 34
title = 2
author_name = 2
author_url = 2
url = 2
[file_oembed__keys]
id = N
[file_redirection]
id = 129
url = 2
file_id = 129
redirections = 1
httpcode = 1
[file_redirection__keys]
id = N
[file_thumbnail]
id = 129
file_id = 129
url = 2
width = 1
height = 1
[file_thumbnail__keys]
id = N
[file_to_post]
id = 129
file_id = 129
post_id = 129
[file_to_post__keys]
id = N

View File

@ -206,3 +206,12 @@ $config['sphinx']['port'] = 3312;
// print "Error\n";
// exit(1);
// }
// How often to send snapshots; in # of web hits. Ideally,
// try to do this once per month (that is, make this equal to number
// of hits per month)
// $config['snapshot']['frequency'] = 10000;
// If you don't want to report statistics to the central server, uncomment.
// $config['snapshot']['run'] = 'never';
// If you want to report statistics in a cron job instead.
// $config['snapshot']['run'] = 'cron';

View File

@ -426,12 +426,12 @@ create table group_inbox (
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
create table file (
id integer primary key auto_increment,
url varchar(255), mimetype varchar(50),
size integer,
title varchar(255),
date integer(11),
protected integer(1),
id integer primary key auto_increment,
url varchar(255), mimetype varchar(50),
size integer,
title varchar(255),
date integer(11),
protected integer(1),
unique(url)
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci;
@ -447,40 +447,38 @@ create table file_oembed (
height integer,
html text,
title varchar(255),
author_name varchar(50),
author_url varchar(255),
url varchar(255),
author_name varchar(50),
author_url varchar(255),
url varchar(255),
unique(file_id)
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci;
create table file_redirection (
id integer primary key auto_increment,
url varchar(255),
file_id integer,
redirections integer,
httpcode integer,
id integer primary key auto_increment,
url varchar(255),
file_id integer,
redirections integer,
httpcode integer,
unique(url)
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
create table file_thumbnail (
id integer primary key auto_increment,
file_id integer,
url varchar(255),
width integer,
height integer,
id integer primary key auto_increment,
file_id integer,
url varchar(255),
width integer,
height integer,
unique(file_id),
unique(file_id),
unique(url)
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
create table file_to_post (
id integer primary key auto_increment,
file_id integer,
post_id integer,
id integer primary key auto_increment,
file_id integer,
post_id integer,
unique(file_id, post_id)
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;

View File

@ -7,6 +7,7 @@ VALUES
('cliqset', 'Cliqset', 'http://www.cliqset.com/', now()),
('deskbar','Deskbar-Applet','http://www.gnome.org/projects/deskbar-applet/', now()),
('Do','Gnome Do','http://do.davebsd.com/wiki/index.php?title=Microblog_Plugin', now()),
('eventbox','EventBox','http://thecosmicmachine.com/eventbox/ ', now()),
('Facebook','Facebook','http://apps.facebook.com/identica/', now()),
('feed2omb','feed2omb','http://projects.ciarang.com/p/feed2omb/', now()),
('gravity', 'Gravity', 'http://mobileways.de/gravity', now()),

View File

@ -69,6 +69,8 @@ function main()
}
global $user, $action, $config;
Snapshot::check();
if (!_have_config()) {
$msg = sprintf(_("No configuration file found. Try running ".
"the installation program first."));

View File

@ -159,6 +159,10 @@ $config =
'newuser' =>
array('subscribe' => null,
'welcome' => null),
'snapshot' =>
array('run' => 'web',
'frequency' => 10000,
'reporturl' => 'http://laconi.ca/stats/report'),
);
$config['db'] = &PEAR::getStaticProperty('DB_DataObject','options');

View File

@ -38,14 +38,14 @@ require_once INSTALLDIR.'/lib/noticeform.php';
class FacebookAction extends Action
{
var $facebook = null;
var $fbuid = null;
var $flink = null;
var $action = null;
var $app_uri = null;
var $app_name = null;
/**
* Constructor
*
@ -60,71 +60,71 @@ class FacebookAction extends Action
function __construct($output='php://output', $indent=true, $facebook=null, $flink=null)
{
parent::__construct($output, $indent);
$this->facebook = $facebook;
$this->flink = $flink;
if ($this->flink) {
$this->fbuid = $flink->foreign_id;
$this->fbuid = $flink->foreign_id;
$this->user = $flink->getUser();
}
$this->args = array();
}
function prepare($argarray)
{
{
parent::prepare($argarray);
$this->facebook = getFacebook();
$this->fbuid = $this->facebook->require_login();
$this->action = $this->trimmed('action');
$app_props = $this->facebook->api_client->Admin_getAppProperties(
array('canvas_name', 'application_name'));
$this->app_uri = 'http://apps.facebook.com/' . $app_props['canvas_name'];
$this->app_name = $app_props['application_name'];
$this->flink = Foreign_link::getByForeignID($this->fbuid, FACEBOOK_SERVICE);
return true;
}
function showStylesheets()
{
// Add a timestamp to the file so Facebook cache wont ignore our changes
$ts = filemtime(INSTALLDIR.'/theme/base/css/display.css');
$this->element('link', array('rel' => 'stylesheet',
'type' => 'text/css',
'href' => theme_path('css/display.css', 'base') . '?ts=' . $ts));
$this->element('link', array('rel' => 'stylesheet',
'type' => 'text/css',
'href' => theme_path('css/display.css', 'base') . '?ts=' . $ts));
$theme = common_config('site', 'theme');
$ts = filemtime(INSTALLDIR. '/theme/' . $theme .'/css/display.css');
$this->element('link', array('rel' => 'stylesheet',
'type' => 'text/css',
'href' => theme_path('css/display.css', null) . '?ts=' . $ts));
$ts = filemtime(INSTALLDIR.'/theme/base/css/facebookapp.css');
$this->element('link', array('rel' => 'stylesheet',
'type' => 'text/css',
'href' => theme_path('css/facebookapp.css', 'base') . '?ts=' . $ts));
}
function showScripts()
{
// Add a timestamp to the file so Facebook cache wont ignore our changes
$ts = filemtime(INSTALLDIR.'/js/facebookapp.js');
$this->element('script', array('src' => common_path('js/facebookapp.js') . '?ts=' . $ts));
}
/**
* Start an Facebook ready HTML document
*
@ -138,11 +138,11 @@ class FacebookAction extends Action
* @return void
*/
function startHTML($type=null)
{
function startHTML($type=null)
{
$this->showStylesheets();
$this->showScripts();
$this->elementStart('div', array('class' => 'facebook-page'));
}
@ -177,18 +177,18 @@ class FacebookAction extends Action
$this->showFooter();
$this->elementEnd('div');
}
function showAside()
{
}
function showHead($error, $success)
{
if ($error) {
$this->element("h1", null, $error);
}
if ($success) {
$this->element("h1", null, $success);
}
@ -198,10 +198,10 @@ class FacebookAction extends Action
$this->element('fb:add-section-button', array('section' => 'profile'));
$this->elementEnd('span');
$this->elementEnd('fb:if-section-not-added');
}
// Make this into a widget later
function showLocalNav()
{
@ -229,8 +229,8 @@ class FacebookAction extends Action
$this->elementEnd('li');
$this->elementEnd('ul');
}
}
/**
* Show header of the page.
*
@ -245,7 +245,7 @@ class FacebookAction extends Action
$this->showNoticeForm();
$this->elementEnd('div');
}
/**
* Show page, a template method.
*
@ -258,7 +258,7 @@ class FacebookAction extends Action
$this->showBody();
$this->endHTML();
}
function showInstructions()
{
@ -278,7 +278,7 @@ class FacebookAction extends Action
$this->element('a',
array('href' => common_local_url('register')), _('Register'));
$this->text($loginmsg_part2);
$this->elementEnd('p');
$this->elementEnd('p');
$this->elementEnd('dd');
$this->elementEnd('dl');
@ -317,7 +317,7 @@ class FacebookAction extends Action
$this->elementEnd('ul');
$this->submit('submit', _('Login'));
$this->elementEnd('fieldset');
$this->elementEnd('fieldset');
$this->elementEnd('form');
$this->elementStart('p');
@ -329,73 +329,73 @@ class FacebookAction extends Action
$this->elementEnd('div');
}
function updateProfileBox($notice)
{
// Need to include inline CSS for styling the Profile box
$app_props = $this->facebook->api_client->Admin_getAppProperties(array('icon_url'));
$icon_url = $app_props['icon_url'];
$app_props = $this->facebook->api_client->Admin_getAppProperties(array('icon_url'));
$icon_url = $app_props['icon_url'];
$style = '<style>
.entry-title *,
.entry-content * {
font-size:14px;
font-family:"Lucida Sans Unicode", "Lucida Grande", sans-serif;
}
.entry-title a,
.entry-content a {
color:#002E6E;
}
.entry-title *,
.entry-content * {
font-size:14px;
font-family:"Lucida Sans Unicode", "Lucida Grande", sans-serif;
}
.entry-title a,
.entry-content a {
color:#002E6E;
}
.entry-title .vcard .photo {
float:left;
display:inline;
margin-right:11px;
margin-bottom:11px
margin-right:11px;
margin-bottom:11px
}
.entry-title {
margin-bottom:11px;
}
.entry-title {
margin-bottom:11px;
}
.entry-title p.entry-content {
display:inline;
margin-left:5px;
margin-left:5px;
}
div.entry-content {
clear:both;
}
div.entry-content {
clear:both;
}
div.entry-content dl,
div.entry-content dt,
div.entry-content dd {
display:inline;
text-transform:lowercase;
text-transform:lowercase;
}
div.entry-content dd,
div.entry-content .device dt {
margin-left:0;
margin-right:5px;
div.entry-content .device dt {
margin-left:0;
margin-right:5px;
}
div.entry-content dl.timestamp dt,
div.entry-content dl.response dt {
div.entry-content dl.response dt {
display:none;
}
div.entry-content dd a {
display:inline-block;
}
#facebook_laconica_app {
text-indent:-9999px;
height:16px;
width:16px;
display:block;
background:url('.$icon_url.') no-repeat 0 0;
float:right;
}
</style>';
#facebook_laconica_app {
text-indent:-9999px;
height:16px;
width:16px;
display:block;
background:url('.$icon_url.') no-repeat 0 0;
float:right;
}
</style>';
$this->xw->openMemory();
@ -407,12 +407,12 @@ class FacebookAction extends Action
$fbml_main = "<fb:narrow>$style " . $this->xw->outputMemory(false) . "</fb:narrow>";
$this->facebook->api_client->profile_setFBML(null, $this->fbuid, $fbml, null, null, $fbml_main);
$this->facebook->api_client->profile_setFBML(null, $this->fbuid, $fbml, null, null, $fbml_main);
$this->xw->openURI('php://output');
}
/**
* Generate pagination links
*
@ -457,24 +457,24 @@ class FacebookAction extends Action
$this->elementEnd('div');
}
}
function updateFacebookStatus($notice)
function updateFacebookStatus($notice)
{
$prefix = $this->facebook->api_client->data_getUserPreference(FACEBOOK_NOTICE_PREFIX, $this->fbuid);
$content = "$prefix $notice->content";
if ($this->facebook->api_client->users_hasAppPermission('status_update', $this->fbuid)) {
$this->facebook->api_client->users_setStatus($content, $this->fbuid, false, true);
}
}
function saveNewNotice()
{
$user = $this->flink->getUser();
$content = $this->trimmed('status_textarea');
if (!$content) {
$this->showPage(_('No notice content!'));
return;
@ -492,9 +492,9 @@ class FacebookAction extends Action
$cmd = $inter->handle_command($user, $content_shortened);
if ($cmd) {
// XXX fix this
$cmd->execute(new WebChannel());
return;
}
@ -510,20 +510,20 @@ class FacebookAction extends Action
}
common_broadcast_notice($notice);
// Also update the user's Facebook status
$this->updateFacebookStatus($notice);
$this->updateProfileBox($notice);
}
}
class FacebookNoticeForm extends NoticeForm
class FacebookNoticeForm extends NoticeForm
{
var $post_action = null;
/**
* Constructor
*
@ -532,13 +532,13 @@ class FacebookNoticeForm extends NoticeForm
* @param string $content content to pre-fill
*/
function __construct($out=null, $action=null, $content=null,
function __construct($out=null, $action=null, $content=null,
$post_action=null, $user=null)
{
parent::__construct($out, $action, $content, $user);
$this->post_action = $post_action;
}
/**
* Action of the form
*
@ -554,7 +554,7 @@ class FacebookNoticeForm extends NoticeForm
class FacebookNoticeList extends NoticeList
{
/**
* constructor
*
@ -565,7 +565,7 @@ class FacebookNoticeList extends NoticeList
{
parent::__construct($notice, $out);
}
/**
* show the list of notices
*
@ -619,7 +619,7 @@ class FacebookNoticeList extends NoticeList
}
class FacebookNoticeListItem extends NoticeListItem
{
{
/**
* constructor
@ -646,51 +646,19 @@ class FacebookNoticeListItem extends NoticeListItem
function show()
{
$this->showStart();
$this->showNotice();
$this->showNoticeInfo();
$this->out->elementStart('div', 'entry-title');
$this->showAuthor();
$this->showContent();
$this->out->elementEnd('div');
$this->out->elementStart('div', 'entry-content');
$this->showNoticeLink();
$this->showNoticeSource();
$this->showReplyTo();
$this->out->elementEnd('div');
// XXX: Need to update to show attachements and controls
$this->showEnd();
}
function showNoticeLink()
{
$noticeurl = common_local_url('shownotice',
array('notice' => $this->notice->id));
// XXX: we need to figure this out better. Is this right?
if (strcmp($this->notice->uri, $noticeurl) != 0 &&
preg_match('/^http/', $this->notice->uri)) {
$noticeurl = $this->notice->uri;
}
$this->out->elementStart('dl', 'timestamp');
$this->out->element('dt', null, _('Published'));
$this->out->elementStart('dd', null);
$this->out->elementStart('a', array('rel' => 'bookmark',
'href' => $noticeurl));
$dt = common_date_iso8601($this->notice->created);
$this->out->element('abbr', array('class' => 'published',
'title' => $dt),
common_date_string($this->notice->created));
$this->out->elementEnd('a');
$this->out->elementEnd('dd');
$this->out->elementEnd('dl');
}
}
class FacebookProfileBoxNotice extends FacebookNoticeListItem
{
{
/**
* constructor
*
@ -703,36 +671,24 @@ class FacebookProfileBoxNotice extends FacebookNoticeListItem
{
parent::__construct($notice, $out);
}
/**
* Recipe function for displaying a single notice in the
* Facebook App's Profile
* Recipe function for displaying a single notice in the
* Facebook App profile notice box
*
* @return void
*/
function show()
{
$this->out->elementStart('div', 'entry-title');
$this->showAuthor();
$this->showContent();
$this->out->elementEnd('div');
$this->out->elementStart('div', 'entry-content');
$this->showNoticeLink();
$this->showNoticeSource();
$this->showReplyTo();
$this->out->elementEnd('div');
$this->showNotice();
$this->showNoticeInfo();
$this->showAppLink();
}
function showAppLink()
function showAppLink()
{
$this->facebook = getFacebook();
$app_props = $this->facebook->api_client->Admin_getAppProperties(
@ -740,7 +696,7 @@ class FacebookProfileBoxNotice extends FacebookNoticeListItem
$this->app_uri = 'http://apps.facebook.com/' . $app_props['canvas_name'];
$this->app_name = $app_props['application_name'];
$this->out->elementStart('a', array('id' => 'facebook_laconica_app',
'href' => $this->app_uri));
$this->out->text($this->app_name);

227
lib/snapshot.php Normal file
View File

@ -0,0 +1,227 @@
<?php
/**
* Laconica, the distributed open-source microblogging tool
*
* A snapshot of site stats that can report itself to headquarters
*
* 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 Stats
* @package Laconica
* @author Evan Prodromou <evan@controlyourself.ca>
* @copyright 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);
}
/**
* A snapshot of site stats that can report itself to headquarters
*
* This class will collect statistics on the site and report them to
* a statistics server of the admin's choice. (Default is the big one
* at laconi.ca.)
*
* It can either be called from a cron job, or run occasionally by the
* Web site.
*
* @category Stats
* @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 Snapshot
{
var $stats = null;
/**
* Constructor for a snapshot
*/
function __construct()
{
}
/**
* Static function for reporting statistics
*
* This function checks whether it should report statistics, based on
* the current configuation settings. If it should, it creates a new
* Snapshot object, takes a snapshot, and reports it to headquarters.
*
* @return void
*/
static function check()
{
switch (common_config('snapshot', 'run')) {
case 'web':
// skip if we're not running on the Web.
if (!isset($_SERVER) || !array_key_exists('REQUEST_METHOD', $_SERVER)) {
break;
}
// Run once every frequency hits
// XXX: do frequency by time (once a week, etc.) rather than
// hits
if (rand() % common_config('snapshot', 'frequency') == 0) {
$snapshot = new Snapshot();
$snapshot->take();
$snapshot->report();
}
break;
case 'cron':
// skip if we're running on the Web
if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
break;
}
common_log(LOG_INFO, 'Running snapshot from cron job');
// We're running from the command line; assume
$snapshot = new Snapshot();
$snapshot->take();
common_log(LOG_INFO, count($snapshot->stats) . " statistics being uploaded.");
$snapshot->report();
break;
case 'never':
break;
default:
common_log(LOG_WARNING, "Unrecognized value for snapshot run config.");
}
}
/**
* Take a snapshot of the server
*
* Builds an array of statistical and configuration data based
* on the local database and config files. We avoid grabbing any
* information that could be personal or private.
*
* @return void
*/
function take()
{
$this->stats = array();
// Some basic identification stuff
$this->stats['version'] = LACONICA_VERSION;
$this->stats['phpversion'] = phpversion();
$this->stats['name'] = common_config('site', 'name');
$this->stats['root'] = common_root_url();
// non-identifying stats on various tables. Primary
// interest is size and rate of activity of service.
$tables = array('user',
'notice',
'subscription',
'remote_profile',
'user_group');
foreach ($tables as $table) {
$this->tableStats($table);
}
// stats on some important config options
$this->stats['theme'] = common_config('site', 'theme');
$this->stats['dbtype'] = common_config('db', 'type');
$this->stats['xmpp'] = common_config('xmpp', 'enabled');
$this->stats['inboxes'] = common_config('inboxes', 'enabled');
$this->stats['queue'] = common_config('queue', 'enabled');
$this->stats['license'] = common_config('license', 'url');
$this->stats['fancy'] = common_config('site', 'fancy');
$this->stats['private'] = common_config('site', 'private');
$this->stats['closed'] = common_config('site', 'closed');
$this->stats['memcached'] = common_config('memcached', 'enabled');
$this->stats['language'] = common_config('site', 'language');
$this->stats['timezone'] = common_config('site', 'timezone');
}
/**
* Reports statistics to headquarters
*
* Posts statistics to a reporting server.
*
* @return void
*/
function report()
{
// XXX: Use OICU2 and OAuth to make authorized requests
$postdata = http_build_query($this->stats);
$opts =
array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: '.
'application/x-www-form-urlencoded',
'content' => $postdata,
'user_agent' => 'Laconica/'.LACONICA_VERSION
)
);
$context = stream_context_create($opts);
$reporturl = common_config('snapshot', 'reporturl');
$result = @file_get_contents($reporturl, false, $context);
return $result;
}
/**
* Updates statistics for a single table
*
* Determines the size of a table and its oldest and newest rows.
* Goal here is to see how active a site is. Note that it
* fills up the instance stats variable.
*
* @param string $table name of table to check
*
* @return void
*/
function tableStats($table)
{
$inst = DB_DataObject::factory($table);
$inst->selectAdd();
$inst->selectAdd('count(*) as cnt, '.
'min(created) as first, '.
'max(created) as last');
if ($inst->find(true)) {
$this->stats[$table.'count'] = $inst->cnt;
$this->stats[$table.'first'] = $inst->first;
$this->stats[$table.'last'] = $inst->last;
}
$inst->free();
unset($inst);
}
}

View File

@ -0,0 +1,37 @@
#!/usr/bin/env php
<?php
/*
* Laconica - a distributed open-source microblogging tool
* Copyright (C) 2009, Control Yourself, 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/>.
*/
# Abort if called from a web server
if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
print "This script must be run from the command line\n";
exit(1);
}
ini_set("max_execution_time", "0");
ini_set("max_input_time", "0");
set_time_limit(0);
mb_internal_encoding('UTF-8');
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
define('LACONICA', true);
require_once(INSTALLDIR . '/lib/common.php');
Snapshot::check();

View File

@ -1,6 +1,3 @@
@import url("display.css");
@import url("../../identica/css/display.css");
* {
font-size:14px;
font-family:"Lucida Sans Unicode", "Lucida Grande", sans-serif;