Dawid Baruch - DEV blog » PHP http://baruch.pl Blog eksperta IP.Board Tue, 07 May 2013 13:52:48 +0000 pl-PL hourly 1 http://wordpress.org/?v=3.5.1 Domyślna aplikacja w IP.Board http://baruch.pl/2012/06/domyslna-aplikacja-ip-board/ http://baruch.pl/2012/06/domyslna-aplikacja-ip-board/#comments Wed, 13 Jun 2012 07:15:57 +0000 Dawid Baruch http://baruch.pl/?p=358 Na wstępie może napiszę czym tak naprawdę jest domyślna aplikacja w IP.Board. Otóż jest to nic innego jak domyślnie wyświetlana zawartość podczas wchodzenia na „czysty” adres forum. Czystym adresem jest np. http://www.ipsbeyond.pl – dla takiego adresu domyślnie jest używana aplikacja forum. Aby zmienić tą aplikację na dowolnie inną wystarczy wykonać kilka bardzo prostych czynności. A [...]

Post Domyślna aplikacja w IP.Board pojawił się poraz pierwszy w Dawid Baruch - DEV blog.

]]>
Na wstępie może napiszę czym tak naprawdę jest domyślna aplikacja w IP.Board. Otóż jest to nic innego jak domyślnie wyświetlana zawartość podczas wchodzenia na „czysty” adres forum. Czystym adresem jest np. http://www.ipsbeyond.pl – dla takiego adresu domyślnie jest używana aplikacja forum. Aby zmienić tą aplikację na dowolnie inną wystarczy wykonać kilka bardzo prostych czynności.

A mianowicie logujemy się na FTP i przechodzimy do katalogu głównego forum. Następnie edytujemy plik initdata.php i szukamy w nim takiego wpisu:

define( 'IPS_DEFAULT_PUBLIC_APP', 'forums' );

Aby zmienić domyślną aplikację np. na blog wystarczy zamienić słowo forums na blog. Zapisać zmiany i wgrać na serwer.

A co w przypadku gdy chcemy pozwolić np. użytkownikom decydować o tym, jakiego wyglądu chcą używać? Tutaj sprawa nie jest już niestety taka prosta, o czym przekonałem się sam niedawno. Wydawało by się, że to nie jest w cale trudne, bo wystarczy w bazie danych w tabeli ibf_members dodać nową kolumnę, która będzie decydować o wybranym wyglądzie i odpowiednio ją wykorzystać gdzieś w skrypcie. Podstawowe pytanie każdego użytkownika w tym momencie powinno brzmieć gdzie? Ja osobiście postanowiłem to zrobić w głównym pliku czyli ipsRegistry.php.

Trochę to trwało ale się udało tego dokonać. Przedstawię fragment zmian jakie dokonałem w core systemu aby to wszystko działało jak należy.

Zacznijmy od zmiany w initdata.php

Na wstępie szukamy:

if ( ! defined( 'IPS_DEFAULT_APP' ) )
{
	define( 'IPS_DEFAULT_APP', ( IPS_AREA == 'public' ) ? IPS_DEFAULT_PUBLIC_APP : 'core' );
}

i zamieniamy to na:

if ( ! defined( 'IPS_DEFAULT_APP' ) && IN_ACP )
{
	define( 'IPS_DEFAULT_APP', 'core' );
}

następnie w ipsRegistry.php

szukamy:

/* _manageIncomingURLs MUST be called first!!! */
		self::_setUpAppData();

		/* Load app / coreVariables.. must be called after app Data */
		self::_loadAppCoreVariables( IPS_APP_COMPONENT );

		/* Must be called after _manageIncomingURLs */
		self::$handles['db']->getDB()->setDebugMode( ( IPS_SQL_DEBUG_MODE ) ? ( isset($_GET['debug']) ? intval($_GET['debug']) : 0 ) : 0 );

		/* Get caches */
		self::$handles['caches']   = ips_CacheRegistry::instance();

		/* Make sure all is well before we proceed */
		try
		{
			self::instance()->setUpSettings();
		}
		catch( Exception $e )
		{
			print file_get_contents( DOC_IPS_ROOT_PATH . 'cache/skin_cache/settingsEmpty.html' );
			exit;
		}
		
		/* Bah, now let's go over any input cleaning routines that have settings *sighs* */
		self::$request = IPSLib::postParseIncomingRecursively( self::$request );
		
		/* Set up dummy member class to prevent errors if cache rebuild required */
		self::$handles['member']   = ips_MemberRegistryDummy::instance();
		
		/* Build module and application caches */
		self::instance()->checkCaches();
		
		/* Set up app specific redirects. Must be called before member/sessions setup */
		self::_parseAppResets();
		
		/* Re-assign member */
		unset( self::$handles['member'] );
		self::$handles['member']   = ips_MemberRegistry::instance();
		
		/* Load other classes */
		$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/class_localization.php', 'class_localization' );
		self::instance()->setClass( 'class_localization', new $classToLoad( self::instance() ) );
		
		$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/class_public_permissions.php', 'classPublicPermissions' );
		self::instance()->setClass( 'permissions'       , new $classToLoad( self::instance() ) );

		/* Must be called before output initiated */
		self::getAppClass( IPS_APP_COMPONENT );
		
		if ( IPS_AREA == 'admin' )
		{
			require_once( IPS_ROOT_PATH . 'sources/classes/output/publicOutput.php' );/*noLibHook*/
			$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/output/adminOutput.php', 'adminOutput' );
			self::instance()->setClass( 'output'           , new $classToLoad( self::instance() ) );
			
			$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . "sources/classes/class_admin_functions.php", 'adminFunctions' );
			self::instance()->setClass( 'adminFunctions'   , new $classToLoad( self::instance() ) );
			
			$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/class_permissions.php', 'class_permissions' );
			self::instance()->setClass( 'class_permissions', new $classToLoad( self::instance() ) );
		}
		else
		{
			$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH  . 'sources/classes/output/publicOutput.php', 'output' );
			self::instance()->setClass( 'output', new $classToLoad( self::instance(), TRUE ) );
			
			register_shutdown_function( array( 'ipsRegistry', '__myDestruct' ) );
		}
		
		/* Post member processing */
		self::$handles['member']->postOutput();

		/* Add SEO templates to the output system */
		self::instance()->getClass('output')->seoTemplates = self::$_seoTemplates;

		//-----------------------------------------
		// Sort out report center early, so counts
		// and cache is right
		//-----------------------------------------

		$memberData	=& self::$handles['member']->fetchMemberData();
		$memberData['showReportCenter']	= false;

i zastępujemy to następującym kodem:

//Modify by SolutionDEVs
				
	    if( IPS_AREA == 'public' && self::$request[ 'do' ] == 'logout' )
	    {     
	        if ( ! defined( 'IPS_DEFAULT_APP' ) )
		    {
        		if ( IN_ACP )
                {
                	define( 'IPS_DEFAULT_APP', 'core' );
                }
                else
                {
                    define( 'IPS_DEFAULT_APP', 'forums' );
                }
		    }
		    
	        /* _manageIncomingURLs MUST be called first!!! */
		    self::_setUpAppData();   
		    
		    /* Load app / coreVariables.. must be called after app Data */
		    self::_loadAppCoreVariables( IPS_APP_COMPONENT );
		    
		    /* Set up app specific redirects. Must be called before member/sessions setup */
		    self::_parseAppResets();
	    }
		    
		/* Must be called after _manageIncomingURLs */
		self::$handles['db']->getDB()->setDebugMode( ( IPS_SQL_DEBUG_MODE ) ? ( isset($_GET['debug']) ? intval($_GET['debug']) : 0 ) : 0 );
		
		/* Get caches */
		self::$handles['caches']   = ips_CacheRegistry::instance();
		
		/* Make sure all is well before we proceed */
		try
		{
			self::instance()->setUpSettings();
		}
		catch( Exception $e )
		{
			print file_get_contents( DOC_IPS_ROOT_PATH . 'cache/skin_cache/settingsEmpty.html' );
			exit;
		}
		
		/* Bah, now let's go over any input cleaning routines that have settings *sighs* */
		self::$request = IPSLib::postParseIncomingRecursively( self::$request );
	
		/* Set up dummy member class to prevent errors if cache rebuild required */
		self::$handles['member']   = ips_MemberRegistryDummy::instance();
		
		/* Build module and application caches */
		self::instance()->checkCaches();
		
		/* Re-assign member */
		unset( self::$handles['member'] );
		self::$handles['member']   = ips_MemberRegistry::instance();
		
		/* Load other classes */
		$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/class_localization.php', 'class_localization' );
		self::instance()->setClass( 'class_localization', new $classToLoad( self::instance() ) );
		
		$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/class_public_permissions.php', 'classPublicPermissions' );
		self::instance()->setClass( 'permissions'       , new $classToLoad( self::instance() ) );

		/* Post member processing */
		self::$handles['member']->postOutput();
		
		$memberData	=& self::$handles['member']->fetchMemberData();

		if ( ! defined( 'IPS_DEFAULT_APP' ) )
		{
    		if ( IN_ACP )
            {
            	define( 'IPS_DEFAULT_APP', 'core' );
            }
            else
            {
                if( ( $memberData[ 'member_id' ] == 0 ) || ( $memberData[  'member_id' ] > 0 && $memberData[  'sd32_type_view' ] != 1 ) )
                {
                    define( 'IPS_DEFAULT_APP', 'forums' );
                }
                else
                {
                    define( 'IPS_DEFAULT_APP', 'MOJA_APLIKACJA' );
                    
                }
            }
		}
		
		/* _manageIncomingURLs MUST be called first!!! */
		self::_setUpAppData();

		/* Load app / coreVariables.. must be called after app Data */
		self::_loadAppCoreVariables( IPS_APP_COMPONENT );
		
		/* Set up app specific redirects. Must be called before member/sessions setup */
		self::_parseAppResets();
		
		
		/* Must be called before output initiated */
		self::getAppClass( IPS_APP_COMPONENT );
		
		if ( IPS_AREA == 'admin' )
		{
			require_once( IPS_ROOT_PATH . 'sources/classes/output/publicOutput.php' );/*noLibHook*/
			$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/output/adminOutput.php', 'adminOutput' );
			self::instance()->setClass( 'output'           , new $classToLoad( self::instance() ) );
			
			$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . "sources/classes/class_admin_functions.php", 'adminFunctions' );
			self::instance()->setClass( 'adminFunctions'   , new $classToLoad( self::instance() ) );
			
			$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH . 'sources/classes/class_permissions.php', 'class_permissions' );
			self::instance()->setClass( 'class_permissions', new $classToLoad( self::instance() ) );
		}
		else
		{
			$classToLoad = IPSLib::loadLibrary( IPS_ROOT_PATH  . 'sources/classes/output/publicOutput.php', 'output' );
			self::instance()->setClass( 'output', new $classToLoad( self::instance(), TRUE ) );
			
			register_shutdown_function( array( 'ipsRegistry', '__myDestruct' ) );
		}
		
		/* Add SEO templates to the output system */
		self::instance()->getClass('output')->seoTemplates = self::$_seoTemplates;

		//-----------------------------------------
		// Sort out report center early, so counts
		// and cache is right
		//-----------------------------------------

		$memberData	=& self::$handles['member']->fetchMemberData();
		$memberData['showReportCenter']	= false;
		
		if( IPS_AREA == 'public' )
		{
    		self::$handles['member']->sessionClass()->updateMySession( array( 'current_appcomponent' => IPS_APP_COMPONENT ) );
		}

Następnie jedyne co jeszcze musimy zrobić, to wprowadzić jakieś ustawienie w panelu użytkownika, lub w popup’ie. Metodę wykonania zostawiam już Wam :)

Jako opcja decydująca o wyborze aplikacji decyduje pole sd32_type_view w tabeli ibf_members, które możemy dodać w następujący sposób:

ALTER TABLE ibf_members ADD COLUMN sd32_type_view TINYINT UNSIGNED NOT NULL DEFAULT 0;

Jeśli ustawimy to pole na wartość 1, wtedy będzie odpalana domyślnie nasza aplikacja, natomiast goście i użytkownicy, którzy mają inną wartość w tym polu będą widzieć forum.

Artykuł był pisany w oparciu o wersję IP.Board 3.2.3 i nie obiecuję, że w najnowszej wersji 3.3.3 coś się nie zmieniło w ipsRegistry we fragmencie, który poddaliśmy edycji.

Post Domyślna aplikacja w IP.Board pojawił się poraz pierwszy w Dawid Baruch - DEV blog.

]]>
http://baruch.pl/2012/06/domyslna-aplikacja-ip-board/feed/ 0
Własna wyszukiwarka w aplikacji IP.Board http://baruch.pl/2012/05/wlasna-wyszukiwarka-aplikacji-ip-board/ http://baruch.pl/2012/05/wlasna-wyszukiwarka-aplikacji-ip-board/#comments Tue, 15 May 2012 11:08:24 +0000 Dawid Baruch http://baruch.pl/?p=241 Dzisiejszy wpis jest delikatnie inny od wcześniejszych wpisów, ponieważ będzie dokładnie opisywał proces tworzenia własnej wyszukiwarki w aplikacjach IP.Board. Artykuł ten jest kontynuacją cyklu wpisów na temat tworzenia dodatków do IP.Board. Nie pozostaje mi nic innego jak zaprosić do czytania dalszej części wpisu. Zapewne zapytać dlaczego cykl tworzenia aplikacji do IP.Board zaczynam od stworzenia wyszukiwarki [...]

Post Własna wyszukiwarka w aplikacji IP.Board pojawił się poraz pierwszy w Dawid Baruch - DEV blog.

]]>
Dzisiejszy wpis jest delikatnie inny od wcześniejszych wpisów, ponieważ będzie dokładnie opisywał proces tworzenia własnej wyszukiwarki w aplikacjach IP.Board. Artykuł ten jest kontynuacją cyklu wpisów na temat tworzenia dodatków do IP.Board. Nie pozostaje mi nic innego jak zaprosić do czytania dalszej części wpisu.

Zapewne zapytać dlaczego cykl tworzenia aplikacji do IP.Board zaczynam od stworzenia wyszukiwarki a nie od stworzenia szkieletu aplikacji? Odpowiedź jest dość prosta (przynajmniej dla mnie). Wiedzę zdobytą w tej publikacji możemy wykorzystać w dowolnej aplikacji, którą mamy zainstalowaną, a która nie posiada jeszcze własnej wyszukiwarki. Natomiast temat tworzenia szkieletu aplikacji jest bardziej skomplikowany i wymaga więcej czasu ode mnie na napisanie tego, oraz od czytelnika aby przyswoił wiedzę.

Opis tworzenia wyszukiwarki zacznę od opisu struktury katalogów, bo ona jest tutaj bardzo ważna. Na poniższym obrazku przedstawiona jest cała struktura folderu search, który musi znajdować się w katalogu extensions naszej aplikacji:

Teraz znając już strukturę omówię dokładnie co jest czym ;)

Zaczniemy od pliku config.php. Jest to plik konfiguracyjny, który decyduje o tym gdzie można używać wyszukiwarki (chodzi tutaj o wyszukiwanie nowych wpisów, treści użytkownika itp.)

<?php
/* Można szukać w aplikacji */
$CONFIG['can_search']	      = 1;

/* Można widzieć nową zawartość */
$CONFIG['can_viewNewContent'] = 0;

/* Można pokazać aktywną zawartość */
$CONFIG['can_activeContent']  = 0;

