Browse Source

- Rewrite the WidgetWrapper and clean the old BOSH related code

- Rewrite the AccountNext widget and move everything XMPP related to Moxl
- New behaviour for the Websocket unregistration
pull/16/head
Jaussoin Timothée 11 years ago
parent
commit
33f0e26879
  1. 34
      app/assets/js/movim_websocket.js
  2. 291
      app/widgets/AccountNext/AccountNext.php
  3. 45
      app/widgets/AccountNext/_accountnext_form.tpl
  4. 10
      app/widgets/AccountNext/_accountnext_oob.tpl
  5. 9
      app/widgets/AccountNext/_accountnext_registered.tpl
  6. 12
      app/widgets/AccountNext/accountnext.js
  7. 8
      app/widgets/AccountNext/accountnext.tpl
  8. 6
      app/widgets/AccountNext/locales.ini
  9. 2
      app/widgets/ContactPubsubSubscription/ContactPubsubSubscription.php
  10. 7
      app/widgets/Login/Login.php
  11. 2
      app/widgets/Login/login.js
  12. 1
      app/widgets/Menu/Menu.php
  13. 4
      app/widgets/Subscribe/subscribe.js
  14. 16
      lib/XMPPtoForm.php
  15. 16
      linker.php
  16. 1
      locales/locales.ini
  17. 4
      src/Movim/Daemon/Session.php
  18. 10
      system/Event.php
  19. 1
      system/Session.php
  20. 254
      system/widget/WidgetWrapper.php
  21. 3
      themes/movim/css/style.css
  22. BIN
      themes/movim/img/icons/placeholder/clipboard.png

34
app/assets/js/movim_websocket.js

