Location: PHPKode > projects > BusinessWiki > extensions/Dashboard/Dashboard_body.php
<?php

class Dashboard extends SpecialPage {
	public function __construct() {
		parent::__construct( 'Dashboard' );
		wfLoadExtensionMessages( 'Dashboard' );
	}
 
	public function execute( $par ) {
		global $wgRequest, $wgOut, $wgUser, $wgParser;
		
		$this->setHeaders();
		
		switch ( $par ) {
		    case 'oldstyle':
		        DashboardStyle::setStyle( DASHBOARD_OLDSTYLE );		        
		        $wgOut->redirect( Title::newMainPage()->getLocalURL() );
		        return;
		    case 'newstyle':
		        DashboardStyle::setStyle( DASHBOARD_NEWSTYLE );		        
		        $wgOut->redirect( $this->getTitle()->getLocalURL() );
		        return;
		    case 'add':
        		$wgOut->setPageTitle( 'Add new gadget to dashboard' );
        		
        		$template = new DashboardAddTemplate();
        		$template->set( 'gadgets', DashboardGadgets::getArray() );
        		$template->set( 'addUrl', $this->getTitle()->getLocalUrl() . '&add=' );
        		
        		$wgOut->addTemplate( $template );
        		
		        return;
		}
		
		$dashboardLayout = new DashboardLayout();
		
		$id = $wgRequest->getText( 'add' );
		if ( !empty( $id ) ) {		    
		    if ( false === ( $layout = $dashboardLayout->getLayout() ) ) {
		        $wgOut->showErrorPage( 'error', 'notloggedin' );
		        
		        return;
		    }
		    
		    $dashboardLayout->addGadget( $id );
		    
		    $wgOut->redirect( $this->getTitle()->getLocalURL() );
		}
		
		$oldTitle = $wgOut->getHTMLTitle();
		$wgOut->setPageTitle( '' );
		$wgOut->setHTMLTitle( $oldTitle );
		unset( $oldTitle );
		
		$dashboardOutput = new DashboardOutput();
        
        $dashboardOutput->addFiles( $wgOut );
        
        $dashboardLayout = new DashboardLayout();
        
        if ( false === ( $layout = $dashboardLayout->getLayout() ) ) {
            $wgOut->showErrorPage( 'error', 'notloggedin' );
            
            return;
        }
        
		$template = new DashboardTemplate();
		$template->set( 'layout', $layout );
		
		$parserOptions = ParserOptions::newFromUser( $wgUser );
		$parserOptions->setEditSection( false );
		$parserOptions->setTidy( true );

		// $mainPageTitle = Title::newMainPage();
		$mainPageTitle = Title::newFromDBkey('Ogłoszenia');
		$mainPageArticle = new Article( $mainPageTitle );
		$parserOutput = $wgParser->parse( $mainPageArticle->fetchContent(), $mainPageTitle, $parserOptions, true, true );
		$template->set( 'content', $parserOutput->getText() );
		
		$wgOut->addTemplate( $template );		
		
		$prefs = array();
		foreach ( (array) $layout as $column ) {
			foreach ( $column as $gadgets ) {
			    $prefs[] = $gadgets;
			}
		}
		
		global $wgHooks;
		
		$wgHooks['MakeGlobalVariablesScript'][] = array(
		    $dashboardOutput,
		    'addGlobalVariables',
		    $prefs
		);
	}
}

class DashboardStyle {
	public static function getStyle() {
	    global $wgUser;
	    
	    $dbr =& wfGetDB( DB_SLAVE );
	    
	    $res = $dbr->select(
	        'user_dashboard',
	        array( 'user_dashboard_oldstyle' ),
	        array( 'user_id' => $wgUser->getId() ),
	        __METHOD__
	    );
	    
	    if ( $dbr->numRows( $res ) ) {
	        $row = $dbr->fetchObject( $res );
	        
	        return $row->user_dashboard_oldstyle;
	    }	    
	    
	    self::setStyle( DASHBOARD_OLDSTYLE );
	    
	    return DASHBOARD_OLDSTYLE;
	}
	
