Skip to content

Commit 6d5e06e

Browse files
committed
Ajaxified administration of simple pages.
1 parent 076c17d commit 6d5e06e

9 files changed

Lines changed: 480 additions & 47 deletions

File tree

controllers/AjaxController.php

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
<?php
2+
/**
3+
* The Simple Pages Ajax controller class.
4+
*
5+
* @package SimplePages
6+
*/
7+
class SimplePages_AjaxController extends Omeka_Controller_AbstractActionController
8+
{
9+
/**
10+
* Controller-wide initialization. Sets the underlying model to use.
11+
*/
12+
public function init()
13+
{
14+
// Don't render the view script.
15+
$this->_helper->viewRenderer->setNoRender(true);
16+
17+
$this->_helper->db->setDefaultModelName('SimplePagesPage');
18+
}
19+
20+
/**
21+
* Handle AJAX requests to update a simple page.
22+
*/
23+
public function updateAction()
24+
{
25+
if (!$this->_checkAjax('update')) {
26+
return;
27+
}
28+
29+
// Handle action.
30+
try {
31+
$status = $this->_getParam('status');
32+
if (!in_array($status, array('public', 'private'))) {
33+
$this->getResponse()->setHttpResponseCode(400);
34+
return;
35+
}
36+
37+
$id = (integer) $this->_getParam('id');
38+
$simplePage = $this->_helper->db->find($id);
39+
if (!$simplePage) {
40+
$this->getResponse()->setHttpResponseCode(400);
41+
return;
42+
}
43+
$simplePage->is_published = ($status == 'public');
44+
$simplePage->save();
45+
} catch (Exception $e) {
46+
$this->getResponse()->setHttpResponseCode(500);
47+
}
48+
}
49+
50+
/**
51+
* Handle AJAX requests to delete a simple page.
52+
*/
53+
public function deleteAction()
54+
{
55+
if (!$this->_checkAjax('delete')) {
56+
return;
57+
}
58+
59+
// Handle action.
60+
try {
61+
$id = (integer) $this->_getParam('id');
62+
$simplePage = $this->_helper->db->find($id);
63+
if (!$simplePage) {
64+
$this->getResponse()->setHttpResponseCode(400);
65+
return;
66+
}
67+
$simplePage->delete();
68+
} catch (Exception $e) {
69+
$this->getResponse()->setHttpResponseCode(500);
70+
}
71+
}
72+
73+
/**
74+
* Handle AJAX requests to change a list of simple pages.
75+
*/
76+
public function changeAction()
77+
{
78+
if (!$this->_checkAjax('change')) {
79+
return;
80+
}
81+
82+
// Handle action.
83+
try {
84+
$remove = $this->_getParam('remove');
85+
$remove = $remove ?: array();
86+
if (!is_array($remove)) {
87+
$this->getResponse()->setHttpResponseCode(400);
88+
return;
89+
}
90+
91+
$order = $this->_getParam('order');
92+
if (!is_array($order) || empty($order)) {
93+
$this->getResponse()->setHttpResponseCode(400);
94+
return;
95+
}
96+
97+
// Secure and normalize order.
98+
$newOrder = array();
99+
// Remove root.
100+
unset($order[0]);
101+
foreach ($order as $input) {
102+
$newOrder[(integer) $input['id']] = (integer) $input['parent_id'];
103+
}
104+
105+
// Delete pages to remove and update order array.
106+
foreach ($remove as $id) {
107+
$id = (integer) $id;
108+
$simplePage = $this->_helper->db->find($id);
109+
if (!$simplePage) {
110+
$this->getResponse()->setHttpResponseCode(400);
111+
return;
112+
}
113+
// Remove deleted pages from new order and attach children to
114+
// new parent.
115+
$newParentId = $newOrder[$id];
116+
unset($newOrder[$id]);
117+
foreach ($newOrder as &$parentId) {
118+
if ($parentId == $id) {
119+
$parentId = $newParentId;
120+
}
121+
}
122+
$simplePage->delete();
123+
}
124+
125+
// Reorder pages if needed.
126+
simple_pages_update_order($newOrder);
127+
} catch (Exception $e) {
128+
$this->getResponse()->setHttpResponseCode(500);
129+
}
130+
}
131+
132+
/**
133+
* Check AJAX requests.
134+
*
135+
* 400 Bad Request
136+
* 403 Forbidden
137+
* 500 Internal Server Error
138+
*
139+
* @param string $action
140+
*/
141+
protected function _checkAjax($action)
142+
{
143+
// Only allow AJAX requests.
144+
$request = $this->getRequest();
145+
if (!$request->isXmlHttpRequest()) {
146+
$this->getResponse()->setHttpResponseCode(403);
147+
return false;
148+
}
149+
150+
// Allow only valid calls.
151+
if ($request->getControllerName() != 'ajax'
152+
|| $request->getActionName() != $action
153+
) {
154+
$this->getResponse()->setHttpResponseCode(400);
155+
return false;
156+
}
157+
158+
// Allow only allowed users.
159+
if (!is_allowed('SimplePages_Page', $action)) {
160+
$this->getResponse()->setHttpResponseCode(403);
161+
return false;
162+
}
163+
164+
return true;
165+
}
166+
}