/* Można pokazać treść użytkownika */
$CONFIG['can_userContent'] = 0;

/* Typy treści */
$CONFIG['contentTypes'] = array( 'content', 'comments' );
?>

W pliku tym umieszczamy taką zawartość i decydujemy co ma być włączone a co nie. Ustawienia dotyczące typu treści dają nam możliwość w wyszukiwarce wybrania np. sekcji w jakiej chcemy szukać. Przykładowo nasza aplikacja posiada treści i komentarze, w związku z tym możemy szukać w typie treść i w typie komentarze.

Kolejnym plikiem jest form.php, który odpowiada za wyświetlenie formularza z opcjami w wyszukiwarce zaawansowanej. Kod pliku umieszczony jest poniżej.

<?php
/**
 * SolutionrDEVs Application
 * Wyszukiwarka
 *
 * @author      Dawid Baruch
 * @copyright   (c) 2005 - 2012 SolutionDEVs
 * @package     SolutionDEVs Apps
 * @subpackage  PHP
 * @link        http://www.solutiondevs.pl
 * @version     1.0.0 
 *
 */

if ( ! defined( 'IN_IPB' ) )
{
	print "<h1>Incorrect access</h1>You cannot access this file directly. If you have recently upgraded, make sure you upgraded all the relevant files.<br />Author: Dawid Baruch <a href='http://www.solutiondevs.pl'><strong>SolutionDEVs.pl</strong></a>";
	exit();
}

class search_form_application
{
	/**
	 * Construct
	 *
	 */
	public function __construct()
	{
		/* Make object */
		$this->registry   =  ipsRegistry::instance();
		$this->DB         =  $this->registry->DB();
		$this->settings   =& $this->registry->fetchSettings();
		$this->request    =& $this->registry->fetchRequest();
		$this->lang       =  $this->registry->getClass('class_localization');
		$this->member     =  $this->registry->member();
		$this->memberData =& $this->registry->member()->fetchMemberData();
		$this->cache      =  $this->registry->cache();
		$this->caches     =& $this->registry->cache()->fetchCaches();
		
		/* Language */
		$this->registry->class_localization->loadLanguageFile( array( 'public_view' ), 'application' );
	}
	

	/**
	 * Return sort drop down
	 * 
	 *
	 * @access	public
	 * @return	array
	 */
	public function fetchSortDropDown()
	{
		$array = array( 
						'content' => array( 
					    					'date'		=> $this->lang->words[ 'sd32_content_date' ],
					    					'title'		=> $this->lang->words[ 'sd32_content_title' ],
										),
					    'comments'  => array( 
					    					'date'		=> $this->lang->words[ 'sd32_comment_date' ],
					    					'title'		=> $this->lang->words[ 'sd32_comment_title' ],
				    					) 
					);
		
		return $array;
	}
	
	/**
	 * Return sort in
	 * Optional function to allow apps to define searchable 'sub-apps'.
	 * 
	 *
	 * @access	public
	 * @return	array
	 */
	public function fetchSortIn()
	{
		$array = array( 
						array( 'content',	$this->lang->words[ 'sd32_search_content' ] ),
					    array( 'comment',	$this->lang->words[ 'sd32_search_comment' ] ) 
					);
		
		return $array;
	}
	
	/**
	 * Retuns the html for displaying the extra groups search filters
	 *
	 * @access	public
	 * @return	string	Filter HTML
	 **/
	public function getHtml()
	{
		return array( 'title' => ipsRegistry::$applications['application']['app_public_title'], 'html' => '' );
	}
}

Metoda fetchSortDropDown() musi zwracać tablicę w podobnej postaci jak w powyższym kodzie. Tablica ta jako klucz zawiera typ treści, a jako wartość tablicę zawierającą pary klucz => opis. Klucz jest nazwą po jakiej będziemy sortować wyniki wyszukiwania.

Metoda fetchSortIn() Zwraca nam tablicę, która definiuje typy treści oraz ich opisową nazwę (nazwę jaką zobaczy użytkownik).

Metoda getHtml() Zwraca nam kod dla dodatkowych ustawień wyszukiwania. Jeśli nie chcemy dawać nic ponad standardowe opcje + możliwość wyszukiwania po różnych typach treści to nie musimy się przejmować tą metodą.

Kolejnym plikiem omówionym przeze mnie będzie format.php

<?php
/**
 * SolutionrDEVs Application
 * Wyszukiwarka
 *
 * @author      Dawid Baruch
 * @copyright   (c) 2005 - 2012 SolutionDEVs
 * @package     SolutionDEVs Apps
 * @subpackage  PHP
 * @link        http://www.solutiondevs.pl
 * @version     1.0.0 
 *
 */

if ( ! defined( 'IN_IPB' ) )
{
	print "<h1>Incorrect access</h1>You cannot access this file directly. If you have recently upgraded, make sure you upgraded all the relevant files.<br />Author: Dawid Baruch <a href='http://www.solutiondevs.pl'><strong>SolutionDEVs.pl</strong></a>";
	exit();
}

class search_format_application extends search_format
{
	/**
	 * Constructor
	 */
	public function __construct( ipsRegistry $registry )
	{
		parent::__construct( $registry );
		
		/* Language */
		$this->registry->class_localization->loadLanguageFile( array( 'public_view' ), 'application' );
	}
	
	/**
	 * Parse search results
	 *
	 * @access	private
	 * @param	array 	$r				Search result
	 * @return	array 	$html			Blocks of HTML
	 */
	public function parseAndFetchHtmlBlocks( $rows )
	{
		/* INIT */
		$search_term        = IPSSearchRegistry::get('in.clean_search_term');
				
		/* Go through and build HTML */
		foreach( $rows as $id => $data )
		{
			/* Format content */
			list( $html, $sub ) = $this->formatContent( $data );
			
			$data['content_title'] = IPSText::searchHighlight( $data['content_title'], $search_term );
			
			$results[ $id ] = array( 'html' => $html, 'app' => $data['app'], 'type' => $data['type'], 'sub' => $sub );
		}
		
		return $results;
	}
	
	/**
	 * Formats the forum search result for display
	 *
	 * @access	public
	 * @param	array   $search_row		Array of data from search_index
	 * @return	mixed	Formatted content, ready for display, or array containing a $sub section flag, and content
	 **/
	public function formatContent( $data )
	{
		$template		= ( IPSSearchRegistry::get('application.searchInKey') == 'topics' ) ? 'groupsTopicsSearchResult' : 'groupsGroupSearchResult';

		return array( ipsRegistry::getClass( 'output' )->getTemplate( 'application' )->$template( $data, IPSSearchRegistry::get('display.onlyTitles') ), 0 );
	}

	/**
	 * Decides which type of search this was
	 *
	 * @access public
	 * @return array
	 */
	public function processResults( $ids )
	{
		$this->templates = array( 'group' => 'application', 'template' => 'groupsSearchResult' );
		
		if ( IPSSearchRegistry::get('application.searchInKey') == 'comment' )
		{
			/* Set up wrapper */
			return $this->_processCommentResults( $ids );
		}
		else
		{
			return $this->_processContentResults( $ids );
		}
	}
	
