SEO SQUIRRLY™ - Version 3.1.1

Version Description

  • Added rel="prev" and rel="next" in head
  • Added SEO META Duplicates notification
  • Fixed the snippet for home page when the home is a specific page
  • Added more details in SEO Analytics *
Download this release

Release Info

Developer cifi
Plugin Icon 128x128 SEO SQUIRRLY™
Version 3.1.1
Comparing to
See all releases

Version 3.1.1

Files changed (115) hide show
  1. classes/SQ_Action.php +182 -0
  2. classes/SQ_BlockController.php +83 -0
  3. classes/SQ_DisplayController.php +108 -0
  4. classes/SQ_Error.php +88 -0
  5. classes/SQ_FrontController.php +129 -0
  6. classes/SQ_HookController.php +82 -0
  7. classes/SQ_ObjController.php +160 -0
  8. classes/SQ_Ranking.php +209 -0
  9. classes/SQ_Sitemap.php +381 -0
  10. classes/SQ_Tools.php +774 -0
  11. classes/SQ_Traffic.php +28 -0
  12. config/config.php +31 -0
  13. config/paths.php +35 -0
  14. controllers/SQ_Frontend.php +110 -0
  15. controllers/SQ_Menu.php +304 -0
  16. controllers/SQ_Post.php +262 -0
  17. controllers/SQ_PostsList.php +351 -0
  18. core/SQ_BlockAccount/SQ_BlockAccount.php +18 -0
  19. core/SQ_BlockAffiliate/SQ_BlockAffiliate.php +47 -0
  20. core/SQ_BlockAnalytics/SQ_BlockAnalytics.php +9 -0
  21. core/SQ_BlockAudit/SQ_BlockAudit.php +9 -0
  22. core/SQ_BlockDashboard/SQ_BlockDashboard.php +8 -0
  23. core/SQ_BlockHelp/SQ_BlockHelp.php +8 -0
  24. core/SQ_BlockPostsAnalytics/SQ_BlockPostsAnalytics.php +40 -0
  25. core/SQ_BlockStatus/SQ_BlockStatus.php +11 -0
  26. core/SQ_BlockSupport/SQ_BlockSupport.php +114 -0
  27. core/SQ_Blocklogin/SQ_Blocklogin.php +148 -0
  28. core/SQ_Blockresearch/SQ_Blockresearch.php +17 -0
  29. core/SQ_Blocksearch/SQ_Blocksearch.php +54 -0
  30. core/SQ_Blockseo/SQ_Blockseo.php +39 -0
  31. core/SQ_Loading/SQ_Loading.php +45 -0
  32. core/config.xml +133 -0
  33. languages/squirrly-seo-de_DE.mo +0 -0
  34. languages/squirrly-seo-de_DE.po +856 -0
  35. languages/squirrly-seo-ro_RO.mo +0 -0
  36. languages/squirrly-seo-ro_RO.po +1277 -0
  37. languages/squirrly-seo-ru_RU.mo +0 -0
  38. languages/squirrly-seo-ru_RU.po +1193 -0
  39. models/SQ_BlockPostsAnalytics.php +466 -0
  40. models/SQ_BlockStatus.php +158 -0
  41. models/SQ_Blocksearch.php +72 -0
  42. models/SQ_Blockseo.php +40 -0
  43. models/SQ_Frontend.php +1492 -0
  44. models/SQ_Ico.php +229 -0
  45. models/SQ_Menu.php +346 -0
  46. models/SQ_Post.php +226 -0
  47. models/SQ_PostsList.php +117 -0
  48. readme.txt +384 -0
  49. screenshot-1.png +0 -0
  50. screenshot-2.png +0 -0
  51. screenshot-3.png +0 -0
  52. screenshot-4.png +0 -0
  53. screenshot-5.png +0 -0
  54. screenshot-6.png +0 -0
  55. screenshot-7.png +0 -0
  56. squirrly.php +62 -0
  57. themes/default/SQ_BlocStatus.php +1 -0
  58. themes/default/SQ_BlockAccount.php +41 -0
  59. themes/default/SQ_BlockAffiliate.php +105 -0
  60. themes/default/SQ_BlockAnalytics.php +281 -0
  61. themes/default/SQ_BlockAudit.php +9 -0
  62. themes/default/SQ_BlockDashboard.php +50 -0
  63. themes/default/SQ_BlockHelp.php +15 -0
  64. themes/default/SQ_BlockPostsAnalytics.php +27 -0
  65. themes/default/SQ_BlockSupport.php +79 -0
  66. themes/default/SQ_Blocklogin.php +49 -0
  67. themes/default/SQ_Blockresearch.php +33 -0
  68. themes/default/SQ_Blocksearch.php +50 -0
  69. themes/default/SQ_Blockseo.php +6 -0
  70. themes/default/SQ_Menu.php +496 -0
  71. themes/default/SQ_notices.php +16 -0
  72. themes/default/css/sq_blockaudit.css +1 -0
  73. themes/default/css/sq_blockresearch.css +1 -0
  74. themes/default/css/sq_blocksearch.css +1 -0
  75. themes/default/css/sq_blockseo.css +1 -0
  76. themes/default/css/sq_frontend.css +1 -0
  77. themes/default/css/sq_global.css +1 -0
  78. themes/default/css/sq_menu.css +1 -0
  79. themes/default/css/sq_post.css +1 -0
  80. themes/default/css/sq_postslist.css +1 -0
  81. themes/default/img/avatar-margin.png +0 -0
  82. themes/default/img/banners/banner1.jpg +0 -0
  83. themes/default/img/banners/banner1.png +0 -0
  84. themes/default/img/banners/banner2.jpg +0 -0
  85. themes/default/img/banners/banner2.png +0 -0
  86. themes/default/img/banners/banner3.png +0 -0
  87. themes/default/img/complete.png +0 -0
  88. themes/default/img/dashboard_analytics.png +0 -0
  89. themes/default/img/dashboard_assistant.png +0 -0
  90. themes/default/img/dashboard_audit.png +0 -0
  91. themes/default/img/dashboard_research.png +0 -0
  92. themes/default/img/header_back.png +0 -0
  93. themes/default/img/header_stars.png +0 -0
  94. themes/default/img/heading.png +0 -0
  95. themes/default/img/loading.gif +0 -0
  96. themes/default/img/menu_icon_16.png +0 -0
  97. themes/default/img/minloading.gif +0 -0
  98. themes/default/img/settings_edit.png +0 -0
  99. themes/default/img/settings_howto.jpg +0 -0
  100. themes/default/img/settings_login.jpg +0 -0
  101. themes/default/img/settings_login_done.jpg +0 -0
  102. themes/default/img/sprite.png +0 -0
  103. themes/default/img/sq_searching.gif +0 -0
  104. themes/default/img/status/backgroundv2.jpg +0 -0
  105. themes/default/img/status/squirrly_cheers.png +0 -0
  106. themes/default/js/jcache.js +21 -0
  107. themes/default/js/jquery.progressbar.js +20 -0
  108. themes/default/js/sq_blockaudit.js +3 -0
  109. themes/default/js/sq_blocklogin.js +22 -0
  110. themes/default/js/sq_blocksupport.js +18 -0
  111. themes/default/js/sq_menu.js +36 -0
  112. themes/default/js/sq_rank.js +33 -0
  113. themes/default/js/tinymce.js +2 -0
  114. themes/default/js/xregexp.js +4 -0
  115. uninstall.php +15 -0