helpers/SimplePageFunctions.php

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,20 +126,42 @@ function simple_pages_display_breadcrumbs($pageId = null, $seperator=' > ', $inc
126126
return $html;
127127
}
128128

129-
function simple_pages_display_hierarchy($parentPageId = 0, $partialFilePath = 'index/browse-hierarchy-page.php')
129+
/**
130+
* Recursively list the pages under a page for editing.
131+
*
132+
* @param SimplePage $page A page to list.
133+
* @return string
134+
*/
135+
function simple_pages_edit_page_list($page)
130136
{
131-
$html = '';
132-
$childrenPages = get_db()->getTable('SimplePagesPage')->findChildrenPages($parentPageId);
133-
if (count($childrenPages)) {
137+
$html = '<li class="page" id="page_' . $page->id . '">';
138+
$html .= '<div class="sortable-item">';
139+
$html .= sprintf('<a href="%s">%s</a>', html_escape(record_url($page)), html_escape($page->title));
140+
$html .= ' (' . html_escape($page->slug) . ')';
141+
$html .= '<ul class="action-links group">';
142+
$html .= '<li>' . sprintf('<a href="%s" id="simplepage-%s" class="simplepage toggle-status status %s">%s</a>',
143+
ADMIN_BASE_URL,
144+
$page->id,
145+
($page->is_published ? 'public' : 'private'),
146+
($page->is_published ? __('Published') : __('Private'))) . '</li>';
147+
$html .= '<li>' . link_to($page, 'edit', __('Edit'), array('class' => 'edit')) . '</li>';
148+
$html .= '</ul>';
149+
$html .= '<br />';
150+
$html .= __('<strong>%1$s</strong> on %2$s',
151+
html_escape(metadata($page, 'modified_username')),
152+
html_escape(format_date(metadata($page, 'updated'), Zend_Date::DATETIME_SHORT)));
153+
$html .= '<a class="delete-toggle delete-element" href="#">' . __('Delete') . '</a>';
154+
$html .= '</div>';
155+
156+
$childrenPages = $page->getChildren();
157+
if (count($childrenPages)) {
134158
$html .= '<ul>';
135-
foreach($childrenPages as $childPage) {
136-
$html .= '<li>';
137-
$html .= get_view()->partial($partialFilePath, array('simple_pages_page' => $childPage));
138-
$html .= simple_pages_display_hierarchy($childPage->id, $partialFilePath);
139-
$html .= '</li>';
159+
foreach ($childrenPages as $childPage) {
160+
$html .= simple_pages_edit_page_list($childPage);
140161
}
141162
$html .= '</ul>';
142163
}
164+
$html .= '</li>';
143165
return $html;
144166
}
145167

@@ -171,4 +193,56 @@ function simple_pages_get_parent_options($page)
171193
}
172194
}
173195
return $valuePairs;
174-
}
196+
}
197+
198+
/**
199+
* Update orders of all simple pages that have been modified.
200+
*/
201+
function simple_pages_update_order($newOrder)
202+
{
203+
$db = get_db();
204+
$table = $db->SimplePagesPage;
205+
206+
// Pages are ordered by order, then by title, so two passes are needed.
207+
208+
// First step: update parent if needed.
209+
$sql = "SELECT `id`, `parent_id` FROM `$table` ORDER BY `order` ASC, `title` ASC";
210+
$currentOrder = $db->fetchPairs($sql);
211+
212+
foreach ($newOrder as $id => $parentId) {
213+
if ($currentOrder[$id] != $parentId) {
214+
$db->update($table,
215+
array('parent_id' => $parentId),
216+
'id = ' . $id);
217+
// Update old hierarchy for next step.
218+
$currentOrder[$id] = $parentId;
219+
}
220+
}
221+
222+
// Second step: update order if needed for each sibling.
223+
// For each parent, check if current children are ordered as new ones.
224+
while (!empty($newOrder)) {
225+
$parentId = reset($newOrder);
226+
227+
// Get all current and new pages with this parent.
228+
$currentChildren = array_intersect($currentOrder, array($parentId));
229+
$newChildren = array_intersect($newOrder, array($parentId));
230+
231+
// Compare them and update all values if they are different.
232+
// Orders are compared as csv because no function allows to check order.
233+
if (implode(',', array_keys($currentChildren)) != implode(',', array_keys($newChildren))) {
234+
// Order by 10 for easier insert and update of edited pages.
235+
$order = 10;
236+
foreach ($newChildren as $id => $parentId) {
237+
$db->update($table,
238+
array('order' => $order),
239+
'id = ' . $id);
240+
$order += 10;
241+
}
242+
}
243+
244+
// Remove filtered keys before loop.
245+
$currentOrder = array_diff_key($currentOrder, $currentChildren);
246+
$newOrder = array_diff_key($newOrder, $newChildren);
247+
}
248+
}

