Windwalker
$ php bin/windwalker generator init com_flower sakura.sakuras [--client] [--tmpl]
Joomla
# None...
Windwalker has a powerful extension generator, you can generate components, modules and plugins by default template or customize your templates.
$ php bin/windwalker generator init com_flower sakura.sakuras [--client] [--tmpl]
# None...
Simpler component entry than Joomla native. You can override component initialise process in your Component object.
// No direct access
defined('_JEXEC') or die;
include_once JPATH_COMPONENT_ADMINISTRATOR . '/src/init.php';
echo with(new FlowerComponent)->execute();
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// require helper files
JLoader::register('FlowerHelper', dirname(__FILE__) . '/helpers/flower.php');
$controller = JControllerLegacy::getInstance('Flower');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
Tasks like: display, save, update, reorder and delete etc. They are all has default controllers in Windwalker. You don't need to write them out, just override it if you require a new process.
// Use default controller
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
class FlowerControllerflower extends JControllerAdmin
{
public function getModel($name = 'flowers', $prefix = 'FlowerModel')
{
$model = parent::getModel($name, $prefix, array('ignore_request' => true));
return $model;
}
}
Tired to write getItem(), getPagination() and other methods again and again? Windwalker auto loaded them in View object. You can also override default behavior.
protected function prepareData()
{
// Use default
}
public function display($tpl = null)
{
$this->state = $this->get('State');
$this->items = $this->get('Items');
$this->pagination = $this->get('Pagination');
WeblinksHelper::addSubmenu('flowers');
// Check for errors.
if (count($errors = $this->get('Errors')))
{
JError::raiseError(500, implode("\n", $errors));
return false;
}
$this->addToolbar();
$this->sidebar = JHtmlSidebar::render();
parent::display($tpl);
}
Setting toolbar in Joomla is very bother, Windwalker prepared a set of default buttons. You can just configure them to decide which should show on page. Also, the ACL has auto handled.
protected function configureToolbar($buttonSet = array(), $canDo = null)
{
// Get default button set.
$buttonSet = parent::configureToolbar($buttonSet, $canDo);
// In debug mode, we remove trash button but use delete button instead.
if (JDEBUG)
{
$buttonSet['trash']['access'] = false;
$buttonSet['delete']['access'] = true;
}
return $buttonSet;
}
protected function addToolbar()
{
require_once JPATH_COMPONENT . '/helpers/flower.php';
$state = $this->get('State');
$canDo = JHelperContent::getActions('com_weblinks', 'category', $state->get('filter.category_id'));
$user = JFactory::getUser();
$bar = JToolBar::getInstance('toolbar');
JToolbarHelper::title(JText::_('COM_WEBLINKS_MANAGER_WEBLINKS'), 'link weblinks');
if (count($user->getAuthorisedCategories('com_weblinks', 'core.create')) > 0)
{
JToolbarHelper::addNew('weblink.add');
}
if ($canDo->get('core.edit'))
{
JToolbarHelper::editList('weblink.edit');
}
if ($canDo->get('core.edit.state')) {
JToolbarHelper::publish('weblinks.publish', 'JTOOLBAR_PUBLISH', true);
JToolbarHelper::unpublish('weblinks.unpublish', 'JTOOLBAR_UNPUBLISH', true);
JToolbarHelper::archiveList('weblinks.archive');
JToolbarHelper::checkin('weblinks.checkin');
}
if ($state->get('filter.state') == -2 && $canDo->get('core.delete'))
{
JToolbarHelper::deleteList('', 'weblinks.delete', 'JTOOLBAR_EMPTY_TRASH');
} elseif ($canDo->get('core.edit.state'))
{
JToolbarHelper::trash('weblinks.trash');
}
// Add a batch button
if ($user->authorise('core.create', 'com_weblinks') && $user->authorise('core.edit', 'com_weblinks') && $user->authorise('core.edit.state', 'com_weblinks'))
{
JHtml::_('bootstrap.modal', 'collapseModal');
$title = JText::_('JTOOLBAR_BATCH');
// Instantiate a new JLayoutFile instance and render the batch button
$layout = new JLayoutFile('joomla.toolbar.batch');
$dhtml = $layout->render(array('title' => $title));
$bar->appendButton('Custom', $dhtml, 'batch');
}
if ($user->authorise('core.admin', 'com_weblinks'))
{
JToolbarHelper::preferences('com_weblinks');
}
JToolbarHelper::help('JHELP_COMPONENTS_WEBLINKS_LINKS');
}
Windwalekr Grid system is very smart, you can configure search, filter and batch in XML files. Save you from the query building hell.
<form>
<!-- Batch -->
<fields name="batch">
<field name="access"
type="accesslevel"
label="JLIB_HTML_BATCH_ACCESS_LABEL"
description="JLIB_HTML_BATCH_ACCESS_LABEL_DESC"
labelclass="control-label"
class="input-xlarge inputbox"
>
<option>JLIB_HTML_BATCH_NOCHANGE</option>
</field>
<field name="language"
type="contentlanguage"
label="JLIB_HTML_BATCH_LANGUAGE_LABEL"
description="JLIB_HTML_BATCH_LANGUAGE_LABEL_DESC"
labelclass="control-label"
class="input-xlarge inputbox"
>
<option>JLIB_HTML_BATCH_LANGUAGE_NOCHANGE</option>
</field>
<field name="created_by"
type="winduser"
label="JAUTHOR"
description="JLIB_HTML_BATCH_USER_LABEL_DESC"
labelclass="control-label"
class="input-xlarge inputbox"
>
<option>JSELECT</option>
</field>
<field name="catid"
type="category"
label="JLIB_HTML_BATCH_MENU_LABEL"
description=""
extension="com_flower"
labelclass="control-label"
class="input-xlarge inputbox"
action="true"
>
<option>JOPTION_SELECT_CATEGORY</option>
</field>
<field name="task"
type="radio"
label="JLIB_RULES_ACTION"
description=""
labelclass="control-label"
class="combo btn-group"
default="sakuras.batch.move"
>
<option value="sakuras.batch.move">JLIB_HTML_BATCH_MOVE</option>
<option value="sakuras.batch.copy">JLIB_HTML_BATCH_COPY</option>
</field>
</fields>
</form>
// No, you have to use php to write Batch in controller yourself
Windwalekr provides a powerful QueryHelper and FilterHelper, you don't need to configure so much terrible things in ModelList.
class FlowerModelSakuras extends ListModel
{
/**
* Some default filter fields will be merged to
* the auto-generated fields
*/
protected $filterFields = array('sakura.start_date');
protected function configureTables()
{
$queryHelper = $this->getContainer()->get('model.sakuras.helper.query', Container::FORCE_NEW);
$queryHelper->addTable('sakura', '#__flower_sakuras')
->addTable('category', '#__categories', 'sakura.catid = category.id')
->addTable('user', '#__users', 'sakura.created_by = user.id')
->addTable('viewlevel', '#__viewlevels', 'sakura.access = viewlevel.id')
->addTable('lang', '#__languages', 'sakura.language = lang.lang_code');
// Auto generate filter fields, you can also write it manually
$this->filterFields = array_merge(
$this->filterFields,
$queryHelper->getFilterFields()
);
}
protected function populateState($ordering = 'id', $direction = 'ASC')
{
// All filter and search will be handled by parent.
parent::populateState($ordering, $direction);
}
protected function processFilters(\JDatabaseQuery $query, $filters = array())
{
if (!isset($filters['sakura.state']) && property_exists($this->getTable(), 'state'))
{
$query->where($query->quoteName('sakura.state') . ' >= 0');
}
return parent::processFilters($query, $filters);
}
protected function configureFilters($filterHelper)
{
// Override filter behavior here
}
protected function configureSearches($searchHelper)
{
// Override search behavior here
}
}
class FlowerModelSakuras extends JModelList
{
public function __construct($config = array())
{
if (empty($config['filter_fields']))
{
$config['filter_fields'] = array(
'id', 'a.id',
'title', 'a.title',
'alias', 'a.alias',
'checked_out', 'a.checked_out',
'checked_out_time', 'a.checked_out_time',
'catid', 'a.catid', 'category_title',
'state', 'a.state',
'access', 'a.access', 'access_level',
'created', 'a.created',
'created_by', 'a.created_by',
'ordering', 'a.ordering',
'featured', 'a.featured',
'language', 'a.language',
'hits', 'a.hits',
'publish_up', 'a.publish_up',
'publish_down', 'a.publish_down',
'url', 'a.url',
);
}
parent::__construct($config);
}
protected function populateState($ordering = null, $direction = null)
{
$search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search');
$this->setState('filter.search', $search);
$accessId = $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access', null, 'int');
$this->setState('filter.access', $accessId);
$published = $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'string');
$this->setState('filter.state', $published);
$categoryId = $this->getUserStateFromRequest($this->context . '.filter.category_id', 'filter_category_id', '');
$this->setState('filter.category_id', $categoryId);
$language = $this->getUserStateFromRequest($this->context . '.filter.language', 'filter_language', '');
$this->setState('filter.language', $language);
$tag = $this->getUserStateFromRequest($this->context . '.filter.tag', 'filter_tag', '');
$this->setState('filter.tag', $tag);
$params = JComponentHelper::getParams('com_Sakuras');
$this->setState('params', $params);
parent::populateState('a.title', 'asc');
}
protected function getListQuery()
{
// Create a new query object.
$db = $this->getDbo();
$query = $db->getQuery(true);
$user = JFactory::getUser();
$query->select(
'a.id, a.title, a.alias, a.checked_out, a.checked_out_time, a.catid,' .
'a.hits,' .
'a.state, a.access, a.ordering,' .
'a.language, a.publish_up, a.publish_down'
);
$query->from($db->quoteName('#__flower_sakuras') . ' AS a');
$query->select('l.title AS language_title')
->join('LEFT', $db->quoteName('#__languages') . ' AS l ON l.lang_code = a.language')
->select('uc.name AS editor')
->join('LEFT', '#__users AS uc ON uc.id=a.checked_out')
->select('ag.title AS access_level')
->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access')
->select('c.title AS category_title')
->join('LEFT', '#__categories AS c ON c.id = a.catid');
if ($access = $this->getState('filter.access'))
{
$query->where('a.access = ' . (int) $access);
}
if (!$user->authorise('core.admin'))
{
$groups = implode(',', $user->getAuthorisedViewLevels());
$query->where('a.access IN (' . $groups . ')');
}
$published = $this->getState('filter.state');
if (is_numeric($published))
{
$query->where('a.state = ' . (int) $published);
}
elseif ($published === '')
{
$query->where('(a.state IN (0, 1))');
}
$categoryId = $this->getState('filter.category_id');
if (is_numeric($categoryId))
{
$query->where('a.catid = ' . (int) $categoryId);
}
$search = $this->getState('filter.search');
if (!empty($search))
{
if (stripos($search, 'id:') === 0)
{
$query->where('a.id = ' . (int) substr($search, 3));
}
else
{
$search = $db->quote('%' . $db->escape($search, true) . '%');
$query->where('(a.title LIKE ' . $search . ' OR a.alias LIKE ' . $search . ')');
}
}
if ($language = $this->getState('filter.language'))
{
$query->where('a.language = ' . $db->quote($language));
}
$orderCol = $this->state->get('list.ordering');
$orderDirn = $this->state->get('list.direction');
if ($orderCol == 'a.ordering' || $orderCol == 'category_title')
{
$orderCol = 'c.title ' . $orderDirn . ', a.ordering';
}
$query->order($db->escape($orderCol . ' ' . $orderDirn));
return $query;
}
}
$ php composer.phar create-project windwalker/phoenix libraries/windwalker 2.*
This document is for Windwalker Joomla RAD, if you are finding Windwalker PHP framework, please see: Windwalker Framework