	public function _processContentResults( $ids )
	{
		/* INIT */
		$sort_by     		= IPSSearchRegistry::get('in.search_sort_by');
		$sort_order         = IPSSearchRegistry::get('in.search_sort_order');
		$search_term        = IPSSearchRegistry::get('in.clean_search_term');
		$content_title_only = IPSSearchRegistry::get('opt.searchTitleOnly');
		$onlyPosts          = IPSSearchRegistry::get('opt.onlySearchPosts');
		$order_dir 			= ( $sort_order == 'asc' ) ? 'asc' : 'desc';
		$sortKey			= '';
		$sortType			= '';
		$rows				= array();
		$_rows				= array();
		$members			= array();
		$results			= array();
		
		/* Got some? */
		if ( count( $ids ) )
		{
			/* Sorting */
			switch( $sort_by )
			{
				default:
				case 'date':
					$sortKey  = 'last_post';
					$sortType = 'numerical';
				break;
				
				case 'title':
					$sortKey  = 'g_name';
					$sortType = 'string';
				break;
			}

			/* Set vars */
			IPSSearch::$ask = $sortKey;
			IPSSearch::$aso = strtolower( $order_dir );
			IPSSearch::$ast = $sortType;
			
			/* Fetch data */
			$this->DB->build( array( 
									'select'   => "g.*",
									'from'	   => array( 'c_groups' => 'g' ),
		 							'where'	   => 'g.g_id IN( ' . implode( ',', $ids ) . ')',
									'add_join' => array(
														array(
																'select' => 'f.*',
																'from'   => array( 'forums' => 'f' ),
																'where'  => "f.id=g.g_forum",
																'type'   => 'inner',
															),
														array(
																'select' => 't.*',
																'from'   => array( 'topics' => 't' ),
																'where'  => "t.tid=f.last_id",
																'type'   => 'inner',
															),
														)
							)	);
	
			/* Grab data */
			$res = $this->DB->execute();
			
			/* Grab the results */
			while( $row = $this->DB->fetch( $res ) )
			{
			    IPSText::getTextClass('bbcode')->parse_html 				= 0;
        		IPSText::getTextClass('bbcode')->parse_nl2br				= 1;
        		IPSText::getTextClass('bbcode')->parse_bbcode				= 1;
        		IPSText::getTextClass('bbcode')->parse_smilies				= 0;
        		IPSText::getTextClass('bbcode')->parsing_section			= 'group_add';
    
        		$row['g_desc'] = IPSText::getTextClass( 'bbcode' )->preDisplayParse( $row['g_desc'] );
    		
				$_rows[] = $row;
			}

			/* Sort */
			if ( count( $_rows ) )
			{
				usort( $_rows, array("IPSSearch", "usort") );
		
				foreach( $_rows as $id => $row )
				{				
					/* Got author but no member data? */
					if ( ! empty( $row['last_poster_id'] ) )
					{
						$members[ $row['last_poster_id'] ] = $row['last_poster_id'];
					}
					
					$results[ $row['id'] ] = $this->genericizeResults( $row );
				}
			}

			/* Need to load members? */
		    if ( count( $members ) )
			{
				$mems = IPSMember::load( $members, 'all' );
				
				foreach( $results as $id => $r )
				{
					if ( ! empty( $r['last_poster_id'] ) AND isset( $mems[ $r['last_poster_id'] ] ) )
					{
						$_mem = IPSMember::buildDisplayData( $mems[ $r['last_poster_id'] ], array( 'reputation' => 0, 'warn' => 0 ) );

						$results[ $id ] = array_merge( $results[ $id ], $_mem );
					}
				}
			}
		}

		return $results;
	}
	
	/**
	 * Formats / grabs extra data for results
	 * Takes an array of IDS (can be IDs from anything) and returns an array of expanded data.
	 *
	 * @access public
	 * @return array
	 */
	public function _processCommentResults( $ids )
	{
		/* INIT */
		$sort_by     		= IPSSearchRegistry::get('in.search_sort_by');
		$sort_order         = IPSSearchRegistry::get('in.search_sort_order');
		$search_term        = IPSSearchRegistry::get('in.clean_search_term');
		$content_title_only = IPSSearchRegistry::get('opt.searchTitleOnly');
		$onlyPosts          = IPSSearchRegistry::get('opt.onlySearchPosts');
		$order_dir 			= ( $sort_order == 'asc' ) ? 'asc' : 'desc';
		$sortKey			= '';
		$sortType			= '';
		$rows				= array();
		$_rows				= array();
		$members			= array();
		$results			= array();
		
		/* Got some? */
		if ( count( $ids ) )
		{
			/* Sorting */
			switch( $sort_by )
			{
				default:
				case 'date':
					$sortKey  = 'last_post';
					$sortType = 'numerical';
				break;
				
				case 'title':
					$sortKey  = 'g_name';
					$sortType = 'string';
				break;
				
				case 'reply':
					$sortKey	= 'posts';
					$sortType	= 'numerical';
				break;
				
				case 'views':
					$sortKey	= 'views';
					$sortType	= 'numerical';
				break;
			}

			/* Set vars */
			IPSSearch::$ask = $sortKey;
			IPSSearch::$aso = strtolower( $order_dir );
			IPSSearch::$ast = $sortType;
			
			/* Fetch data */
			$this->DB->build( array( 
									'select'   => "t.*",
									'from'	   => array( 'topics' => 't' ),
		 							'where'	   => 't.tid IN( ' . implode( ',', $ids ) . ')',
									'add_join' => array(
														array(
																'select' => 'g.*',
																'from'   => array( 'c_groups' => 'g' ),
																'where'  => "g.g_forum=t.forum_id",
																'type'   => 'inner',
															),
														)
							)	);
							
			/* Grab data */
			$res = $this->DB->execute();
			
			/* Grab the results */
			while( $row = $this->DB->fetch( $res ) )
			{
			    IPSText::getTextClass('bbcode')->parse_html 				= 0;
        		IPSText::getTextClass('bbcode')->parse_nl2br				= 1;
        		IPSText::getTextClass('bbcode')->parse_bbcode				= 1;
        		IPSText::getTextClass('bbcode')->parse_smilies				= 0;
        		IPSText::getTextClass('bbcode')->parsing_section			= 'group_add';
    
        		$row['g_desc'] = IPSText::getTextClass( 'bbcode' )->preDisplayParse( $row['g_desc'] );
        		
				$_rows[] = $row;
			}

			/* Sort */
			if ( count( $_rows ) )
			{
				usort( $_rows, array("IPSSearch", "usort") );
		
				foreach( $_rows as $id => $row )
				{				
					/* Got author but no member data? */
					if ( ! empty( $row['last_poster_id'] ) )
					{
						$members[ $row['last_poster_id'] ] = $row['last_poster_id'];
					}

					$results[ $row['id'] ] = $this->genericizeResults( $row );
				}
			}

			/* Need to load members? */
			if ( count( $members ) )
			{
				$mems = IPSMember::load( $members, 'all' );
				
				foreach( $results as $id => $r )
				{
				    // Modify by Dawid
					if ( ! empty( $r['last_poster_id'] ) AND isset( $mems[ $r['last_poster_id'] ] ) )
					{
						$_mem = IPSMember::buildDisplayData( $mems[ $r['last_poster_id'] ], array( 'reputation' => 0, 'warn' => 0 ) );

						$results[ $id ] = array_merge( $results[ $id ], $_mem );
					}
				}
			}
		}

		return $results;
	}
	
	/**
	 * Reassigns fields in a generic way for results output
	 *
	 * @param  array  $r
	 * @return array
	 **/
	public function genericizeResults( $r )
	{
		if ( IPSSearchRegistry::get('application.searchInKey') == 'commen' )
		{
			$r['app']                 = 'application';
			$r['content']             = $r['g_desc'];
			$r['content_title']       = $r['title'];
			$r['updated']             = $r['last_post'];
			$r['type_2']              = 'topics';
			$r['type_id_2']           = $r['tid'];
			$r['type_id_3']           = $r['g_id'];
			$r['content_subtitle']    = $r['g_name'];
		}
		else
		{
			$r['app']                 = 'application';
			$r['content']             = $r['g_desc'];
			$r['content_title']       = $r['g_name'];
			$r['updated']             = $r['last_post'];
			$r['type_2']              = 'groups';
			$r['type_id_2']           = $r['g_id'];
			$r['content_subtitle']    = $r['title'];
		}

		return $r;
	}

}

Plik ten odpowiada za prezentację wyników wyszukiwania. Dokładniej metodzie parseAndFetchHtmlBlocks() zwracamy kod html dla poszczególnych wierszy wyników.

