Shortlinks by Pretty Links – Best WordPress Link Tracking Plugin - Version 1.3.36

Version Description

Download this release

Release Info

Developer supercleanse
Plugin Icon 128x128 Shortlinks by Pretty Links – Best WordPress Link Tracking Plugin
Version 1.3.36
Comparing to
See all releases

Version 1.3.36

Files changed (242) hide show
  1. classes/models/PrliClick.php +239 -0
  2. classes/models/PrliGroup.php +114 -0
  3. classes/models/PrliLink.php +324 -0
  4. classes/models/PrliUtils.php +628 -0
  5. classes/models/models.inc.php +11 -0
  6. classes/views/prli-clicks/csv.php +24 -0
  7. classes/views/prli-clicks/head.php +105 -0
  8. classes/views/prli-clicks/list.php +151 -0
  9. classes/views/prli-groups/edit.php +58 -0
  10. classes/views/prli-groups/head.php +44 -0
  11. classes/views/prli-groups/list.php +88 -0
  12. classes/views/prli-groups/new.php +59 -0
  13. classes/views/prli-links/bar.php +12 -0
  14. classes/views/prli-links/edit.php +22 -0
  15. classes/views/prli-links/form.php +116 -0
  16. classes/views/prli-links/head.php +91 -0
  17. classes/views/prli-links/list.php +170 -0
  18. classes/views/prli-links/new.php +22 -0
  19. classes/views/prli-links/ultra-cloak.php +11 -0
  20. classes/views/prli-options/form.php +165 -0
  21. classes/views/prli-options/head.php +36 -0
  22. classes/views/shared/errors.php +19 -0
  23. classes/views/shared/nav.php +1 -0
  24. classes/views/shared/table-nav.php +93 -0
  25. images/arrow_down.png +0 -0
  26. images/arrow_up.png +0 -0
  27. images/bar_background.png +0 -0
  28. images/bar_map.png +0 -0
  29. images/bookmark.png +0 -0
  30. images/browser/abilon.png +0 -0
  31. images/browser/adobe.png +0 -0
  32. images/browser/akregator.png +0 -0
  33. images/browser/alcatel.png +0 -0
  34. images/browser/amaya.png +0 -0
  35. images/browser/amigavoyager.png +0 -0
  36. images/browser/analogx.png +0 -0
  37. images/browser/apt.png +0 -0
  38. images/browser/avant.png +0 -0
  39. images/browser/aweb.png +0 -0
  40. images/browser/bpftp.png +0 -0
  41. images/browser/bytel.png +0 -0
  42. images/browser/chimera.png +0 -0
  43. images/browser/chrome.png +0 -0
  44. images/browser/cyberdog.png +0 -0
  45. images/browser/da.png +0 -0
  46. images/browser/dillo.png +0 -0
  47. images/browser/doris.png +0 -0
  48. images/browser/dreamcast.png +0 -0
  49. images/browser/ecatch.png +0 -0
  50. images/browser/encompass.png +0 -0
  51. images/browser/epiphany.png +0 -0
  52. images/browser/ericsson.png +0 -0
  53. images/browser/feeddemon.png +0 -0
  54. images/browser/feedreader.png +0 -0
  55. images/browser/firefox.png +0 -0
  56. images/browser/flashget.png +0 -0
  57. images/browser/fpexpress.png +0 -0
  58. images/browser/fresco.png +0 -0
  59. images/browser/freshdownload.png +0 -0
  60. images/browser/frontpage.png +0 -0
  61. images/browser/galeon.png +0 -0
  62. images/browser/getright.png +0 -0
  63. images/browser/gnome.png +0 -0
  64. images/browser/gnus.png +0 -0
  65. images/browser/gozilla.png +0 -0
  66. images/browser/hotjava.png +0 -0
  67. images/browser/httrack.png +0 -0
  68. images/browser/ibrowse.png +0 -0
  69. images/browser/icab.png +0 -0
  70. images/browser/java.png +0 -0
  71. images/browser/jetbrains_omea.png +0 -0
  72. images/browser/kmeleon.png +0 -0
  73. images/browser/konqueror.png +0 -0
  74. images/browser/leechget.png +0 -0
  75. images/browser/lg.png +0 -0
  76. images/browser/lotusnotes.png +0 -0
  77. images/browser/lynx.png +0 -0
  78. images/browser/macweb.png +0 -0
  79. images/browser/mediaplayer.png +0 -0
  80. images/browser/motorola.png +0 -0
  81. images/browser/mozilla.png +0 -0
  82. images/browser/mplayer.png +0 -0
  83. images/browser/msie.png +0 -0
  84. images/browser/msie_large.png +0 -0
  85. images/browser/multizilla.png +0 -0
  86. images/browser/ncsa_mosaic.png +0 -0
  87. images/browser/neon.png +0 -0
  88. images/browser/netnewswire.png +0 -0
  89. images/browser/netpositive.png +0 -0
  90. images/browser/netscape.png +0 -0
  91. images/browser/netscape_large.png +0 -0
  92. images/browser/netshow.png +0 -0
  93. images/browser/newsfire.png +0 -0
  94. images/browser/newsgator.png +0 -0
  95. images/browser/newzcrawler.png +0 -0
  96. images/browser/nokia.png +0 -0
  97. images/browser/notavailable.png +0 -0
  98. images/browser/omniweb.png +0 -0
  99. images/browser/opera.png +0 -0
  100. images/browser/panasonic.png +0 -0
  101. images/browser/pdaphone.png +0 -0
  102. images/browser/philips.png +0 -0
  103. images/browser/phoenix.png +0 -0
  104. images/browser/pluck.png +0 -0
  105. images/browser/pulpfiction.png +0 -0
  106. images/browser/real.png +0 -0
  107. images/browser/rss.png +0 -0
  108. images/browser/rssbandit.png +0 -0
  109. images/browser/rssowl.png +0 -0
  110. images/browser/rssreader.png +0 -0
  111. images/browser/rssxpress.png +0 -0
  112. images/browser/safari.png +0 -0
  113. images/browser/sagem.png +0 -0
  114. images/browser/samsung.png +0 -0
  115. images/browser/sharp.png +0 -0
  116. images/browser/sharpreader.png +0 -0
  117. images/browser/shrook.png +0 -0
  118. images/browser/siemens.png +0 -0
  119. images/browser/sony.png +0 -0
  120. images/browser/staroffice.png +0 -0
  121. images/browser/subversion.png +0 -0
  122. images/browser/teleport.png +0 -0
  123. images/browser/trium.png +0 -0
  124. images/browser/unknown.png +0 -0
  125. images/browser/w3c.png +0 -0
  126. images/browser/webcopier.png +0 -0
  127. images/browser/webreaper.png +0 -0
  128. images/browser/webtv.png +0 -0
  129. images/browser/webzip.png +0 -0
  130. images/browser/winxbox.png +0 -0
  131. images/browser/wizz.png +0 -0
  132. images/forward_params.png +0 -0
  133. images/nofollow.png +0 -0
  134. images/not_tracking.png +0 -0
  135. images/os/aix.png +0 -0
  136. images/os/amigaos.png +0 -0
  137. images/os/apple.png +0 -0
  138. images/os/atari.png +0 -0
  139. images/os/beos.png +0 -0
  140. images/os/bsd.png +0 -0
  141. images/os/bsdfreebsd.png +0 -0
  142. images/os/bsdi.png +0 -0
  143. images/os/bsdnetbsd.png +0 -0
  144. images/os/bsdopenbsd.png +0 -0
  145. images/os/commodore.png +0 -0
  146. images/os/cpm.png +0 -0
  147. images/os/debian.png +0 -0
  148. images/os/digital.png +0 -0
  149. images/os/dos.png +0 -0
  150. images/os/dreamcast.png +0 -0
  151. images/os/freebsd.png +0 -0
  152. images/os/gnu.png +0 -0
  153. images/os/hpux.png +0 -0
  154. images/os/ibm.png +0 -0
  155. images/os/imode.png +0 -0
  156. images/os/irix.png +0 -0
  157. images/os/java.png +0 -0
  158. images/os/kfreebsd.png +0 -0
  159. images/os/linux.png +0 -0
  160. images/os/linuxcentos.png +0 -0
  161. images/os/linuxdebian.png +0 -0
  162. images/os/linuxfedora.png +0 -0
  163. images/os/linuxgentoo.png +0 -0
  164. images/os/linuxmandr.png +0 -0
  165. images/os/linuxredhat.png +0 -0
  166. images/os/linuxsuse.png +0 -0
  167. images/os/linuxubuntu.png +0 -0
  168. images/os/mac.png +0 -0
  169. images/os/macintosh.png +0 -0
  170. images/os/macosx.png +0 -0
  171. images/os/netbsd.png +0 -0
  172. images/os/netware.png +0 -0
  173. images/os/next.png +0 -0
  174. images/os/openbsd.png +0 -0
  175. images/os/os2.png +0 -0
  176. images/os/osf.png +0 -0
  177. images/os/psp.png +0 -0
  178. images/os/qnx.png +0 -0
  179. images/os/riscos.png +0 -0
  180. images/os/sco.png +0 -0
  181. images/os/sunos.png +0 -0
  182. images/os/symbian.png +0 -0
  183. images/os/unix.png +0 -0
  184. images/os/unknown.png +0 -0
  185. images/os/vms.png +0 -0
  186. images/os/webtv.png +0 -0
  187. images/os/win.png +0 -0
  188. images/os/win16.png +0 -0
  189. images/os/win2000.png +0 -0
  190. images/os/win2003.png +0 -0
  191. images/os/win95.png +0 -0
  192. images/os/win98.png +0 -0
  193. images/os/wince.png +0 -0
  194. images/os/winlong.png +0 -0
  195. images/os/winme.png +0 -0
  196. images/os/winnt.png +0 -0
  197. images/os/winunknown.png +0 -0
  198. images/os/winxbox.png +0 -0
  199. images/os/winxp.png +0 -0
  200. images/pixel_track.png +0 -0
  201. images/pretty-link-48x48.png +0 -0
  202. images/pretty-link-add.png +0 -0
  203. images/pretty-link-med.png +0 -0
  204. images/pretty-link-small.png +0 -0
  205. images/tracking.png +0 -0
  206. images/ultra-cloak.png +0 -0
  207. images/url_icon.gif +0 -0
  208. includes/jquery/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  209. includes/jquery/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  210. includes/jquery/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
  211. includes/jquery/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  212. includes/jquery/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  213. includes/jquery/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  214. includes/jquery/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  215. includes/jquery/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  216. includes/jquery/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  217. includes/jquery/css/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
  218. includes/jquery/css/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
  219. includes/jquery/css/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
  220. includes/jquery/css/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
  221. includes/jquery/css/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
  222. includes/jquery/css/ui-lightness/jquery-ui-1.7.1.custom.css +404 -0
  223. includes/jquery/js/jquery-1.3.2.min.js +19 -0
  224. includes/jquery/js/jquery-ui-1.7.1.custom.min.js +273 -0
  225. includes/php/php_browsecap.ini +16810 -0
  226. includes/version-2-kvasir/README.txt +8 -0
  227. includes/version-2-kvasir/js/README.txt +12 -0
  228. includes/version-2-kvasir/js/json/json2.js +461 -0
  229. includes/version-2-kvasir/js/swfobject.js +5 -0
  230. includes/version-2-kvasir/open-flash-chart.swf +0 -0
  231. pretty-bar.php +246 -0
  232. pretty-link.php +453 -0
  233. prli-add-link.php +9 -0
  234. prli-api.php +268 -0
  235. prli-clicks.php +231 -0
  236. prli-config.php +103 -0
  237. prli-groups.php +175 -0
  238. prli-image-lookups.php +136 -0
  239. prli-links.php +208 -0
  240. prli-options.php +173 -0
  241. prli-xmlrpc.php +353 -0
  242. readme.txt +85 -0