views/admin/css/simple-pages.css

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
.simplepages-list {
2+
padding: 0;
3+
margin: 0;
4+
}
5+
.simplepages-list li {
6+
list-style: none outside none;
7+
padding-left: 10px;
8+
display: inline-block;
9+
font-family: "Arvo",serif;
10+
margin: 0;
11+
padding: 4px 4px 4px 4px;
12+
}
13+
a.simplepage.status {
14+
position:relative;
15+
padding-left: 20px;
16+
cursor: pointer;
17+
}
18+
a.simplepage.toggle-status.public {
19+
background: url('../../../../../application/views/scripts/images/silk-icons/tick.png') no-repeat scroll 0 0 transparent;
20+
}
21+
a.simplepage.toggle-status.private {
22+
background: url('../../../../../application/views/scripts/images/silk-icons/error.png') no-repeat scroll 0 0 transparent;
23+
}
24+
a.simplepage.transmit {
25+
background: url('../../shared/images/waiting-mini.gif') no-repeat scroll 0 0 transparent !important;
26+
}
27+
.action {
28+
color: #338899;
29+
cursor: pointer;
30+
}
31+
.instructions {
32+
font-size:11px;
33+
color: #888;
34+
clear: both;
35+
}
36+
/* override for core's .undo-delete hiding */
37+
#page-list .undo-delete {
38+
display: inline;
39+
}
40+
#page-list .page ul {
41+
margin-top: 15px;
42+
}
43+
#page-list ul.action-links {
44+
margin-top: 0;
45+
}
46+
#page-list ul.action-links li {
47+
margin-bottom: 0;
48+
}
49+
#page-list ul.action-links li a.edit {
50+
padding-left: 3px;
51+
}

views/admin/index/browse-hierarchy-page.php

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
<?php
2+
$topPages = get_db()->getTable('SimplePagesPage')->findChildrenPages(0, false);
3+
?>
4+
<p class="instructions"><?php
5+
echo ' ' . __('To delete, reorder or nest pages, click and drag a page to the preferred location, then click the update button.');
6+
echo ' ' . __('To publish or unpublish a page, click on the icon (change is immediate).');
7+
?></p>
18
<div id="page-hierarchy">
2-
<?php echo simple_pages_display_hierarchy(0); ?>
3-
</div>
9+
<div id="pages-list-container">
10+
<ul id="page-list" class="sortable" href="<?php echo ADMIN_BASE_URL; ?>">
11+
<?php
12+
foreach($topPages as $page):
13+
echo simple_pages_edit_page_list($page);
14+
endforeach;
15+
?>
16+
</ul>
17+
</div>
18+
</div>

0 commit comments

Comments
 (0)