	public static function setStyle( $style ) {
	    global $wgUser;
	    
	    $dbw =& wfGetDB( DB_MASTER );
	    
	    $dbw->begin();
	    $dbw->update(
	        'user_dashboard',
	        array( 'user_dashboard_oldstyle' => $style ),
	        array( 'user_id' => $wgUser->getId() ),
	        __METHOD__
	    );
	    $dbw->commit();
	    
	    if ( $dbw->affectedRows() ) {
	        return true;
	    }
	    
	    $dbw->begin();
	    $dbw->update(
	        'user_dashboard',
	        array( 'user_dashboard_oldstyle' => $style ),
	        array( 'user_id' => $wgUser->getId() ),
	        __METHOD__
	    );
	    $dbw->commit();
	    
	    return true;
	}
}

class DashboardGadgets {
    static $gadgets = array();
    
    /**
     * @return array
     */
    public static function getArray() {
        global $wgContLanguageCode;
        if ( empty( self::$gadgets ) ) {
            $jsonFile = ($wgContLanguageCode == 'pl') ? 'list_pl.json' : 'list.json';
            if ( false !== ( $file = file_get_contents( 'http://gadgets.divante.pl/' . $jsonFile ) ) ) {
                self::$gadgets = json_decode( trim( $file ) );
            }
        }
        
        return self::$gadgets;
    }
}

class DashboardOutput {
    /**
     * @param OutputPage $out
     */
    public function addFiles( OutputPage &$out ) {
        global $wgStylePath, $wgDefaultSkin, $wgJsMimeType;
        
		$out->addExtensionStyle( "{$wgStylePath}/{$wgDefaultSkin}/Dashboard.css" );
		$out->addScript( "<script type=\"{$wgJsMimeType}\" src=\"http://gadgets.divante.pl/shindig/gadgets.stitched.js\"></script>\n" );
        $out->addScriptFile( '/extensions/Dashboard/Dashboard.js' );
    }
    
    /**
     * @param array $prefs
     * @param array $vars
     * @return boolean
     */
    public function addGlobalVariables( $prefs, &$vars ) {
        $gadgetsCache = DashboardGadgets::getArray();
        $gadgets = array();
        foreach ( $gadgetsCache as $key => $value ) {
            $gadgets[$key] = new stdClass();
            $gadgets[$key]->title = $value->title;
            $gadgets[$key]->url = $value->url;
        }
        
        $vars['wgDashboardGadgets'] = (object) $gadgets;
        
        $vars['wgDashboardPrefs'] = $prefs;
        
        return true;
    }
}

class DashboardLayout {
    private $layout;
    
    /**
     * @return stdClass
     */
    public function getLayout() {
        if ( !empty( $this->layout ) ) {
            return $this->layout;
        }
        
        global $wgUser;
        
	    $dbr =& wfGetDB( DB_SLAVE );
	    
	    if ( $wgUser->isLoggedIn() ) {
		    $layout = $dbr->selectField(
		        'user_dashboard',
		        'user_dashboard',
		        array( 'user_id' => $wgUser->getId() ),
		        __METHOD__
		    );
		    
		    if ( !empty( $layout ) ) {
		        $layout = json_decode( $layout );
		    }
	    } else {
	        return false;
	    }
	    
	    $this->layout = $layout;
	    
	    if ( empty( $this->layout ) ) {
	        $this->setDefaultLayout();
	        
	        $this->layout = $this->getLayout();
	    }
	    
	    return $this->layout;
    }
    
    private function setDefaultLayout() {
        $layout = new stdClass();
        $layout->column1 = array();
        $layout->column2 = array();
        $layout->column3 = array();
        
        $this->layout = $layout;        
        
        $this->addGadget( 'ce39f53a5761a1910a24bf30a34ef5b2' );
        $this->addGadget( 'e328471acd15a15ca555451bf9563224' );
        $this->addGadget( 'e42519c12fd757f62efe8dd740c93d78' );
        $this->addGadget( 'fbe5e30d6f56b12f168195f839a2c5bd' );
        $this->addGadget( 'b37df7bf18729fa4732810df76d6cfe0' );
        $this->addGadget( '88d9f55d4a97f6921b33628b7e9c8907' );
    }
    