classes/SQ_Action.php ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Set the ajax action and call for wordpress
5
+ */
6
+ class SQ_Action extends SQ_FrontController {
7
+
8
+ /** @var array with all form and ajax actions */
9
+ var $actions = array();
10
+
11
+ /** @var array from core config */
12
+ private static $config;
13
+
14
+ /**
15
+ * The hookAjax is loaded as custom hook in hookController class
16
+ *
17
+ * @return void
18
+ */
19
+ public function hookInit() {
20
+
21
+ /* Only if ajax */
22
+ if ((isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') || strpos($_SERVER['PHP_SELF'], '/admin-ajax.php') !== false) {
23
+ $this->actions = array();
24
+ $this->getActions(((isset($_GET['action']) ? $_GET['action'] : (isset($_POST['action']) ? $_POST['action'] : ''))));
25
+ }
26
+ }
27
+
28
+ /**
29
+ * The hookSubmit is loaded when action si posted
30
+ *
31
+ * @return void
32
+ */
33
+ public function hookMenu() {
34
+ /* Only if post */
35
+ if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
36
+ return;
37
+ }
38
+ if (strpos($_SERVER['PHP_SELF'], '/admin-ajax.php') !== false) {
39
+ return;
40
+ }
41
+
42
+ $this->actions = array();
43
+ $this->getActions(((isset($_GET['action']) ? $_GET['action'] : (isset($_POST['action']) ? $_POST['action'] : ''))));
44
+ }
45
+
46
+ /**
47
+ * The hookHead is loaded as admin hook in hookController class for script load
48
+ * Is needed for security check as nonce
49
+ *
50
+ * @return void
51
+ */
52
+ public function hookHead() {
53
+
54
+ echo '<script type="text/javascript" src="https://www.google.com/jsapi"></script>
55
+ <script type="text/javascript">
56
+ var sqQuery = {
57
+ "ajaxurl": "' . admin_url('admin-ajax.php') . '",
58
+ "adminposturl": "' . admin_url('post.php') . '",
59
+ "adminlisturl": "' . admin_url('edit.php') . '",
60
+ "nonce": "' . wp_create_nonce(_SQ_NONCE_ID_) . '"
61
+ }
62
+
63
+ if(parseInt(jQuery.fn.jquery.replace(/\./g,"")) < 162)
64
+ google.load("jquery", "1.6.2");
65
+ </script>';
66
+ }
67
+
68
+ /**
69
+ * Get all actions from config.xml in core directory and add them in the WP
70
+ *
71
+ * @return void
72
+ */
73
+ public function getActions($cur_action) {
74
+
75
+ /* if config allready in cache */
76
+ if (!isset(self::$config)) {
77
+ $config_file = _SQ_CORE_DIR_ . 'config.xml';
78
+ if (!file_exists($config_file)) {
79
+ return;
80
+ }
81
+
82
+ /* load configuration blocks data from core config files */
83
+ $data = file_get_contents($config_file);
84
+ self::$config = json_decode(json_encode((array) simplexml_load_string($data)), 1);
85
+ }
86
+
87
+ if (is_array(self::$config)) {
88
+ foreach (self::$config['block'] as $block) {
89
+ if ($block['active'] == 1) {
90
+ /* if there is a single action */
91
+ if (isset($block['actions']['action']))
92
+
93
+ /* if there are more actions for the current block */ {
94
+ if (!is_array($block['actions']['action'])) {
95
+ /* add the action in the actions array */
96
+ if ($block['actions']['action'] == $cur_action) {
97
+ $this->actions[] = array('class' => $block['name'], 'path' => $block['path']);
98
+ }
99
+ } else {
100
+ /* if there are more actions for the current block */
101
+ foreach ($block['actions']['action'] as $action) {
102
+ /* add the actions in the actions array */
103
+ if ($action == $cur_action) {
104
+ $this->actions[] = array('class' => $block['name'], 'path' => $block['path']);
105
+ }
106
+ }
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
112
+
113
+ /* add the actions in WP */
114
+ foreach ($this->actions as $actions) {
115
+ if ($actions['path'] == 'core') {
116
+ SQ_ObjController::getBlock($actions['class'])->action();
117
+ } elseif ($actions['path'] == 'controllers') {
118
+ SQ_ObjController::getController($actions['class'])->action();
119
+ }
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Call the Squirrly Api Server
125
+ * @param string $module
126
+ * @param array $args
127
+ * @return json | string
128
+ */
129
+ public static function apiCall($module, $args = array(), $timeout = 90) {
130
+ $parameters = "";
131
+
132
+ if (SQ_Tools::$options['sq_api'] == '' && $module <> 'sq/login' && $module <> 'sq/register') {
133
+ return false;
134
+ }
135
+
136
+ $extra = array('user_url' => urlencode(get_bloginfo('wpurl')),
137
+ 'lang' => WPLANG,
138
+ 'versq' => SQ_VERSION_ID,
139
+ 'verwp' => WP_VERSION_ID,
140
+ 'verphp' => PHP_VERSION_ID,
141
+ 'token' => SQ_Tools::$options['sq_api']);
142
+
143
+ if ($module <> "") {
144
+ $module .= "/";
145
+ }
146
+
147
+ if (is_array($args)) {
148
+ $args = array_merge($args, $extra);
149
+ } else {
150
+ $args = $extra;
151
+ }
152
+
153
+ foreach ($args as $key => $value) {
154
+ if ($value <> '') {
155
+ $parameters .= ($parameters == "" ? "" : "&") . $key . "=" . $value;
156
+ }
157
+ }
158
+
159
+
160
+ /* If the call is for login on register then use base64 is exists */
161
+ if ($module == 'sq/login' || $module == 'sq/register') {
162
+ if (function_exists('base64_encode')) {
163
+ $parameters = 'q=' . base64_encode($parameters);
164
+ }
165
+ }
166
+
167
+
168
+ $url = self::cleanUrl(_SQ_API_URL_ . $module . "?" . $parameters);
169
+ //SQ_Tools::dump($url);
170
+ return SQ_Tools::sq_remote_get($url, array('timeout' => $timeout));
171
+ }
172
+
173
+ /**
174
+ * Clear the url before the call
175
+ * @param string $url
176
+ * @return string
177
+ */
178
+ private static function cleanUrl($url) {
179
+ return str_replace(array(' '), array('+'), $url);
180
+ }
181
+
182
+ }
classes/SQ_BlockController.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The main class for core blocks
5
+ *
6
+ */
7
+ class SQ_BlockController {
8
+
9
+ /** @var object of the model class */
10
+ protected $model;
11
+
12
+ /** @var boolean */
13
+ public $flush = true;
14
+
15
+ /** @var object of the view class */
16
+ protected $view;
17
+
18
+ /** @var name of the class */
19
+ private $name;
20
+
21
+ public function __construct() {
22
+ /** check the admin condition */
23
+ if (!is_admin())
24
+ return;
25
+
26
+ /* get the name of the current class */
27
+ $this->name = get_class($this);
28
+
29
+ /* create the model and view instances */
30
+ $this->model = SQ_ObjController::getModel($this->name);
31
+ }
32
+
33
+ /**
34
+ * load sequence of classes
35
+ *
36
+ * @return void
37
+ */
38
+ public function init() {
39
+
40
+ $this->view = SQ_ObjController::getController('SQ_DisplayController', false);
41
+ $this->view->setBlock($this->name);
42
+
43
+ /* check if there is a hook defined in the block class */
44
+ SQ_ObjController::getController('SQ_HookController', false)
45
+ ->setBlockHooks($this);
46
+
47
+ if ($this->flush) {
48
+ echo $this->output();
49
+ } else {
50
+ return $this->output();
51
+ }
52
+ }
53
+
54
+ protected function output() {
55
+ $this->hookHead();
56
+ return $this->view->echoBlock($this);
57
+ }
58
+
59
+ /**
60
+ * This function is called from Ajax class as a wp_ajax_action
61
+ *
62
+ */
63
+ protected function action() {
64
+ // check to see if the submitted nonce matches with the
65
+ // generated nonce we created
66
+ if (class_exists('wp_verify_nonce'))
67
+ if (!wp_verify_nonce(SQ_Tools::getValue(_SQ_NONCE_ID_), _SQ_NONCE_ID_))
68
+ die('Invalid request!');
69
+ }
70
+
71
+ /**
72
+ * This function will load the media in the header for each class
73
+ *
74
+ * @return void
75
+ */
76
+ protected function hookHead() {
77
+ if (!is_admin())
78
+ return;
79
+ SQ_ObjController::getController('SQ_DisplayController', false)
80
+ ->loadMedia($this->name);
81
+ }
82
+
83
+ }
classes/SQ_DisplayController.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The class handles the theme part in WP
5
+ */
6
+ class SQ_DisplayController {
7
+
8
+ private static $name;
9
+ private static $cache;
10
+
11
+ public function init() {
12
+ /* Load the global CSS file */
13
+ self::loadMedia('sq_global');
14
+ }
15
+
16
+ /**
17
+ * echo the css link from theme css directory
18
+ *
19
+ * @param string $uri The name of the css file or the entire uri path of the css file
20
+ * @param string $media
21
+ *
22
+ * @return string
23
+ */
24
+ public static function loadMedia($uri = '', $media = 'all', $params = null) {
25
+ if (strpos($_SERVER['PHP_SELF'], '/admin-ajax.php') !== false || (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER ['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'))
26
+ return;
27
+
28
+ $css_uri = '';
29
+ $js_uri = '';
30
+ $local = true;
31
+
32
+ if (isset(self::$cache[$uri]))
33
+ return;
34
+ self::$cache[$uri] = true;
35
+
36
+ /* if is a custom css file */
37
+ if (strpos($uri, '/') === false) {
38
+ $name = strtolower($uri);
39
+ if (file_exists(_SQ_THEME_DIR_ . 'css/' . $name . '.css')) {
40
+ $css_uri = _SQ_THEME_URL_ . 'css/' . $name . '.css?ver=' . SQ_VERSION_ID;
41
+ }
42
+ if (file_exists(_SQ_THEME_DIR_ . 'js/' . $name . '.js')) {
43
+ $js_uri = _SQ_THEME_URL_ . 'js/' . $name . '.js?ver=' . SQ_VERSION_ID;
44
+ }
45
+ } else {
46
+ $name = strtolower(basename($uri));
47
+ if (strpos($uri, '.css') !== FALSE)
48
+ $css_uri = $uri;
49
+ elseif (strpos($uri, '.js') !== FALSE) {
50
+ $js_uri = $uri;
51
+ }
52
+ $local = false;
53
+ }
54
+
55
+
56
+ if ($css_uri <> '') {
57
+ if (wp_style_is($name))
58
+ wp_deregister_style($name);
59
+
60
+ wp_register_style($name, $css_uri, null, SQ_VERSION_ID, 'all');
61
+ wp_enqueue_style($name);
62
+ }
63
+
64
+ if ($js_uri <> '') {
65
+ if (wp_script_is($name))
66
+ wp_deregister_script($name);
67
+
68
+ wp_register_script($name, $js_uri);
69
+ wp_enqueue_script($name);
70
+ }
71
+ }
72
+
73
+ public function setBlock($block) {
74
+ self::$name = $block;
75
+ }
76
+
77
+ /**
78
+ * echo the block content from theme directory
79
+ *
80
+ * @return string
81
+ */
82
+ public static function echoBlock($view) {
83
+ global $post_ID;
84
+ if (file_exists(_SQ_THEME_DIR_ . self::$name . '.php')) {
85
+ ob_start();
86
+
87
+ /* includes the block from theme directory */
88
+ include(_SQ_THEME_DIR_ . self::$name . '.php');
89
+ $block_content = ob_get_contents();
90
+ ob_end_clean();
91
+
92
+ return $block_content;
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Called for any class to show the block content
98
+ *
99
+ * @param string $block the name of the block file in theme directory (class name by default)
100
+ *
101
+ * @return string of the current class view
102
+ */
103
+ public function output($block, $obj) {
104
+ self::$name = $block;
105
+ echo $this->echoBlock($obj);
106
+ }
107
+
108
+ }
classes/SQ_Error.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class SQ_Error extends SQ_FrontController {
4
+
5
+ /** @var array */
6
+ private static $errors, $switch_off;
7
+
8
+ /**
9
+ * The error controller for Squirrly
10
+ */
11
+ public function __construct() {
12
+ parent::__construct();
13
+
14
+ /* Verify dependences */
15
+ if (!function_exists('get_class')) {
16
+ self::setError(__('Function get_class does not exists! Is required for Squirrly to work properly.', _SQ_PLUGIN_NAME_));
17
+ }
18
+ if (!function_exists('file_exists')) {
19
+ self::setError(__('Function file_exists does not exists! Is required for Squirrly to work properly.', _SQ_PLUGIN_NAME_));
20
+ }
21
+
22
+ if (!defined('ABSPATH'))
23
+ self::setError(__('The home directory is not set!', _SQ_PLUGIN_NAME_), 'fatal');
24
+
25
+ /* Check the PHP version */
26
+ if (PHP_VERSION_ID < 5000) {
27
+ self::setError(__('The PHP version has to be greater then 4.0', _SQ_PLUGIN_NAME_), 'fatal');
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Show the error in wrodpress
33
+ *
34
+ * @param string $error
35
+ * @param boolean $stop
36
+ *
37
+ * @return void;
38
+ */
39
+ public static function setError($error = '', $type = 'notice', $id = '') {
40
+ self::$errors[] = array('id' => $id,
41
+ 'type' => $type,
42
+ 'text' => $error);
43
+ }
44
+
45
+ /**
46
+ * This hook will show the error in WP header
47
+ */
48
+ function hookNotices() {
49
+ if (is_array(self::$errors))
50
+ foreach (self::$errors as $error) {
51
+
52
+ switch ($error['type']) {
53
+ case 'fatal':
54
+ self::showError(ucfirst(_SQ_PLUGIN_NAME_ . " " . $error['type']) . ': ' . $error['text'], $error['id']);
55
+ die();
56
+ break;
57
+ case 'settings':
58
+ if (isset(SQ_Tools::$options['ignore_warn']) && SQ_Tools::$options['ignore_warn'] == 1)
59
+ break;
60
+
61
+ /* switch off option for notifications */
62
+ self::$switch_off = "<a href=\"javascript:void(0);\" onclick=\"jQuery.post( ajaxurl, {action: 'sq_warnings_off', nonce: '" . wp_create_nonce('sq_none') . "'}, function(data) { if (data) { jQuery('#sq_ignore_warn').attr('checked', true); jQuery('.sq_message').hide(); jQuery('#toplevel_page_squirrly .awaiting-mod').fadeOut('slow'); } });\" >" . __("Turn off warnings!", _SQ_PLUGIN_NAME_) . "</a>";
63
+ self::showError(ucfirst(_SQ_PLUGIN_NAME_) . " " . __('Notice: ', _SQ_PLUGIN_NAME_) . $error['text'] . " " . self::$switch_off, $error['id']);
64
+ break;
65
+ default:
66
+
67
+ self::showError(ucfirst(_SQ_PLUGIN_NAME_) . " " . __('Note: ', _SQ_PLUGIN_NAME_) . $error['text'], $error['id']);
68
+ }
69
+ }
70
+ self::$errors = array();
71
+ }
72
+
73
+ /**
74
+ * Show the notices to WP
75
+ *
76
+ * @return void
77
+ */
78
+ public static function showError($message, $id = '') {
79
+ $type = 'sq_error';
80
+
81
+ if (file_exists(_SQ_THEME_DIR_ . 'SQ_notices.php')) {
82
+ include (_SQ_THEME_DIR_ . 'SQ_notices.php');
83
+ } else {
84
+ echo $message;
85
+ }
86
+ }
87
+
88
+ }
classes/SQ_FrontController.php ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The main class for controllers
5
+ *
6
+ */
7
+ class SQ_FrontController {
8
+
9
+ /** @var object of the model class */
10
+ public $model;
11
+
12
+ /** @var boolean */
13
+ public $flush = true;
14
+
15
+ /** @var object of the view class */
16
+ public $view;
17
+
18
+ /** @var name of the class */
19
+ private $name;
20
+
21
+ public function __construct() {
22
+
23
+ /* get the name of the current class */
24
+ $this->name = get_class($this);
25
+
26
+
27
+ /* load the model and hooks here for wordpress actions to take efect */
28
+ /* create the model and view instances */
29
+ $this->model = SQ_ObjController::getModel($this->name);
30
+
31
+ //IMPORTANT TO LOAD HOOKS HERE
32
+ /* check if there is a hook defined in the controller clients class */
33
+ SQ_ObjController::getController('SQ_HookController', false)
34
+ ->setAdminHooks($this);
35
+ }
36
+
37
+ /**
38
+ * load sequence of classes
39
+ * Function called usualy when the controller is loaded in WP
40
+ *
41
+ * @return void
42
+ */
43
+ public function init() {
44
+
45
+ $this->view = SQ_ObjController::getController('SQ_DisplayController', false);
46
+ $this->view->setBlock($this->name);
47
+
48
+
49
+ /* load the blocks for this controller */
50
+ SQ_ObjController::getController('SQ_ObjController', false)->getBlocks($this->name);
51
+
52
+ if ($this->flush) {
53
+ echo $this->output();
54
+ } else {
55
+ return $this->output();
56
+ }
57
+ }
58
+
59
+ protected function output() {
60
+ $this->hookHead();
61
+ return $this->view->echoBlock($this);
62
+ }
63
+
64
+ /**
65
+ * initialize settings
66
+ * Called from index
67
+ *
68
+ * @return void
69
+ */
70
+ public function run() {
71
+ /** check the admin condition */
72
+ if (!is_admin())
73
+ return;
74
+
75
+ /* Load error class */
76
+ SQ_ObjController::getController('SQ_Error', false);
77
+ /* Load Tools */
78
+ SQ_ObjController::getController('SQ_Tools', false);
79
+
80
+
81
+
82
+ /* Load the Submit Actions Handler */
83
+ SQ_ObjController::getController('SQ_Action', false);
84
+
85
+ SQ_ObjController::getController('SQ_DisplayController', false);
86
+
87
+ /* show the admin menu and post actions */
88
+ $this->loadMenu();
89
+
90
+ /* Load the Sitemap Generator */
91
+ SQ_ObjController::getController('SQ_Sitemap', false);
92
+ }
93
+
94
+ /**
95
+ * initialize menu
96
+ *
97
+ * @return void
98
+ */
99
+ private function loadMenu() {
100
+ /* get the menu from controller */
101
+ SQ_ObjController::getController('SQ_Menu');
102
+ }
103
+
104
+ /**
105
+ * first function call for any class
106
+ *
107
+ */
108
+ protected function action() {
109
+ // check to see if the submitted nonce matches with the
110
+ // generated nonce we created
111
+ if (class_exists('wp_verify_nonce'))
112
+ if (!wp_verify_nonce(SQ_Tools::getValue(_SQ_NONCE_ID_), _SQ_NONCE_ID_))
113
+ die('Invalid request!');
114
+ }
115
+
116
+ /**
117
+ * This function will load the media in the header for each class
118
+ *
119
+ * @return void
120
+ */
121
+ public function hookHead() {
122
+ if (!is_admin())
123
+ return;
124
+ SQ_ObjController::getController('SQ_DisplayController', false)->init();
125
+ SQ_ObjController::getController('SQ_DisplayController', false)
126
+ ->loadMedia($this->name);
127
+ }
128
+
129
+ }
classes/SQ_HookController.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The class handles the actions in WP
5
+ */
6
+ class SQ_HookController {
7
+
8
+ /** @var array the WP actions list from admin */
9
+ private $admin_hooks = array();
10
+ private $custom_hooks = array();
11
+ private $block_hooks = array();
12
+
13
+ public function __construct() {
14
+ $this->admin_hooks = array('init' => 'admin_init',
15
+ 'head' => 'admin_head',
16
+ 'footer' => 'admin_footer',
17
+ 'wmenu' => '_admin_menu',
18
+ 'menu' => 'admin_menu',
19
+ 'submenu' => 'add_submenu_page',
20
+ 'loaded' => 'plugins_loaded',
21
+ 'xml' => 'admin_xml_ns',
22
+ 'scripts' => 'admin_enqueue_scripts',
23
+ 'notices' => 'admin_notices',
24
+ 'shutdown' => 'shutdown',
25
+ 'fronttitletheme' => 'thematic_doctitle',
26
+ 'frontinit' => 'init',
27
+ 'fronthead' => 'wp_head',
28
+ 'frontfooter' => 'wp_footer',
29
+ 'frontcontent' => 'the_content',
30
+ );
31
+ $this->block_hooks = array('getContent' => 'getContent');
32
+ }
33
+
34
+ /**
35
+ * Calls the specified action in WP
36
+ * @param oject $instance The parent class instance
37
+ *
38
+ * @return void
39
+ */
40
+ public function setAdminHooks($instance) {
41
+
42
+ /* for each admin action check if is defined in class and call it */
43
+ foreach ($this->admin_hooks as $hook => $value) {
44
+
45
+ if (is_callable(array($instance, 'hook' . ucfirst($hook)))) {
46
+ //echo $value . '<br>';
47
+ //print_r(array($instance, 'hook'.ucfirst($hook)));
48
+ //call the WP add_action function
49
+ add_action($value, array($instance, 'hook' . ucfirst($hook)), 5);
50
+ }
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Calls the specified action in WP
56
+ * @param string $action
57
+ * @param array $callback Contains the class name or object and the callback function
58
+ *
59
+ * @return void
60
+ */
61
+ public function setAction($action, $obj, $callback) {
62
+
63
+ /* calls the custom action function from WP */
64
+ add_action($action, array($obj, $callback), 10);
65
+ }
66
+
67
+ /**
68
+ * Calls the specified action in WP
69
+ * @param oject $instance The parent class instance
70
+ *
71
+ * @return void
72
+ */
73
+ public function setBlockHooks($instance) {
74
+ $param_arr = array();
75
+
76
+ /* for each admin action check if is defined in class and call it */
77
+ foreach ($this->block_hooks as $hook => $value)
78
+ if (is_callable(array($instance, 'hook' . ucfirst($hook))))
79
+ call_user_func_array(array($instance, 'hook' . ucfirst($hook)), $param_arr);
80
+ }
81
+
82
+ }
classes/SQ_ObjController.php ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The class creates object for plugin classes
5
+ */
6
+ class SQ_ObjController {
7
+
8
+ /** @var array of instances */
9
+ public static $instances;
10
+
11
+ /** @var array from core config */
12
+ private static $config;
13
+
14
+ private static function includeController($className, $core) {
15
+ /* check if class is already defined */
16
+ if (!class_exists($className, false))
17
+ /* if $core == true then call the class from core directory */
18
+ try {
19
+ if (file_exists(($core ? _SQ_CONTROLLER_DIR_ : _SQ_CLASSES_DIR_) . $className . '.php'))
20
+ include_once(($core ? _SQ_CONTROLLER_DIR_ : _SQ_CLASSES_DIR_) . $className . '.php');
21
+ } catch (Exception $e) {
22
+ echo 'Controller Error: ' . $e->getMessage();
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Get the instance of the specified class
28
+ *
29
+ * @param string $className
30
+ * @param bool $core TRUE is the class is a core class or FALSE if it is from classes directory
31
+ *
32
+ * @return object of the class|false
33
+ */
34
+ public static function getController($className, $core = true) {
35
+ if (!isset(self::$instances[$className])) {
36
+ /* if $core == true then call the class from core directory */
37
+ self::includeController($className, $core);
38
+
39
+ if (class_exists($className)) {
40
+ self::$instances[$className] = new $className;
41
+ return self::$instances[$className];
42
+ }
43
+ } else
44
+ return self::$instances[$className];
45
+
46
+ return false;
47
+ }
48
+
49
+ private static function includeModel($className) {
50
+
51
+ /* check if class is already defined */
52
+ if (file_exists(_SQ_MODEL_DIR_ . $className . '.php'))
53
+ try {
54
+ include_once(_SQ_MODEL_DIR_ . $className . '.php');
55
+ } catch (Exception $e) {
56
+ echo 'Model Error: ' . $e->getMessage();
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Get the instance of the specified model class
62
+ *
63
+ * @param string $className
64
+ *
65
+ * @return object of the class
66
+ */
67
+ public static function getModel($className) {
68
+ /* add Model prefix */
69
+ $prefix = 'Model_';
70
+
71
+ if (!isset(self::$instances[$prefix . $className])) {
72
+ /* if $core == true then call the class from core directory */
73
+ self::includeModel($className);
74
+
75
+ //echo $className . '<br />';
76
+ if (class_exists($prefix . $className)) {
77
+ $classModel = $prefix . $className;
78
+ self::$instances[$prefix . $className] = new $classModel;
79
+ return self::$instances[$prefix . $className];
80
+ }
81
+ } else
82
+ return self::$instances[$prefix . $className];
83
+
84
+ return;
85
+ }
86
+
87
+ private static function includeBlock($className) {
88
+
89
+ /* check if class is already defined */
90
+ try {
91
+ require_once(_SQ_CORE_DIR_ . $className . '/' . $className . '.php');
92
+ } catch (Exception $e) {
93
+ echo 'Model Error: ' . $e->getMessage();
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Get the instance of the specified block from core directory
99
+ *
100
+ * @param string $className
101
+ *
102
+ * @return object of the class
103
+ */
104
+ public static function getBlock($className) {
105
+
106
+ if (!isset(self::$instances[$className])) {
107
+ /* if $core == true then call the class from core directory */
108
+ self::includeBlock($className);
109
+
110
+ //echo $className . '<br />';
111
+ if (class_exists($className)) {
112
+ self::$instances[$className] = new $className;
113
+ return self::$instances[$className];
114
+ } else
115
+ exit("Block error: Can't call $className class");
116
+ } else
117
+ return self::$instances[$className];
118
+
119
+ return;
120
+ }
121
+
122
+ /**
123
+ * Get all core classes from config.xml in core directory
124
+ *
125
+ * @param string $for
126
+ */
127
+ public function getBlocks($for) {
128
+ /* if config allready in cache */
129
+ if (!isset(self::$config)) {
130
+ $config_file = _SQ_CORE_DIR_ . 'config.xml';
131
+ if (!file_exists($config_file))
132
+ return;
133
+
134
+ /* load configuration blocks data from core config files */
135
+ $data = file_get_contents($config_file);
136
+ self::$config = json_decode(json_encode((array) simplexml_load_string($data)), 1);
137
+ ;
138
+ }
139
+ //print_r(self::$config);
140
+ if (is_array(self::$config))
141
+ foreach (self::$config['block'] as $block) {
142
+ if ($block['active'] == 1)
143
+ if (isset($block['controllers']['controller']))
144
+ if (!is_array($block['controllers']['controller'])) {
145
+ /* if the block should load for the current controller */
146
+ if ($for == $block['controllers']['controller']) {
147
+ SQ_ObjController::getBlock($block['name'])->init();
148
+ }
149
+ } else {
150
+ foreach ($block['controllers']['controller'] as $controller) {
151
+ /* if the block should load for the current controller */
152
+ if ($for == $controller) {
153
+ SQ_ObjController::getBlock($block['name'])->init();
154
+ }
155
+ }
156
+ }
157
+ }
158
+ }
159
+
160
+ }
classes/SQ_Ranking.php ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class for Google Ranking Record
5
+ */
6
+ class SQ_Ranking extends SQ_FrontController {
7
+
8
+ private $keyword;
9
+ private $post_id;
10
+
11
+ //--
12
+ public function getCountry() {
13
+ return SQ_Tools::$options['sq_google_country'];
14
+ }
15
+
16
+ /**
17
+ * Get the google language from settings
18
+ * @return type
19
+ */
20
+ public function getLanguage() {
21
+ return SQ_Tools::$options['sq_google_language'];
22
+ }
23
+
24
+ /**
25
+ * Set the Post id
26
+ * @return type
27
+ */
28
+ public function setPost($post_id) {
29
+ $this->post_id = $post_id;
30
+ }
31
+
32
+ /**
33
+ * Get the current keyword
34
+ * @param type $keyword
35
+ */
36
+ public function setKeyword($keyword) {
37
+ $this->keyword = str_replace(" ", "+", urlencode(strtolower($keyword)));
38
+ }
39
+
40
+ /**
41
+ * Process Ranking on brief request
42
+ * @param type $return
43
+ */
44
+ public function processRanking($post_id, $keyword) {
45
+ $this->setPost($post_id);
46
+ $this->setKeyword($keyword);
47
+
48
+ if (isset($this->keyword)) {
49
+ return $this->getGoogleRank();
50
+ }
51
+ return false;
52
+ }
53
+
54
+ /**
55
+ * Call google to get the keyword position
56
+ *
57
+ * @param integer $post_id
58
+ * @param string $keyword
59
+ * @param string $country: com | country extension
60
+ * @param string $language: en | local language
61
+ * @return boolean|int
62
+ */
63
+ public function getGoogleRank() {
64
+ global $wpdb;
65
+ $country = $this->getCountry();
66
+
67
+ if (!function_exists('preg_match_all'))
68
+ return;
69
+
70
+ $arg = array('timeout' => 10);
71
+ $arg['q'] = $this->keyword;
72
+ $arg['hl'] = $this->getLanguage();
73
+ $arg['num'] = '100';
74
+ $arg['as_qdr'] = 'all';
75
+ $arg['safe'] = 'off';
76
+ $arg['pws'] = '0';
77
+
78
+ //Grab the remote informations from google
79
+ $response = utf8_decode(SQ_Tools::sq_remote_get("https://www.google.$country/search", $arg));
80
+
81
+ //Check the values for block IP
82
+ if (strpos($response, "computer virus or spyware application") !== false ||
83
+ strpos($response, "entire network is affected") !== false ||
84
+ strpos($response, "http://www.download.com/Antivirus") !== false ||
85
+ strpos($response, "/images/yellow_warning.gif") !== false ||
86
+ strpos($response, "302 Moved") !== false) {
87
+ return -2; //return error
88
+ }
89
+
90
+
91
+ //Get the permalink of the current post
92
+ $permalink = get_permalink($this->post_id);
93
+ preg_match_all('/<h3 class="r"><a href="\/url\?q=(.*?)&amp;sa=U&amp;ei=/', $response, $matches);
94
+
95
+ $pos = -1;
96
+ if (!empty($matches[1])) {
97
+ foreach ($matches[1] as $index => $url) {
98
+
99
+ if (strpos($url, $permalink) !== false) {
100
+ $pos = $index + 1;
101
+ break;
102
+ }
103
+ }
104
+ }
105
+ return $pos;
106
+ }
107
+
108
+ /**
109
+ * Do google rank with cron
110
+ * @global type $wpdb
111
+ */
112
+ public function processCron() {
113
+ global $wpdb;
114
+ set_time_limit(400);
115
+ /* Load the Submit Actions Handler */
116
+ SQ_ObjController::getController('SQ_Tools', false);
117
+ SQ_ObjController::getController('SQ_Action', false);
118
+
119
+ //check 20 keyword at one time
120
+ $sql = "SELECT `post_id`, `meta_value`
121
+ FROM `" . $wpdb->postmeta . "`
122
+ WHERE (`meta_key` = 'sq_post_keyword')
123
+ ORDER BY `post_id` DESC";
124
+
125
+ if ($rows = $wpdb->get_results($sql)) {
126
+ $count = 0;
127
+ foreach ($rows as $row) {
128
+ if ($count > 20) {
129
+ break; //check only 10 keywords at the time
130
+ }
131
+ if ($row->meta_value <> '') {
132
+ $json = json_decode($row->meta_value);
133
+ //If keyword is set and no rank or last check is 2 days ago
134
+ if (isset($json->keyword) && $json->keyword <> '' &&
135
+ (!isset($json->rank) ||
136
+ (isset($json->update) && (time() - $json->update > (60 * 60 * 24 * 2))) || //if indexed then check every 2 days
137
+ (isset($json->update) && isset($json->rank) && $json->rank == -1 && (time() - $json->update > (60 * 60 * 24))) //if not indexed than check often
138
+ )) {
139
+
140
+ $json->rank = $this->processRanking($row->post_id, $json->keyword);
141
+ if ($json->rank == -1) {
142
+ $count++;
143
+ sleep(mt_rand(10, 20));
144
+ //if not indexed with the keyword then find the url
145
+ if ($this->processRanking($row->post_id, get_permalink($row->post_id)) > 0) {
146
+ $json->rank = 0; //for permalink index set 0
147
+ }
148
+ }
149
+
150
+
151
+ if (isset($json->rank)) {
152
+ $json->country = $this->getCountry();
153
+ $json->language = $this->getLanguage();
154
+ SQ_ObjController::getModel('SQ_Post')->saveKeyword($row->post_id, $json);
155
+ set_transient('sq_rank' . $row->post_id, $json->rank, (60 * 60 * 24));
156
+
157
+ //if rank proccess has no error
158
+ if ($json->rank >= -1) {
159
+ $args = array();
160
+ $args['post_id'] = $row->post_id;
161
+ $args['rank'] = (string) $json->rank;
162
+ $args['country'] = $this->getCountry();
163
+ $args['language'] = $this->getLanguage();
164
+
165
+ SQ_Action::apiCall('sq/user-analytics/saveserp', $args);
166
+ }
167
+ $count++;
168
+ sleep(mt_rand(10, 20));
169
+ }
170
+ }
171
+ }
172
+ }
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Get keyword from earlier version
178
+ *
179
+ */
180
+ public function getKeywordHistory() {
181
+ global $wpdb;
182
+ //Check if ranks is saved in database
183
+ $sql = "SELECT a.`global_rank`, a.`keyword`, a.`post_id`
184
+ FROM `sq_analytics` as a
185
+ INNER JOIN (SELECT MAX(`id`) as id FROM `sq_analytics` WHERE `keyword` <> '' GROUP BY `post_id`) as a1 ON a1.id = a.id ";
186
+
187
+ if ($rows = $wpdb->get_results($sql)) {
188
+ foreach ($rows as $values) {
189
+ if ($json = SQ_ObjController::getModel('SQ_Post')->getKeyword($values->post_id)) {
190
+ $json->keyword = urldecode($values->keyword);
191
+ if ($values->global_rank > 0) {
192
+ $json->rank = $values->global_rank;
193
+ }
194
+ SQ_ObjController::getModel('SQ_Post')->saveKeyword($values->post_id, $json);
195
+ } else {
196
+ $args = array();
197
+ $args['keyword'] = urldecode($values->keyword);
198
+ if ($values->global_rank > 0) {
199
+ $json->rank = $values->global_rank;
200
+ }
201
+ SQ_ObjController::getModel('SQ_Post')->saveKeyword($values->post_id, json_decode(json_encode($args)));
202
+ }
203
+ }
204
+ }
205
+ }
206
+
207
+ }
208
+
209
+ ?>
classes/SQ_Sitemap.php ADDED
@@ -0,0 +1,381 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class for Sitemap Generator
5
+ */
6
+ class SQ_Sitemap extends SQ_FrontController {
7
+ /* @var string file path */
8
+
9
+ var $file;
10
+ var $opt = array();
11
+ var $data = array();
12
+ var $args = array();
13
+ var $posts_limit = 0;
14
+
15
+ public function __construct() {
16
+ if (!isset(SQ_Tools::$options['sq_use']) || SQ_Tools::$options['sq_use'] == 0)
17
+ return;
18
+ if (isset(SQ_Tools::$options['sq_auto_sitemap']) && SQ_Tools::$options['sq_auto_sitemap'] == 0)
19
+ return;
20
+
21
+ $this->filename = 'sitemap.xml';
22
+
23
+ $this->file = ABSPATH . $this->filename;
24
+ //For sitemap ping
25
+ $this->args['timeout'] = 5;
26
+ $this->opt = array('home' => array(1, 'daily'),
27
+ 'page' => array(0.6, 'monthly'),
28
+ 'post' => array(0.8, 'weekly'),
29
+ 'static' => array(0.6, 'weekly'),
30
+ 'category' => array(0.4, 'monthly'),
31
+ 'archive' => array(0.3, 'weekly'),
32
+ 'oldarchive' => array(0.3, 'monthly'),
33
+ 'tag' => array(0.3, 'weekly'),
34
+ 'author' => array(0.3, 'monthly'),
35
+ );
36
+
37
+ //Existing posts was deleted
38
+ add_action('delete_post', array($this, 'generateSitemap'), 9999, 1);
39
+ //Existing post was published
40
+ add_action('publish_post', array($this, 'generateSitemap'), 9999, 1);
41
+ //Existing page was published
42
+ add_action('publish_page', array($this, 'generateSitemap'), 9999, 1);
43
+ }
44
+
45
+ public function init() {
46
+ return;
47
+ }
48
+
49
+ public function action() {
50
+
51
+ }
52
+
53
+ /**
54
+ * Generate the XML sitemap for google
55
+ */
56
+ public function generateSitemap() {
57
+ global $wpdb, $wp_query, $wp_version;
58
+ /* get the home url */
59
+ $home = get_bloginfo('url');
60
+ $homeID = 0;
61
+ $wpCompat = (floatval($wp_version) < 2.1);
62
+
63
+ /* If the site starts with a page */
64
+ if (get_option('show_on_front') == 'page' && get_option('page_on_front')) {
65
+ $page = get_page(get_option('page_on_front'));
66
+ if ($page) {
67
+ $homeID = $page->ID;
68
+ $lastmod = ($page->post_modified_gmt && $page->post_modified_gmt != '0000-00-00 00:00:00' ? $page->post_modified_gmt : $page->post_date_gmt);
69
+ $this->addLine($home, $this->getTimestamp($lastmod), $this->opt['home'][1], $this->opt['home'][0]);
70
+ }
71
+ } else
72
+ $this->addLine($home, $this->getTimestamp(get_lastpostmodified('GMT')), $this->opt['home'][1], $this->opt['home'][0]);
73
+
74
+ /* * ******************************************************************** */
75
+ //Add the pages
76
+ $query = array();
77
+
78
+ /* CREATE QUERY */
79
+ $query['what'] = "`ID`, `post_author`, `post_date`, `post_date_gmt`, `post_status`, `post_name`, `post_modified`, `post_modified_gmt`, `post_parent`, `post_type` ";
80
+
81
+ /* from */
82
+ $query['from'] = " `" . $wpdb->posts . "` ";
83
+ /* where */
84
+ $query['where'] = '(';
85
+
86
+
87
+ if ($wpCompat)
88
+ $query['where'] .= "(post_status = 'publish' AND post_date_gmt <= '" . gmdate('Y-m-d H:i:59') . "')";
89
+ else
90
+ $query['where'] .= "(post_status = 'publish' AND (post_type = 'post' OR post_type = '')) ";
91
+
92
+ $query['where'] .= " OR ";
93
+ if ($wpCompat)
94
+ $query['where'] .= " post_status='static' ";
95
+ else
96
+ $query['where'] .= " (post_status = 'publish' AND post_type = 'page') ";
97
+
98
+ $query['where'] .= ") ";
99
+ $query['where'] .= " AND post_password=''";
100
+ /* order */
101
+ $query['order'] = " ORDER BY post_modified DESC";
102
+ /* limit */
103
+ $query['limit'] = ((int) $this->posts_limit > 0) ? " LIMIT 0," . $this->posts_limit : '';
104
+
105
+
106
+ $posts = $wpdb->get_results('SELECT ' . $query['what'] . ' FROM ' . $query['from'] . ' WHERE ' . $query['where'] . ' ' . $query['order'] . ' ' . $query['limit'] . ' ');
107
+ if (!$posts) {
108
+ trigger_error(ucfirst(_SQ_PLUGIN_NAME_) . " failed to connect to database: " . mysql_error(), E_USER_NOTICE); //E_USER_NOTICE will be displayed on our debug mode
109
+ return;
110
+ }
111
+
112
+ /* loop */
113
+ foreach ($posts as $post) {
114
+ $out = array();
115
+ $permalink = get_permalink($post->ID);
116
+ if ($permalink != $home && $post->ID != $homeID) {
117
+
118
+ $isPage = false;
119
+ if ($wpCompat)
120
+ $isPage = ($post->post_status == 'static');
121
+ else
122
+ $isPage = ($post->post_type == 'page');
123
+
124
+ if ($isPage) {
125
+ $out['priority'] = $this->opt['page'][0];
126
+ $out['changefreq'] = $this->opt['page'][1];
127
+ } else {
128
+ $out['priority'] = $this->opt['post'][0];
129
+ $out['changefreq'] = $this->opt['post'][1];
130
+ }
131
+ $out['lastmod'] = ($post->post_modified_gmt && $post->post_modified_gmt != '0000-00-00 00:00:00' ? $post->post_modified_gmt : $post->post_date_gmt);
132
+
133
+ //Add it
134
+ $this->addLine($permalink, $this->getTimestamp($out['lastmod']), $out['changefreq'], $out['priority']);
135
+
136
+ $subPage = '';
137
+ if (isset($post->postPages) > 0)
138
+ for ($i = 1; $i <= $post->postPages; $i++) {
139
+ if (get_option('permalink_structure') == '') {
140
+ $subPage = $permalink . '&amp;page=' . ($p + 1);
141
+ } else {
142
+ $subPage = trailingslashit($permalink) . user_trailingslashit($p + 1, 'single_paged');
143
+ }
144
+
145
+ $this->addLine($subPage, $this->getTimestamp($out['lastmod']), $out['changefreq'], $out['priority']);
146
+ }
147
+ }
148
+ }
149
+
150
+ /* * ******************************************************************** */
151 <