classes/models/PrliClick.php ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class PrliClick
3
+ {
4
+ function table_name()
5
+ {
6
+ global $wpdb;
7
+ return $wpdb->prefix . 'prli_clicks';
8
+ }
9
+
10
+ function get_ip_exclude_list()
11
+ {
12
+ $exclude_list = get_option('prli_exclude_ips');
13
+ $exclude_list = preg_replace('#[ \t]#','',$exclude_list);
14
+
15
+ if($exclude_list)
16
+ return "'" . implode("','", explode(',',$exclude_list)) . "'";
17
+ else
18
+ return '';
19
+ }
20
+
21
+ function get_exclude_where_clause( $where = '', $abbr = 'cl')
22
+ {
23
+ $exclude_list = $this->get_ip_exclude_list();
24
+
25
+ if($where == '')
26
+ $starts_with = '';
27
+ else
28
+ $starts_with = ' AND';
29
+
30
+ if( $exclude_list != '')
31
+ return $starts_with . " $abbr.ip NOT IN (" . $exclude_list . ')';
32
+ else
33
+ return '';
34
+ }
35
+
36
+ function getOne( $id )
37
+ {
38
+ global $wpdb, $prli_link, $prli_utils;
39
+ $click_table = $wpdb->prefix . "prli_clicks";
40
+ $query = 'SELECT cl.*, (SELECT count(*) FROM '. $this->table_name() .' cl2 WHERE cl2.ip = cl.ip) as ip_count, (SELECT count(*) FROM '. $this->table_name() .' cl3 WHERE cl3.vuid = cl.vuid) as vuid_count, li.name as link_name FROM ' . $this->table_name() . ' cl, ' . $prli_link->table_name() . ' li WHERE li.id = cl.link_id AND id=' . $id . $prli_utils->prepend_and_or_where(' AND',$this->get_exclude_where_clause());
41
+
42
+ return $wpdb->get_row($query);
43
+ }
44
+
45
+ // SELECT cl.*,li.name as link_name FROM wp_prli_clicks cl, wp_prli_links li WHERE li.id = cl.link_id ORDER BY created_at DESC
46
+ function getAll($where = '', $order = '')
47
+ {
48
+ global $wpdb, $prli_link, $prli_utils;
49
+ $click_table = $wpdb->prefix . "prli_clicks";
50
+ $where .= $this->get_exclude_where_clause( $where );
51
+ $where = $prli_utils->prepend_and_or_where(' AND', $where);
52
+ $query = 'SELECT cl.*, (SELECT count(*) FROM '. $this->table_name() .' cl2 WHERE cl2.ip = cl.ip) as ip_count, (SELECT count(*) FROM '. $this->table_name() .' cl3 WHERE cl3.vuid = cl.vuid) as vuid_count, li.name as link_name FROM ' . $this->table_name() . ' cl, ' . $prli_link->table_name() . ' li WHERE li.id = cl.link_id' . $where . $order;
53
+ return $wpdb->get_results($query);
54
+ }
55
+
56
+ // Delete all of the clicks from the database.
57
+ function clearAllClicks()
58
+ {
59
+ global $wpdb;
60
+ $query = "TRUNCATE TABLE " . $this->table_name();
61
+ return $wpdb->query($query);
62
+ }
63
+
64
+ // Pagination Methods
65
+ function getRecordCount($where='')
66
+ {
67
+ global $wpdb, $prli_link, $prli_utils;
68
+ $where .= $this->get_exclude_where_clause( $where );
69
+ $where = $prli_utils->prepend_and_or_where(' WHERE', $where);
70
+ $query = 'SELECT COUNT(*) FROM ' . $this->table_name() . ' cl'. $where;
71
+ return $wpdb->get_var($query);
72
+ }
73
+
74
+ function getPageCount($p_size, $where='')
75
+ {
76
+ return ceil((int)$this->getRecordCount($where) / (int)$p_size);
77
+ }
78
+
79
+ function getPage($current_p,$p_size, $where = '', $order = '')
80
+ {
81
+ global $wpdb, $prli_link, $prli_utils;
82
+ $click_table = $wpdb->prefix . "prli_clicks";
83
+ $end_index = $current_p * $p_size;
84
+ $start_index = $end_index - $p_size;
85
+ $where .= $this->get_exclude_where_clause( $where );
86
+ $where = $prli_utils->prepend_and_or_where(' AND', $where);
87
+ $query = 'SELECT cl.*, (SELECT count(*) FROM '. $this->table_name() .' cl2 WHERE cl2.ip = cl.ip) as ip_count, (SELECT count(*) FROM '. $this->table_name() .' cl3 WHERE cl3.vuid = cl.vuid) as vuid_count, li.name as link_name FROM ' . $this->table_name() . ' cl, ' . $prli_link->table_name() . ' li WHERE li.id = cl.link_id' . $where . $order . ' LIMIT ' . $start_index . ',' . $p_size . ';';
88
+ $results = $wpdb->get_results($query);
89
+ return $results;
90
+ }
91
+
92
+ function generateUniqueVisitorId($num_chars = 6)
93
+ {
94
+ global $wpdb, $prli_utils;
95
+
96
+ // We're doing a base 36 hash which is why we're always doing everything by 36
97
+ $max_vuid_value = pow(36,$num_chars);
98
+ $min_vuid_value = 37;
99
+ $vuid = base_convert( mt_rand($min_vuid_value,$max_vuid_value), 10, 36 );
100
+
101
+ $query = "SELECT DISTINCT vuid FROM ".$this->table_name();
102
+ $vuids = $wpdb->get_col($query,0);
103
+
104
+ // It is highly unlikely that we'll ever see 2 identical random vuids
105
+ // but just in case, here's some code to prevent collisions
106
+ while( in_array($vuid,$vuids) )
107
+ $vuid = base_convert( mt_rand($min_vuid_value,$max_vuid_value), 10, 36 );
108
+
109
+ return $vuid;
110
+ }
111
+
112
+ function get_counts_by_days($start_timestamp, $end_timestamp, $link_id = "all", $type = "all", $group = '')
113
+ {
114
+ global $wpdb, $prli_link;
115
+
116
+ $query = "SELECT DATE(cl.created_at) as cldate,COUNT(*) as clcount FROM ".$this->table_name()." cl WHERE cl.created_at BETWEEN '".date("Y-n-j",$start_timestamp)." 00:00:00' AND '".date("Y-n-j",$end_timestamp)." 23:59:59'".$search_where.$this->get_exclude_where_clause( ' AND' );
117
+
118
+ if($link_id != "all")
119
+ $query .= " AND link_id=$link_id";
120
+
121
+ if(!empty($group))
122
+ $query .= " AND link_id IN (SELECT id FROM " . $prli_link->table_name() . " WHERE group_id=$group)";
123
+
124
+ if($type == "unique")
125
+ $query .= " AND first_click=1";
126
+
127
+ $query .= ' GROUP BY DATE(cl.created_at)';
128
+
129
+ $clicks_array = $wpdb->get_results($query);
130
+
131
+ $temp_array = array();
132
+ $counts_array = array();
133
+ $dates_array = array();
134
+
135
+ // Refactor Array for use later on
136
+ foreach($clicks_array as $c)
137
+ $temp_array[$c->cldate] = $c->clcount;
138
+
139
+ // Get the dates array
140
+ for($c = $start_timestamp; $c <= $end_timestamp; $c += 60*60*24)
141
+ $dates_array[] = date("Y-m-d",$c);
142
+
143
+ // Make sure counts array is in order and includes zero click days
144
+ foreach($dates_array as $date_str)
145
+ {
146
+ if(isset($temp_array[$date_str]))
147
+ $counts_array[$date_str] = $temp_array[$date_str];
148
+ else
149
+ $counts_array[$date_str] = 0;
150
+ }
151
+
152
+ return $counts_array;
153
+ }
154
+
155
+
156
+ function setupClickLineGraph($start_timestamp,$end_timestamp, $link_id = "all", $type = "all", $group = '')
157
+ {
158
+ global $wpdb, $prli_utils, $prli_link, $prli_group;
159
+
160
+ $dates_array = $this->get_counts_by_days($start_timestamp,$end_timestamp,$link_id,$type,$group);
161
+
162
+ $top_click_count = $prli_utils->getTopValue(array_values($dates_array));
163
+
164
+ if(!empty($group))
165
+ $link_slug = "group: '" . $wpdb->get_var("SELECT name FROM ".$prli_group->table_name()." WHERE id=$group") . "'";
166
+ else if($link_id == "all")
167
+ $link_slug = "all links";
168
+ else
169
+ $link_slug = "'/".$wpdb->get_var("SELECT slug FROM ".$prli_link->table_name()." WHERE id=$link_id") . "'";
170
+
171
+ if($type == "all")
172
+ $type_string = "All hits";
173
+ else
174
+ $type_string = "Unique hits";
175
+
176
+ $json_array = array(
177
+ "elements" => array( array(
178
+ "type" => "line",
179
+ "values" => array_values($dates_array),
180
+ "dot-style" => array(
181
+ "type" => "dot",
182
+ "dot-size" => 4,
183
+ "colour" => "#ffc94e",
184
+ "halo-size" => 1,
185
+ "tip" => "#val# Hits<br>#x_label#"
186
+ ),
187
+ "width" => 2
188
+ ) ),
189
+ "title" => array(
190
+ "text" => 'Pretty Link: '.$type_string.' on '.$link_slug. ' between ' . date("Y-n-j",$start_timestamp) . ' and ' . date("Y-n-j",$end_timestamp),
191
+ "style" => "font-size: 16px; font-weight: bold; color: #3030d0; text-align: center; padding-bottom: 5px;"
192
+ ),
193
+ "bg_colour" => "-1",
194
+ "y_axis" => array(
195
+ "min" => 0,
196
+ "max" => $top_click_count,
197
+ "steps" => (int)(($top_click_count>=10)?$top_click_count/10:1),
198
+ "colour" => "#A2ACBA"
199
+ ),
200
+ "x_axis" => array(
201
+ "colour" => "#A2ACBA",
202
+ "grid-colour" => "#ffefa7",
203
+ "offset" => false,
204
+ "steps" => 4,
205
+ "labels" => array(
206
+ "steps" => 2,
207
+ "rotate" => 25,
208
+ "colour" => "#000000",
209
+ "labels" => array_keys($dates_array)
210
+ )
211
+ )
212
+ );
213
+
214
+ return $prli_utils->prli_json_encode($json_array);
215
+ }
216
+
217
+
218
+ // Set defaults and grab get or post of each possible param
219
+ function get_params_array()
220
+ {
221
+ $values = array(
222
+ 'paged' => (isset($_GET['paged'])?$_GET['paged']:(isset($_POST['paged'])?$_POST['paged']:1)),
223
+ 'l' => (isset($_GET['l'])?$_GET['l']:(isset($_POST['l'])?$_POST['l']:'all')),
224
+ 'group' => (isset($_GET['group'])?$_GET['group']:(isset($_POST['group'])?$_POST['group']:'')),
225
+ 'ip' => (isset($_GET['ip'])?$_GET['ip']:(isset($_POST['ip'])?$_POST['ip']:'')),
226
+ 'vuid' => (isset($_GET['vuid'])?$_GET['vuid']:(isset($_POST['vuid'])?$_POST['vuid']:'')),
227
+ 'sdate' => (isset($_GET['sdate'])?$_GET['sdate']:(isset($_POST['sdate'])?$_POST['sdate']:'')),
228
+ 'edate' => (isset($_GET['edate'])?$_GET['edate']:(isset($_POST['edate'])?$_POST['edate']:'')),
229
+ 'type' => (isset($_GET['type'])?$_GET['type']:(isset($_POST['type'])?$_POST['type']:'all')),
230
+ 'search' => (isset($_GET['search'])?$_GET['search']:(isset($_POST['search'])?$_POST['search']:'')),
231
+ 'sort' => (isset($_GET['sort'])?$_GET['sort']:(isset($_POST['sort'])?$_POST['sort']:'')),
232
+ 'sdir' => (isset($_GET['sdir'])?$_GET['sdir']:(isset($_POST['sdir'])?$_POST['sdir']:''))
233
+ );
234
+
235
+ return $values;
236
+ }
237
+
238
+ }
239
+ ?>
classes/models/PrliGroup.php ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class PrliGroup
3
+ {
4
+ function table_name()
5
+ {
6
+ global $wpdb;
7
+ return $wpdb->prefix . 'prli_groups';
8
+ }
9
+
10
+ function create( $values )
11
+ {
12
+ global $wpdb, $wp_rewrite;
13
+
14
+ $query = 'INSERT INTO ' . $this->table_name() .
15
+ ' (name,description,created_at) VALUES (\'' .
16
+ $values['name'] . '\',\'' .
17
+ $values['description'] . '\',' .
18
+ 'NOW())';
19
+ $query_results = $wpdb->query($query);
20
+ return $wpdb->insert_id;
21
+ }
22
+
23
+ function update( $id, $values )
24
+ {
25
+ global $wpdb, $wp_rewrite;
26
+
27
+ $query = 'UPDATE ' . $this->table_name() .
28
+ ' SET name=\'' . $values['name'] . '\', ' .
29
+ ' description=\'' . $values['description'] . '\' ' .
30
+ ' WHERE id='.$id;
31
+ $query_results = $wpdb->query($query);
32
+ return $query_results;
33
+ }
34
+
35
+ function destroy( $id )
36
+ {
37
+ require_once(PRLI_MODELS_PATH.'/models.inc.php');
38
+ global $wpdb, $prli_link, $wp_rewrite;
39
+
40
+ // Disconnect the links from this group
41
+ $query = 'UPDATE ' . $prli_link->table_name() .
42
+ ' SET group_id = NULL ' .
43
+ ' WHERE group_id='.$id;
44
+ $query_results = $wpdb->query($query);
45
+
46
+ $destroy = 'DELETE FROM ' . $this->table_name() . ' WHERE id=' . $id;
47
+ return $wpdb->query($destroy);
48
+ }
49
+
50
+ function getOne( $id )
51
+ {
52
+ global $wpdb, $prli_link, $prli_click;
53
+ $query = 'SELECT gr.*, (SELECT COUNT(*) FROM ' . $prli_link->table_name() . ' li WHERE li.group_id = gr.id) as link_count, (SELECT COUNT(*) FROM ' . $prli_click->table_name() . ' cl WHERE link_id IN (SELECT li2.id FROM ' . $prli_link->table_name() . ' li2 WHERE li2.group_id=gr.id)) as click_count FROM ' . $this->table_name() . ' gr WHERE id=' . $id . ';';
54
+ return $wpdb->get_row($query);
55
+ }
56
+
57
+ function getAll( $where = '', $order_by = '', $return_type = OBJECT )
58
+ {
59
+ global $wpdb, $prli_utils, $prli_link, $prli_click;
60
+ $query = 'SELECT gr.*, (SELECT COUNT(*) FROM ' . $prli_link->table_name() . ' li WHERE li.group_id = gr.id) as link_count, (SELECT COUNT(*) FROM ' . $prli_click->table_name() . ' cl WHERE link_id IN (SELECT li2.id FROM ' . $prli_link->table_name() . ' li2 WHERE li2.group_id=gr.id)) as click_count FROM ' . $this->table_name() . ' gr' . $prli_utils->prepend_and_or_where(' WHERE', $where) . $order_by;
61
+ return $wpdb->get_results($query, $return_type);
62
+ }
63
+
64
+ // Pagination Methods
65
+ function getRecordCount($where="")
66
+ {
67
+ global $wpdb, $prli_utils;
68
+ $query = 'SELECT COUNT(*) FROM ' . $this->table_name() . $prli_utils->prepend_and_or_where(' WHERE', $where);
69
+ return $wpdb->get_var($query);
70
+ }
71
+
72
+ function getPageCount($p_size, $where="")
73
+ {
74
+ return ceil((int)$this->getRecordCount($where) / (int)$p_size);
75
+ }
76
+
77
+ function getPage($current_p,$p_size, $where = "", $order_by = '')
78
+ {
79
+ global $wpdb, $prli_link, $prli_utils, $prli_click;
80
+ $end_index = $current_p * $p_size;
81
+ $start_index = $end_index - $p_size;
82
+ $query = 'SELECT gr.*, (SELECT COUNT(*) FROM ' . $prli_link->table_name() . ' li WHERE li.group_id = gr.id) as link_count, (SELECT COUNT(*) FROM ' . $prli_click->table_name() . ' cl WHERE link_id IN (SELECT li2.id FROM ' . $prli_link->table_name() . ' li2 WHERE li2.group_id=gr.id)) as click_count FROM ' . $this->table_name() . ' gr' . $prli_utils->prepend_and_or_where(' WHERE', $where) . $order_by .' LIMIT ' . $start_index . ',' . $p_size;
83
+ $results = $wpdb->get_results($query);
84
+ return $results;
85
+ }
86
+
87
+ // Set defaults and grab get or post of each possible param
88
+ function get_params_array()
89
+ {
90
+ $values = array(
91
+ 'action' => (isset($_GET['action'])?$_GET['action']:(isset($_POST['action'])?$_POST['action']:'list')),
92
+ 'id' => (isset($_GET['id'])?$_GET['id']:(isset($_POST['id'])?$_POST['id']:'')),
93
+ 'paged' => (isset($_GET['paged'])?$_GET['paged']:(isset($_POST['paged'])?$_POST['paged']:1)),
94
+ 'group' => (isset($_GET['group'])?$_GET['group']:(isset($_POST['group'])?$_POST['group']:'')),
95
+ 'search' => (isset($_GET['search'])?$_GET['search']:(isset($_POST['search'])?$_POST['search']:'')),
96
+ 'sort' => (isset($_GET['sort'])?$_GET['sort']:(isset($_POST['sort'])?$_POST['sort']:'')),
97
+ 'sdir' => (isset($_GET['sdir'])?$_GET['sdir']:(isset($_POST['sdir'])?$_POST['sdir']:''))
98
+ );
99
+
100
+ return $values;
101
+ }
102
+
103
+ function validate( $values )
104
+ {
105
+ global $wpdb, $prli_utils;
106
+
107
+ $errors = array();
108
+ if( empty($values['name']) )
109
+ $errors[] = "Group must have a name.";
110
+
111
+ return $errors;
112
+ }
113
+ }
114
+ ?>
classes/models/PrliLink.php ADDED
@@ -0,0 +1,324 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class PrliLink
3
+ {
4
+ function table_name()
5
+ {
6
+ global $wpdb;
7
+ return $wpdb->prefix . 'prli_links';
8
+ }
9
+
10
+ function create( $values )
11
+ {
12
+ global $wpdb;
13
+
14
+ $values['name'] = (!empty($values['name'])?$values['name']:$values['slug']);
15
+ $query_str = "INSERT INTO {$this->table_name()} " .
16
+ '(url,'.
17
+ 'slug,'.
18
+ 'name,'.
19
+ 'param_forwarding,'.
20
+ 'param_struct,'.
21
+ 'redirect_type,'.
22
+ 'description,'.
23
+ 'gorder,'.
24
+ 'track_me,'.
25
+ 'nofollow,'.
26
+ 'use_prettybar,'.
27
+ 'use_ultra_cloak,'.
28
+ 'track_as_img,'.
29
+ 'group_id,'.
30
+ 'created_at) ' .
31
+ 'VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%d,%d,%d,%d,%d,%d,NOW())';
32
+
33
+ $query = $wpdb->prepare( $query_str,
34
+ $values['url'],
35
+ $values['slug'],
36
+ $values['name'],
37
+ $values['param_forwarding'],
38
+ $values['param_struct'],
39
+ $values['redirect_type'],
40
+ $values['description'],
41
+ $values['gorder'],
42
+ (int)isset($values['track_me']),
43
+ (int)isset($values['nofollow']),
44
+ (int)isset($values['use_prettybar']),
45
+ (int)isset($values['use_ultra_cloak']),
46
+ (int)isset($values['track_as_img']),
47
+ (isset($values['group_id'])?(int)$values['group_id']:'NULL') );
48
+ $query_results = $wpdb->query($query);
49
+
50
+ if($query_results)
51
+ return $wpdb->insert_id;
52
+ else
53
+ return false;
54
+ }
55
+
56
+ function update( $id, $values )
57
+ {
58
+ global $wpdb;
59
+
60
+ $values['name'] = (!empty($values['name'])?$values['name']:$values['slug']);
61
+ $query_str = "UPDATE {$this->table_name()} " .
62
+ 'SET url=%s, ' .
63
+ 'slug=%s, ' .
64
+ 'name=%s, ' .
65
+ 'param_forwarding=%s, ' .
66
+ 'param_struct=%s, ' .
67
+ 'redirect_type=%s, ' .
68
+ 'description=%s, ' .
69
+ 'gorder=%s, ' .
70
+ 'track_me=%d, ' .
71
+ 'nofollow=%d, ' .
72
+ 'use_prettybar=%d, ' .
73
+ 'use_ultra_cloak=%d, ' .
74
+ 'track_as_img=%d, ' .
75
+ 'group_id=%d ' .
76
+ ' WHERE id=%d';
77
+
78
+ $query = $wpdb->prepare( $query_str,
79
+ $values['url'],
80
+ $values['slug'],
81
+ $values['name'],
82
+ $values['param_forwarding'],
83
+ $values['param_struct'],
84
+ $values['redirect_type'],
85
+ $values['description'],
86
+ $values['gorder'],
87
+ (int)isset($values['track_me']),
88
+ (int)isset($values['nofollow']),
89
+ (int)isset($values['use_prettybar']),
90
+ (int)isset($values['use_ultra_cloak']),
91
+ (int)isset($values['track_as_img']),
92
+ (isset($values['group_id'])?(int)$values['group_id']:'NULL'),
93
+ $id );
94
+
95
+ $query_results = $wpdb->query($query);
96
+ return $query_results;
97
+ }
98
+
99
+ function update_group( $id, $value, $group_id )
100
+ {
101
+ global $wpdb;
102
+ $query = 'UPDATE ' . $this->table_name() .
103
+ ' SET group_id=' . (isset($value)?$group_id:'NULL') .
104
+ ' WHERE id='.$id;
105
+ $query_results = $wpdb->query($query);
106
+ return $query_results;
107
+ }
108
+
109
+ function destroy( $id )
110
+ {
111
+ require_once(PRLI_MODELS_PATH.'/models.inc.php');
112
+ global $wpdb, $prli_click;
113
+
114
+ $reset = 'DELETE FROM ' . $prli_click->table_name() . ' WHERE link_id=' . $id;
115
+ $destroy = 'DELETE FROM ' . $this->table_name() . ' WHERE id=' . $id;
116
+
117
+ $wpdb->query($reset);
118
+ return $wpdb->query($destroy);
119
+ }
120
+
121
+ function reset( $id )
122
+ {
123
+ require_once(PRLI_MODELS_PATH.'/models.inc.php');
124
+ global $wpdb, $prli_click;
125
+
126
+ $reset = 'DELETE FROM ' . $prli_click->table_name() . ' WHERE link_id=' . $id;
127
+ return $wpdb->query($reset);
128
+ }
129
+
130
+ function getOneFromSlug( $slug, $return_type = OBJECT )
131
+ {
132
+ global $wpdb, $prli_click;
133
+ $query = 'SELECT li.*, ' .
134
+ '(SELECT COUNT(*) FROM ' . $prli_click->table_name() . ' cl ' .
135
+ 'WHERE cl.link_id = li.id' . $prli_click->get_exclude_where_clause( ' AND' ) . ') as clicks, ' .
136
+ '(SELECT COUNT(*) FROM ' . $prli_click->table_name() . ' cl ' .
137
+ 'WHERE cl.link_id = li.id ' .
138
+ 'AND cl.first_click <> 0' . $prli_click->get_exclude_where_clause( ' AND' ) . ') as uniques ' .
139
+ 'FROM ' . $this->table_name() . ' li ' .
140
+ 'WHERE slug=\'' . $slug . '\'';
141
+ return $wpdb->get_row($query, $return_type);
142
+ }
143
+
144
+ function getOne( $id )
145
+ {
146
+ global $wpdb, $prli_click;
147
+ $query = 'SELECT li.*, ' .
148
+ '(SELECT COUNT(*) FROM ' . $prli_click->table_name() . ' cl ' .
149
+ 'WHERE cl.link_id = li.id' . $prli_click->get_exclude_where_clause( ' AND' ) . ') as clicks, ' .
150
+ '(SELECT COUNT(*) FROM ' . $prli_click->table_name() . ' cl ' .
151
+ 'WHERE cl.link_id = li.id ' .
152
+ 'AND cl.first_click <> 0' . $prli_click->get_exclude_where_clause( ' AND' ) . ') as uniques ' .
153
+ 'FROM ' . $this->table_name() . ' li ' .
154
+ 'WHERE id=' . $id;
155
+ return $wpdb->get_row($query);
156
+ }
157
+
158
+ function get_link_min( $id, $return_type = OBJECT )
159
+ {
160
+ global $wpdb;
161
+ $query_str = 'SELECT id,'.
162
+ 'url,'.
163
+ 'slug,'.
164
+ 'name,'.
165
+ 'description,'.
166
+ 'group_id,'.
167
+ 'redirect_type,'.
168
+ 'track_me,'.
169
+ 'use_prettybar,'.
170
+ 'use_ultra_cloak,'.
171
+ 'param_forwarding,'.
172
+ 'param_struct,'.
173
+ 'track_as_img '.
174
+ "FROM {$this->table_name()} ".
175
+ 'WHERE id=%d';
176
+ $query = $wpdb->prepare($query_str, $id);
177
+ return $wpdb->get_row($query, $return_type);
178
+ }
179
+
180
+ function getAll($where = '', $order_by = '', $return_type = OBJECT)
181
+ {
182
+ global $wpdb, $prli_click, $prli_group, $prli_utils;
183
+ $query = 'SELECT li.*, ' .
184
+ '(SELECT COUNT(*) FROM ' . $prli_click->table_name() . ' cl ' .
185
+ 'WHERE cl.link_id = li.id' . $prli_click->get_exclude_where_clause( ' AND' ) . ') as clicks, ' .
186
+ '(SELECT COUNT(*) FROM ' . $prli_click->table_name() . ' cl ' .
187
+ 'WHERE cl.link_id = li.id ' .
188
+ 'AND cl.first_click <> 0' . $prli_click->get_exclude_where_clause( ' AND' ) . ') as uniques, ' .
189
+ 'gr.name as group_name ' .
190
+ 'FROM '. $this->table_name() . ' li ' .
191
+ 'LEFT OUTER JOIN ' . $prli_group->table_name() . ' gr ON li.group_id=gr.id' .
192
+ $prli_utils->prepend_and_or_where(' WHERE', $where) . $order_by;
193
+ return $wpdb->get_results($query, $return_type);
194
+ }
195
+
196
+ // Pagination Methods
197
+ function getRecordCount($where="")
198
+ {
199
+ global $wpdb, $prli_utils;
200
+ $query = 'SELECT COUNT(*) FROM ' . $this->table_name() . ' li' . $prli_utils->prepend_and_or_where(' WHERE', $where);
201
+ return $wpdb->get_var($query);
202
+ }
203
+
204
+ function getPageCount($p_size, $where="")
205
+ {
206
+ return ceil((int)$this->getRecordCount($where) / (int)$p_size);
207
+ }
208
+
209
+ function getPage($current_p,$p_size, $where = "", $order_by = '', $return_type = OBJECT)
210
+ {
211
+ global $wpdb, $prli_click, $prli_utils, $prli_group;
212
+ $end_index = $current_p * $p_size;
213
+ $start_index = $end_index - $p_size;
214
+ $query = 'SELECT li.*, ' .
215
+ '(SELECT COUNT(*) FROM ' . $prli_click->table_name() . ' cl ' .
216
+ 'WHERE cl.link_id = li.id' . $prli_click->get_exclude_where_clause( ' AND' ) . ') as clicks, ' .
217
+ '(SELECT COUNT(*) FROM ' . $prli_click->table_name() . ' cl ' .
218
+ 'WHERE cl.link_id = li.id ' .
219
+ 'AND cl.first_click <> 0' . $prli_click->get_exclude_where_clause( ' AND' ) . ') as uniques, ' .
220
+ 'gr.name as group_name ' .
221
+ 'FROM ' . $this->table_name() . ' li ' .
222
+ 'LEFT OUTER JOIN ' . $prli_group->table_name() . ' gr ON li.group_id=gr.id' .
223
+ $prli_utils->prepend_and_or_where(' WHERE', $where) . $order_by . ' ' .
224
+ 'LIMIT ' . $start_index . ',' . $p_size . ';';
225
+ $results = $wpdb->get_results($query, $return_type);
226
+ return $results;
227
+ }
228
+
229
+ /** I'm generating a slug that is by default 2-3 characters long.
230
+ * This gives us a possibility of 36^3 - 37 = 46,619 possible
231
+ * random slugs. That should be *more* than enough slugs for
232
+ * any website -- if I get any feedback that we need more then
233
+ * I can always make a config option to raise the # of chars.
234
+ */
235
+ function generateValidSlug($num_chars = 3)
236
+ {
237
+ global $wpdb, $prli_utils;
238
+
239
+ // We're doing a base 36 hash which is why we're always doing everything by 36
240
+ $max_slug_value = pow(36,$num_chars);
241
+ $min_slug_value = 37; // we want to have at least 2 characters in the slug
242
+ $slug = base_convert( rand($min_slug_value,$max_slug_value), 10, 36 );
243
+
244
+ $query = "SELECT slug FROM " . $this->table_name(); // . " WHERE slug='" . $slug . "'";
245
+ $slugs = $wpdb->get_col($query,0);
246
+
247
+ // It is highly unlikely that we'll ever see 2 identical random slugs
248
+ // but just in case, here's some code to prevent collisions
249
+ while( in_array($slug,$slugs) or !$prli_utils->slugIsAvailable($slug) )
250
+ $slug = base_convert( rand($min_slug_value,$max_slug_value), 10, 36 );
251
+
252
+ return $slug;
253
+ }
254
+
255
+ function get_pretty_link_url($slug)
256
+ {
257
+ global $prli_blogurl;
258
+
259
+ $link = $this->getOneFromSlug($slug);
260
+
261
+ if((isset($link->param_forwarding) and $link->param_forwarding == 'custom') and
262
+ (isset($link->track_as_img) and $link->track_as_img == 1))
263
+ return "&lt;img src=\"".$prli_blogurl . '/' . $link->slug . $link->param_struct . "\" width=\"1\" height=\"1\" style=\"display: none\" /&gt;";
264
+ else if((!isset($link->param_forwarding) or $link->param_forwarding != 'custom') and
265
+ (isset($link->track_as_img) and $link->track_as_img == 1))
266
+ return "&lt;img src=\"".$prli_blogurl . '/' . $link->slug . "\" width=\"1\" height=\"1\" style=\"display: none\" /&gt;";
267
+ else if((isset($link->param_forwarding) and $link->param_forwarding == 'custom') and
268
+ (!isset($link->track_as_img) or $link->track_as_img == 0))
269
+ return $prli_blogurl . '/' . $link->slug . $link->param_struct;
270
+ else
271
+ return $prli_blogurl . '/' . $link->slug;
272
+ }
273
+
274
+ // Set defaults and grab get or post of each possible param
275
+ function get_params_array()
276
+ {
277
+ $values = array(
278
+ 'action' => (isset($_GET['action'])?$_GET['action']:(isset($_POST['action'])?$_POST['action']:'list')),
279
+ 'regenerate' => (isset($_GET['regenerate'])?$_GET['regenerate']:(isset($_POST['regenerate'])?$_POST['regenerate']:'false')),
280
+ 'id' => (isset($_GET['id'])?$_GET['id']:(isset($_POST['id'])?$_POST['id']:'')),
281
+ 'group_name' => (isset($_GET['group_name'])?$_GET['group_name']:(isset($_POST['group_name'])?$_POST['group_name']:'')),
282
+ 'paged' => (isset($_GET['paged'])?$_GET['paged']:(isset($_POST['paged'])?$_POST['paged']:1)),
283
+ 'group' => (isset($_GET['group'])?$_GET['group']:(isset($_POST['group'])?$_POST['group']:'')),
284
+ 'search' => (isset($_GET['search'])?$_GET['search']:(isset($_POST['search'])?$_POST['search']:'')),
285
+ 'sort' => (isset($_GET['sort'])?$_GET['sort']:(isset($_POST['sort'])?$_POST['sort']:'')),
286
+ 'sdir' => (isset($_GET['sdir'])?$_GET['sdir']:(isset($_POST['sdir'])?$_POST['sdir']:''))
287
+ );
288
+
289
+ return $values;
290
+ }
291
+
292
+ function validate( $values )
293
+ {
294
+ global $wpdb, $prli_utils, $prli_blogurl;
295
+
296
+ $errors = array();
297
+ if( ( $values['url'] == null or $values['url'] == '') and $values['track_as_img'] != 'on' )
298
+ $errors[] = "Target URL can't be blank -- unless this Pretty Link is being used as a tracking pixel (see Advanced Options on this page)";
299
+
300
+ if( $values['slug'] == null or $values['slug'] == '' )
301
+ $errors[] = "Pretty Link can't be blank";
302
+
303
+ if( $values['url'] == "$prli_blogurl/".$values['slug'] )
304
+ $errors[] = "Target URL must be different than the Pretty Link";
305
+
306
+ if( !empty($values['url']) and !preg_match('/^http.?:\/\/.*\..*$/', $values['url'] ) )
307
+ $errors[] = "Link URL must be a correctly formatted url";
308
+
309
+ if( !preg_match('/^[a-zA-Z0-9\.\-_\/]+$/', $values['slug'] ) )
310
+ $errors[] = "Pretty Link must not contain spaces or special characters";
311
+
312
+ if( !$prli_utils->slugIsAvailable($values['slug'],$values['id']) )
313
+ $errors[] = "This pretty link slug is already taken, please choose a different one";
314
+
315
+ if( isset($values['param_forwarding']) and $values['param_forwarding'] == 'custom' and empty($values['param_struct']) )
316
+ $errors[] = "If Custom Parameter Forwarding has been selected then you must specify a forwarding format.";
317
+
318
+ if( isset($values['param_forwarding']) and $values['param_forwarding'] == 'custom' and !preg_match('#%.*?%#', $values['param_struct']) )
319
+ $errors[] = "Your parameter forwarding must have at least one parameter specified in the format ex: <code>/%var1%/%var_two%/%varname3% ...</code>";
320
+
321
+ return $errors;
322
+ }
323
+ }
324
+ ?>
classes/models/PrliUtils.php ADDED
@@ -0,0 +1,628 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once('models.inc.php');
3
+
4
+ class PrliUtils
5
+ {
6
+
7
+ /** Okay I realize that Percentagize isn't really a word but
8
+ * this is so that the values we have will work with google
9
+ * charts.
10
+ */
11
+ function percentagizeArray($data,$max_value)
12
+ {
13
+ $new_data = array();
14
+ foreach($data as $point)
15
+ {
16
+ if( $max_value > 0 )
17
+ {
18
+ $new_data[] = $point / $max_value * 100;
19
+ }
20
+ else
21
+ {
22
+ $new_data[] = 0;
23
+ }
24
+ }
25
+ return $new_data;
26
+ }
27
+
28
+ function getTopValue($values_array)
29
+ {
30
+ rsort($values_array);
31
+ return $values_array[0];
32
+ }
33
+
34
+ function getFirstClickDate()
35
+ {
36
+ global $wpdb;
37
+
38
+ $clicks_table = $wpdb->prefix . "prli_clicks";
39
+ $query = "SELECT created_at FROM $clicks_table ORDER BY created_at LIMIT 1";
40
+ $first_click = $wpdb->get_var($query);
41
+
42
+ if(isset($first_click))
43
+ {
44
+ return strtotime($first_click);
45
+ }
46
+ else
47
+ return null;
48
+ }
49
+
50
+ function getMonthsArray()
51
+ {
52
+ global $wpdb;
53
+ global $prli_click;
54
+
55
+ $months = array();
56
+ $year = date("Y");
57
+ $month = date("m");
58
+ $current_timestamp = time();
59
+ $current_month_timestamp = mktime(0, 0, 0, date("m", $current_timestamp), 1, date("Y", $current_timestamp));
60
+
61
+ $clicks_table = $prli_click->tableName();
62
+ $first_click = $wpdb->get_var("SELECT created_at FROM $clicks_table ORDER BY created_at LIMIT 1;");
63
+ $first_timestamp = ((empty($first_click))?$current_timestamp:strtotime($first_click));
64
+ $first_date = mktime(0, 0, 0, date("m", $first_timestamp), 1, date("Y", $first_timestamp));
65
+
66
+ while($current_month_timestamp >= $first_date)
67
+ {
68
+ $months[] = $current_month_timestamp;
69
+ if(date("m") == 1)
70
+ {
71
+ $current_month_timestamp = mktime(0, 0, 0, 12, 1, date("Y", $current_month_timestamp)-1);
72
+ }
73
+ else
74
+ {
75
+ $current_month_timestamp = mktime(0, 0, 0, date("m", $current_month_timestamp)-1, 1, date("Y", $current_month_timestamp));
76
+ }
77
+ }
78
+ return $months;
79
+ }
80
+
81
+ // For Pagination
82
+ function getLastRecordNum($r_count,$current_p,$p_size)
83
+ {
84
+ return (($r_count < ($current_p * $p_size))?$r_count:($current_p * $p_size));
85
+ }
86
+
87
+ // For Pagination
88
+ function getFirstRecordNum($r_count,$current_p,$p_size)
89
+ {
90
+ if($current_p == 1)
91
+ {
92
+ return 1;
93
+ }
94
+ else
95
+ {
96
+ return ($this->getLastRecordNum($r_count,($current_p - 1),$p_size) + 1);
97
+ }
98
+ }
99
+
100
+ function slugIsAvailable( $full_slug, $id = '' )
101
+ {
102
+ global $wpdb, $prli_blogurl, $prli_link;
103
+
104
+ // We don't care about anything after the slash for now because we don't want
105
+ // to have to worry about comparing against every imaginable combination in WordPress
106
+ $slug_components = explode('/',$full_slug);
107
+ $slug = $slug_components[0];
108
+
109
+ // Check slug uniqueness against posts, pages and categories
110
+ $posts_table = $wpdb->prefix . "posts";
111
+ $terms_table = $wpdb->prefix . "terms";
112
+
113
+ $post_slug = $wpdb->get_var("SELECT post_name FROM $posts_table WHERE post_name='$slug'");
114
+ $term_slug = $wpdb->get_col("SELECT slug FROM $terms_table WHERE slug='$slug'");
115
+
116
+ if( $post_slug == $slug or $term_slug == $slug )
117
+ return false;
118
+
119
+ // Check slug against files on the root wordpress install
120
+ $root_dir = opendir(ABSPATH);
121
+
122
+ while (($file = readdir($root_dir)) !== false) {
123
+ $haystack = strtolower($file);
124
+ if($haystack == $slug)
125
+ return false;
126
+ }
127
+
128
+ // Check slug against other slugs in the prli links database.
129
+ // We'll use the full_slug here because its easier to guarantee uniqueness.
130
+ if($id != null and $id != '')
131
+ $query = "SELECT slug FROM " . $prli_link->table_name() . " WHERE slug='" . $full_slug . "' AND id <> " . $id;
132
+ else
133
+ $query = "SELECT slug FROM " . $prli_link->table_name() . " WHERE slug='" . $full_slug . "'";
134
+
135
+ $link_slug = $wpdb->get_var($query);
136
+
137
+ if( $link_slug == $full_slug )
138
+ return false;
139
+
140
+ // TODO: Check permalink structure to avoid the ability of creating a year or something as a slug
141
+
142
+ return true;
143
+ }
144
+
145
+ /* Needed because we don't know if the target uesr will have a browsercap file installed
146
+ on their server ... particularly in a shared hosting environment this is difficult
147
+ */
148
+ function php_get_browser($agent = NULL)
149
+ {
150
+ $agent=$agent?$agent:$_SERVER['HTTP_USER_AGENT'];
151
+ $yu=array();
152
+ $q_s=array("#\.#","#\*#","#\?#");
153
+ $q_r=array("\.",".*",".?");
154
+ $brows=parse_ini_file(PRLI_PATH."/includes/php/php_browsecap.ini",true);
155
+ foreach($brows as $k=>$t)
156
+ {
157
+ if(fnmatch($k,$agent))
158
+ {
159
+ $yu['browser_name_pattern']=$k;
160
+ $pat=preg_replace($q_s,$q_r,$k);
161
+ $yu['browser_name_regex']=strtolower("^$pat$");
162
+ foreach($brows as $g=>$r)
163
+ {
164
+ if($t['Parent']==$g)
165
+ {
166
+ foreach($brows as $a=>$b)
167
+ {
168
+ if($r['Parent']==$a)
169
+ {
170
+ $yu=array_merge($yu,$b,$r,$t);
171
+ foreach($yu as $d=>$z)
172
+ {
173
+ $l=strtolower($d);
174
+ $hu[$l]=$z;
175
+ }
176
+ }
177
+ }
178
+ }
179
+ }
180
+
181
+ break;
182
+ }
183
+ }
184
+
185
+ return $hu;
186
+ }
187
+
188
+ // This is where the magic happens!
189
+ function track_link($slug,$values)
190
+ {
191
+ global $wpdb, $prli_click, $prli_link;
192
+
193
+ $query = "SELECT * FROM ".$prli_link->table_name()." WHERE slug='$slug' LIMIT 1";
194
+ $pretty_link = $wpdb->get_row($query);
195
+
196
+ if(isset($pretty_link->track_me) and $pretty_link->track_me)
197
+ {
198
+ $first_click = false;
199
+
200
+ $click_ip = $_SERVER['REMOTE_ADDR'];
201
+ $click_referer = $_SERVER['HTTP_REFERER'];
202
+ $click_host = gethostbyaddr($click_ip);
203
+
204
+ $click_uri = $_SERVER['REQUEST_URI'];
205
+ $click_user_agent = $_SERVER['HTTP_USER_AGENT'];
206
+ $click_browser = $this->php_get_browser();
207
+
208
+ //Set Cookie if it doesn't exist
209
+ $cookie_name = 'prli_click_' . $pretty_link->id;
210
+ //Used for unique click tracking
211
+ $cookie_expire_time = time()+60*60*24*30; // Expire in 30 days
212
+
213
+ $visitor_cookie = 'prli_visitor';
214
+ //Used for visitor activity
215
+ $visitor_cookie_expire_time = time()+60*60*24*365; // Expire in 1 year
216
+
217
+
218
+ if($_COOKIE[$cookie_name] == null)
219
+ {
220
+ setcookie($cookie_name,$slug,$cookie_expire_time);
221
+ $first_click = true;
222
+ }
223
+
224
+ // Retrieve / Generate visitor id
225
+ if($_COOKIE[$visitor_cookie] == null)
226
+ {
227
+ $visitor_uid = $prli_click->generateUniqueVisitorId();
228
+ setcookie($visitor_cookie,$visitor_uid,$visitor_cookie_expire_time);
229
+ }
230
+ else
231
+ $visitor_uid = $_COOKIE[$visitor_cookie];
232
+
233
+ //Record Click in DB
234
+ $insert = "INSERT INTO ".$prli_click->table_name()." (link_id,vuid,ip,browser,btype,bversion,os,referer,uri,host,first_click,created_at) VALUES ($pretty_link->id,'$visitor_uid','$click_ip','$click_user_agent','".$click_browser['browser']."','".$click_browser['version']."','".$click_browser['platform']."','$click_referer','$click_uri','$click_host','$first_click',NOW())";
235
+
236
+ $results = $wpdb->query( $insert );
237
+
238
+ }
239
+
240
+ // Reformat Parameters
241
+ $param_string = '';
242
+
243
+ if(isset($pretty_link->param_forwarding) and $pretty_link->param_forwarding and isset($values) and count($values) >= 1)
244
+ {
245
+ $first_param = true;
246
+ foreach($values as $key => $value)
247
+ {
248
+ if($first_param)
249
+ {
250
+ $param_string = (preg_match("#\?#", $pretty_link->url)?"&":"?");
251
+ $first_param = false;
252
+ }
253
+ else
254
+ $param_string .= "&";
255
+
256
+ $param_string .= "$key=$value";
257
+ }
258
+ }
259
+
260
+ //Redirect to Product URL
261
+ if(!isset($pretty_link->track_as_img) or $pretty_link->track_as_img == 0)
262
+ {
263
+ if(isset($pretty_link->nofollow) and $pretty_link->nofollow)
264
+ header('X-Robots-Tag: noindex, nofollow');
265
+
266
+ // If we're using the pretty bar then don't redirect -- load the pretty bar view
267
+ if( isset($pretty_link->use_prettybar) and $pretty_link->use_prettybar )
268
+ {
269
+ global $prli_blogurl;
270
+ require_once PRLI_VIEWS_PATH . '/prli-links/bar.php';
271
+ }
272
+ else if( isset($pretty_link->use_ultra_cloak) and $pretty_link->use_ultra_cloak )
273
+ require_once PRLI_VIEWS_PATH . '/prli-links/ultra-cloak.php';
274
+ else
275
+ {
276
+ if ((int)$pretty_link->redirect_type == 301)
277
+ header("HTTP/1.1 301 Moved Permanently");
278
+ elseif ((int)$pretty_link->redirect_type == 307)
279
+ {
280
+ if($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.0')
281
+ header("HTTP/1.1 302 Found");
282
+ else
283
+ header("HTTP/1.1 307 Temporary Redirect");
284
+ }
285
+
286
+ header('Location: '.$pretty_link->url.$param_string);
287
+ }
288
+ }
289
+ }
290
+
291
+ function get_custom_forwarding_rule($param_struct)
292
+ {
293
+ $param_struct = preg_replace('#%.*?%#','(.*?)',$param_struct);
294
+ return preg_replace('#\(\.\*\?\)$#','(.*)',$param_struct); // replace the last one with a greedy operator