    /**
     * @param string $state
     * @return string
     */
    public function saveLayout( $state ) {
        global $wgUser;

        if ( !$wgUser->isLoggedIn() ) {
            return (string) false;
        }
        
        $dbw =& wfGetDB( DB_MASTER );

        $id = $wgUser->getId();
        
        $dbw->begin();
        $dbw->update(
            'user_dashboard',
            array( 'user_dashboard' => $state ),
            array( 'user_id' => $id ),
            __METHOD__
        );
        if ( $dbw->affectedRows() == 0 ) {
            $dbw->insert(
                'user_dashboard',
                array( 'user_id' => $id, 'user_dashboard' => $state ),
                __METHOD__
            );
        }
        $dbw->commit();
        
        return (string) true;
    }
    
    /**
     * @param string $id
     * @return boolean
     */
    public function addGadget( $id ) {
        if ( false === ( $layout = $this->getLayout() ) ) {
            return false;
        }
        
	    $temp = array(
	        'column1' => count( $layout->column1 ),
	        'column2' => count( $layout->column2 ),
	        'column3' => count( $layout->column3 )
	    );
	    
	    if ( !function_exists( 'aksort' ) ) {
		    function aksort( &$array, $valRev = false, $keyRev = false ) {
                if ( $valRev ) {
                    arsort($array);
                } else {
                    asort($array);
                }
                
                $vals = array_count_values( $array );
                
                $i = 0;
                
                foreach ( $vals AS $val => $num ) {
                    $first = array_splice( $array, 0, $i );
                    $tmp = array_splice( $array, 0, $num );
                    
                    if ( $keyRev ) {
                        krsort( $tmp );
                    } else {
                        ksort( $tmp );
                    }
                    
                    $array = array_merge( $first, $tmp, $array );
                    
                    unset( $tmp );
                    
                    $i = $num;
                }
            }
	    }
	    
	    aksort( $temp );
	    
	    $target = array_keys( $temp );
	    $target = $target[0];
	    
	    $gadgets = DashboardGadgets::getArray();
	    
	    $gadget = new stdClass();
	    $gadget->gadget = $id;
	    $gadget->id = substr( uniqid(rand(), true), 0, 8 );
	    $gadget->toggle = 'down';
	    
	    $gadget->prefs = $gadgets->$id->prefs;
	    foreach ( (array) $gadget->prefs as $key => $value ) {
	        switch ( $key ) {
	            case 'bwi_server':
	                global $wgServer;
	                $value = $wgServer;
	                break;
	            case 'bwi_user':
	                global $wgUser;
	                $value = $wgUser->getId();
	                break;
	            default:
	                $value = $gadget->prefs->$key;
	        }
	        
	        $gadget->prefs->$key = $value;
	    }
	    
	    array_unshift( $layout->$target, $gadget );
	    
	    $this->saveLayout( json_encode( $layout ) );
	    
	    return true;    
    }
    
    /**
     * @param string $name
     * @param string $id
     * @param string $prefs
     * @return boolean
     */
    public function savePrefs( $name, $id, $prefs ) {
        global $wgUser;
        
        $dbw =& wfGetDB( DB_MASTER );
        
        $layout = $this->getLayout();
    
        $array = array( &$layout->column1, &$layout->column2, &$layout->column3 );
        foreach ( $array as &$column ) {
            foreach ( $column as &$gadget ) {
                if ( $gadget->gadget == $name && $gadget->id == $id ) {
                    $gadget->prefs = json_decode( $prefs );
                }
            }
        }
        
        $dbw->begin();
        $dbw->update(
            'user_dashboard',
            array( 'user_dashboard' => json_encode( $layout ) ),
            array( 'user_id' => $wgUser->getId() ),
            __METHOD__
        );
        $dbw->commit();
        	    
        return (string) true;
    }
}

