Skip to content

Commit f661f12

Browse files
committed
Begin support for order-reliable, chainable, normal-phpjs-function-compatible PHPJS_Array objects through array()
1 parent 3a0545c commit f661f12

4 files changed

Lines changed: 142 additions & 18 deletions

File tree

functions/array/array.js

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,129 @@ function array () {
33
// + original by: d3x
44
// * example 1: array('Kevin', 'van', 'Zonneveld');
55
// * returns 1: ['Kevin', 'van', 'Zonneveld']
6-
return Array.prototype.slice.call(arguments);
6+
var mainArgs = arguments, p = this.php_js = this.php_js || {},
7+
_indexOf = function (value, from, strict) {
8+
for (var i = (from || 0), nonstrict = !strict, length=this.length; i < length; i++) {
9+
if (this[i] === value || (nonstrict && this[i] == value)) {
10+
return i;
11+
}
12+
}
13+
return -1;
14+
};
15+
// BEGIN REDUNDANT
16+
if (!p.Relator) {
17+
p.Relator = function () {// Used this functional class for giving privacy to the class we are creating
18+
// Code adapted from http://www.devpro.it/code/192.html
19+
// Relator explained at http://webreflection.blogspot.com/2008/07/javascript-relator-object-aka.html
20+
// Its use as privacy technique described at http://webreflection.blogspot.com/2008/10/new-relator-object-plus-unshared.html
21+
// 1) At top of closure, put: var __ = Relator.$();
22+
// 2) In constructor, put: var _ = __.constructor(this);
23+
// 3) At top of each prototype method, put: var _ = __.method(this);
24+
// 4) Use like: _.privateVar = 5;
25+
function _indexOf (value) {
26+
for (var i = 0, length=this.length; i < length; i++) {
27+
if (this[i] === value) {
28+
return i;
29+
}
30+
}
31+
return -1;
32+
}
33+
function Relator () {
34+
var Stack = [], Array = [];
35+
if (!Stack.indexOf) {
36+
Stack.indexOf = _indexOf;
37+
}
38+
return {
39+
// create a new relator
40+
$ : function () {
41+
return Relator();
42+
},
43+
constructor : function (that) {
44+
var i = Stack.indexOf(that);
45+
~i ? Array[i] : Array[Stack.push(that) - 1] = {};
46+
this.method(that).that = that;
47+
return this.method(that);
48+
},
49+
method : function (that) {
50+
return Array[Stack.indexOf(that)];
51+
}
52+
};
53+
}
54+
return Relator();
55+
}();
56+
}
57+
// END REDUNDANT
58+
59+
if (p && p.ini && p.ini['phpjs.return_phpjs_arrays'].local_value.toLowerCase() === 'on') {
60+
if (!p.PHPJS_Array) {
61+
// We keep this Relator outside the class in case adding prototype methods below
62+
// Prototype methods added elsewhere can also use this ArrayRelator to share these "pseudo-global mostly-private" variables
63+
var __ = p.ArrayRelator = p.ArrayRelator || p.Relator.$();
64+
// We could instead allow arguments of {key:XX, value:YY} but even more cumbersome to write
65+
p.PHPJS_Array = function PHPJS_Array () {
66+
var _ = __.constructor(this), args = arguments;
67+
args = (args.length === 1 && args[0] && typeof args[0] === 'object' &&
68+
args[0].length && !args[0].propertyIsEnumerable('length')) ? args[0] : args; // If first and only arg is an array, use that (Don't depend on this)
69+
if (!_.objectChain) {
70+
_.objectChain = args;
71+
_.object = {};
72+
_.keys = [];
73+
_.values = [];
74+
}
75+
for (var i=0, argl = args.length; i < argl; i++) {
76+
for (var p in args[i]) {
77+
// Allow for access by key; use of private members to store sequence allows these to be iterated via for...in (but for read-only use, with hasOwnProperty or function filtering to avoid prototype methods, and per ES, potentially out of order)
78+
this[p] = _.object[p] = args[i][p];
79+
// Allow for easier access by prototype methods
80+
_.keys[_.keys.length] = p;
81+
_.values[_.values.length] = args[i][p];
82+
break;
83+
}
84+
}
85+
};
86+
var e = p.PHPJS_Array.prototype, that = this;
87+
e.change_key_case = function (cs) {var _ = __.method(this);
88+
var case_fn = (!cs || cs === 'CASE_LOWER') ? 'toLowerCase' : 'toUpperCase';
89+
for (var i=0, kl = _.keys.length; i < kl; i++) {
90+
var oldkey = _.keys[i],
91+
newkey = _.keys[i] = _.keys[i][case_fn]();
92+
this[newkey] = _.object[newkey] = _.objectChain[i][newkey] = _.values[i]; // Fix: should we make a deep copy?
93+
this[oldkey] = _.object[oldkey] = _.objectChain[i][oldkey] = null; // Break reference before deleting
94+
delete this[oldkey];
95+
delete _.object[oldkey];
96+
delete _.objectChain[i][oldkey];
97+
}
98+
return this;
99+
};
100+
// Here we'll return actual arrays since most logical and practical for these functions to do this
101+
e.keys = function (search_value, argStrict) {var _ = __.method(this);
102+
var pos, search = typeof search_value !== 'undefined',
103+
tmp_arr = [],
104+
strict = !!argStrict;
105+
if (!search) {
106+
return _.keys;
107+
}
108+
while ((pos = _indexOf(_.values, pos, strict)) !== -1) {
109+
tmp_arr[tmp_arr.length] = _.keys[pos];
110+
}
111+
return tmp_arr;
112+
};
113+
e.values = function () {var _ = __.method(this);
114+
return _.values;
115+
};
116+
// Our own custom convenience functions
117+
e.$object = function () {var _ = __.method(this);
118+
return _.object;
119+
};
120+
e.$objectChain = function () {var _ = __.method(this);
121+
return _.objectChain;
122+
};
123+
}
124+
function PHPJS_Array() {}
125+
PHPJS_Array.prototype = p.PHPJS_Array.prototype;
126+
var arrInst = new PHPJS_Array();
127+
p.PHPJS_Array.apply(arrInst, mainArgs);
128+
return arrInst;
129+
}
130+
return Array.prototype.slice.call(mainArgs);
7131
}
Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
function array_change_key_case (array) {
1+
function array_change_key_case (array, cs) {
22
// http://kevin.vanzonneveld.net
33
// + original by: Ates Goral (http://magnetiq.com)
44
// + improved by: marrtins
@@ -14,26 +14,20 @@ function array_change_key_case (array) {
1414
// * returns 5: {"FUBAR": 42}
1515
// * example 6: array_change_key_case({ FuBaR: 42 }, 2);
1616
// * returns 6: {"FUBAR": 42}
17-
var case_fn, tmp_ar = {},
18-
argc = arguments.length,
19-
argv = arguments,
20-
key;
17+
var case_fn, key, tmp_ar = {};
2118

2219
if (array instanceof Array) {
2320
return array;
2421
}
25-
26-
if (array instanceof Object) {
27-
if (argc === 1 || argv[1] === 'CASE_LOWER' || argv[1] === 0) {
28-
case_fn = "toLowerCase";
29-
} else {
30-
case_fn = "toUpperCase";
31-
}
22+
if (array && typeof array === 'object' && array.change_key_case) { // Duck-type check for our own array()-created PHPJS_Array
23+
return array.change_key_case(cs);
24+
}
25+
if (array && typeof array === 'object' ) {
26+
case_fn = (!cs || cs === 'CASE_LOWER') ? 'toLowerCase' : 'toUpperCase';
3227
for (key in array) {
3328
tmp_ar[key[case_fn]()] = array[key];
3429
}
3530
return tmp_ar;
3631
}
37-
3832
return false;
3933
}

functions/array/array_keys.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ function array_keys (input, search_value, argStrict) {
1414
include = true,
1515
key = '';
1616

17+
if (input && typeof input === 'object' && input.change_key_case) { // Duck-type check for our own array()-created PHPJS_Array
18+
return input.keys(cs);
19+
}
20+
1721
for (key in input) {
1822
if (input.hasOwnProperty(key)) {
1923
include = true;

functions/array/array_values.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ function array_values (input) {
44
// * example 1: array_values( {firstname: 'Kevin', surname: 'van Zonneveld'} );
55
// * returns 1: {0: 'Kevin', 1: 'van Zonneveld'}
66
var tmp_arr = [],
7-
cnt = 0;
8-
var key = '';
7+
key = '';
8+
9+
if (input && typeof input === 'object' && input.change_key_case) { // Duck-type check for our own array()-created PHPJS_Array
10+
return input.values();
11+
}
912

1013
for (key in input) {
11-
tmp_arr[cnt] = input[key];
12-
cnt++;
14+
tmp_arr[tmp_arr.length] = input[key];
1315
}
1416

1517
return tmp_arr;

0 commit comments

Comments
 (0)