Skip to content

Commit d5fd24a

Browse files
committed
Upgrade plugin for compatibility with CakePHP 3.x
1 parent 5ea3be1 commit d5fd24a

File tree

17 files changed

+608
-580
lines changed

17 files changed

+608
-580
lines changed

README.md

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
#Meta Plugin for CakePHP 2.x
1+
#Meta Plugin for CakePHP 3.x
22

3-
Meta is an SEO Plugin for CakePHP 2.x which manages title, meta description, and meta keywords for each page in your application.
3+
Meta is an SEO Plugin for CakePHP 3.x which manages title, meta description, and meta keywords for each page in your application.
4+
5+
For 2.x compatible version, see the 2.x branch.
46
- - -
57

68
##Installation
79

8-
1. Install manually by putting the contents of this repository in a folder named Meta in your App's Plugin folder. Install with composer by adding the following to your composer.json:
10+
1. Install manually by putting the contents of this repository in a folder named Meta in your App's plugins folder. Install with composer by adding the following to your composer.json:
911

1012
````
1113
"require": {
12-
"houseoftech/cakephp-meta": "*"
14+
"houseoftech/cakephp-meta": "3.*"
1315
}
1416
````
1517

@@ -18,37 +20,69 @@ Meta is an SEO Plugin for CakePHP 2.x which manages title, meta description, and
1820
````
1921
CREATE TABLE `meta` (
2022
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
23+
`path` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
24+
`controller` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
25+
`action` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
26+
`pass` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
27+
`title` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
28+
`description` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
29+
`keywords` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
2130
`template` tinyint(1) NOT NULL DEFAULT '0',
22-
`path` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
23-
`controller` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
24-
`action` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
25-
`pass` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
26-
`title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
27-
`description` text COLLATE utf8_unicode_ci,
28-
`keywords` text COLLATE utf8_unicode_ci,
2931
`created` datetime DEFAULT NULL,
3032
`modified` datetime DEFAULT NULL,
31-
PRIMARY KEY (`id`)
32-
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci PACK_KEYS=0 ;
33+
PRIMARY KEY (`id`),
34+
KEY `path` (`path`),
35+
KEY `controller` (`controller`),
36+
KEY `action` (`action`),
37+
KEY `pass` (`pass`),
38+
KEY `template` (`template`),
39+
KEY `created` (`created`),
40+
KEY `modified` (`modified`)
41+
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 PACK_KEYS=0;
42+
````
43+
44+
3. Load the plugin in your bootstrap file.
45+
46+
````
47+
Plugin::load('Meta', ['bootstrap' => true]);
3348
````
3449

35-
3. Add the component to your AppController.
50+
4. Add the component to your AppController.
3651

3752
````
38-
public $components = array('Meta.Meta');
53+
public function initialize()
54+
{
55+
parent::initialize();
56+
57+
$this->loadComponent('Meta.Meta');
58+
}
3959
````
4060

41-
4. Call the Meta element in your layout's head.
61+
5. Add the helper to your AppView.
4262

4363
````
44-
<?php echo $this->element('Meta.meta');?>
64+
public function initialize()
65+
{
66+
$this->loadHelper('Meta.Meta');
67+
}
4568
````
4669

70+
6. Copy Meta/config/meta_plugin.php file to your app config/ folder if you want to specify database tables to search.
71+
4772
##How to Use
4873

49-
Navigate to the Meta admin page: *http://your_domain/admin/meta/meta*
74+
The MetaHelper, if loaded in your AppView, will automatically add tags during the `afterRender()` callback. All you need to do is make sure the following is in your layout or view file:
5075

51-
You can add records manually via the form or you can use the link called 'Find New Paths'. This is an initializer which searches your existing pages located under Views/Pages/ and the pages table in your database. The initializer will attempt to extract descriptions as well.
76+
````
77+
<title><?= $this->fetch('title') ?></title>
78+
<?= $this->fetch('meta') ?>
79+
````
80+
81+
##How to Manage Meta Records
82+
83+
Navigate to the Meta admin page: *http://your_domain/admin/meta*
84+
85+
You can add records manually via the form or you can use the link called 'Find New Paths'. This is an initializer which searches your existing pages located under src/Template/ and the specified tables in your database. The initializer will attempt to extract descriptions as well.
5286

5387
##Meta Record Fields
5488

@@ -80,15 +114,5 @@ When creating a template, leave this field blank.
80114
###Keywords
81115
*all things, explanation, explaining, all things explained, explanation of all things*
82116

83-
###Templates
84-
When creating a template, you can use variables in the Title, Description, and Keywords fields. Simply use the variable name inside brackets {}.
85-
86-
The available variables depend on the Controller, but most Pages will have available the following list.
87-
88-
- {id} - Automatically assigned integer representing a record in a database.
89-
- {name} - The human readable title of a Page or Post.
90-
- {created} - The date and time the record was first created in format yyyy-mm-dd hh:mm:ss.
91-
- {modified} - The date and time the record was last updated in format yyyy-mm-dd hh:mm:ss.
92-
93117
##License
94118
This project is licensed under the terms of the MIT license.

config/bootstrap.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
use Cake\Core\Configure;
3+
4+
// Optionally load additional config defaults from app
5+
if (file_exists(ROOT . DS . 'config' . DS . 'meta_plugin.php')) {
6+
Configure::load('meta_plugin');
7+
}

config/meta_plugin.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
/**
3+
* Default config values for the Meta plugin
4+
*
5+
* To modify the config, copy to your app's config folder
6+
*/
7+
8+
return [
9+
'Meta' => [
10+
// Default meta content for any page which no record is found for
11+
'defaultTitle' => '',
12+
'defaultDescription' => '',
13+
'defaultKeywords' => '',
14+
15+
// Tables to auto_load meta records for (e.g. Pages)
16+
/**
17+
* Format for searchTables
18+
*
19+
* Provide associated array where key is table name
20+
* and value is array mapping meta fields to table fields
21+
*
22+
* [
23+
* 'Pages' => [
24+
* 'path' => '/pages/{path}',
25+
* 'controller' => 'Pages',
26+
* 'action' => 'display',
27+
* 'pass' => '{path}',
28+
* 'title' => '{name}',
29+
* 'description' => '{content}',
30+
* ]
31+
* ]
32+
*
33+
*/
34+
'searchTables' => [],
35+
]
36+
];

config/routes.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
namespace Meta\Config;
3+
4+
use Cake\Routing\Router;
5+
6+
Router::prefix('admin', function (RouteBuilder $routes) {
7+
$routes->plugin('Meta', function (RouteBuilder $routes) {
8+
$routes->connect('/:controller', ['action' => 'index'], ['routeClass' => DashedRoute::class]);
9+
$routes->connect('/:controller/:action/*', [], ['routeClass' => 'DashedRoute']);
10+
});
11+
});
12+
13+
Router::plugin('Meta', function ($routes) {
14+
$routes->connect('/', ['controller' => 'Meta', 'action' => 'index'], ['routeClass' => 'DashedRoute']);
15+
$routes->connect('/:controller', ['action' => 'index'], ['routeClass' => 'DashedRoute']);
16+
$routes->connect('/:controller/:action/*', [], ['routeClass' => 'DashedRoute']);
17+
});
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
<?php
2+
namespace Meta\Controller\Admin;
3+
4+
use App\Controller\AppController;
5+
use Cake\Event\Event;
6+
use Cake\ORM\TableRegistry;
7+
use Cake\Core\Configure;
8+
9+
class MetaController extends AppController
10+
{
11+
public function index()
12+
{
13+
$meta = TableRegistry::get('Meta.Meta');
14+
$this->set('data', $this->paginate($meta));
15+
}
16+
17+
public function add()
18+
{
19+
$metaTable = TableRegistry::get('Meta.Meta');
20+
if (!empty($this->request->data)) {
21+
$data = $metaTable->newEntity($this->request->data());
22+
if ($metaTable->save($data)) {
23+
$this->Flash->success('Meta record added.');
24+
$this->redirect(['action' => 'index'], null, true);
25+
} else {
26+
$this->Flash->error('Error encountered while saving.');
27+
}
28+
}
29+
$this->set('data', $metaTable->newEntity());
30+
$this->render('edit');
31+
}
32+
33+
public function delete($id = null)
34+
{
35+
$metaTable = TableRegistry::get('Meta.Meta');
36+
$data = $metaTable->get($id);
37+
if ($metaTable->delete($data)) {
38+
$this->Flash->success('Meta record deleted.');
39+
} else {
40+
$this->Flash->error('Error encourntered while deleting.');
41+
}
42+
$this->redirect(['action' => 'index'], null, true);
43+
}
44+
45+
public function edit($id = null)
46+
{
47+
$metaTable = TableRegistry::get('Meta.Meta');
48+
$data = $metaTable->get($id);
49+
50+
if (!empty($this->request->data)) {
51+
$metaTable->patchEntity($data, $this->request->data());
52+
if ($metaTable->save($data)) {
53+
$this->Flash->success('Meta record updated.');
54+
$this->redirect(['action' => 'index'], null, true);
55+
} else {
56+
$this->Flash->error('Error encountered while saving.');
57+
}
58+
}
59+
$this->set('data', $data);
60+
}
61+
62+
public function autoAdd()
63+
{
64+
$count = 0;
65+
$searchTables = Configure::read('Meta.searchTables');
66+
67+
$metaTable = TableRegistry::get('Meta.Meta');
68+
$meta = $metaTable->find('list', [
69+
'valueField' => 'path'
70+
]);
71+
$meta = $meta->toArray();
72+
73+
// add meta data for database records
74+
if (is_array($searchTables) && count($searchTables)) {
75+
foreach($searchTables as $searchTable => $tableMap) {
76+
if ($table = TableRegistry::get($searchTable)) {
77+
$data = $table->find('all');
78+
79+
foreach($data as $row) {
80+
$row = $row->toArray();
81+
foreach($tableMap as $metaField => &$tableField) {
82+
if (strstr($tableField, '{')) {
83+
foreach($row as $field => $value) {
84+
$tableField = str_replace('{'.$field.'}', $value, $tableField);
85+
86+
if ($metaField == 'description' && (strlen($tableField) > 160 || strstr($tableField, '<'))) {
87+
$tableField = $this->_extractDescription($tableField);
88+
}
89+
}
90+
}
91+
}
92+
93+
$tableMap['controller'] = ucfirst($tableMap['controller']);
94+
95+
if (empty($meta) || in_array($tableMap['path'], $meta) == false) {
96+
$newMeta = $metaTable->newEntity($tableMap);
97+
$metaTable->save($newMeta);
98+
$count++;
99+
}
100+
}
101+
}
102+
}
103+
}
104+
105+
// add meta data for view files
106+
$newPaths = [];
107+
$newPaths = $this->_findPaths(APP . 'Template');
108+
if (count($newPaths)) {
109+
foreach ($newPaths as $path => $info) {
110+
if (in_array($path, $meta) == false) {
111+
$newData['Meta']['path'] = $path;
112+
113+
$pathArray = explode('/', substr($path, 1), 3);
114+
$newData['Meta']['controller'] = ucfirst($pathArray[0]);
115+
if (stristr($pathArray[0], 'pages')) {
116+
$newData['Meta']['action'] = 'display';
117+
$newData['Meta']['pass'] = $pathArray[1];
118+
if (isset($pathArray[2])) {
119+
$newData['Meta']['pass'] .= '/'.$pathArray[2];
120+
}
121+
} else {
122+
$newData['Meta']['action'] = $pathArray[1];
123+
if (isset($pathArray[2])) {
124+
$newData['Meta']['pass'] = $pathArray[2];
125+
}
126+
}
127+
128+
$newData['Meta']['title'] = $info['title'];
129+
$newData['Meta']['description'] = $info['description'];
130+
$newMeta = $metaTable->newEntity($newData);
131+
$metaTable->save($newMeta);
132+
$count++;
133+
unset($newData);
134+
}
135+
}
136+
}
137+
138+
if ($count) {
139+
$this->Flash->success("$count new paths found and saved.");
140+
} else {
141+
$this->Flash->error("No new paths found.");
142+
}
143+
144+
$this->redirect(['action' => 'index']);
145+
}
146+
147+
private function _findPaths($dir)
148+
{
149+
if (!is_dir($dir)) {
150+
return [];
151+
}
152+
153+
$exclusions = [
154+
'.',
155+
'..',
156+
'.DS_Store',
157+
'.svn',
158+
'empty',
159+
'ajax.ctp',
160+
'Admin',
161+
'Element',
162+
'Email',
163+
'Error',
164+
'Layout',
165+
'display.ctp'
166+
];
167+
$paths = [];
168+
$dir = dir($dir);
169+
170+
while (($file = $dir->read()) !== false) {
171+
if (array_search($file, $exclusions) === false) {
172+
$filePath = $dir->path . DS . $file;
173+
if (is_dir($filePath)) {
174+
$paths = array_merge($paths, $this->_findPaths($filePath));
175+
} elseif (stristr($file, '.ctp')) {
176+
$fileExt = strchr($file, '.');
177+
$fileName = basename($file, $fileExt);
178+
$path = str_replace('\\', '/', str_replace(APP . 'Template', '', $dir->path . DS . $fileName));
179+
$path = strtolower($path);
180+
181+
$pathParts = array_values(array_filter(explode('/', $path)));
182+
if ($pathParts[0] == 'Pages') {
183+
unset($pathParts[0]);
184+
}
185+
$title = \Cake\Utility\Inflector::humanize(implode(' - ', $pathParts));
186+
187+
if (($fileHandle = fopen($filePath, 'r')) !== false) {
188+
$description = $this->_extractDescription(fread($fileHandle, 3072));
189+
}
190+
$paths = array_merge($paths, [$path => ['title' => $title, 'description' => $description]]);
191+
}
192+
}
193+
}
194+
$dir->close();
195+
196+
ksort($paths);
197+
return $paths;
198+
}
199+
200+
private function _extractDescription($content)
201+
{
202+
$description = strip_tags($content);
203+
$description = preg_replace('/\s\s+/', ' ', $description); // strip whitespace
204+
$description = preg_replace('/\[\{\[.*\]\}\]/', '', $description); // strip element plugins
205+
$description = substr($description, 0, 150);
206+
return $description;
207+
}
208+
}

0 commit comments

Comments
 (0)