class DashboardGadget {
    private $params;
    
    private $skin;
    
    /**
     * @param string $params
     */
    public function __construct( $params ) {
        global $wgUser;
        
        $this->params = json_decode( $params );        
        $this->skin = $wgUser->getSkin();            
    }
    
    /**
     * @return array
     */
    public function getParams() {
        return $this->params;
    }
    
    /**
     * @param string $url
     * @param string $text
     * @param boolean $escape
     * @return unknown
     * 
     * @todo Document
     */
    public function link( $url, $text, $escape = false ) {
        return $this->skin->makeExternalLink(
            $url, $text, $escape, '', array( 'target' => '_top' )
        );
    }
}

class DashboardGadget_Recentchanges extends DashboardGadget {
    /**
     * @param string $params
     */
    public function __construct( $params ) {
        parent::__construct( $params );
    }
    
    /**
     * @param stdClass $row
     * @return array
     * 
     * FIXME: Cleanup
     */
    private function extractRowInfo( $row ) {
		$title = Title::makeTitle( $row->rc_namespace, $row->rc_title );

		$vals = array();
		
		$vals['title'] = $title->getPrefixedText();

		$type = intval( $row->rc_type );

		switch ( $type ) {
			case RC_EDIT:
			    $vals['type'] = 'edit'; break;
			case RC_NEW:
			    $vals['type'] = 'new'; break;
			case RC_MOVE:
			    $vals['type'] = 'move'; break;
			case RC_LOG:
			    $vals['type'] = 'log'; break;
			case RC_MOVE_OVER_REDIRECT:
			    $vals['type'] = 'move over redirect'; break;
		    default:
		        $vals['type'] = $type;
		}

		$vals['rcid'] = intval($row->rc_id);

		$vals['user'] = $row->rc_user_text;
		if(!$row->rc_user)
			$vals['anon'] = '';

		if ($row->rc_bot)
			$vals['bot'] = '';
		if ($row->rc_new)
			$vals['new'] = '';
		if ($row->rc_minor)
			$vals['minor'] = '';

		$vals['timestamp'] = wfTimestamp( TS_ISO_8601, $row->rc_timestamp );

		$vals['comment'] = $row->rc_comment;
			
		if ($row->rc_type == RC_LOG) {
			$vals['logid'] = $row->rc_logid;
			$vals['logtype'] = $row->rc_log_type;
			$vals['logaction'] = $row->rc_log_action;
		}
		
		return $vals;        
    }
    
    /**
     * @return array
     */
    private function getData() {
        $dbr =& wfGetDB( DB_SLAVE );
        
        $res = $dbr->select(
            'recentchanges',
            array(
            	'rc_timestamp', 'rc_namespace', 'rc_title', 'rc_type',
            	'rc_id', 'rc_comment', 'rc_user_text', 'rc_logid',
            	'rc_log_type', 'rc_log_action'
            ),
			array( 'rc_deleted' => 0 ),
			__METHOD__,
			array(
				'ORDER BY' => 'rc_timestamp DESC',
				'LIMIT' => $this->getParams()->limit
			),
			array( 'USE INDEX' => 'rc_timestamp' )            
        );
        
        $data = array();
        
		while ( $row = $dbr->fetchObject( $res ) ) {
			$data[] = $this->extractRowInfo( $row );
		}
    		
   		return $data;
    }
    