Natomiast metoda formatContent() decyduje o tym jakiego szablonu użyć dla konkretnego typu treści.

Pozostałe metody wydaje mi się, że są na tyle przejrzyste, że nie trzeba ich opisywać jakoś szczegółowo.

Przejdźmy zatem do ostatniego już pliku – sql.php

<?php
/**
 * SolutionrDEVs Application
 * Wyszukiwarka
 *
 * @author      Dawid Baruch
 * @copyright   (c) 2005 - 2012 SolutionDEVs
 * @package     SolutionDEVs Apps
 * @subpackage  PHP
 * @link        http://www.solutiondevs.pl
 * @version     1.0.0 
 *
 */

if ( ! defined( 'IN_IPB' ) )
{
	print "<h1>Incorrect access</h1>You cannot access this file directly. If you have recently upgraded, make sure you upgraded all the relevant files.<br />Author: Dawid Baruch <a href='http://www.solutiondevs.pl'><strong>SolutionDEVs.pl</strong></a>";
	exit();
}

class search_engine_application extends search_engine
{
	/**
	 * Constructor
	 */
	public function __construct( ipsRegistry $registry )
	{
		/* Hard limit */
		IPSSearchRegistry::set('set.hardLimit', ( ipsRegistry::$settings['search_hardlimit'] ) ? ipsRegistry::$settings['search_hardlimit'] : 200 );

		parent::__construct( $registry );
	}
	
	/**
	 * Decide what type of search we're using
	 *
	 * @access	public
	 * @return	array
	 */
	public function search()
	{
		if ( IPSSearchRegistry::get('application.searchInKey') == 'comment' )
		{
			return $this->_commentSearch();
		}
		else
		{
			return $this->_contentSearch();
		}
	}
	
	/**
	 * Perform a comment search.
	 * Returns an array of a total count (total number of matches)
	 * and an array of IDs ( 0 => 1203, 1 => 928, 2 => 2938 ).. matching the required number based on pagination. The ids returned would be based on the filters and type of search
	 *
	 * So if we had 1000 replies, and we are on page 2 of 25 per page, we'd return 25 items offset by 25
	 *
	 * @access public
	 * @return array
	 */
	public function _contentSearch()
	{
		/* INIT */ 
		$count       		= 0;
		$results     		= array();
		$sort_by     		= IPSSearchRegistry::get('in.search_sort_by');
		$sort_order         = IPSSearchRegistry::get('in.search_sort_order');
		$search_term        = IPSSearchRegistry::get('in.clean_search_term');
		$content_title_only = IPSSearchRegistry::get('opt.searchTitleOnly');
		$order_dir 			= ( $sort_order == 'asc' ) ? 'asc' : 'desc';
		$rows    			= array();
		$count   			= 0;
		$c                  = 0;
		$got     			= 0;
		$sortKey			= '';
		$sortType			= '';

		/* Sorting */
	    switch( $sort_by )
		{
			default:
			case 'date':
				$sortKey  = 'last_post';
				$sortType = 'numerical';
			break;
			
			case 'title':
				$sortKey  = 'g_name';
				$sortType = 'string';
			break;
		}

		/* Fetch data */
		$this->DB->build( array( 
									'select'   => "g.g_id, g.g_name",
									'from'	   => array( 'c_groups' => 'g' ),
									'where'	   => $this->_buildWhereStatement( $search_term, $content_title_only, 'groups' ),
									'limit'    => array(0, IPSSearchRegistry::get('set.hardLimit') + 1),
									'order'	   => "{$sortKey} {$order_dir}",
									'add_join' => array(
														array(
																'from'   => array( 'forums' => 'f' ),
																'where'  => "f.id=g.g_forum",
																'type'   => 'inner',
															),
														array(
																'select' => 't.tid, t.last_poster_id, t.last_post',
																'from'   => array( 'topics' => 't' ),
																'where'  => "t.tid=f.last_id",
																'type'   => 'inner',
															),
														)
						)	);
						
		$this->DB->execute();
		
		/* Fetch count */
		$count = intval( $this->DB->getTotalRows() );
		
		if ( $count > IPSSearchRegistry::get('set.hardLimit') )
		{
			$count = IPSSearchRegistry::get('set.hardLimit');
			
			IPSSearchRegistry::set('set.resultsCutToLimit', true );
		}

		$_rows = array();
		
		/* Fetch to sort */
		while ( $r = $this->DB->fetch() )
		{
			$_rows[ $r['g_id'] ] = $r;
		}
		
		/* Set vars */
		IPSSearch::$ask = $sortKey;
		IPSSearch::$aso = strtolower( $order_dir );
		IPSSearch::$ast = $sortType;
		
		/* Sort */
		if ( count( $_rows ) )
		{
			usort( $_rows, array("IPSSearch", "usort") );

			/* Build result array */
			foreach( $_rows as $r )
			{
				$c++;
				
				if ( IPSSearchRegistry::get('in.start') AND IPSSearchRegistry::get('in.start') >= $c )
				{
					continue;
				}
				
				$rows[ $got ] = $r['g_id'];
							
				$got++;
				
				/* Done? */
				if ( IPSSearchRegistry::get('opt.search_per_page') AND $got >= IPSSearchRegistry::get('opt.search_per_page') )
				{
					break;
				}
			}
		}

		/* Return it */
		return array( 'count' => $count, 'resultSet' => $rows );
	}
	
	/**
	 * Perform an image search.
	 * Returns an array of a total count (total number of matches)
	 * and an array of IDs ( 0 => 1203, 1 => 928, 2 => 2938 ).. matching the required number based on pagination. The ids returned would be based on the filters and type of search
	 *
	 * So if we had 1000 replies, and we are on page 2 of 25 per page, we'd return 25 items offset by 25
	 *
	 * @access public
	 * @return array
	 */
	public function _commentSearch()
	{
		/* INIT */ 
		$count       		= 0;
		$results     		= array();
		$sort_by     		= IPSSearchRegistry::get('in.search_sort_by');
		$sort_order         = IPSSearchRegistry::get('in.search_sort_order');
		$search_term        = IPSSearchRegistry::get('in.clean_search_term');
		$content_title_only = IPSSearchRegistry::get('opt.searchTitleOnly');
		$order_dir 			= ( $sort_order == 'asc' ) ? 'asc' : 'desc';
		$rows    			= array();
		$count   			= 0;
		$c                  = 0;
		$got     			= 0;
		$sortKey			= '';
		$sortType			= '';

		/* Sorting */
	    switch( $sort_by )
		{
			default:
			case 'date':
				$sortKey  = 'last_post';
				$sortType = 'numerical';
			break;
			
			case 'title':
				$sortKey  = 'g_name';
				$sortType = 'string';
			break;
			
			case 'reply':
				$sortKey	= 'posts';
				$sortType	= 'numerical';
			break;
			
			case 'views':
				$sortKey	= 'views';
				$sortType	= 'numerical';
			break;
		}

		/* Fetch data */
		$this->DB->build( array( 
								'select'   => "t.tid, t.last_post, t.last_poster_id, t.views, t.posts",
								'from'	   => array( 'topics' => 't' ),
								'where'	   => $this->_buildWhereStatement( $search_term, $content_title_only ),
								'limit'    => array(0, IPSSearchRegistry::get('set.hardLimit') + 1),
		                        'order'	   => "t.{$sortKey} {$order_dir}",
								'add_join' => array(
														array(
																'select' => 'g.g_id, g.g_name',
																'from'   => array( 'c_groups' => 'g' ),
																'where'  => "g.g_forum=t.forum_id",
																'type'   => 'inner',
															),
														)
								)	);
								
		$this->DB->execute();
		
		/* Fetch count */
		$count = intval( $this->DB->getTotalRows() );
		
		if ( $count > IPSSearchRegistry::get('set.hardLimit') )
		{
			$count = IPSSearchRegistry::get('set.hardLimit');
			
			IPSSearchRegistry::set('set.resultsCutToLimit', true );
		}

		$_rows = array();
		
		/* Fetch to sort */
		while ( $r = $this->DB->fetch() )
		{
			$_rows[ $r['tid'] ] = $r;
		}
		
		/* Set vars */
		IPSSearch::$ask = $sortKey;
		IPSSearch::$aso = strtolower( $order_dir );
		IPSSearch::$ast = $sortType;
		
		/* Sort */
		if ( count( $_rows ) )
		{
			usort( $_rows, array("IPSSearch", "usort") );

			/* Build result array */
			foreach( $_rows as $r )
			{
				$c++;
				
				if ( IPSSearchRegistry::get('in.start') AND IPSSearchRegistry::get('in.start') >= $c )
				{
					continue;
				}
				
				$rows[ $got ] = $r['tid'];
							
				$got++;
				
				/* Done? */
				if ( IPSSearchRegistry::get('opt.search_per_page') AND $got >= IPSSearchRegistry::get('opt.search_per_page') )
				{
					break;
				}
			}
		}

		/* Return it */
		return array( 'count' => $count, 'resultSet' => $rows );
	}
	
