Oxwall is the most popular SNS framework that using PHP was developed as a project of Skalfa LLC. This is a supplementary explanation of the “Plugin Development Crash Course”. Check it out.
* This tutorial doesn’t include explanation of background and detail of codes. Please refer original tutorials.
1. Setup CentoOS-7 on the VirtualBox see this.
* You should be changed to the name of user account like “oxwall”.
2. Install packages to running the Oxwall
2.1 PHP/HTTP install
[oxwall@localhost ~]$ sudo yum install -y epel-release [oxwall@localhost ~]$ sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm [oxwall@localhost ~]$ sudo yum -y install --enablerepo=remi,remi-php70 php php-devel php-mbstring php-pdo php-gd php-mysql php-xml [oxwall@localhost ~]$ sudo yum -y --enablerepo=remi,remi-php70 install php-pecl-zip [oxwall@localhost ~]$ sudo yum -y --enablerepo=remi,remi-php70 install php-pecl-mysql
2.2 MySQL install
[oxwall@localhost ~]$ sudo yum -y localinstall http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm [oxwall@localhost ~]$ sudo yum -y install mysql mysql-devel mysql-server mysql-utilities [oxwall@localhost ~]$ sudo systemctl start mysqld [oxwall@localhost ~]$ sudo systemctl enable mysqld [oxwall@localhost ~]$ sudo cat /var/log/mysqld.log | grep password 2018-01-29T02:35:32.202031Z 1 [Note] A temporary password is generated for root@localhost: o6K;lud#>kGa [oxwall@localhost ~]$ sudo mysql_secure_installation
* Please Note: Password “o6K;lud#>kGa” is needed to setup MySQL. Then New password setup, Remove Anonymous users, Disallow root login remotely, Remove test database and access to it, Reload privilege tables now.
2.3 HTTP setup
[oxwall@localhost ~]$ sudo vi /etc/httpd/conf/httpd.conf
151 AllowOverride All
[oxwall@localhost ~]$ sudo vi /etc/sysconfig/selinux
7 SELINUX=disabled
[oxwall@localhost ~]$ sudo systemctl start httpd [oxwall@localhost ~]$ sudo systemctl enable httpd [oxwall@localhost ~]$ sudo firewall-cmd --permanent --zone=public --add-service=http [oxwall@localhost ~]$ sudo firewall-cmd --reload
2.4 Reboot
[oxwall@localhost ~]$ sudo reboot
2.5 Now, You can access to the http server from Safari.
3. Oxwall install/setup
3.1 Download and unzip
[root@localhost ~]$ cd /var/www/html [root@localhost ~]$ sudo su [root@localhost html]# wget https://developers.oxwall.com/dl/oxwall-1.8.4.1.zip [root@localhost html]# unzip oxwall-1.8.4.1.zip [root@localhost html]# wget https://www.phpmyadmin.net/downloads/phpMyAdmin-latest-all-languages.tar.gz [root@localhost html]# tar -xvzf phpMyAdmin-latest-all-languages.tar.gz [root@localhost html]# mv phpMyAdmin-4.7.7-all-languages phpMyAdmin [root@localhost html]# sudo groupadd www [root@localhost html]# sudo usermod -a -G www oxwall [root@localhost html]# sudo chown -R root:www /var/www [root@localhost html]# sudo chmod 2775 /var/www
[root@localhost html]# vi .htaccess
14 RewriteCond %{REQUEST_URI} !(^/phpMyAdmin/)
3.1 MySQL database setup, access to http://192.168.56.101/phpMyAdmin, login as root
3.2 Create MySQL DB, [New ] -> Name:”oxwall_db” Collation: utf8_general_ci -> [Create]
3.3 Restart HTTP
[root@localhost html]# systemctl restart httpd
3.4 Access to the 192.168.56.101
3.5 Fill out Site info appropriately
3.6 Fill out database info
3.6 Copy and paste code replacing the existing one into ow_includes/config.php file.
3.7 Cron settings, then [CONTINUE]
[root@localhost html]# crontab -e
*/1 * * * * /bin/php /var/www/html/ow_cron/run.php
3.7 Remove install folder, then page refresh.
[root@localhost html]# rm -rf ow_install
4. Next step is the Oxwall tutorial’s tutorial
4.1 Get Developer key, Go to Oxwall Store
– Sign up *Free
– Get Developer Key, [STORE] -> [DEVELOPER TOOL], Copy “Your Developer Key”.
4.3 Create Plugin files , and files initialize.
[root@localhost html]# cd /var/www/html/ow_plugins [root@localhost ow_plugins]# mkdir crashcourse [root@localhost ow_plugins]# cd crashcourse [root@localhost crashcourse]# touch init.php
[root@localhost crashcourse]# vi plugin.xml
<?xml version="1.0" encoding="UTF-8"?> <plugin> <name>Crash Course</name> <key>crashcourse</key> <description>"Tutorial" page with the ability to choose departments (email addresses).</description> <author>UBUNIFU INC.</author> <authorEmail>xxx@ubunifu.co</authorEmail> <authorUrl>https://ubunifu.co</authorUrl> <developerKey>your_developer_key_here</developerKey> <build>1</build> <copyright>(C) 2018 UBUNIFU INC. All rights reserved.</copyright> <license>The BSD License</license> <licenseUrl>http://www.opensource.org/licenses/bsd-license.php</licenseUrl> </plugin>
[root@localhost crashcourse]# touch install.php [root@localhost crashcourse]# touch uninstall.php [root@localhost crashcourse]# touch activate.php [root@localhost crashcourse]# touch deactivate.php
[root@localhost crashcourse]# echo "<?php" >> install.php [root@localhost crashcourse]# echo "BOL_LanguageService::getInstance()->addPrefix('crashcourse', 'Crash Course');" >> install.php
– Go to Admin area → Plugins → Available Plugins. Click Install on your new plugin.
4.5 Creating a page
[root@localhost crashcourse]# mkdir controllers [root@localhost crashcourse]# mkdir views [root@localhost crashcourse]# mkdir views/controllers [root@localhost crashcourse]# touch controllers/crash.php [root@localhost crashcourse]# touch views/controllers/crash_index.html
[root@localhost crashcourse]# vi controllers/crash.php
<?php class CRASHCOURSE_CTRL_Crash extends OW_ActionController { public function index() { $this->setPageTitle(OW::getLanguage()->text('crashcourse', 'index_page_title')); $this->setPageHeading(OW::getLanguage()->text('crashcourse', 'index_page_heading')); } }
– Access to http://192.168.56.101/crashcourse/crash/index
– Input appropriate. -> [CONTINUE]
– Access to http://192.168.56.101/crashcourse/crash/index
* If you wish to make localization, go to http://192.168.56.101/admin/settings/dev-tools/languages
4.6 Page routing
– Set the routing
[root@localhost crashcourse]# vi init.php
<?php OW::getRouter()->addRoute(new OW_Route('crashcourse.index', 'crash', "CRASHCOURSE_CTRL_Crash", 'index'));
– Access to http://192.168.56.101/crash
– Adds a link into the bottom menu.
[root@localhost crashcourse]# vi activate.php
<?php OW::getNavigation()->addMenuItem(OW_Navigation::BOTTOM, 'crashcourse.index', 'crashcourse', 'bottom_menu_item', OW_Navigation::VISIBLE_FOR_ALL);
[root@localhost crashcourse]# vi deactivate.php
<?php OW::getNavigation()->deleteMenuItem('crashcourse', 'bottom_menu_item');
– Go to [Installed plugins] page, then deactivate Crash Course and Re-activate Crash Course. Now, you can see a link in bottom menu.
4.7 Using forms
– Adds code into the crash.php
[root@localhost crashcourse]# vi controllers/crash.php
<?php class CRASHCOURSE_CTRL_Crash extends OW_ActionController { public function index() { $this->setPageTitle(OW::getLanguage()->text('crashcourse', 'index_page_title')); $this->setPageHeading(OW::getLanguage()->text('crashcourse', 'index_page_heading')); $contactEmails = array( 'admin@site.com' => 'Site administration', 'support@site.com' => 'Technical support', 'billing@site.com' => 'Billing department' ); $form = new Form('contact_form'); $fieldTo = new Selectbox('to'); foreach ( $contactEmails as $email => $label ) { $fieldTo->addOption($email, $label); } $fieldTo->setRequired(); $fieldTo->setHasInvitation(false); $fieldTo->setLabel($this->text('crashcourse', 'form_label_to')); $form->addElement($fieldTo); $fieldFrom = new TextField('from'); $fieldFrom->setLabel($this->text('crashcourse', 'form_label_from')); $fieldFrom->setRequired(); $fieldFrom->addValidator(new EmailValidator()); $form->addElement($fieldFrom); $fieldSubject = new TextField('subject'); $fieldSubject->setLabel($this->text('crashcourse', 'form_label_subject')); $fieldSubject->setRequired(); $form->addElement($fieldSubject); $fieldMessage = new Textarea('message'); $fieldMessage->setLabel($this->text('crashcourse', 'form_label_message')); $fieldMessage->setRequired(); $form->addElement($fieldMessage); // Using captcha here to prevent bot spam $fieldCaptcha = new CaptchaField('captcha'); $fieldCaptcha->setLabel($this->text('crashcourse', 'form_label_captcha')); $form->addElement($fieldCaptcha); $submit = new Submit('send'); $submit->setValue($this->text('crashcourse', 'form_label_submit')); $form->addElement($submit); $this->addForm($form); if ( OW::getRequest()->isPost() ) { if ( $form->isValid($_POST) ) { $data = $form->getValues(); $mail = OW::getMailer()->createMail(); $mail->addRecipientEmail($data['to']); $mail->setSender($data['from']); $mail->setSubject($data['subject']); $mail->setTextContent($data['message']); OW::getMailer()->addToQueue($mail); OW::getSession()->set('crashcourse.dept', $contactEmails[$data['to']]); $this->redirectToAction('sent'); } } } public function sent() { $dept = null; if ( OW::getSession()->isKeySet('crashcourse.dept') ) { $dept = OW::getSession()->get('crashcourse.dept'); OW::getSession()->delete('crashcourse.dept'); } else { $this->redirectToAction('index'); } $feedback = $this->text('crashcourse', 'message_sent', ( $dept === null ) ? null : array('dept' => $dept)); $this->assign('feedback', $feedback); } private function text( $prefix, $key, array $vars = null ) { return OW::getLanguage()->text($prefix, $key, $vars); } }
– Create a view
[root@localhost crashcourse]# vi views/controllers/crash_index.html
{form name='contact_form'} <table class="ow_table_1 ow_form ow_automargin ow_superwide"> <tr class="ow_alt1"> <td class="ow_label">{label name='to'}</td> <td class="ow_value">{input name='to'}{error name='to'}</td> </tr> <tr class="ow_alt2"> <td class="ow_label">{label name='from'}</td> <td class="ow_value">{input name='from'}{error name='from'}</td> </tr> <tr class="ow_alt1"> <td class="ow_label">{label name='subject'}</td> <td class="ow_value">{input name='subject'}{error name='subject'}</td> </tr> <tr class="ow_alt2"> <td class="ow_label">{label name='message'}</td> <td class="ow_value">{input name='message'}{error name='message'}</td> </tr> <tr class="ow_alt1"> <td class="ow_label">{label name='captcha'}</td> <td class="ow_value ow_center">{input name='captcha'}{error name='captcha'}</td> </tr> <tr> <td class="ow_center" colspan="2">{submit name='send' class='ow_button ow_ic_mail'}</td> </tr> </table> {/form}
– Create view for the sent
[root@localhost crashcourse]# vi views/controllers/crash_sent.html
<div class="ow_center">{$feedback}</div>
4.8 Cache clear * If you don’t clear the cache, modified pages are not reflected.
– Go to https://developers.oxwall.com/store/item/579
– Download plugin
– FTP enable/setup for to upload plugin.
[root@localhost html]# yum install -y vsftpd ftp
[root@localhost html]# vi /etc/vsftpd/user_list
#root
[root@localhost html]# vi /etc/vsftpd/ftpusers
#root
[root@localhost html]# echo "setsebool -P ftp_home_dir on" >> /etc/sysconfig/selinux [root@localhost html]# firewall-cmd --permanent --add-port=21/tcp [root@localhost html]# firewall-cmd --reload [root@localhost html]# systemctl enable vsftpd [root@localhost html]# systemctl start vsftpd
– Plugin upload, [Add new] -> [Choose file] -> “Casheextreme.zip” -> [UPLOAD]
– FTP info input, host: 192.168.56.101, Login: root, Password: ****, -> [ENTER]
– Install plugin
– Cache clear, [Installed Plugin] -> Cache Extreme -> [SETTINGS] -> [CLEAN IT UP]
– Access to http://192.168.56.101/crash
4.9 Using database
– Adds files for database
[root@localhost crashcourse]# mkdir bol [root@localhost crashcourse]# touch bol/department.php [root@localhost crashcourse]# touch bol/department_dao.php [root@localhost crashcourse]# touch bol/service.php
[root@localhost crashcourse]# vi bol/department.php
<?php class CRASHCOURSE_BOL_Department extends OW_Entity { /** * @var string */ public $email; }
[root@localhost crashcourse]# vi bol/department_dao.php
<?php class CRASHCOURSE_BOL_DepartmentDao extends OW_BaseDao { /** * Constructor. * */ protected function __construct() { parent::__construct(); } /** * Singleton instance. * * @var CRASHCOURSE_BOL_DepartmentDao */ private static $classInstance; /** * Returns an instance of class (singleton pattern implementation). * * @return CRASHCOURSE_BOL_DepartmentDao */ public static function getInstance() { if ( self::$classInstance === null ) { self::$classInstance = new self(); } return self::$classInstance; } /** * @see OW_BaseDao::getDtoClassName() * */ public function getDtoClassName() { return 'CRASHCOURSE_BOL_Department'; } /** * @see OW_BaseDao::getTableName() * */ public function getTableName() { return OW_DB_PREFIX . 'crashcourse_department'; } }
[root@localhost crashcourse]# vi bol/service.php
<?php class CRASHCOURSE_BOL_Service { /** * Singleton instance. * * @var CRASHCOURSE_BOL_Service */ private static $classInstance; /** * Returns an instance of class (singleton pattern implementation). * * @return CRASHCOURSE_BOL_Service */ public static function getInstance() { if ( self::$classInstance === null ) { self::$classInstance = new self(); } return self::$classInstance; } private function __construct() { } public function getDepartmentLabel( $id ) { return OW::getLanguage()->text('crashcourse', $this->getDepartmentKey($id)); } public function addDepartment( $email, $label ) { $contact = new CRASHCOURSE_BOL_Department(); $contact->email = $email; CRASHCOURSE_BOL_DepartmentDao::getInstance()->save($contact); BOL_LanguageService::getInstance()->addValue( OW::getLanguage()->getCurrentId(), 'crashcourse', $this->getDepartmentKey($contact->id), trim($label)); } public function deleteDepartment( $id ) { $id = (int) $id; if ( $id > 0 ) { $key = BOL_LanguageService::getInstance()->findKey('crashcourse', $this->getDepartmentKey($id)); BOL_LanguageService::getInstance()->deleteKey($key->id, true); CRASHCOURSE_BOL_DepartmentDao::getInstance()->deleteById($id); } } private function getDepartmentKey( $name ) { return 'dept_' . trim($name); } public function getDepartmentList() { return CRASHCOURSE_BOL_DepartmentDao::getInstance()->findAll(); } }
[root@localhost crashcourse]# vi install.php
<?php BOL_LanguageService::getInstance()->addPrefix('crashcourse', 'Crash Course'); $sql = "CREATE TABLE `" . OW_DB_PREFIX . "crashcourse_department` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `email` VARCHAR(200) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM ROW_FORMAT=DEFAULT"; OW::getDbo()->query($sql);
4.10 Creating Settings page in Admin area
– Create the admin.php
[root@localhost crashcourse]# vi controllers/admin.php
<?php class CRASHCOURSE_CTRL_Admin extends ADMIN_CTRL_Abstract { public function dept() { $this->setPageTitle(OW::getLanguage()->text('crashcourse', 'admin_dept_title')); $this->setPageHeading(OW::getLanguage()->text('crashcourse', 'admin_dept_heading')); $contactEmails = array(); $deleteUrls = array(); $contacts = CRASHCOURSE_BOL_Service::getInstance()->getDepartmentList(); foreach ( $contacts as $contact ) { /* @var $contact CRASHCOURSE_BOL_Department */ $contactEmails[$contact->id]['name'] = $contact->id; $contactEmails[$contact->id]['email'] = $contact->email; $contactEmails[$contact->id]['label'] = CRASHCOURSE_BOL_Service::getInstance()->getDepartmentLabel($contact->id); $deleteUrls[$contact->id] = OW::getRouter()->urlFor(__CLASS__, 'delete', array('id' => $contact->id)); } $this->assign('contacts', $contactEmails); $this->assign('deleteUrls', $deleteUrls); $form = new Form('add_dept'); $this->addForm($form); $fieldEmail = new TextField('email'); $fieldEmail->setRequired(); $fieldEmail->addValidator(new EmailValidator()); $fieldEmail->setInvitation(OW::getLanguage()->text('crashcourse', 'label_invitation_email')); $fieldEmail->setHasInvitation(true); $form->addElement($fieldEmail); $fieldLabel = new TextField('label'); $fieldLabel->setRequired(); $fieldLabel->setInvitation(OW::getLanguage()->text('crashcourse', 'label_invitation_label')); $fieldLabel->setHasInvitation(true); $form->addElement($fieldLabel); $submit = new Submit('add'); $submit->setValue(OW::getLanguage()->text('crashcourse', 'form_add_dept_submit')); $form->addElement($submit); if ( OW::getRequest()->isPost() ) { if ( $form->isValid($_POST) ) { $data = $form->getValues(); CRASHCOURSE_BOL_Service::getInstance()->addDepartment($data['email'], $data['label']); $this->redirect(); } } } public function delete( $params ) { if ( isset($params['id']) ) { CRASHCOURSE_BOL_Service::getInstance()->deleteDepartment((int) $params['id']); } $this->redirect(OW::getRouter()->urlForRoute('crashcourse.admin')); } }
– Create the admin_dept.html
[root@localhost crashcourse]# vi views/controllers/admin_dept.html
<table class="ow_table_1 ow_automargin" style="width: 400px;"> {foreach from=$contacts item=contact} <tr class="{cycle values='ow_alt1,ow_alt2'}"> <td width="1"><a href="{$deleteUrls[$contact.name]}" onclick="return confirm('{text key="base+are_you_sure"}');" style="width:16px; height:16px; display:block; margin:0 auto;background-repeat:no-repeat;background-position: 50% 50%;" class="ow_ic_delete"></a></td> <td>{$contact.email}</td> <td>{$contact.label}</td> </tr> {/foreach} </table> {form name='add_dept'} <table class="ow_table_1 ow_form ow_automargin" style="width: 400px;"> <tr class="ow_alt1"> <td class="ow_value">{input name='email'}</td> <td class="ow_value">{input name='label'}</td> </tr> <tr> <td class="ow_center" colspan="2">{submit name='add' class='ow_button ow_ic_save'}</td> </tr> </table> {/form}
– Cache clear
– [Installed plugin] -> Crash Course -> [UNINSTALL]
– [Available plugin] -> Crash Course -> [INSTALL]
– Access to http://192.168.56.101/crashcourse/admin/dept
– Modify controllers/crash.php
[root@localhost crashcourse]# vi controllers/crash.php
<?php class CRASHCOURSE_CTRL_Crash extends OW_ActionController { public function index() { $this->setPageTitle(OW::getLanguage()->text('crashcourse', 'index_page_title')); $this->setPageHeading(OW::getLanguage()->text('crashcourse', 'index_page_heading')); $contactEmails = array(); $contacts = CRASHCOURSE_BOL_Service::getInstance()->getDepartmentList(); foreach ( $contacts as $contact ) { /* @var $contact CRASHCOURSE_BOL_Department */ $contactEmails[$contact->email] = CRASHCOURSE_BOL_Service::getInstance()->getDepartmentLabel($contact->id); } $form = new Form('contact_form'); $fieldTo = new Selectbox('to'); foreach ( $contactEmails as $email => $label ) { $fieldTo->addOption($email, $label); } $fieldTo->setRequired(); $fieldTo->setHasInvitation(false); $fieldTo->setLabel($this->text('crashcourse', 'form_label_to')); $form->addElement($fieldTo); $fieldFrom = new TextField('from'); $fieldFrom->setLabel($this->text('crashcourse', 'form_label_from')); $fieldFrom->setRequired(); $fieldFrom->addValidator(new EmailValidator()); $form->addElement($fieldFrom); $fieldSubject = new TextField('subject'); $fieldSubject->setLabel($this->text('crashcourse', 'form_label_subject')); $fieldSubject->setRequired(); $form->addElement($fieldSubject); $fieldMessage = new Textarea('message'); $fieldMessage->setLabel($this->text('crashcourse', 'form_label_message')); $fieldMessage->setRequired(); $form->addElement($fieldMessage); // Using captcha here to prevent bot spam $fieldCaptcha = new CaptchaField('captcha'); $fieldCaptcha->setLabel($this->text('crashcourse', 'form_label_captcha')); $form->addElement($fieldCaptcha); $submit = new Submit('send'); $submit->setValue($this->text('crashcourse', 'form_label_submit')); $form->addElement($submit); $this->addForm($form); if ( OW::getRequest()->isPost() ) { if ( $form->isValid($_POST) ) { $data = $form->getValues(); $mail = OW::getMailer()->createMail(); $mail->addRecipientEmail($data['to']); $mail->setSender($data['from']); $mail->setSubject($data['subject']); $mail->setTextContent($data['message']); OW::getMailer()->addToQueue($mail); OW::getSession()->set('crashcourse.dept', $contactEmails[$data['to']]); $this->redirectToAction('sent'); } } } public function sent() { $dept = null; if ( OW::getSession()->isKeySet('crashcourse.dept') ) { $dept = OW::getSession()->get('crashcourse.dept'); OW::getSession()->delete('crashcourse.dept'); } else { $this->redirectToAction('index'); } $feedback = $this->text('crashcourse', 'message_sent', ( $dept === null ) ? null : array('dept' => $dept)); $this->assign('feedback', $feedback); } private function text( $prefix, $key, array $vars = null ) { return OW::getLanguage()->text($prefix, $key, $vars); } }
– Access to http://192.168.56.101/crash
– Adds SETTING button
[root@localhost crashcourse]# vi init.php
<?php OW::getRouter()->addRoute(new OW_Route('crashcourse.index', 'crash', "CRASHCOURSE_CTRL_Crash", 'index')); OW::getRouter()->addRoute(new OW_Route('crashcourse.admin', 'admin/plugins/crashcourse', "CRASHCOURSE_CTRL_Admin", 'dept'));
[root@localhost crashcourse]# vi install.php
<?php BOL_LanguageService::getInstance()->addPrefix('crashcourse', 'Crash Course'); $sql = "CREATE TABLE `" . OW_DB_PREFIX . "crashcourse_department` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `email` VARCHAR(200) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM ROW_FORMAT=DEFAULT"; OW::getDbo()->query($sql); OW::getPluginManager()->addPluginSettingsRouteName('crashcourse', 'crashcourse.admin');
– Cache clear
– [Installed plugin] -> Crash Course -> [UNINSTALL]
– [Available plugin] -> Crash Course -> [INSTALL]
– [Installed plugin] -> Crash Course -> [SETTINGS]
Done 😃
- Tags
- CentOS, Oxwall, VirtualBox