	private function getChangeIcon( $ns, $type, $action, $comment ) {
		switch ( $ns ) {
			case NS_MAIN:
				$iconObj = 'page'; break;
			case NS_USER:
				$iconObj = 'user'; break;
			case NS_IMAGE:
				$iconObj = 'file'; break;
			case NS_CATEGORY:
				$iconObj = 'folder'; break;
		}
		
		if ( empty( $iconObj ) ) {
			$iconObj = 'page';
		}
		switch ( $type ) {
			case 'new':
				$iconAction = 'create'; break;
			case 'edit':
				$iconAction = 'edit'; break;
			case 'move':
				$iconAction = 'move'; break;
			case 'log':
				$iconAction = $action; break;
		}
		
		if ( $comment == 'New comment' ) {
			list( $iconObj, $iconAction ) = array( 'comment', 'create' );
		}
		
		return array(
			'file' => "rc_{$iconObj}_{$iconAction}_16_white.png",
			'title' => ucfirst( $iconObj ) . ' ' . ucfirst( $iconAction )
		);
	}
    
    public function __toString() {
        $data = $this->getData();
    	
        $html = '';
        
        if ( empty( $data ) ) {
            return $html;
        }
        
        $html .= Xml::openElement( 'ul', array( 'id' => 'rcbox' ) );        
	    foreach ( $data as $item ) {
			$namespace = $item['ns'];
			$type = $item['type']; /* edit, log, new etc.. */
			$logaction = ( $type == 'log' ) ? $item['logaction'] : '';
			$comment = isset( $item['comment'] ) ? $item['comment'] : '';
			
			$icon = $this->getChangeIcon( $namespace, $type, $logaction, $comment );
						
			$text = ( mb_strlen( $item['title'] ) > 14 )
			    ? mb_substr( $item['title'], 0, 13 ) . "&hellip;"
			    : $item['title'];
			    
			$html .=
			    Xml::openElement( 'li', array( 'title' => $icon['title'] ) ) .
			    $this->link( RecentChange::newFromId( $item['rcid'] )->getTitle()->getFullUrl(), $text ) .
			    ' ' . Xml::element( 'span', array( 'style' => 'color: #777777' ), wfTimestamp( TS_DB, $item['timestamp'] ) ) .
			    ' ' . $this->link( User::newFromName( $item['user'] )->getUserPage()->getFullUrl(), $item['user'] ) .
			    Xml::closeElement( 'li' );
	    }
	    $html .= Xml::closeElement( 'ul' );
    	
        return $html;
    }
}

class DashboardGadget_Mycontributions extends DashboardGadget {
    /**
     * @param string $params
     */
    public function __construct( $params ) {
        parent::__construct( $params );
    }
    
    /**
     * @param stdClass $row
     * @return array
     */
    private function extractRowInfo( $row ) {
		return array(
		    'revid' => intval( $row->rev_id ),
		    'title' => Title::makeTitle( $row->page_namespace, $row->page_title )->getPrefixedText(),
		    'timestamp' => wfTimestamp( TS_ISO_8601, $row->rev_timestamp ),
		    'comment' => $row->rev_comment		
		);
    }
    
    /**
     * @return array
     */
    private function getData() {
        $dbr =& wfGetDB( DB_SLAVE );

        $res = $dbr->select(
            array( 'revision', 'page' ),
            array(
            	'rev_id', 'page_namespace', 'page_title',
            	'rev_timestamp', 'rev_comment'
            ),
            array(
                'page_id = rev_page',
                'rev_deleted' => 0,
                'rev_user' => $this->getParams()->user
            ),
            __METHOD__,
            array(
            	'ORDER BY' => 'rev_user_text DESC, rev_timestamp DESC',
            	'LIMIT' => $this->getParams()->limit
            ),
            array( 'USE INDEX' => 'usertext_timestamp' )
        );
        
        $data = array();
        
		while ( $row = $dbr->fetchObject( $res ) ) {
			$data[] = $this->extractRowInfo( $row );
		}
    		
   		return $data;
    }
    
