/
block.php
362 lines (325 loc) · 9.49 KB
/
block.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
<?php
/**
* @package Habari
*
*/
/**
* Habari Block class
* Block class for theme display of pluggable content
*
* @property string $type The type of block this is
* @property string $title The title of this block
* @property mixed $data The data associated to this block
* @property integer $id The id of this block in the database
*
*/
class Block extends QueryRecord implements IsContent, FormStorage
{
public $_first = false;
public $_last = false;
public $_area_index = 0;
public $_area = '';
private $data_values = array( '_show_title' => true );
/**
* Constructor for the Block class.
* @param array $paramarray an associative array of initial block field values.
*/
public function __construct( $paramarray = array() )
{
// Defaults
$this->fields = array_merge(
self::default_fields(),
$this->fields,
$this->newfields
);
parent::__construct( $paramarray );
$this->exclude_fields( 'id' );
$this->unserialize_data();
}
/**
* Overrides QueryRecord __get to implement custom object properties
*
* @param string $name Name of property to return
* @return mixed The requested field value
*/
public function __get( $name )
{
switch($name) {
case 'css_classes':
$classes = array();
if(array_key_exists( $name, $this->data_values )) {
$classes = $this->data_values[$name];
}
if(is_string($classes)) {
$classes = explode(' ', $classes);
}
if($this->_first) {
$classes[] = 'first';
}
if($this->_last) {
$classes[] = 'last';
}
if($this->_area_index) {
$classes[] = 'index_' . $this->_area_index;
}
$classes[] = 'block-type-' . Utils::slugify($this->type);
$classes[] = 'block';
$classes = Plugins::filter('block_classes', $classes, $this);
return implode(' ', $classes);
break;
default:
if ( array_key_exists( $name, $this->data_values ) ) {
return $this->data_values[$name];
}
else {
return parent::__get( $name );
}
}
}
/**
* Overrides QueryRecord __set to implement custom object properties
*
* @param string $name Name of property to return
* @param mixed $value The value to set the property to
* @return mixed The value of the property
*/
public function __set( $name, $value )
{
switch ( $name ) {
case 'id':
case 'title':
case 'data':
parent::__set( $name, $value );
$this->unserialize_data();
return parent::__get( $name );
break;
case 'type':
return parent::__set( $name, $value );
break;
default:
$this->data_values[ $name ] = $value;
return $this->data_values[ $name ];
break;
}
}
/**
* Overrides QueryRecord __isset, returns whether this Block has the named
* data. Falls back to QueryRecord's __isset.
*
* @param string $name The name of the parameter
* @return boolean True if the value is set, false if not
*/
public function __isset( $name )
{
return ( isset( $this->data_values[$name] ) || parent::__isset( $name ) );
}
/**
* Return the defined database columns for a Block.
* @return array Array of columns in the Block table
*/
public static function default_fields()
{
return array(
'id' => 0,
'title' => '',
'data' => '',
'type' => '',
);
}
/**
* Render and return the block content
*
* @param Theme $theme the theme object with which the block will be rendered
* @return string The rendered block content
*/
public function fetch( $theme )
{
Plugins::act( 'block_content_' . $this->type, $this, $theme );
Plugins::act( 'block_content', $this, $theme );
$output = implode( '', $theme->content_return( $this ) );
return $output;
}
/**
* Return the content types that this object represents
*
* @see IsContent
* @return array An array of strings representing the content type of this object
*/
public function content_type()
{
$types = array(
'block.' . $this->type,
'block',
);
if ( isset( $this->title ) ) {
array_unshift( $types, 'block.' . $this->type . '.' . Utils::slugify( $this->title ) );
}
if ( isset( $this->_area ) ) {
$areas = array();
foreach ( $types as $type ) {
$areas[] = $this->_area . '.' . $type;
}
$types = array_merge( $areas, $types );
}
$types = Plugins::filter( 'block_content_type_' . $this->type, $types, $this );
$types = Plugins::filter( 'block_content_type', $types, $this );
return $types;
}
/**
* Unserialize the stored block data
*/
public function unserialize_data()
{
if ( trim( $this->data ) != '' ) {
$this->data_values = unserialize( $this->data );
}
}
/**
* Saves form fields that are tied to this block. Implements FormStorage.
*
* @param string $key The name of the form field to store.
* @param mixed $value The value of the form field
*/
public function field_save( $key, $value )
{
$this->$key = $value;
$this->update();
}
/**
* Load the form value from the block
*
* @param string $key The name of the form field to load
* @return mixed The value of the block for the form
*/
public function field_load( $key )
{
return $this->$key;
}
/**
* Insert this block into the database
*
* @return boolean|null True on success, null if the action wasn't allowed
*/
public function insert()
{
// Let plugins disallow and act before we write to the database
$allow = true;
$allow = Plugins::filter( 'block_insert_allow', $allow, $this );
if ( ! $allow ) {
return null;
}
Plugins::act( 'block_insert_before', $this );
$this->data = serialize( $this->data_values );
$result = parent::insertRecord( DB::table( 'blocks' ) );
// Make sure the id is set in the block object to match the row id
$this->newfields['id'] = DB::last_insert_id();
// Update the block's fields with anything that changed
$this->fields = array_merge( $this->fields, $this->newfields );
// We've inserted the block, reset newfields
$this->newfields = array();
EventLog::log( _t( 'New block %1$s: %2$s', array( $this->id, $this->title ) ), 'info', 'content', 'habari' );
// Let plugins act after we write to the database
Plugins::act( 'block_insert_after', $this );
return $result;
}
/**
* Update this block in the database
*
* @return boolean|null True on success, null if the update isn't allowed
*/
public function update()
{
$allow = true;
$allow = Plugins::filter( 'block_update_allow', $allow, $this );
if ( ! $allow ) {
return null;
}
Plugins::act( 'block_update_before', $this );
$this->data = serialize( $this->data_values );
$result = parent::updateRecord( DB::table( 'blocks' ), array( 'id' => $this->id ) );
$this->fields = array_merge( $this->fields, $this->newfields );
$this->newfields = array();
Plugins::act( 'block_update_after', $this );
return $result;
}
/**
* Delete this block
*
*/
public function delete()
{
// Let plugins disallow and act before we write to the database
$allow = true;
$allow = Plugins::filter( 'block_delete_allow', $allow, $this );
if ( !$allow ) {
return false;
}
Plugins::act( 'block_delete_before', $this );
$result = parent::deleteRecord( '{blocks_areas}', array( 'block_id'=>$this->id ) );
$result = $result && parent::deleteRecord( '{blocks}', array( 'id'=>$this->id ) );
EventLog::log( _t( 'Block %1$s (%2$s) deleted.', array( $this->id, $this->title ) ), 'info', 'content', 'habari' );
// Let plugins act after we write to the database
Plugins::act( 'block_delete_after', $this );
return $result;
}
/**
* Get the form used to update this block
*
* @return FormUI The altered FormUI element that edits this block
*/
public function get_form()
{
$form = new FormUI( 'block-' . $this->id, 'block' );
$form->on_success( array( $this, 'save_block' ) );
Plugins::act( 'block_form_' . $this->type, $form, $this );
Plugins::act( 'block_form', $form, $this );
return $form;
}
/**
* Display a standard success message upon saving the form
*
* @param FormUI $form The form that will be saved
* @return bool Returning false tells the form that the save was handled
*/
public function save_block( FormUI $form )
{
$form->save();
return false;
}
/**
* Add this block to a particular area in the theme
*
* @param string $area The name of the area to add to
* @param integer $order The position of the block within the area
* @param string $scope The scope id into which to add this block
*/
public function add_to_area( $area, $order = null, $scope = null )
{
if( is_null( $scope ) ) {
$scope = 0;
}
if( is_null( $order ) || ! is_int( $order ) ) {
$order = DB::get_value( 'SELECT max(display_order) + 1 FROM {blocks_areas} WHERE area = :area AND scope_id = :scope', array( 'area' => $area, 'scope' => $scope ) );
if( is_null( $order ) ) {
$order = 1;
}
}
else {
DB::query( 'UPDATE {blocks_areas} SET display_order = display_order + 1 WHERE area = :area AND scope_id = :scope AND display_order >= :order', array( 'area' => $area, 'scope' => $scope, 'order' => $order ) );
}
// If the block isn't saved in the database, insert it.
if( !$this->id ) {
$this->insert();
}
$result = DB::query( 'INSERT INTO {blocks_areas} (block_id, area, scope_id, display_order) VALUES (:block_id, :area, :scope_id, :display_order)', array( 'block_id' => $this->id, 'area' => $area, 'scope_id' => $scope, 'display_order' => $order ) );
}
/**
* Convert this block into a string, just in case there isn't a template associated to this block type
* @return string The string representation of this content, as a bad fallback
*/
public function __toString()
{
return $this->title;
}
}
?>