44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/app/models/Item.php:
--------------------------------------------------------------------------------
1 | load();
11 | return $this->query;
12 | }
13 |
14 | public function loadpages($pageoffset,$pagelimit) {
15 | if($pageoffset<0 || $pageoffset>999999999) $pageoffset=0;
16 | $this->load(array('active>?',0),array('order'=>'datetime DESC','offset'=>$pageoffset,'limit'=>$pagelimit));
17 | return $this->query;
18 | }
19 |
20 | public function loadpagesByTok($pageoffset,$pagelimit,$ctok) {
21 | if($pageoffset<0 || $pageoffset>999999999) $pageoffset=0;
22 | $this->load(array('cid=?',$ctok),array('order'=>'datetime DESC','offset'=>$pageoffset,'limit'=>$pagelimit));
23 | return $this->query;
24 | }
25 |
26 |
27 | public function itemcount() {
28 | return $this->count();
29 |
30 | }
31 |
32 | public function itemcountByTok($tok) {
33 | return $this->count(array('tok=?',$tok));
34 |
35 | }
36 |
37 | public function catcountByTok($tok) {
38 | return $this->count(array('cid=?',$tok));
39 |
40 | }
41 |
42 | public function cat($id) {
43 | $this->load(array('cid=?',$id));
44 | return $this->query;
45 | }
46 |
47 |
48 | public function add() {
49 | $this->copyFrom('POST');
50 | $this->save();
51 |
52 | }
53 |
54 | public function getById($id) {
55 | $this->load(array('tok=?',$id));
56 | $this->copyTo('POST');
57 | }
58 |
59 | public function getIdByTok($tok) {
60 | $this->load(array('tok=?',$tok));
61 | $this->copyTo('ID');
62 | }
63 |
64 | public function edit($id) {
65 | $this->load(array('tok=?',$id));
66 | $this->copyFrom('POST');
67 | $this->update();
68 | }
69 |
70 | public function search($query,$searchlimit) {
71 | $this->load(array('title LIKE ? OR note LIKE ?',"%$query%","%$query%"),array('order'=>'datetime DESC','limit'=>$searchlimit));
72 | return $this->query;
73 | }
74 |
75 | public function deleteCat($cid) {
76 | $this->load(array('cid=?',$cid));
77 | $this->copyFrom('POST');
78 | $this->update();
79 | }
80 |
81 | public function delete($id) {
82 | $this->load(array('tok=?',$id));
83 | $this->erase();
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/app/views/item/update.htm:
--------------------------------------------------------------------------------
1 |
77 |
--------------------------------------------------------------------------------
/app/views/b3.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
{{ @title }}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
23 |
24 |
25 |
26 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | {{ @message }}
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
77 |
78 |
79 |
81 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/app/views/pagination.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | >1
10 |
11 |
12 | class="active">
{{ @i+1 }}
13 |
14 |
15 |
»
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/lib/db/jig.php:
--------------------------------------------------------------------------------
1 | dir.$file))
43 | return array();
44 | $raw=$fw->read($dst);
45 | switch ($this->format) {
46 | case self::FORMAT_JSON:
47 | $data=json_decode($raw,TRUE);
48 | break;
49 | case self::FORMAT_Serialized:
50 | $data=$fw->unserialize($raw);
51 | break;
52 | }
53 | return $data;
54 | }
55 |
56 | /**
57 | * Write data to file
58 | * @return int
59 | * @param $file string
60 | * @param $data array
61 | **/
62 | function write($file,array $data=NULL) {
63 | $fw=\Base::instance();
64 | switch ($this->format) {
65 | case self::FORMAT_JSON:
66 | $out=json_encode($data,@constant('JSON_PRETTY_PRINT'));
67 | break;
68 | case self::FORMAT_Serialized:
69 | $out=$fw->serialize($data);
70 | break;
71 | }
72 | $out=$fw->write($this->dir.$file,$out);
73 | return $out;
74 | }
75 |
76 | /**
77 | * Return SQL profiler results
78 | * @return string
79 | **/
80 | function log() {
81 | return $this->log;
82 | }
83 |
84 | /**
85 | * Jot down log entry
86 | * @return NULL
87 | * @param $frame string
88 | **/
89 | function jot($frame) {
90 | if ($frame)
91 | $this->log.=date('r').' '.$frame.PHP_EOL;
92 | }
93 |
94 | /**
95 | * Clean storage
96 | * @return NULL
97 | **/
98 | function drop() {
99 | if ($glob=@glob($this->dir.'/*',GLOB_NOSORT))
100 | foreach ($glob as $file)
101 | @unlink($file);
102 | }
103 |
104 | /**
105 | * Instantiate class
106 | * @param $dir string
107 | * @param $format int
108 | **/
109 | function __construct($dir,$format=self::FORMAT_JSON) {
110 | if (!is_dir($dir))
111 | mkdir($dir,\Base::MODE,TRUE);
112 | $this->dir=$dir;
113 | $this->format=$format;
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/lib/matrix.php:
--------------------------------------------------------------------------------
1 | $cols)
43 | foreach ($cols as $keyy=>$valy)
44 | $out[$keyy][$keyx]=$valy;
45 | $var=$out;
46 | }
47 |
48 | /**
49 | * Sort a multi-dimensional array variable on a specified column
50 | * @return bool
51 | * @param $var array
52 | * @param $col mixed
53 | * @param $order int
54 | **/
55 | function sort(array &$var,$col,$order=SORT_ASC) {
56 | uasort(
57 | $var,
58 | function($val1,$val2) use($col,$order) {
59 | list($v1,$v2)=array($val1[$col],$val2[$col]);
60 | $out=is_numeric($v1) && is_numeric($v2)?
61 | Base::instance()->sign($v1-$v2):strcmp($v1,$v2);
62 | if ($order==SORT_DESC)
63 | $out=-$out;
64 | return $out;
65 | }
66 | );
67 | $var=array_values($var);
68 | }
69 |
70 | /**
71 | * Change the key of a two-dimensional array element
72 | * @return NULL
73 | * @param $var array
74 | * @param $old string
75 | * @param $new string
76 | **/
77 | function changekey(array &$var,$old,$new) {
78 | $keys=array_keys($var);
79 | $vals=array_values($var);
80 | $keys[array_search($old,$keys)]=$new;
81 | $var=array_combine($keys,$vals);
82 | }
83 |
84 | /**
85 | * Return month calendar of specified date, with optional setting for
86 | * first day of week (0 for Sunday)
87 | * @return array
88 | * @param $date string
89 | * @param $first int
90 | **/
91 | function calendar($date='now',$first=0) {
92 | $parts=getdate(strtotime($date));
93 | $days=cal_days_in_month(CAL_GREGORIAN,$parts['mon'],$parts['year']);
94 | $ref=date('w',strtotime(date('Y-m',$parts[0]).'-01'))+(7-$first)%7;
95 | $out=array();
96 | for ($i=0;$i<$days;$i++)
97 | $out[floor(($ref+$i)/7)][($ref+$i)%7]=$i+1;
98 | return $out;
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/db/db.sql:
--------------------------------------------------------------------------------
1 |
2 |
3 | CREATE TABLE IF NOT EXISTS `cats` (
4 | `id` int(11) NOT NULL AUTO_INCREMENT,
5 | `tok` int(11) NOT NULL,
6 | `url` varchar(255) NOT NULL DEFAULT '',
7 | `name` varchar(255) NOT NULL DEFAULT '',
8 | `node` int(11) DEFAULT NULL,
9 | `dsc` text,
10 | `badge` int(5) DEFAULT NULL,
11 | `badgecolor` int(5) DEFAULT NULL,
12 | `active` tinyint(1) NOT NULL DEFAULT '1',
13 | PRIMARY KEY (`id`)
14 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
15 |
16 |
17 | CREATE TABLE IF NOT EXISTS `items` (
18 | `id` int(11) NOT NULL AUTO_INCREMENT,
19 | `tok` int(11) NOT NULL,
20 | `url` varchar(255) NOT NULL DEFAULT '',
21 | `title` varchar(255) NOT NULL DEFAULT '',
22 | `user` int(8) DEFAULT NULL,
23 | `note` text,
24 | `type` int(5) DEFAULT NULL,
25 | `cid` int(11) NOT NULL,
26 | `sticked` tinyint(1) DEFAULT NULL,
27 | `badge` varchar(255) NOT NULL DEFAULT '',
28 | `badgecolor` varchar(6) NOT NULL DEFAULT '',
29 | `screen` tinyint(1) DEFAULT NULL,
30 | `datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
31 | `active` tinyint(1) NOT NULL DEFAULT '1',
32 | PRIMARY KEY (`id`)
33 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
34 |
35 |
36 |
37 | CREATE TABLE IF NOT EXISTS `tag2item` (
38 | `id` int(11) NOT NULL AUTO_INCREMENT,
39 | `iid` int(11) NOT NULL,
40 | `tid` int(11) NOT NULL,
41 | PRIMARY KEY (`id`)
42 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
43 |
44 |
45 | CREATE TABLE IF NOT EXISTS `tags` (
46 | `id` int(11) NOT NULL AUTO_INCREMENT,
47 | `tok` int(11) NOT NULL,
48 | `url` varchar(255) NOT NULL DEFAULT '',
49 | `title` varchar(255) NOT NULL DEFAULT '',
50 | `label` varchar(255) NOT NULL DEFAULT '',
51 | `dsc` text,
52 | `node` int(11) DEFAULT NULL,
53 | `active` tinyint(1) NOT NULL DEFAULT '1',
54 | PRIMARY KEY (`id`)
55 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
56 |
57 |
58 |
59 | CREATE VIEW catgroup AS
60 | SELECT
61 | cats.name AS cat,
62 | cats.tok AS tok,
63 | cats.url AS url,
64 | count(*) AS itemcount
65 | FROM cats
66 | JOIN items ON
67 | items.cid=cats.tok
68 | GROUP BY
69 | cats.name
70 | ORDER BY itemcount DESC;
71 |
72 |
73 | CREATE VIEW taggroup AS
74 | SELECT
75 | tags.label AS tag,
76 | tags.tok AS tok,
77 | tags.url AS url,
78 | count(*) AS tagcount
79 | FROM tags
80 | JOIN tag2item ON
81 | tag2item.tid = tags.id
82 | GROUP BY
83 | tags.label
84 | ORDER BY tagcount DESC;
85 |
86 |
87 | CREATE VIEW itemstag AS
88 | SELECT
89 | items.title AS title,
90 | items.note AS note,
91 | items.tok AS tok,
92 | items.url AS url,
93 | tag2item.tid AS tagid,
94 | tags.tok AS tagtok,
95 | tags.label AS label
96 | FROM items
97 | JOIN tag2item ON
98 | items.id=tag2item.iid
99 | JOIN tags ON
100 | tags.id=tag2item.tid;
101 |
102 |
103 | CREATE VIEW taglist AS
104 | SELECT
105 | tags.label,
106 | tags.tok,
107 | tags.url,
108 | items.tok as itok,
109 | items.cid as ctok
110 | FROM tags
111 | JOIN tag2item ON
112 | tag2item.tid = tags.id
113 | JOIN items ON
114 | tag2item.iid = items.id
115 | ORDER BY items.tok;
116 |
117 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/lib/web/geo.php:
--------------------------------------------------------------------------------
1 | getLocation();
29 | $trn=$ref->getTransitions($now=time(),$now);
30 | $out=array(
31 | 'offset'=>$ref->
32 | getOffset(new \DateTime('now',new \DateTimeZone('GMT')))/3600,
33 | 'country'=>$loc['country_code'],
34 | 'latitude'=>$loc['latitude'],
35 | 'longitude'=>$loc['longitude'],
36 | 'dst'=>$trn[0]['isdst']
37 | );
38 | unset($ref);
39 | return $out;
40 | }
41 |
42 | /**
43 | * Return geolocation data based on specified/auto-detected IP address
44 | * @return array|FALSE
45 | * @param $ip string
46 | **/
47 | function location($ip=NULL) {
48 | $fw=\Base::instance();
49 | $web=\Web::instance();
50 | if (!$ip)
51 | $ip=$fw->get('IP');
52 | $public=filter_var($ip,FILTER_VALIDATE_IP,
53 | FILTER_FLAG_IPV4|FILTER_FLAG_IPV6|
54 | FILTER_FLAG_NO_RES_RANGE|FILTER_FLAG_NO_PRIV_RANGE);
55 | if (function_exists('geoip_db_avail') &&
56 | geoip_db_avail(GEOIP_CITY_EDITION_REV1) &&
57 | $out=@geoip_record_by_name($ip)) {
58 | $out['request']=$ip;
59 | $out['region_code']=$out['region'];
60 | $out['region_name']=geoip_region_name_by_code(
61 | $out['country_code'],$out['region']);
62 | unset($out['country_code3'],$out['region'],$out['postal_code']);
63 | return $out;
64 | }
65 | if (($req=$web->request('http://www.geoplugin.net/json.gp'.
66 | ($public?('?ip='.$ip):''))) &&
67 | $data=json_decode($req['body'],TRUE)) {
68 | $out=array();
69 | foreach ($data as $key=>$val)
70 | if (!strpos($key,'currency') && $key!=='geoplugin_status'
71 | && $key!=='geoplugin_region')
72 | $out[$fw->snakecase(substr($key, 10))]=$val;
73 | return $out;
74 | }
75 | return FALSE;
76 | }
77 |
78 | /**
79 | * Return weather data based on specified latitude/longitude
80 | * @return array|FALSE
81 | * @param $latitude float
82 | * @param $longitude float
83 | **/
84 | function weather($latitude,$longitude) {
85 | $fw=\Base::instance();
86 | $web=\Web::instance();
87 | $query=array(
88 | 'lat'=>$latitude,
89 | 'lng'=>$longitude,
90 | 'username'=>$fw->hash($fw->get('IP'))
91 | );
92 | return ($req=$web->request(
93 | 'http://ws.geonames.org/findNearByWeatherJSON?'.
94 | http_build_query($query))) &&
95 | ($data=json_decode($req['body'],TRUE)) &&
96 | isset($data['weatherObservation'])?
97 | $data['weatherObservation']:
98 | FALSE;
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/ui/js/main.js:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | /* Delete Item */
5 | $('.deleteitem').click(function(){
6 |
7 | var e = $(this).attr("id").split('itemtok_')
8 | var tok = e[1]
9 |
10 | var retval = confirm("Do you want to delete this item?");
11 | if( retval == true ){
12 | window.location = base+'/i/delete/'+tok
13 | return true;
14 | }else return false;
15 |
16 |
17 | });
18 |
19 |
20 | /* Delete Tag */
21 | $('.deletetag').click(function(){
22 |
23 | var e = $(this).attr("id").split('tagtok_')
24 | var tok = e[1]
25 |
26 | var retval = confirm("Do you want to delete this tag?");
27 | if( retval == true ){
28 | window.location = base+'/t/delete/'+tok
29 | return true;
30 | }else return false;
31 |
32 |
33 | });
34 |
35 |
36 |
37 | /* Delete Category */
38 | $('.deletecat').click(function(){
39 |
40 | var e = $(this).attr("id").split('cattok_')
41 | var tok = e[1]
42 |
43 | var retval = confirm("Do you want to delete this category?");
44 | if( retval == true ){
45 | window.location = base+'/c/delete/'+tok
46 | return true;
47 | }else return false;
48 |
49 |
50 | });
51 |
52 |
53 |
54 | /* Hide messages after X s. */
55 | $(".hide5s").fadeOut(5000);
56 | $(".hide10s").fadeOut(10000);
57 |
58 |
59 |
60 |
61 |
62 |
63 | /* Validate Category */
64 | $('.validcat').submit(function(){
65 |
66 | $( "#message" ).html('');
67 |
68 | if( $('#name').val()=='' ){
69 | $( "#message" ).append( '
'+
70 | ''+
71 | 'The filed name cannot be empty!'+
72 | '
' );
73 |
74 | $('#name').focus();
75 | $(".hide5s").fadeOut(10000);
76 | return false;
77 | }
78 |
79 | return true;
80 | alert(1)
81 | });
82 |
83 |
84 |
85 |
86 | /* Validate Item */
87 | $('.validitem').submit(function(){
88 |
89 | $( "#message" ).html('');
90 |
91 | if( $('#title').val()=='' ){
92 | $( "#message" ).html( '
'+
93 | ''+
94 | 'The filed title cannot be empty!'+
95 | '
' );
96 | $('#title').focus();
97 | $(".hide5s").fadeOut(10000);
98 | return false;
99 | }
100 |
101 | return true;
102 |
103 | });
104 |
105 |
106 |
107 |
108 | /* Validate Tag */
109 | $('.validtag').submit(function(){
110 |
111 | $( "#message" ).html('');
112 |
113 | if( $('#title').val()=='' ){
114 | $( "#message" ).html( '
'+
115 | ''+
116 | 'The filed title cannot be empty!'+
117 | '
' );
118 | $('#title').focus();
119 | $(".hide5s").fadeOut(10000);
120 | return false;
121 | }
122 | if( $('#label').val()=='' ){
123 | $( "#message" ).html( '
'+
124 | ''+
125 | 'The filed label cannot be empty!'+
126 | '
' );
127 | $('#label').focus();
128 | $(".hide5s").fadeOut(10000);
129 | return false;
130 | }
131 |
132 | return true;
133 |
134 | });
135 |
136 |
--------------------------------------------------------------------------------
/app/views/tags/items.htm:
--------------------------------------------------------------------------------
1 |
2 |
{{ @label}}
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | 
27 |
{{ trim(@item.title) }}
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | {{ trim(@item.note) }}
36 |
37 |
38 |
39 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | 
78 |
{{ trim(@item.title) }}
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | {{ trim(@item.note) }}
87 |
88 |
89 |
90 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/lib/session.php:
--------------------------------------------------------------------------------
1 | exists($id.'.@',$data)?$data['data']:FALSE;
44 | }
45 |
46 | /**
47 | * Write session data
48 | * @return TRUE
49 | * @param $id string
50 | * @param $data string
51 | **/
52 | function write($id,$data) {
53 | $fw=Base::instance();
54 | $headers=$fw->get('HEADERS');
55 | $jar=session_get_cookie_params();
56 | Cache::instance()->set($id.'.@',
57 | array(
58 | 'data'=>$data,
59 | 'ip'=>$fw->get('IP'),
60 | 'agent'=>isset($headers['User-Agent'])?
61 | $headers['User-Agent']:'',
62 | 'stamp'=>time()
63 | ),
64 | $jar['lifetime']
65 | );
66 | return TRUE;
67 | }
68 |
69 | /**
70 | * Destroy session
71 | * @return TRUE
72 | * @param $id string
73 | **/
74 | function destroy($id) {
75 | Cache::instance()->clear($id.'.@');
76 | return TRUE;
77 | }
78 |
79 | /**
80 | * Garbage collector
81 | * @return TRUE
82 | * @param $max int
83 | **/
84 | function cleanup($max) {
85 | Cache::instance()->reset('.@',$max);
86 | return TRUE;
87 | }
88 |
89 | /**
90 | * Return IP address associated with specified session ID
91 | * @return string|FALSE
92 | * @param $id string
93 | **/
94 | function ip($id=NULL) {
95 | return Cache::instance()->exists(($id?:session_id()).'.@',$data)?
96 | $data['ip']:FALSE;
97 | }
98 |
99 | /**
100 | * Return Unix timestamp associated with specified session ID
101 | * @return string|FALSE
102 | * @param $id string
103 | **/
104 | function stamp($id=NULL) {
105 | return Cache::instance()->exists(($id?:session_id()).'.@',$data)?
106 | $data['stamp']:FALSE;
107 | }
108 |
109 | /**
110 | * Return HTTP user agent associated with specified session ID
111 | * @return string|FALSE
112 | * @param $id string
113 | **/
114 | function agent($id=NULL) {
115 | return Cache::instance()->exists(($id?:session_id()).'.@',$data)?
116 | $data['agent']:FALSE;
117 | }
118 |
119 | /**
120 | * Instantiate class
121 | * @return object
122 | **/
123 | function __construct() {
124 | session_set_save_handler(
125 | array($this,'open'),
126 | array($this,'close'),
127 | array($this,'read'),
128 | array($this,'write'),
129 | array($this,'destroy'),
130 | array($this,'cleanup')
131 | );
132 | register_shutdown_function('session_commit');
133 | }
134 |
135 | }
136 |
--------------------------------------------------------------------------------
/app/views/item/list.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ @label}}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | 
27 |
{{ trim(@item.title) }}
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | {{ trim(@item.note) }}
36 |
37 |
38 |
39 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | 
76 |
{{ trim(@item.title) }}
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | {{ trim(@item.note) }}
85 |
86 |
87 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | no items
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/lib/magic.php:
--------------------------------------------------------------------------------
1 | ispublic();
57 | unset($ref);
58 | return $out;
59 | }
60 | return FALSE;
61 | }
62 |
63 | /**
64 | * Convenience method for checking property value
65 | * @return mixed
66 | * @param $key string
67 | **/
68 | function offsetexists($key) {
69 | return $this->visible($key)?isset($this->$key):$this->exists($key);
70 | }
71 |
72 | /**
73 | * Alias for offsetexists()
74 | * @return mixed
75 | * @param $key string
76 | **/
77 | function __isset($key) {
78 | return $this->offsetexists($key);
79 | }
80 |
81 | /**
82 | * Convenience method for assigning property value
83 | * @return mixed
84 | * @param $key string
85 | * @param $val scalar
86 | **/
87 | function offsetset($key,$val) {
88 | return $this->visible($key)?($this->key=$val):$this->set($key,$val);
89 | }
90 |
91 | /**
92 | * Alias for offsetset()
93 | * @return mixed
94 | * @param $key string
95 | * @param $val scalar
96 | **/
97 | function __set($key,$val) {
98 | return $this->offsetset($key,$val);
99 | }
100 |
101 | /**
102 | * Convenience method for retrieving property value
103 | * @return mixed
104 | * @param $key string
105 | **/
106 | function offsetget($key) {
107 | return $this->visible($key)?$this->$key:$this->get($key);
108 | }
109 |
110 | /**
111 | * Alias for offsetget()
112 | * @return mixed
113 | * @param $key string
114 | **/
115 | function __get($key) {
116 | return $this->offsetget($key);
117 | }
118 |
119 | /**
120 | * Convenience method for checking property value
121 | * @return NULL
122 | * @param $key string
123 | **/
124 | function offsetunset($key) {
125 | if ($this->visible($key))
126 | unset($this->$key);
127 | else
128 | $this->clear($key);
129 | }
130 |
131 | /**
132 | * Alias for offsetunset()
133 | * @return NULL
134 | * @param $key string
135 | **/
136 | function __unset($key) {
137 | $this->offsetunset($key);
138 | }
139 |
140 | }
141 |
--------------------------------------------------------------------------------
/ui/js/track.js:
--------------------------------------------------------------------------------
1 | var _gauges=_gauges||[];(function(){var h=(_gauges['slice'])?_gauges.slice(0):[];_gauges={track_referrer:true,image:new Image(),track:function(){this.setCookie('_gauges_cookie',1,1);var a=this.url();if(a){this.image.src=a;var b=60*60,d=b*24,f=d*31,c=d*365,i=c*10;if(!this.getCookie('_gauges_unique_hour')){this.setCookie('_gauges_unique_hour',1,b)}if(!this.getCookie('_gauges_unique_day')){this.setCookie('_gauges_unique_day',1,d)}if(!this.getCookie('_gauges_unique_month')){this.setCookie('_gauges_unique_month',1,f)}if(!this.getCookie('_gauges_unique_year')){this.setCookie('_gauges_unique_year',1,c)}if(!this.getCookie('_gauges_unique')){this.setCookie('_gauges_unique',1,i)}}},push:function(a){var b=a.shift();if(b=='track'){_gauges.track()}},url:function(){var a,b,d=this.$('gauges-tracker');if(d){b=d.getAttribute('data-site-id');a=d.src.replace('/track.js','/track.gif');a+="?h[site_id]="+b;a+="&h[resource]="+this.resource();a+="&h[referrer]="+this.referrer();a+="&h[title]="+this.title();a+="&h[user_agent]="+this.agent();a+="&h[unique]="+this.unique();a+="&h[unique_hour]="+this.uniqueHour();a+="&h[unique_day]="+this.uniqueDay();a+="&h[unique_month]="+this.uniqueMonth();a+="&h[unique_year]="+this.uniqueYear();a+="&h[screenx]="+this.screenWidth();a+="&h[browserx]="+this.browserWidth();a+="&h[browsery]="+this.browserHeight();a+="×tamp="+this.timestamp()}return a},domain:function(){return window.location.hostname},referrer:function(){var a='';if(!this.track_referrer){return a}this.track_referrer=false;try{a=top.document.referrer}catch(e1){try{a=parent.document.referrer}catch(e2){a=''}}if(a==''){a=document.referrer}return this.escape(a)},agent:function(){return this.escape(navigator.userAgent)},escape:function(a){return(typeof(encodeURIComponent)=='function')?encodeURIComponent(a):escape(a)},resource:function(){return this.escape(document.location.href)},timestamp:function(){return new Date().getTime()},title:function(){return(document.title&&document.title!="")?this.escape(document.title):''},uniqueHour:function(){if(!this.getCookie('_gauges_cookie')){return 0}return this.getCookie('_gauges_unique_hour')?0:1},uniqueDay:function(){if(!this.getCookie('_gauges_cookie')){return 0}return this.getCookie('_gauges_unique_day')?0:1},uniqueMonth:function(){if(!this.getCookie('_gauges_cookie')){return 0}return this.getCookie('_gauges_unique_month')?0:1},uniqueYear:function(){if(!this.getCookie('_gauges_cookie')){return 0}return this.getCookie('_gauges_unique_year')?0:1},unique:function(){if(!this.getCookie('_gauges_cookie')){return 0}return this.getCookie('_gauges_unique')?0:1},screenWidth:function(){try{return screen.width}catch(e){return 0}},browserDimensions:function(){var a=0,b=0;try{if(typeof(window.innerWidth)=='number'){a=window.innerWidth;b=window.innerHeight}else if(document.documentElement&&document.documentElement.clientWidth){a=document.documentElement.clientWidth;b=document.documentElement.clientHeight}else if(document.body&&document.body.clientWidth){a=document.body.clientWidth;b=document.body.clientHeight}}catch(e){}return{width:a,height:b}},browserWidth:function(){return this.browserDimensions().width},browserHeight:function(){return this.browserDimensions().height},$:function(a){if(document.getElementById){return document.getElementById(a)}return null},setCookie:function(a,b,d){var f,c;b=escape(b);if(d){f=new Date();f.setTime(f.getTime()+(d*1000));c='; expires='+f.toGMTString()}else{c=''}document.cookie=a+"="+b+c+"; path=/"},getCookie:function(a){var b=a+"=",d=document.cookie.split(';');for(var f=0;f
load(array('@session_id==?',$id));
46 | return $this->dry()?FALSE:$this->get('data');
47 | }
48 |
49 | /**
50 | * Write session data
51 | * @return TRUE
52 | * @param $id string
53 | * @param $data string
54 | **/
55 | function write($id,$data) {
56 | $fw=\Base::instance();
57 | $headers=$fw->get('HEADERS');
58 | $this->load(array('@session_id==?',$id));
59 | $this->set('session_id',$id);
60 | $this->set('data',$data);
61 | $this->set('ip',$fw->get('IP'));
62 | $this->set('agent',
63 | isset($headers['User-Agent'])?$headers['User-Agent']:'');
64 | $this->set('stamp',time());
65 | $this->save();
66 | return TRUE;
67 | }
68 |
69 | /**
70 | * Destroy session
71 | * @return TRUE
72 | * @param $id string
73 | **/
74 | function destroy($id) {
75 | $this->erase(array('@session_id==?',$id));
76 | return TRUE;
77 | }
78 |
79 | /**
80 | * Garbage collector
81 | * @return TRUE
82 | * @param $max int
83 | **/
84 | function cleanup($max) {
85 | $this->erase(array('@stamp+?',$max,time()));
86 | return TRUE;
87 | }
88 |
89 | /**
90 | * Return IP address associated with specified session ID
91 | * @return string|FALSE
92 | * @param $id string
93 | **/
94 | function ip($id=NULL) {
95 | $this->load(array('@session_id==?',$id?:session_id()));
96 | return $this->dry()?FALSE:$this->get('ip');
97 | }
98 |
99 | /**
100 | * Return Unix timestamp associated with specified session ID
101 | * @return string|FALSE
102 | * @param $id string
103 | **/
104 | function stamp($id=NULL) {
105 | $this->load(array('@session_id==?',$id?:session_id()));
106 | return $this->dry()?FALSE:$this->get('stamp');
107 | }
108 |
109 | /**
110 | * Return HTTP user agent associated with specified session ID
111 | * @return string|FALSE
112 | * @param $id string
113 | **/
114 | function agent($id=NULL) {
115 | $this->load(array('@session_id==?',$id?:session_id()));
116 | return $this->dry()?FALSE:$this->get('agent');
117 | }
118 |
119 | /**
120 | * Instantiate class
121 | * @param $db object
122 | * @param $table string
123 | **/
124 | function __construct(\DB\Jig $db,$table='sessions') {
125 | parent::__construct($db,'sessions');
126 | session_set_save_handler(
127 | array($this,'open'),
128 | array($this,'close'),
129 | array($this,'read'),
130 | array($this,'write'),
131 | array($this,'destroy'),
132 | array($this,'cleanup')
133 | );
134 | register_shutdown_function('session_commit');
135 | }
136 |
137 | }
138 |
--------------------------------------------------------------------------------
/lib/db/mongo/session.php:
--------------------------------------------------------------------------------
1 | load(array('session_id'=>$id));
46 | return $this->dry()?FALSE:$this->get('data');
47 | }
48 |
49 | /**
50 | * Write session data
51 | * @return TRUE
52 | * @param $id string
53 | * @param $data string
54 | **/
55 | function write($id,$data) {
56 | $fw=\Base::instance();
57 | $headers=$fw->get('HEADERS');
58 | $this->load(array('session_id'=>$id));
59 | $this->set('session_id',$id);
60 | $this->set('data',$data);
61 | $this->set('ip',$fw->get('IP'));
62 | $this->set('agent',
63 | isset($headers['User-Agent'])?$headers['User-Agent']:'');
64 | $this->set('stamp',time());
65 | $this->save();
66 | return TRUE;
67 | }
68 |
69 | /**
70 | * Destroy session
71 | * @return TRUE
72 | * @param $id string
73 | **/
74 | function destroy($id) {
75 | $this->erase(array('session_id'=>$id));
76 | return TRUE;
77 | }
78 |
79 | /**
80 | * Garbage collector
81 | * @return TRUE
82 | * @param $max int
83 | **/
84 | function cleanup($max) {
85 | $this->erase(array('$where'=>'this.stamp+'.$max.'<'.time()));
86 | return TRUE;
87 | }
88 |
89 | /**
90 | * Return IP address associated with specified session ID
91 | * @return string|FALSE
92 | * @param $id string
93 | **/
94 | function ip($id=NULL) {
95 | $this->load(array('session_id'=>$id?:session_id()));
96 | return $this->dry()?FALSE:$this->get('ip');
97 | }
98 |
99 | /**
100 | * Return Unix timestamp associated with specified session ID
101 | * @return string|FALSE
102 | * @param $id string
103 | **/
104 | function stamp($id=NULL) {
105 | $this->load(array('session_id'=>$id?:session_id()));
106 | return $this->dry()?FALSE:$this->get('stamp');
107 | }
108 |
109 | /**
110 | * Return HTTP user agent associated with specified session ID
111 | * @return string|FALSE
112 | * @param $id string
113 | **/
114 | function agent($id=NULL) {
115 | $this->load(array('session_id'=>$id?:session_id()));
116 | return $this->dry()?FALSE:$this->get('agent');
117 | }
118 |
119 | /**
120 | * Instantiate class
121 | * @param $db object
122 | * @param $table string
123 | **/
124 | function __construct(\DB\Mongo $db,$table='sessions') {
125 | parent::__construct($db,$table);
126 | session_set_save_handler(
127 | array($this,'open'),
128 | array($this,'close'),
129 | array($this,'read'),
130 | array($this,'write'),
131 | array($this,'destroy'),
132 | array($this,'cleanup')
133 | );
134 | register_shutdown_function('session_commit');
135 | }
136 |
137 | }
138 |
--------------------------------------------------------------------------------
/lib/db/sql/session.php:
--------------------------------------------------------------------------------
1 | load(array('session_id=?',$id));
46 | return $this->dry()?FALSE:$this->get('data');
47 | }
48 |
49 | /**
50 | * Write session data
51 | * @return TRUE
52 | * @param $id string
53 | * @param $data string
54 | **/
55 | function write($id,$data) {
56 | $fw=\Base::instance();
57 | $headers=$fw->get('HEADERS');
58 | $this->load(array('session_id=?',$id));
59 | $this->set('session_id',$id);
60 | $this->set('data',$data);
61 | $this->set('ip',$fw->get('IP'));
62 | $this->set('agent',
63 | isset($headers['User-Agent'])?$headers['User-Agent']:'');
64 | $this->set('stamp',time());
65 | $this->save();
66 | return TRUE;
67 | }
68 |
69 | /**
70 | * Destroy session
71 | * @return TRUE
72 | * @param $id string
73 | **/
74 | function destroy($id) {
75 | $this->erase(array('session_id=?',$id));
76 | return TRUE;
77 | }
78 |
79 | /**
80 | * Garbage collector
81 | * @return TRUE
82 | * @param $max int
83 | **/
84 | function cleanup($max) {
85 | $this->erase(array('stamp+?',$max,time()));
86 | return TRUE;
87 | }
88 |
89 | /**
90 | * Return IP address associated with specified session ID
91 | * @return string|FALSE
92 | * @param $id string
93 | **/
94 | function ip($id=NULL) {
95 | $this->load(array('session_id=?',$id?:session_id()));
96 | return $this->dry()?FALSE:$this->get('ip');
97 | }
98 |
99 | /**
100 | * Return Unix timestamp associated with specified session ID
101 | * @return string|FALSE
102 | * @param $id string
103 | **/
104 | function stamp($id=NULL) {
105 | $this->load(array('session_id=?',$id?:session_id()));
106 | return $this->dry()?FALSE:$this->get('stamp');
107 | }
108 |
109 | /**
110 | * Return HTTP user agent associated with specified session ID
111 | * @return string|FALSE
112 | * @param $id string
113 | **/
114 | function agent($id=NULL) {
115 | $this->load(array('session_id=?',$id?:session_id()));
116 | return $this->dry()?FALSE:$this->get('agent');
117 | }
118 |
119 | /**
120 | * Instantiate class
121 | * @param $db object
122 | * @param $table string
123 | **/
124 | function __construct(\DB\SQL $db,$table='sessions') {
125 | $db->exec(
126 | 'CREATE TABLE IF NOT EXISTS '.
127 | (($name=$db->name())?($name.'.'):'').$table.' ('.
128 | 'session_id VARCHAR(40),'.
129 | 'data TEXT,'.
130 | 'ip VARCHAR(40),'.
131 | 'agent VARCHAR(255),'.
132 | 'stamp INTEGER,'.
133 | 'PRIMARY KEY(session_id)'.
134 | ');'
135 | );
136 | parent::__construct($db,$table);
137 | session_set_save_handler(
138 | array($this,'open'),
139 | array($this,'close'),
140 | array($this,'read'),
141 | array($this,'write'),
142 | array($this,'destroy'),
143 | array($this,'cleanup')
144 | );
145 | register_shutdown_function('session_commit');
146 | }
147 |
148 | }
149 |
--------------------------------------------------------------------------------
/lib/db/cursor.php:
--------------------------------------------------------------------------------
1 | query[$this->ptr]);
58 | }
59 |
60 | /**
61 | * Return first record (mapper object) that matches criteria
62 | * @return object|FALSE
63 | * @param $filter string|array
64 | * @param $options array
65 | * @param $ttl int
66 | **/
67 | function findone($filter=NULL,array $options=NULL,$ttl=0) {
68 | return ($data=$this->find($filter,$options,$ttl))?$data[0]:FALSE;
69 | }
70 |
71 | /**
72 | * Return array containing subset of records matching criteria,
73 | * total number of records in superset, number of subsets available,
74 | * and actual subset position
75 | * @return array
76 | * @param $pos int
77 | * @param $size int
78 | * @param $filter string|array
79 | * @param $options array
80 | **/
81 | function paginate($pos=0,$size=10,$filter=NULL,array $options=NULL) {
82 | $total=$this->count($filter,$options);
83 | $count=ceil($total/$size);
84 | $pos=max(0,min($pos,$count-1));
85 | return array(
86 | 'subset'=>$this->find($filter,
87 | array_merge(
88 | $options?:array(),
89 | array('limit'=>$size,'offset'=>$pos*$size)
90 | )
91 | ),
92 | 'total'=>$total,
93 | 'count'=>$count,
94 | 'pos'=>$pos<$count?$pos:0
95 | );
96 | }
97 |
98 | /**
99 | * Map to first record that matches criteria
100 | * @return array|FALSE
101 | * @param $filter string|array
102 | * @param $options array
103 | **/
104 | function load($filter=NULL,array $options=NULL) {
105 | return ($this->query=$this->find($filter,$options)) &&
106 | $this->skip(0)?$this->query[$this->ptr=0]:FALSE;
107 | }
108 |
109 | /**
110 | * Move pointer to first record in cursor
111 | * @return mixed
112 | **/
113 | function first() {
114 | return $this->query[$this->ptr=0];
115 | }
116 |
117 | /**
118 | * Move pointer to last record in cursor
119 | * @return mixed
120 | **/
121 | function last() {
122 | return $this->query[$this->ptr=($ctr=count($this->query))?$ctr-1:0];
123 | }
124 |
125 | /**
126 | * Map to nth record relative to current cursor position
127 | * @return mixed
128 | * @param $ofs int
129 | **/
130 | function skip($ofs=1) {
131 | $this->ptr+=$ofs;
132 | return $this->ptr>-1 && $this->ptrquery)?
133 | $this->query[$this->ptr]:FALSE;
134 | }
135 |
136 | /**
137 | * Map next record
138 | * @return mixed
139 | **/
140 | function next() {
141 | return $this->skip();
142 | }
143 |
144 | /**
145 | * Map previous record
146 | * @return mixed
147 | **/
148 | function prev() {
149 | return $this->skip(-1);
150 | }
151 |
152 | /**
153 | * Save mapped record
154 | * @return mixed
155 | **/
156 | function save() {
157 | return $this->query?$this->update():$this->insert();
158 | }
159 |
160 | /**
161 | * Delete current record
162 | * @return int|bool
163 | **/
164 | function erase() {
165 | $this->query=array_slice($this->query,0,$this->ptr,TRUE)+
166 | array_slice($this->query,$this->ptr,NULL,TRUE);
167 | $this->ptr=0;
168 | }
169 |
170 | /**
171 | * Reset cursor
172 | * @return NULL
173 | **/
174 | function reset() {
175 | $this->query=array();
176 | $this->ptr=0;
177 | }
178 |
179 | }
180 |
--------------------------------------------------------------------------------
/ui/js/application.js:
--------------------------------------------------------------------------------
1 | // NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT
2 | // IT'S ALL JUST JUNK FOR OUR DOCS!
3 | // ++++++++++++++++++++++++++++++++++++++++++
4 |
5 | !function ($) {
6 |
7 | $(function(){
8 |
9 | var $window = $(window)
10 |
11 | // Disable certain links in docs
12 | $('section [href^=#]').click(function (e) {
13 | e.preventDefault()
14 | })
15 |
16 | // back to top
17 | setTimeout(function () {
18 | $('.bs-sidebar').affix({
19 | offset: {
20 | top: function () { return $window.width() <= 980 ? 290 : 210 }
21 | , bottom: 270
22 | }
23 | })
24 | }, 100)
25 |
26 | setTimeout(function () {
27 | $('.bs-top').affix()
28 | }, 100)
29 |
30 | // add-ons
31 | $('.add-on :checkbox').on('click', function () {
32 | var $this = $(this)
33 | , method = $this.attr('checked') ? 'addClass' : 'removeClass'
34 | $(this).parents('.add-on')[method]('active')
35 | })
36 |
37 | // add tipsies to grid for scaffolding
38 | if ($('#grid-system').length) {
39 | $('#grid-system').tooltip({
40 | selector: '.show-grid > [class*="span"]'
41 | , title: function () { return $(this).width() + 'px' }
42 | })
43 | }
44 |
45 | // tooltip demo
46 | $('.tooltip-demo').tooltip({
47 | selector: "a[data-toggle=tooltip]"
48 | })
49 |
50 | $('.tooltip-test').tooltip()
51 | $('.popover-test').popover()
52 |
53 | $('.bs-docs-navbar').tooltip({
54 | selector: "a[data-toggle=tooltip]",
55 | container: ".bs-docs-navbar .nav"
56 | })
57 |
58 | // popover demo
59 | $("a[data-toggle=popover]")
60 | .popover()
61 | .click(function(e) {
62 | e.preventDefault()
63 | })
64 |
65 | // button state demo
66 | $('#fat-btn')
67 | .click(function () {
68 | var btn = $(this)
69 | btn.button('loading')
70 | setTimeout(function () {
71 | btn.button('reset')
72 | }, 3000)
73 | })
74 |
75 | // carousel demo
76 | $('.bs-docs-carousel-example').carousel()
77 |
78 | // javascript build logic
79 | var inputsComponent = $("#components.download input")
80 | , inputsPlugin = $("#plugins.download input")
81 | , inputsVariables = $("#variables.download input")
82 |
83 | // toggle all plugin checkboxes
84 | $('#components.download .toggle-all').on('click', function (e) {
85 | e.preventDefault()
86 | inputsComponent.attr('checked', !inputsComponent.is(':checked'))
87 | })
88 |
89 | $('#plugins.download .toggle-all').on('click', function (e) {
90 | e.preventDefault()
91 | inputsPlugin.attr('checked', !inputsPlugin.is(':checked'))
92 | })
93 |
94 | $('#variables.download .toggle-all').on('click', function (e) {
95 | e.preventDefault()
96 | inputsVariables.val('')
97 | })
98 |
99 | // request built javascript
100 | $('.download-btn .btn').on('click', function () {
101 |
102 | var css = $("#components.download input:checked")
103 | .map(function () { return this.value })
104 | .toArray()
105 | , js = $("#plugins.download input:checked")
106 | .map(function () { return this.value })
107 | .toArray()
108 | , vars = {}
109 | , img = ['glyphicons-halflings.png', 'glyphicons-halflings-white.png']
110 |
111 | $("#variables.download input")
112 | .each(function () {
113 | $(this).val() && (vars[ $(this).prev().text() ] = $(this).val())
114 | })
115 |
116 | $.ajax({
117 | type: 'POST'
118 | , url: /\?dev/.test(window.location) ? 'http://localhost:3000' : 'http://bootstrap.herokuapp.com'
119 | , dataType: 'jsonpi'
120 | , params: {
121 | js: js
122 | , css: css
123 | , vars: vars
124 | , img: img
125 | }
126 | })
127 | })
128 | })
129 |
130 | // Modified from the original jsonpi https://github.com/benvinegar/jquery-jsonpi
131 | $.ajaxTransport('jsonpi', function(opts, originalOptions, jqXHR) {
132 | var url = opts.url;
133 |
134 | return {
135 | send: function(_, completeCallback) {
136 | var name = 'jQuery_iframe_' + jQuery.now()
137 | , iframe, form
138 |
139 | iframe = $('