	/**
	 * Perform the search for viewUserContent, viewActiveContent, and viewNewContent
	 *
	 * @access	public
	 * @return	array
	 */
	public function _getNonSearchData( $where )
	{
		/* Init */
		$start		= IPSSearchRegistry::get('in.start');
		$perPage	= IPSSearchRegistry::get('opt.search_per_page');
		IPSSearchRegistry::set( 'in.search_sort_by'   , 'date' );
		IPSSearchRegistry::set( 'in.search_sort_order', 'desc' );
		IPSSearchRegistry::set( 'groups.searchInKey'	, in_array( $this->request['search_app_filters']['application']['searchInKey'], array( 'comment', 'content' ) ) ? $this->request['search_app_filters']['application']['searchInKey'] : 'contet' );
		
		/* Fetch the count */
		if( IPSSearchRegistry::get('gapplication.searchInKey') == 'comment' )
		{
			$count = $this->DB->buildAndFetch( 
												array( 
														'select'	=> 'count(*) as count',
														'from'		=> array( 'topis' => 't' ),
														'where'		=> $where,
														'add_join'	=> array(
																				array(
                        																'from'   => array( 'c_groups' => 'g' ),
                        																'where'  => "g.g_forum=t.forum_id",
                        																'type'   => 'inner',
                        															),
																				)
													)	
											);
		}
		else
		{
			$count = $this->DB->buildAndFetch( 
												array( 
														'select'	=> 'count(*) as count',
														'from'		=> array( 'c_groups' => 'g' ),
														'where'		=> $where,
														'add_join' => array(
                        														array(
                        																'from'   => array( 'forums' => 'f' ),
                        																'where'  => "f.id=g.g_forum",
                        																'type'   => 'inner',
                        															),
                        														array(
                        																'from'   => array( 'topics' => 't' ),
                        																'where'  => "t.tid=f.last_id",
                        																'type'   => 'inner',
                        															),
                    														)
													)	
											);
		}

		/* Fetch the data */
		$imgIds = array();
		
		if ( $count['count'] )
		{
			if( IPSSearchRegistry::get('application.searchInKey') == 'comment' )
			{
				$this->DB->build( array( 
											'select'	=> 't.tid as id',
											'from'		=> array( 'topics' => 't' ),
										 	'where'		=> $where,
										 	'order'		=> 't.last_post DESC',
										 	'limit'		=> array( $start, $perPage ),
										 	'add_join'	=> array(
																	array(
            																'from'   => array( 'c_groups' => 'g' ),
            																'where'  => "g.g_forum=t.forum_id",
            																'type'   => 'inner',
            															),
																	) 
								)	);
			}
			else
			{
				$this->DB->build( array( 
											'select'	=> 'g.g_id as id',
											'from'		=> array( 'c_groups' => 'g' ),
										 	'where'		=> $where,
										 	'order'		=> 't.last_post DESC',
										 	'limit'		=> array( $start, $perPage ),
										 	'add_join'	=> array(
																	array(
            																'from'   => array( 'forums' => 'f' ),
            																'where'  => "f.id=g.g_forum",
            																'type'   => 'inner',
            															),
            														array(
            																'from'   => array( 'topics' => 't' ),
            																'where'  => "t.tid=f.last_id",
            																'type'   => 'inner',
            															),
																	) 
								)	);
			}
			$this->DB->execute();

			while( $row = $this->DB->fetch() )
			{
				$imgIds[] = $row['id'];
			}
		}

		/* Return it */
		return array( 'count' => $count['count'], 'resultSet' => $imgIds );
	}
	
	/**
	 * Builds the where portion of a search string
	 *
	 * @access	private
	 * @param	string	$search_term		The string to use in the search
	 * @param	bool	$content_title_only	Search only title records
	 * @return	string
	 */
	private function _buildWhereStatement( $search_term, $content_title_only=false, $type='topics' )
	{
		/* INI */
		$where_clause	= array();
		$searchInCats	= array();
		
		if( $search_term )
		{
			$search_term	= trim($search_term);
			
			if( $type == 'topics' )
			{
				$where_clause[] = "t.title LIKE '%{$search_term}%'";
			}
			else
			{
				$where_clause[] = "(g.g_name LIKE '%{$search_term}%' OR g.g_desc LIKE '%{$search_term}%')";
			}
		}
		
		/* Exclude some items */
		if( !$this->memberData['g_is_supmod'] )
		{
			if( $type == 'topics' )
			{
				$where_clause[] = 't.approved=1 AND t.tdelete_time=0';	
			}
			
			/* Approved only */
			$where_clause[]	= 'g.g_approval=1';	
		}
		
		/* Date Restrict */
		if( $this->search_begin_timestamp && $this->search_end_timestamp )
		{
			$where_clause[] = $this->DB->buildBetween( "t.last_post", $this->search_begin_timestamp, $this->search_end_timestamp );
		}
		else
		{
			if( $this->search_begin_timestamp )
			{
				$where_clause[] = "t.last_post > {$this->search_begin_timestamp}";
			}
			
			if( $this->search_end_timestamp )
			{
				$where_clause[] = "t.last_post < {$this->search_end_timestamp}";
			}
		}
		
		/* Add in AND where conditions */
		if( isset( $this->whereConditions['AND'] ) && count( $this->whereConditions['AND'] ) )
		{
			$where_clause = array_merge( $where_clause, $this->whereConditions['AND'] );
		}
		
		/* ADD in OR where conditions */
		if( isset( $this->whereConditions['OR'] ) && count( $this->whereConditions['OR'] ) )
		{
			$where_clause[] = '( ' . implode( ' OR ', $this->whereConditions['OR'] ) . ' )';
		}
		
		/* Build and return the string */
		return implode( " AND ", $where_clause );
	}
	
	/**
	 * Remap standard columns (Apps can override )
	 *
	 * @access	public
	 * @param	string	$column		sql table column for this condition
	 * @return	string				column
	 * @return	void
	 */
	public function remapColumn( $column )
	{
		$column = $column == 'member_id' ? 'g.member_id' : $column;

		return $column;
	}
		
	/**
	 * Returns an array used in the searchplugin's setCondition method
	 *
	 * @access	public
	 * @param	array 	$data	Array of forums to view
	 * @return	array 	Array with column, operator, and value keys, for use in the setCondition call
	 **/
	public function buildFilterSQL( $data )
	{
		/* INIT */
		$return		= array();
		$searchIn	= $this->request['search_app_filters']['application']['searchInKey'];

		/* Set up some defaults */
		IPSSearchRegistry::set( 'opt.noPostPreview'  , false );
		IPSSearchRegistry::set( 'opt.onlySearchPosts', false );
		
		IPSSearchRegistry::set( 'application.searchInKey', in_array( $searchIn, array( 'comment', 'conetnt' ) ) ? $searchIn : 'content' );
		
		return array();
	}