    public function __toString() {
        $data = $this->getData();
    	
        $html = '';
        
        if ( empty( $data ) ) {
            return $html;
        }
        
        $html .= Xml::openElement( 'ul', array( 'id' => 'mcbox' ) );        
	    foreach ( $data as $item ) {
			$text = ( mb_strlen( $item['title'] ) > 14 )
			    ? mb_substr( $item['title'], 0, 13 ) . "&hellip;"
			    : $item['title'];
			    
			$html .=
			    Xml::openElement( 'li', array( 'title' => $item['comment'] ) ) .
			    $this->link( Revision::newFromId( $item['revid'] )->getTitle()->getFullUrl(), $text ) .
			    ' ' . Xml::element( 'span', array( 'style' => 'color: #777777' ), wfTimestamp( TS_DB, $item['timestamp'] ) ) .
			    Xml::closeElement( 'li' );
	    }
	    $html .= Xml::closeElement( 'ul' );
    	
        return $html;
    }
}

class DashboardGadget_Mywatchlist extends DashboardGadget {
    /**
     * @param string $params
     */
    public function __construct( $params ) {
        parent::__construct( $params );
    }
    
    /**
     * @param stdClass $row
     * @return array
     */
    private function extractRowInfo( $row ) {
		return array(
		    'pageid' => intval( $row->page_id ),
		    'title' => Title::makeTitle( $row->page_namespace, $row->page_title )->getPrefixedText(),
		    'timestamp' => wfTimestamp( TS_ISO_8601, $row->rc_timestamp )		
		);
    }
    
    /**
     * @return array
     */
    private function getData() {
		$dbr =& wfGetDB( DB_SLAVE );
		
		$res = $dbr->select(
			array( 'watchlist', 'page', 'recentchanges' ),
			array( 'page_id', 'page_namespace', 'page_title', 'rc_timestamp' ),
			array(
				'wl_user' => $this->getParams()->user, 'page_namespace = wl_namespace',
				'page_title = wl_title', 'MOD(wl_namespace, 2) = 0'
			),
			__METHOD__,
			array( 'ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => 5 ),
			array( 'recentchanges' => array( 'LEFT JOIN', 'rc_id = page_latest' ) )
		);
                
        $data = array();
        
		while ( $row = $dbr->fetchObject( $res ) ) {
			$data[] = $this->extractRowInfo( $row );
		}
    		
   		return $data;
    }
    
    public function __toString() {
        $data = $this->getData();
    	
        $html = '';
        
        if ( empty( $data ) ) {
            return $html;
        }
        
        $html .= Xml::openElement( 'ul', array( 'id' => 'mwbox' ) );        
	    foreach ( $data as $item ) {
			$text = ( mb_strlen( $item['title'] ) > 14 )
			    ? mb_substr( $item['title'], 0, 13 ) . "&hellip;"
			    : $item['title'];
			    
			$html .=
			    Xml::openElement( 'li' ) .
			    $this->link( Title::newFromId( $item['pageid'] )->getFullUrl(), $text ) .
			    ' ' . Xml::element( 'span', array( 'style' => 'color: #777777' ), wfTimestamp( TS_DB, $item['timestamp'] ) ) .
			    Xml::closeElement( 'li' );
	    }
	    $html .= Xml::closeElement( 'ul' );
    	
        return $html;
    }
}

class ApiDashboard extends ApiBase {
	public function __construct( $main, $action ) {
		parent::__construct( $main, $action );
	}

	public function execute() {
		$params = $this->extractRequestParams();
		
		$className = 'DashboardGadget_' . ucfirst( $params['name'] );
		
		if ( !class_exists( $className ) ) {
		    $r = 'Error.';
		    
		    $this->getResult()->addValue( null, $this->getModuleName(), $r );
		}
		
		$gadget = new $className( $params['params'] );
		
		$r = array( 'html' => (string) $gadget );
		$this->getResult()->addValue( null, $this->getModuleName(), $r );
	}

	public function mustBePosted() { return false; }

	public function getAllowedParams() {
		return array (
			'name' => null,
			'params' => null
		);
	}

	public function getParamDescription() {
		return array (
			'name' => 'Gadget name',
			'params' => 'Gadget params'
		);
	}

	public function getDescription() {
		return array(
			'Gadgets Backend.'
		);
	}

	protected function getExamples() {
		return array (
			'api.php?action='
		);
	}

	public function getVersion() {
		return __CLASS__;
	}
}
Return current item: BusinessWiki