@ -4,14 +4,6 @@
* This file define the websocket behaviour and handle its connection * This file define the websocket behaviour and handle its connection
*/ */
WebSocket.prototype.register = function() {
this.send(JSON.stringify(
{
'func' : 'register',
'sid' : localStorage.movimSession,
'baseuri' : BASE_URI
}));
};
WebSocket.prototype.unregister = function() { WebSocket.prototype.unregister = function() {
this.send(JSON.stringify({'func' : 'unregister'})); this.send(JSON.stringify({'func' : 'unregister'}));
}; };
@ -28,6 +20,7 @@ WebSocket.prototype.admin = function(key) {
var MovimWebsocket = { var MovimWebsocket = {
connection: null, connection: null,
attached: null, attached: null,
unregistered: false,
launchAttached : function() { launchAttached : function() {
for(var i = 0; i < this.attached.length; i++) { for(var i = 0; i < this.attached.length; i++) {
@ -49,12 +42,6 @@ var MovimWebsocket = {
var obj = JSON.parse(data); var obj = JSON.parse(data);
if(obj.id) {
localStorage.movimSession = obj.id;
document.cookie = 'MOVIM_SESSION_ID=' + obj.id;
this.register();
}
if(obj.func == 'registered') { if(obj.func == 'registered') {
MovimWebsocket.launchAttached(); MovimWebsocket.launchAttached();
} }
@ -69,7 +56,12 @@ var MovimWebsocket = {
this.connection.onclose = function(e) { this.connection.onclose = function(e) {
console.log("Connection closed by the server or session closed"); console.log("Connection closed by the server or session closed");
if(e.code == 1006 || e.code == 1000) { if(e.code == 1006 || e.code == 1000) {
movim_disconnect();
if(MovimWebsocket.unregistered == false) {
movim_disconnect();
} else {
MovimWebsocket.unregistered = false;
MovimWebsocket.init();
}
} }
}; };
@ -105,7 +97,7 @@ var MovimWebsocket = {
if(funcalls != null) { if(funcalls != null) {
for(h = 0; h < funcalls.length; h++) { for(h = 0; h < funcalls.length; h++) {
var funcall = funcalls[h]; var funcall = funcalls[h];
//console.log(funcall);
console.log(funcall);
if(funcall.func != null && (typeof window[funcall.func] == 'function')) { if(funcall.func != null && (typeof window[funcall.func] == 'function')) {
try { try {
window[funcall.func].apply(null, funcall.params); window[funcall.func].apply(null, funcall.params);
@ -123,14 +115,20 @@ var MovimWebsocket = {
} }
}, },
unregister : function() {
unregister : function(reload) {
if(reload == false) this.unregistered = true;
this.connection.unregister(); this.connection.unregister();
} }
} }
function remoteUnregister() function remoteUnregister()
{ {
MovimWebsocket.unregister();
MovimWebsocket.unregister(false);
}
function remoteUnregisterReload()
{
MovimWebsocket.unregister(true);
} }
window.onbeforeunload = function() { window.onbeforeunload = function() {

291
app/widgets/AccountNext/AccountNext.php

@ -17,234 +17,105 @@
* *
* See COPYING for licensing information. * See COPYING for licensing information.
*/ */
use Moxl\Xec\Action\Disco\Request;
use Moxl\Xec\Action\Register\Get;
use Moxl\Xec\Action\Register\Set;
class AccountNext extends WidgetBase { class AccountNext extends WidgetBase {
function load() function load()
{ {
$this->addcss('accountnext.css');
$this->addjs('accountnext.js'); $this->addjs('accountnext.js');
$xml = requestURL('http://movim.eu/server-vcards.xml', 1);
if($xml) {
$xml = simplexml_load_string($xml);
$xml = (array)$xml->children();
$this->view->assign('servers', $xml['vcard']);
} else {
$this->view->assign('servers', false);
}
if(isset($_GET['s'])) {
$this->view->assign(
'getsubscriptionform',
$this->call('ajaxDiscoverServer', "'".$_GET['s']."'")
);
$this->view->assign('ndd', $_GET['s']);
} else {
$this->view->assign('getsubscriptionform','');
$this->view->assign('ndd', '');
}
$this->registerEvent('register_get_handle', 'onForm');
$this->registerEvent('register_set_handle', 'onRegistered');
$this->registerEvent('register_set_errorconflict', 'onRegisterError');
$this->registerEvent('register_set_errornotacceptable', 'onRegisterNotAcceptable');
$this->registerEvent('register_get_errorserviceunavailable', 'onServiceUnavailable');
} }
function ajaxDiscoverServer($ndd) {
try {
$dns = dns_get_record('_xmpp-client._tcp.'.$ndd);
if(isset($dns[0]['target']) && $dns[0]['target'] != null) {
$domain = $dns[0]['target'];
} else {
$domain = $ndd['ndd'];
}
$f = fsockopen($domain, 5222, $errno, $errstr, 10);
if(!$f ) {
RPC::call('movim_reload', Route::urlize('account', 'xmppconnect'));
RPC::commit();
exit;
}
global $language;
$stream = simplexml_load_string('<?xml version="1.0"?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" version="1.0"><iq type="get" id="reg1" xml:lang="'.$language.'"><query xmlns="jabber:iq:register"/></iq></stream:stream>');
$stream->addAttribute('to', $ndd);
if (false === fwrite($f, $stream->asXML())) {
\system\Logs\Logger::log('fail write to stream');
throw new \Exception('fail write to stream');
}
unset($stream);
$response = stream_get_contents($f);
if(!$response) {
RPC::call('movim_reload', Route::urlize('account', 'xmppcomm'));
RPC::commit();
exit;
}
$response = simplexml_load_string($response);
$id = (string)$response->attributes()->id;
$elements = (array)$response->iq->query;
// We close properly our first register request
$stream = simplexml_load_string('<?xml version="1.0"?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" version="1.0"><iq type="set" id="unreg1"><query xmlns="jabber:iq:register"><remove/></query></iq></stream:stream>');
$stream->addAttribute('to', $ndd);
fwrite($f, $stream->asXML());
fclose($f); unset($f);
if(!empty($elements)) {
$formview = $this->tpl();
if($response->iq->query->instructions && $response->iq->query->x) {
$instr = '
<div class="element simple large">
<label>'.(string)$response->iq->query->instructions.'</label>';
if($response->iq->query->x->url)
$instr .= '
<a href="'.(string)$response->iq->query->x->url.'" target="_blank">'.
(string)$response->iq->query->x->url.'
</a>';
$instr .= '
</div>';
}
$form = new XMPPtoForm();
if(!empty($response->iq->query->x)){
$formh = $form->getHTML($response->iq->query->x->asXML());
} else{// no <x> element in the XML
$formh = $form->getHTML($response->iq->query->asXML());
}
if($formh != '')
$instr = '';
$formview->assign('instr', $instr);
$formview->assign('formh', $formh);
$formview->assign('id', $id);
$formview->assign('ndd', $ndd);
$formview->assign('domain', $domain);
$formview->assign(
'submitdata',
$this->call('ajaxSubmitData', "movim_form_to_json('data')"));
$html = $formview->draw('_accountnext_form', true);
function display()
{
$host = $_GET['s'];
$this->view->assign('getsubscriptionform', $this->call('ajaxGetForm', "'".$host."'"));
$this->view->assign('host', $host);
}
/*
if(isset($elements['data'])) {
$html .= '<img src="data:image/jpg;base64,'.$elements['data'].'"/>';
}
*/
} else {
$html = '
<div class="message warning">
'.$this->__('create.notfound').'
</div>';
function onForm($package)
{
$form = $package->content;
$xtf = new \XMPPtoForm();
if(!empty($form->x)){
$ns = $form->x->getNamespaces();
switch($ns['']) {
case 'jabber:x:data' :
$formview = $this->tpl();
$formh = $xtf->getHTML($form->x->asXML());
$formview->assign('submitdata', $this->call('ajaxRegister', "movim_form_to_json('data')"));
$formview->assign('formh', $formh);
$html = $formview->draw('_accountnext_form', true);
RPC::call('movim_fill', 'subscription_form', $html);
break;
case 'jabber:x:oob' :
$oobview = $this->tpl();
$oobview->assign('url', (string)$form->x->url);
$html = $oobview->draw('_accountnext_oob', true);
RPC::call('movim_fill', 'subscription_form', $html);
RPC::call('remoteUnregister');
break;
} }
RPC::call('movim_fill', 'subscription_form', $html);
RPC::commit();
} catch(Exception $e) {
header(sprintf('HTTP/1.1 %d %s', $e->getCode(), $e->getMessage()));
header('Content-Type: text/plain; charset=utf-8');
\system\Logs\Logger::log($e->getMessage());
} else{
$formh = $xtf->getHTML($form->asXML());
} }
} }
function ajaxSubmitData($datas) {
define(XMPP_HOST, $datas->to->value);
define(XMPP_CONN, $datas->ndd->value);
function onRegistered($packet)
{
$data = $packet->content;
$view = $this->tpl();
$view->assign('url', (string)$form->x->url);
unset($datas->to);
unset($datas->ndd);
$html = $view->draw('_accountnext_registered', true);
define(XMPP_PORT, 5222);
try {
// We try to connect to the XMPP Server
$f = fsockopen(XMPP_CONN, XMPP_PORT, $errno, $errstr, 10);
if(!$f) {
RPC::call('movim_reload', Route::urlize('accountnext', 'xmppconnect'));
RPC::commit();
exit;
}
// We create the XML Stanza
$stream = simplexml_load_string('<?xml version="1.0"?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" version="1.0"><iq id="'.$datas->id->value.'" type="set"><query xmlns="jabber:iq:register"><x xmlns="jabber:x:data" type="form"></x></query></iq></stream:stream>');
unset($datas->id);
$stream->addAttribute('to', XMPP_HOST);
$xmpp = new FormtoXMPP();
$stream = $xmpp->getXMPP($stream->asXML(), $datas);
fwrite($f, $stream->asXML());
unset($stream);
$response = stream_get_contents($f);
if(!$response) {
RPC::call('movim_reload', Route::urlize('accountnext', array(XMPP_HOST, 'xmppcomm')));
RPC::commit();
exit;
}
fclose($f); unset($f);
$response = simplexml_load_string($response);
if(!$response) throw new Exception('The XMPP server sent an invalid response', 500);
if($stream_error = $response->xpath('/stream:stream/stream:error')) {
list($stream_error) = $stream_error;
list($cond) = $stream_error->children();
throw new Exception($stream_error->text ? $stream_error->text : $cond->getName(), 500);
}
$iq = $response->iq;
RPC::call('movim_fill', 'subscription_form', $html);
RPC::call('setUsername', $data->username->value);
RPC::call('remoteUnregister');
}
if($iq->error) {
list($cond) = $iq->error->children();
if($cond->getName() == 'conflict') {
RPC::call('movim_reload', Route::urlize('accountnext', array(XMPP_HOST,'userconflict')));
RPC::commit();
exit;
} else if($cond->getName() == 'not-acceptable') {
RPC::call('movim_reload', Route::urlize('accountnext', array(XMPP_HOST,'notacceptable')));
RPC::commit();
exit;
}
throw new Exception($iq->error->text ? $iq->error->text : $cond->getName(), 400);
}
function onRegisterError($package)
{
$error = $package->content;
RPC::call('movim_fill', 'subscription_error', '<div class="message error">'.$error.'</div>');
}
function onRegisterNotAcceptable()
{
RPC::call('movim_fill', 'subscription_error', '<div class="message error">'.$this->__('error.not_acceptable').'</div>');
}
function onServiceUnavailable()
{
RPC::call('movim_fill', 'subscription_form', '<div class="message error">'.$this->__('error.service_unavailable').'</div>');
RPC::call('remoteUnregister');
}
if($iq = $response->iq and $iq->attributes()->type == 'result') {
RPC::call('movim_reload', Route::urlize('login', 'acccreated'));
RPC::commit();
exit;
} else {
RPC::call('movim_reload', Route::urlize('accountnext', array(XMPP_HOST,'unknown')));
RPC::commit();
exit;
}
} catch(Exception $e) {
header(sprintf('HTTP/1.1 %d %s', $e->getCode(), $e->getMessage()));
header('Content-Type: text/plain; charset=utf-8');
\system\Logs\Logger::log($e->getCode().' '.$e->getMessage().' file:'.$e->getFile().' - l.'.$e->getLine());
}
function ajaxGetForm($host)
{
\Moxl\Stanza\Stream::init($host);
} }
function flagPath($country) {
return BASE_URI.'themes/movim/img/flags/'.strtolower($country).'.png';
function ajaxRegister($form)
{
$s = new Set;
$s->setData($form)->request();
} }
} }

45
app/widgets/AccountNext/_accountnext_form.tpl

@ -1,47 +1,14 @@
<form name="data"> <form name="data">
<fieldset>
{$instr}
<div id="subscription_error">
<div class="clear"></div>
</div>
<fieldset>
{$formh} {$formh}
<input
type="hidden"
value="{$domain}"
name="ndd"
id="ndd"
/>
<input
type="hidden"
value="{$ndd}"
name="to"
id="to"
/>
<input
type="hidden"
value="{$id}"
name="id"
id="id"
/>
<input
id="submitb"
type="submit"
style="display: none;"
value="submit"
name="submitb"
/>
<a <a
class="button color green icon yes"
style="float: right;"
onclick="
localStorage.username = document.querySelector('#username').value+'@'+'{$ndd}';
{$submitdata}"
class="button color green oppose"
onclick="{$submitdata}"
> >
{$c->__('button.validate')}
<i class="fa fa-check"></i> {$c->__('button.validate')}
</a> </a>
</fieldset> </fieldset>
</form> </form>

10
app/widgets/AccountNext/_accountnext_oob.tpl

@ -0,0 +1,10 @@
<p>
{$c->__('oob.about')} <a href="{$url}" target="_blank">{$url}</a>
</p>
<a
class="button oppose color green"
href="{$c->route('login')}"
>
<i class="fa fa-home"></i> {$c->__('page.login')}
</a>

9
app/widgets/AccountNext/_accountnext_registered.tpl

@ -0,0 +1,9 @@
<div class="placeholder icon clipboard">
{$c->__('create.successfull')}
<h1 id="username">username@server.com</h1>
<a class="button color green" href="{$c->route('login')}">
<i class="fa fa-home"></i> {$c->__('page.login')}
</a>
</div>

12
app/widgets/AccountNext/accountnext.js

@ -1 +1,13 @@
var AccountNext = {
host : '',
setHost : function(host) {
this.host = host;
},
setUsername : function(user) {
document.querySelector('#username').innerHTML = user + '@' + this.host;
}
}
function setUsername(user) {
AccountNext.setUsername(user);
}

8
app/widgets/AccountNext/accountnext.tpl

@ -1,12 +1,16 @@
<div id="subscribe"> <div id="subscribe">
<h1 class="paddedtopbottom">{$c->__('create.title')} {$c->__('on')} {$ndd}</h1>
<h1 class="paddedtopbottom">{$c->__('create.title')} {$c->__('on')} {$host}</h1>
<div id="subscription_form" class="paddedtopbottom"> <div id="subscription_form" class="paddedtopbottom">
{$c->__('loading')} {$c->__('loading')}
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
{$getsubscriptionform}
MovimWebsocket.attach(function()
{
{$getsubscriptionform}
AccountNext.host = '{$host}';
});
</script> </script>
</div> </div>

6
app/widgets/AccountNext/locales.ini

@ -1,4 +1,10 @@
create.title = 'Create a new account' create.title = 'Create a new account'
create.notfound = 'No account creation form found on the server' create.notfound = 'No account creation form found on the server'
create.on = 'on' create.on = 'on'
create.successfull = 'Your acccount has been successfully registered'
loading = 'Loading' loading = 'Loading'
error.not_acceptable = 'Not Acceptable'
error.service_unavailable = 'The registration system of this server is currently unavailable'
oob.about = 'This server use an external system for the registration, please click on the following URL.'

2
app/widgets/ContactPubsubSubscription/ContactPubsubSubscription.php

@ -41,7 +41,7 @@ class ContactPubsubSubscription extends WidgetBase
foreach($list as $item){ foreach($list as $item){
if(is_array($item)) { if(is_array($item)) {
$html .= '<li><a href="'.Route::urlize('node', array($item['server'], $item['node'])).'">'.$item['title'].'</a></li>';
$html .= '<li><a href="'.Route::urlize('node', array($item[1], $item[0])).'">'.$item[2].'</a></li>';
} }
} }

7
app/widgets/Login/Login.php

@ -138,7 +138,7 @@ class Login extends WidgetBase
break; break;
} }
RPC::call('remoteUnregister');
RPC::call('remoteUnregisterReload');
RPC::call('movim_desktop_notification', $title, $warning); RPC::call('movim_desktop_notification', $title, $warning);
} }
@ -309,14 +309,13 @@ class Login extends WidgetBase
// We create a new session or clear the old one // We create a new session or clear the old one
$s = Sessionx::start(); $s = Sessionx::start();
$s->init($user, $element['pass'], $host, $domain); $s->init($user, $element['pass'], $host, $domain);
// We save the loaded widgets list in the database // We save the loaded widgets list in the database
$wrapper = WidgetWrapper::getInstance(false);
/*$wrapper = WidgetWrapper::getInstance(false);
$sess = Session::start(APP_NAME); $sess = Session::start(APP_NAME);
$sess->set('registered_events', $wrapper->registerEvents());
$sess->set('registered_events', $wrapper->registerEvents());*/
\Moxl\Stanza\Stream::init($host); \Moxl\Stanza\Stream::init($host);
} }

2
app/widgets/Login/login.js

@ -109,7 +109,7 @@ MovimWebsocket.attach(function()
} }
}); });
movim_add_onload(function() {
movim_add_onload(function() {
/* Dump cache variables in localStorage */ /* Dump cache variables in localStorage */
for ( var i = 0, len = localStorage.length; i < len; ++i ) { for ( var i = 0, len = localStorage.length; i < len; ++i ) {
var cache = localStorage.key(i); var cache = localStorage.key(i);

1
app/widgets/Menu/Menu.php

@ -54,6 +54,7 @@ class Menu extends WidgetCommon
RPC::call('movim_append', 'menu_widget', $html); RPC::call('movim_append', 'menu_widget', $html);
} else { } else {
RPC::call('movim_fill', 'menu_widget', $html); RPC::call('movim_fill', 'menu_widget', $html);
RPC::call('movim_posts_unread', 0);
} }
RPC::call('Menu.refresh'); RPC::call('Menu.refresh');
} }

4
app/widgets/Subscribe/subscribe.js

@ -0,0 +1,4 @@
MovimWebsocket.attach(function()
{
remoteUnregister();
});

16
lib/XMPPtoForm.php

@ -139,8 +139,8 @@ class XMPPtoForm{
<input <input
id="'.$s['var'].'" id="'.$s['var'].'"
name="'.$s['var'].'" name="'.$s['var'].'"
xmpptype="'.$s['type'].'"
xmpplabel="'.$s['label'].'"
type="'.$s['type'].'"
label="'.$s['label'].'"
type="checkbox" '.$s->required; type="checkbox" '.$s->required;
if($s->value == "true" || $s->value == "1") if($s->value == "true" || $s->value == "1")
$this->html .= ' checked'; $this->html .= ' checked';
@ -154,8 +154,8 @@ class XMPPtoForm{
<textarea <textarea
id="'.$s["var"].'" id="'.$s["var"].'"
name="'.$s["var"].'" name="'.$s["var"].'"
xmpptype="'.$s['type'].'"
xmpplabel="'.$s['label'].'"
type="'.$s['type'].'"
label="'.$s['label'].'"
required="'.$s->required.'">'; required="'.$s->required.'">';
foreach($s->children() as $value){ foreach($s->children() as $value){
@ -187,8 +187,8 @@ class XMPPtoForm{
$this->html .= ' $this->html .= '
type="'.$type.'" type="'.$type.'"
title="'.$s->desc.'" title="'.$s->desc.'"
xmpptype="'.$s['type'].'"
xmpplabel="'.$s['label'].'"
type="'.$s['type'].'"
label="'.$s['label'].'"
'.$multiple.' '.$req.'/>'; '.$multiple.' '.$req.'/>';
} }
@ -202,8 +202,8 @@ class XMPPtoForm{
<label for="'.$s["var"].'">'.$s["label"].'</label> <label for="'.$s["var"].'">'.$s["label"].'</label>
<div class="select"> <div class="select">
<select <select
xmpptype="'.$s['type'].'"
xmpplabel="'.$s['label'].'"
type="'.$s['type'].'"
label="'.$s['label'].'"
id="'.$s["var"].'" id="'.$s["var"].'"
name="'.$s['var'].'" '.$multiple.' '.$s->required.'>'; name="'.$s['var'].'" '.$multiple.' '.$s->required.'>';

16
linker.php

@ -19,12 +19,16 @@ $stdin = new React\Stream\Stream(STDIN, $loop);
$cd = new \Modl\ConfigDAO(); $cd = new \Modl\ConfigDAO();
$config = $cd->get(); $config = $cd->get();
// We load and register all the widgets
$wrapper = WidgetWrapper::getInstance();
$wrapper->registerAll(true);
$connector($config->websocketurl, array('xmpp'))->then(function($conn) use (&$stdin, $loop) { $connector($config->websocketurl, array('xmpp'))->then(function($conn) use (&$stdin, $loop) {
fwrite(STDERR, colorize(getenv('sid'), 'yellow')." : ".colorize('linker launched', 'blue')."\n"); fwrite(STDERR, colorize(getenv('sid'), 'yellow')." : ".colorize('linker launched', 'blue')."\n");
$conn->on('message', function($message) use ($conn, $loop) { $conn->on('message', function($message) use ($conn, $loop) {
if($message != '') { if($message != '') {
//fwrite(STDERR, colorize($message, 'yellow')." : ".colorize('received', 'green')."\n");
fwrite(STDERR, colorize($message, 'yellow')." : ".colorize('received', 'green')."\n");
if($message == '</stream:stream>') { if($message == '</stream:stream>') {
$conn->close(); $conn->close();
@ -44,12 +48,12 @@ $connector($config->websocketurl, array('xmpp'))->then(function($conn) use (&$st
if(!empty($msg)) { if(!empty($msg)) {
$msg = json_encode($msg); $msg = json_encode($msg);
//fwrite(STDERR, colorize($msg, 'yellow')." : ".colorize('sent to browser', 'green')."\n");
fwrite(STDERR, colorize($msg, 'yellow')." : ".colorize('sent to browser', 'green')."\n");
echo base64_encode(gzcompress($msg, 9))."END"; echo base64_encode(gzcompress($msg, 9))."END";
} }
if(!empty($xml)) { if(!empty($xml)) {
//fwrite(STDERR, colorize(trim($xml), 'yellow')." : ".colorize('sent to XMPP', 'green')."\n");
fwrite(STDERR, colorize(trim($xml), 'yellow')." : ".colorize('sent to XMPP', 'green')."\n");
$conn->send(trim($xml)); $conn->send(trim($xml));
} }
} }
@ -71,7 +75,7 @@ $connector($config->websocketurl, array('xmpp'))->then(function($conn) use (&$st
$buffer = ''; $buffer = '';
foreach ($messages as $message) { foreach ($messages as $message) {
//fwrite(STDERR, colorize($message, 'yellow')." : ".colorize('received from the browser', 'green')."\n");
fwrite(STDERR, colorize($message, 'yellow')." : ".colorize('received from the browser', 'green')."\n");
$msg = json_decode($message); $msg = json_decode($message);
@ -91,7 +95,7 @@ $connector($config->websocketurl, array('xmpp'))->then(function($conn) use (&$st
\Moxl\API::clear(); \Moxl\API::clear();
if(!empty($xml)) { if(!empty($xml)) {
//fwrite(STDERR, colorize(trim($xml), 'yellow')." : ".colorize('sent to XMPP', 'green')."\n");
fwrite(STDERR, colorize(trim($xml), 'yellow')." : ".colorize('sent to XMPP', 'green')."\n");
$conn->send(trim($xml)); $conn->send(trim($xml));
} }
@ -99,7 +103,7 @@ $connector($config->websocketurl, array('xmpp'))->then(function($conn) use (&$st
\RPC::clear(); \RPC::clear();
if(!empty($msg)) { if(!empty($msg)) {
//fwrite(STDERR, colorize($msg, 'yellow')." : ".colorize('sent to the browser', 'green')."\n");
fwrite(STDERR, colorize($msg, 'yellow')." : ".colorize('sent to the browser', 'green')."\n");
echo base64_encode(gzcompress($msg, 9))."END"; echo base64_encode(gzcompress($msg, 9))."END";
} }
} }

1
locales/locales.ini

@ -33,6 +33,7 @@ error.error = 'Error: %s'
error.cannot_load_file = "Cannot load file '%s'" error.cannot_load_file = "Cannot load file '%s'"
error.route = 'Route error, please set all the parameters for the page %s' error.route = 'Route error, please set all the parameters for the page %s'
error.widget_load_error = "Requested widget '%s' doesn't exist." error.widget_load_error = "Requested widget '%s' doesn't exist."
error.widget_call_error = "Requested event '%s' not registered."
error.whoops = "Whoops!" error.whoops = "Whoops!"
error.media_not_found = "It seem that you don't have any pictures here?" error.media_not_found = "It seem that you don't have any pictures here?"
error.media_ask_upload = "You can try to upload a couple by going to the Media page" error.media_ask_upload = "You can try to upload a couple by going to the Media page"

4
src/Movim/Daemon/Session.php

@ -98,7 +98,9 @@ class Session {
public function messageIn(ConnectionInterface $from, $msg) public function messageIn(ConnectionInterface $from, $msg)
{ {
$this->timestamp = time(); $this->timestamp = time();
$this->process->stdin->write($msg."END");
if(isset($this->process)) {
$this->process->stdin->write($msg."END");
}
} }
public function messageOut($msg) public function messageOut($msg)

10
system/Event.php

@ -5,12 +5,10 @@ class Event
function runEvent($type, $event = false) function runEvent($type, $event = false)
{ {
$widgets = WidgetWrapper::getInstance(false); $widgets = WidgetWrapper::getInstance(false);
$widgets->iterate('runEvents', array(
array(
'type' => $type,
'data' => $event,
)));
$widgets->iterate(array(
'type' => $type,
'data' => $event,
));
// Outputting any RPC calls. // Outputting any RPC calls.
RPC::commit(); RPC::commit();

1
system/Session.php

@ -32,7 +32,6 @@ class Session
*/ */
protected function __construct() protected function __construct()
{ {
} }
/** /**

254
system/widget/WidgetWrapper.php

@ -1,74 +1,58 @@
<?php <?php
/**
* @file WidgetWrapper.php
* This file is part of PROJECT.
*
* @brief Description
*
* @author Guillaume Pasquet <gpasquet@lewisday.co.uk>
*
* @version 1.0
* @date 20 January 2011
*
* Copyright (C)2011 Lewis Day Transport Plc.
*
* All rights reserved.
/*
* @file WidgetWraper.php
*
* @brief Handle the Widgets
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/ */
/**
* A container that abstracts the communication between
* widgets and the core of Movim.
*/
class WidgetWrapper class WidgetWrapper
{ {
private $register_widgets;
private $all_widgets = array();
private $loaded_widgets = array();
private $loaded_widgets_old;
private $registered_events = array();
private static $instance; private static $instance;
private $_widgets = array();
private $_events = array();
private $css = array(); // All the css loaded by the widgets so far. private $css = array(); // All the css loaded by the widgets so far.
private $js = array(); // All the js loaded by the widgets so far. private $js = array(); // All the js loaded by the widgets so far.
/**
* Constructor. The parameter instructs the wrapper about whether
* it should save $_SESSION or not.
* @param $register set to false not to save the widgets in SESSION.
*/
private function __construct($register)
private function __construct()
{ {
$this->register_widgets = $register;
$md = \modl\Modl::getInstance();
if($md->_connected) {
$sess = Session::start(APP_NAME);
$widgets = $sess->get('loaded_widgets');
$this->registerAll();
}
if(is_array($widgets)) {
$this->loaded_widgets_old = $widgets;
}
$this->registered_events = $sess->get('registered_events');
// We search all the existent widgets
$this->all_widgets = array();
$widgets_dir = scandir(APP_PATH ."widgets/");
foreach($widgets_dir as $widget_dir) {
if(is_dir(APP_PATH ."widgets/".$widget_dir) &&
$widget_dir != '..' &&
$widget_dir != '.')
array_push($this->all_widgets, $widget_dir);
public function registerAll($load = false)
{
$widgets_dir = scandir(APP_PATH ."widgets/");
foreach($widgets_dir as $widget_dir) {
if(is_dir(APP_PATH ."widgets/".$widget_dir) &&
$widget_dir != '..' &&
$widget_dir != '.') {
if($load) $this->loadWidget($widget_dir, true);
array_push($this->_widgets, $widget_dir);
} }
} }
} }
static function getInstance($register = true)
static function getInstance()
{ {
if(!is_object(self::$instance)) { if(!is_object(self::$instance)) {
self::$instance = new WidgetWrapper($register);
self::$instance = new WidgetWrapper;
} }
return self::$instance; return self::$instance;
} }
@ -76,68 +60,55 @@ class WidgetWrapper
static function destroyInstance() static function destroyInstance()
{ {
if(isset(self::$instance)) { if(isset(self::$instance)) {
self::$instance->destroy();
self::$instance = null; self::$instance = null;
} }
} }
/** /**
* Saves the list of loaded widgets if necessary.
*/
function __destruct()
{
$this->destroy();
}
protected function destroy()
{
if($this->register_widgets && count($this->loaded_widgets) > 0) {
$sess = Session::start();
$sess->set('loaded_widgets', $this->loaded_widgets);
$this->register_widgets = false;
}
}
/**
* Retrieves the list of loaded widgets.
*/
function getLoadedWidgets()
{
if(count($this->loaded_widgets) > 0) {
return $this->loaded_widgets;
} else {
return $this->loaded_widgets_old;
}
}
function getAllWidgets()
{
return $this->all_widgets;
}
/**
* Loads a widget and returns it.
* @desc Loads a widget and returns it
* @param $name the name of the widget
* @param $register know if we are loading in the daemon or displaying
*/ */
public function loadWidget($widget_name)
public function loadWidget($name, $register = false)
{ {
// Attempting to load the user's widgets in priority // Attempting to load the user's widgets in priority
$widget_path = "";
$path = "";
if(file_exists(APP_PATH . "widgets/$widget_name/$widget_name.php")) {
$widget_path = APP_PATH . "widgets/$widget_name/$widget_name.php";
if(file_exists(APP_PATH . "widgets/$name/$name.php")) {
$path = APP_PATH . "widgets/$name/$name.php";
} }
else { else {
throw new MovimException( throw new MovimException(
__('error.widget_load_error', $widget_name));
__('error.widget_load_error', $name));
} }
require_once($widget_path);
$widget = new $widget_name();
return $widget;
require_once($path);
$widget = new $name();
if($register) {
// We save the registered events of the widget for the filter
if(isset($widget->events)) {
foreach($widget->events as $key => $value) {
if(is_array($this->_events)
&& array_key_exists($key, $this->_events)) {
$we = $this->_events[$key];
array_push($we, $name);
$we = array_unique($we);
$this->_events[$key] = $we;
} else {
$this->_events[$key] = array($name);
}
}
}
} else {
// Collecting stuff generated by the widgets.
$this->css = array_merge($this->css, $widget->loadcss());
$this->js = array_merge($this->js, $widget->loadjs());
}
} }
/** /**
* Loads a widget and runs a particular function on it.
* @desc Loads a widget and runs a particular function on it.
* *
* @param $widget_name is the name of the widget. * @param $widget_name is the name of the widget.
* @param $method is the function to be run. * @param $method is the function to be run.
@ -145,52 +116,22 @@ class WidgetWrapper
* be passed along to the method. * be passed along to the method.
* @return what the widget's method returns. * @return what the widget's method returns.
*/ */
function runWidget($widget_name, $method, array $params = NULL)
function runWidget($widget_name, $method, array $params = null)
{ {
if($this->register_widgets &&
/*if($this->register_widgets &&
!in_array($widget_name, $this->loaded_widgets)) !in_array($widget_name, $this->loaded_widgets))
$this->loaded_widgets[] = $widget_name;
$this->loaded_widgets[] = $widget_name;*/
$widget = $this->loadWidget($widget_name);
$this->loadWidget($widget_name);
$widget = new $widget_name();//$this->loadWidget($widget_name);
if(!is_array($params)) if(!is_array($params))
$params = array(); $params = array();
$result = call_user_func_array(array($widget, $method), $params); $result = call_user_func_array(array($widget, $method), $params);
// Collecting stuff generated by the widgets.
$this->css = array_merge($this->css, $widget->loadcss());
$this->js = array_merge($this->js, $widget->loadjs());
return $result; return $result;
} }
/**
* We register all the events of all the widgets in the database
*
* @return the registered events
*/
function registerEvents() {
$widgets = $this->getAllWidgets();
foreach($widgets as $widget_name) {
$widget = $this->loadWidget($widget_name);
// We save the registered events of the widget for the filter
if(isset($widget->events)) {
foreach($widget->events as $key => $value) {
if(is_array($this->registered_events)
&& array_key_exists($key, $this->registered_events)) {
$we = $this->registered_events[$key];
array_push($we, $widget_name);
$we = array_unique($we);
$this->registered_events[$key] = $we;
} else {
$this->registered_events[$key] = array($widget_name);
}
}
}
}
return $this->registered_events;
}
/** /**
* Calls a particular function with the given parameters on * Calls a particular function with the given parameters on
@ -201,50 +142,31 @@ class WidgetWrapper
*/ */
function iterate($method, array $params = NULL) function iterate($method, array $params = NULL)
{ {
// We only load the interesting widgets
if(isset($params)) {
$fct = $params[0]['type'];
if(is_array($this->registered_events) &&
array_key_exists($fct, $this->registered_events))
$widgets = $this->registered_events[$fct];
} else
$widgets = $this->getLoadedWidgets();
if(isset($widgets) && is_array($widgets))
foreach($widgets as $widget)
$this->runWidget($widget, $method, $params);
}
/*
function iterateAll($method, array $params = NULL) {
$widgets = $this->getAllWidgets();
$isevent = array();
foreach($widgets as $widget) {
if($this->runWidget($widget, $method, $params))
$isevent[$widget] = true;
if(array_key_exists($method['type'],$this->_events)) {
foreach($this->_events[$method['type']] as $name) {
$widget = new $name();
$widget->runEvents($method);
unset($widget);
}
} else {
/*throw new MovimException(
__('error.widget_call_error', $method['type']));*/
} }
return $isevent;
} }
*/
/** /**
* Returns the list of loaded CSS.
* @desc Returns the list of loaded CSS.
*/ */
function loadcss() function loadcss()
{ {
if(!is_array($this->css)) // Just being prudent
return array();
else
return $this->css;
return $this->css;
} }
/** /**
* Returns the list of loaded javascripts.
* @desc Returns the list of loaded javascripts.
*/ */
function loadjs() function loadjs()
{ {
if(!is_array($this->js)) // Avoids annoying errors.
return array();
else
return $this->js;
return $this->js;
} }
} }

3
themes/movim/css/style.css

@ -707,7 +707,7 @@ dl dd {
.placeholder.icon { .placeholder.icon {
background-image: url(../img/icons/placeholder/chat.png); background-image: url(../img/icons/placeholder/chat.png);
background-size: 35%; background-size: 35%;
padding-top: 10em;
padding-top: 12em;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center 1em; background-position: center 1em;
} }
@ -717,3 +717,4 @@ dl dd {
.placeholder.icon.explore { background-image: url(../img/icons/placeholder/explore.png); } .placeholder.icon.explore { background-image: url(../img/icons/placeholder/explore.png); }
.placeholder.icon.plane { background-image: url(../img/icons/placeholder/plane.png); } .placeholder.icon.plane { background-image: url(../img/icons/placeholder/plane.png); }
.placeholder.icon.file { background-image: url(../img/icons/placeholder/file.png); } .placeholder.icon.file { background-image: url(../img/icons/placeholder/file.png); }
.placeholder.icon.clipboard { background-image: url(../img/icons/placeholder/clipboard.png); }

BIN
themes/movim/img/icons/placeholder/clipboard.png

After

Width: 512  |  Height: 512  |  Size: 8.3 KiB

Loading…
Cancel
Save