	/**
	 * Can handle boolean searching
	 *
	 * @access	public
	 * @return	boolean
	 */
	public function isBoolean()
	{
		return false;
	}
}

Plik ten jest używany do wyszukiwania treści w bazie danych. Dokładny opis pliku oraz dalszą część artykułu można przeczytać w publikacji Własna wyszukiwarka treści.

Post Własna wyszukiwarka w aplikacji IP.Board pojawił się poraz pierwszy w Dawid Baruch - DEV blog.

]]>
http://baruch.pl/2012/05/wlasna-wyszukiwarka-aplikacji-ip-board/feed/ 0
Joomla! oraz IP.Board – Finalne połączenie http://baruch.pl/2012/04/joomla-oraz-ip-board-finalne-polaczenie/ http://baruch.pl/2012/04/joomla-oraz-ip-board-finalne-polaczenie/#comments Wed, 11 Apr 2012 09:47:54 +0000 Dawid Baruch http://baruch.pl/?p=204 W ostatnich dwóch wpisach (Joomla! 2.5 i IP.Board – kolejna odsłona prac oraz Joomla! 2.5 oraz IP.Board 3.1.4) opisywałem swoje prace nad zagadnieniem połączenia CMS’a jakim jest Joomla oraz forum dyskusyjnego IP.Board. Połączenie to udało się wykonać w oparciu o IP.Converge jedyne co pozostawało do zrobienia to możliwość autologowania na portalu. I tego właśnie będzie [...]

Post Joomla! oraz IP.Board – Finalne połączenie pojawił się poraz pierwszy w Dawid Baruch - DEV blog.

]]>
W ostatnich dwóch wpisach (Joomla! 2.5 i IP.Board – kolejna odsłona prac oraz Joomla! 2.5 oraz IP.Board 3.1.4) opisywałem swoje prace nad zagadnieniem połączenia CMS’a jakim jest Joomla oraz forum dyskusyjnego IP.Board. Połączenie to udało się wykonać w oparciu o IP.Converge jedyne co pozostawało do zrobienia to możliwość autologowania na portalu. I tego właśnie będzie dotyczyć ten wpis.

Sama sprawa autologowania nie jest jakoś bardzo skomplikowana, największym problemem tutaj było odczytanie czy użytkownik jest zalogowany na forum a jeśli tak to trzeba pobrać kilka jego danych takich jak nazwa wyświetlana czy adres e-mail. Dane te są potrzebne do zalogowania użytkownika, lub jeśli nie posiada on konta na portalu – do założenia konta i zalogowania.

Jest kilka sposobów na sprawdzenie, czy użytkownik jest zalogowany:

  1. Pobieramy sesje z bazy danych pasujące do ip danego użytkownika i jego przeglądarki
  2. Pobieramy ręcznie ciasteczko i na jego podstawie sprawdzamy czy użytkownik jest zalogowany
  3. Tworzymy instancję ipsRegistry i sprawdzamy dane

Pierwsze 2 rozwiązania nie są jakby się zdawało idealne, ponieważ ręczne pobieranie sesji z bazy wymaga przetrzymywania w kolejnym miejscu danych do połączenia z bazą. Drugie rozwiązanie za to wymaga od nas trzymania konfiguracji cookie z IP.Board w dodatkowym pliku.

Biorąc wszystkie za i przeciw postanowiłem wybrać rozwiązanie trzecie i utworzyć instancję klasy ipsRegistry i dzięki temu to ona będzie decydować o zalogowaniu bądź nie użytkownika.

Sam kod tworzenia takiego obiektu nie jest skomplikowany, ponieważ wymaga od nas kilku linijek napisanych w php:

define( 'DOC_FORUM_ROOT_PATH', str_replace( "\\", "/", dirname( __FILE__ ) ) . '/forum' );
define('IPS_ENFORCE_ACCESS', true );
require_once( DOC_FORUM_ROOT_PATH.'initdata.php' );
require_once( IPS_ROOT_PATH . 'sources/base/ipsRegistry.php' );
require_once( IPS_ROOT_PATH . 'sources/base/ipsController.php' );

try
{
	$registry = ipsRegistry::instance();
	$registry->init();
	
	$memberData = $registry->member()->fetchMemberData();
}
catch( Excepton $e) {}

I teraz w zmiennej $memberData mamy wszystkie informacje o użytkowniku, czy jest zalogowany, do jakiej grupy należy, jego avatar i wiele więcej, w związku z czym możemy dowolnie te dane przetwarzać. Ja osobiście jak wspominałem potrzebowałem kilku informacji i z nich korzystam.

W związku z tym, że prace nad integracją zostały ukończone firma SolutionDEVs rozpoczyna sprzedaż integracji joomli z IP.Board zarówno w wersji z autologowaniem jak i w wersji bez autologowania. Wszystkich zainteresowanych zapraszam do kontaktu w celu uzyskania informacji na temat tego połączenia.

Post Joomla! oraz IP.Board – Finalne połączenie pojawił się poraz pierwszy w Dawid Baruch - DEV blog.

]]>
http://baruch.pl/2012/04/joomla-oraz-ip-board-finalne-polaczenie/feed/ 0
Hooki przeładowujące funkcjonalność skinów http://baruch.pl/2012/03/hooki-przeladowujace-funkcjonalnosc-skinow/ http://baruch.pl/2012/03/hooki-przeladowujace-funkcjonalnosc-skinow/#comments Fri, 16 Mar 2012 07:56:01 +0000 Dawid Baruch http://baruch.pl/?p=75 W tym wpisie zajmiemy się hookami do IP.Board, które przeładowują szablony skinów. Brzmi dość skomplikowanie ale jest to bardzo prosta i przyjemna rzecz. Mianowicie wszystko chodzi o to, że jeśli chcemy czasami zrobić jakąś warunkową akcję, np. ukryć treść posta dla gości to mamy 2 możliwości. Edytować każdy skin i dodać magiczny fragment kodu: Możemy [...]

Post Hooki przeładowujące funkcjonalność skinów pojawił się poraz pierwszy w Dawid Baruch - DEV blog.

]]>
W tym wpisie zajmiemy się hookami do IP.Board, które przeładowują szablony skinów. Brzmi dość skomplikowanie ale jest to bardzo prosta i przyjemna rzecz.

Mianowicie wszystko chodzi o to, że jeśli chcemy czasami zrobić jakąś warunkową akcję, np. ukryć treść posta dla gości to mamy 2 możliwości.

  1. Edytować każdy skin i dodać magiczny fragment kodu:
    <if test="$this->memberData[ 'member_id' ]"> 
    dotychczasowy kod
    <else />
    Wiadomość dla gości
    </if>
  2. Możemy także stworzyć prosty hook, który zrobi wszystko za nas i nie będziemy musieli kombinować i pamiętać przy każdej instalacji skinu, że musimy dodać tam jakiś kod, żeby działało tak jak dotychczas.

Ponieważ pierwsze rozwiązanie jest dość toporne i łatwo zapomnieć o wstawieniu jakiegoś kodu po aktualizacji forum lub wgraniu nowego skinu, zajmiemy się rozwiązaniem drugim, czyli prostym hookiem. Sam proces tworzenia hooków został już opisany w artykule Tworzenie własnego hooka, dlatego w tym artykule nie będę opisywać całego procesu, a jedynie rzeczy, które różnią się w procesie tworzenia obu hooków. Zapraszam zatem do zapoznania się z procesem tworzenia hooków przeładowujących funkcjonalność skinów w artykule pod tytułem Tworzenie własnego hooka – Przeciążenie skina

Post Hooki przeładowujące funkcjonalność skinów pojawił się poraz pierwszy w Dawid Baruch - DEV blog.

]]>
http://baruch.pl/2012/03/hooki-przeladowujace-funkcjonalnosc-skinow/feed/ 0
Tworzenie własnego hooka w IP.Board http://baruch.pl/2012/03/tworzenie-wlasnego-hooka-ip-board/ http://baruch.pl/2012/03/tworzenie-wlasnego-hooka-ip-board/#comments Tue, 13 Mar 2012 09:05:57 +0000 Dawid Baruch http://baruch.pl/?p=71 Hooki w IP.Board są jak wtyczki w wordpressie lub innym tego typu systemie. Dzięki hookom, możemy rozszerzyć funkcjonalność naszego forum o dodatkowe funkcjonalności jak np. lista ostatnio dodanych plików na forum, ostatnie tematy i inne tego typ rzeczy. Ponieważ IP.Board zdobywa coraz większe uznanie w Polsce i stoi na nim coraz więcej forów postanowiłem napisać [...]

Post Tworzenie własnego hooka w IP.Board pojawił się poraz pierwszy w Dawid Baruch - DEV blog.

]]>
Hooki w IP.Board są jak wtyczki w wordpressie lub innym tego typu systemie. Dzięki hookom, możemy rozszerzyć funkcjonalność naszego forum o dodatkowe funkcjonalności jak np. lista ostatnio dodanych plików na forum, ostatnie tematy i inne tego typ rzeczy.

Ponieważ IP.Board zdobywa coraz większe uznanie w Polsce i stoi na nim coraz więcej forów postanowiłem napisać artykuł, który przybliży proces tworzenia własnych hooków. Publikacja powinna się spodobać wszystkim, którzy chcą pisać własne rozszerzenia. Aby przeczytać artykuł pod tytułem

Zapisz ustawienia. Teraz zaloguj się do FTP i otwórz plik: /cache/lang_cahe/x/lang_global.php

Znajdź:

?>

Dodaj nad tym:

$lang['confirmAdd'] = "Czy chcesz dodać swoją wypowiedź?";

Zapisz plik i gotowe :)

Od teraz bez kliknięcia OK w okienku wypowiedź nie zostanie dodana

Post Okno potwierdzające założenie tematu / dodanie odpowiedzi pojawił się poraz pierwszy w Dawid Baruch - DEV blog.

]]>
http://baruch.pl/2011/10/okno-potwierdzajace-zalozenie-tematu-dodanie-odpowiedzi/feed/ 0
IP.Board na innym porcie MySQL http://baruch.pl/2011/10/ip-board-na-innym-porcie-mysql/ http://baruch.pl/2011/10/ip-board-na-innym-porcie-mysql/#comments Thu, 27 Oct 2011 09:54:43 +0000 Dawid Baruch http://baruch.pl/?p=24 Patrząc na problemy z jakimi ostatnio borykają się niektórzy użytkownicy IP.Board postanowiłem napisać ten tutorialek Mianowicie chodzi o problem z połączeniem do bazy danych na innym porcie niż standardowy. Problemy takie możemy zaobserwować np. na serwerach nazwa.pl na nowej wersji bazy MySQL 5 dostępnej na porcie 3305. Przejdźmy zatem od razu do czynów: Otwórz plik: [...]

Post IP.Board na innym porcie MySQL pojawił się poraz pierwszy w Dawid Baruch - DEV blog.

]]>
Patrząc na problemy z jakimi ostatnio borykają się niektórzy użytkownicy IP.Board postanowiłem napisać ten tutorialek

Mianowicie chodzi o problem z połączeniem do bazy danych na innym porcie niż standardowy. Problemy takie możemy zaobserwować np. na serwerach nazwa.pl na nowej wersji bazy MySQL 5 dostępnej na porcie 3305. Przejdźmy zatem od razu do czynów:

Otwórz plik: /conf_global.php

Znajdź:

$INFO['sql_host'] = 'serwer_bazy_danych'; 

dodaj poniżej:

$INFO['sql_port'] = 'port_na_jakim_dziala_baza';

Zapisz zmiany i wgraj plik.

Otwórz: /sources/ipsclass.php

Znajdź:

# Debug log - Don't use this on a production board!

 $this->DB->obj['debug_log'] = ROOT_PATH . 'cache/sql_debug_log_'.date('m_d_y').'.cgi';
 $this->DB->obj['use_debug_log'] = 0; 

Dodaj poniżej:

if( !empty( $this->vars['sql_port'] ) )
 {
 if ( extension_loaded('mysqli') AND ! defined( 'FORCE_MYSQL_ONLY' ) )
 {
 $this->DB->obj['sql_port'] = $this->vars['sql_port'];
 }
 else
 {
 $this->DB->obj['sql_host'] = "{$this->DB->obj['sql_host']}:{$this->vars['sql_port']}";
 }
 } 

Zapisz zmiany i wgraj plik.

Otwórz plik: /ips_kernel/class_db_mysql_client.php

Znajdź:

$this->connection_id = @mysql_pconnect( $this->obj['sql_host'] ,
 $this->obj['sql_user'] ,
 $this->obj['sql_pass'] ,
 $this->obj['force_new_connection']
 ); 

Zamień na:

if( !empty($this->obj['sql_port'] ) )
 {
 $this->connection_id = @mysql_pconnect( $this->obj['sql_host'] .':' .$this->obj['sql_port'] ,
 $this->obj['sql_user'] ,
 $this->obj['sql_pass'] ,
 $this->obj['force_new_connection']
 );
 }
 else
 {
 $this->connection_id = @mysql_pconnect( $this->obj['sql_host'] ,
 $this->obj['sql_user'] ,
 $this->obj['sql_pass'] ,
 $this->obj['force_new_connection']
 );
 } 

Zapisz zmiany i wgraj plik.

To już wszystkie zmiany. Od teraz wszystko już będzie działać tak jak należy :-)

Post IP.Board na innym porcie MySQL pojawił się poraz pierwszy w Dawid Baruch - DEV blog.

]]>
http://baruch.pl/2011/10/ip-board-na-innym-porcie-mysql/feed/ 0
Przewijane BBCody http://baruch.pl/2011/10/przewijane-bbcody/ http://baruch.pl/2011/10/przewijane-bbcody/#comments Thu, 27 Oct 2011 06:18:28 +0000 Dawid Baruch http://baruch.pl/?p=8 Jeżeli chcemy mieć przewijane BBCody takie jak CODE, QUOTE, HTML, SQL, PHP czy jakikolwiek inny. Otwórz: ACP -> look & Feel -> {Twój Skin} -> Css Advanced znajdź: przedź do i przed tym znakiem wstaw te same czynności wykonaj także dla: następnie znajdź przedź do i przed tym znakiem wstaw Zapisujemy ustawienia i przechodzimy na [...]

Post Przewijane BBCody pojawił się poraz pierwszy w Dawid Baruch - DEV blog.

]]>
Jeżeli chcemy mieć przewijane BBCody takie jak CODE, QUOTE, HTML, SQL, PHP czy jakikolwiek inny.

Otwórz: ACP -> look & Feel -> {Twój Skin} -> Css Advanced

znajdź:

.quotetop

przedź do

}

i przed tym znakiem wstaw

width: 700px;

te same czynności wykonaj także dla:

.codetop,
 .phptop,
 .sqltop,
 .htmltop

następnie znajdź

.quotemain

przedź do

}

i przed tym znakiem wstaw

width: 500px; overflow:auto;

Zapisujemy ustawienia i przechodzimy na zakładkę Maintenance -> Recount & Rebuild -> i wybieramy opcję Rebauild Post Content.

Post Przewijane BBCody pojawił się poraz pierwszy w Dawid Baruch - DEV blog.

]]>
http://baruch.pl/2011/10/przewijane-bbcody/feed/ 0