1+ <?php
2+ namespace ClientAdapter ;
3+ class Env {
4+
5+ public static $ env ;
6+
7+ public static function setCurrEnv (Env $ env ) {
8+ self ::$ env = $ env ;
9+ }
10+
11+ public $ sessUid = 0 ;
12+ public $ clientIp = '0.0.0.0 ' ;
13+ public $ longitude = 0.0 ;
14+ public $ latitude = 0.0 ;
15+
16+ // 供下层应用扩展自有数据
17+ protected $ datas = array ();
18+
19+ public function __get ($ name ) {
20+ $ getter = 'get ' . ucfirst ($ name );
21+ if (!method_exists ($ this , $ getter )) {
22+ return NULL ;
23+ }
24+ return $ this ->$ getter ();
25+ }
26+
27+ /**
28+ * checkEnv
29+ * 检查当前客户端环境, 是否和$envDesc描述的环境match
30+ * @param mixed $envDesc
31+ * @access private
32+ * @return void
33+ */
34+ public static function checkEnv ($ envDesc ) {
35+ $ envDesc = (array )$ envDesc ;
36+ //支持两层array结构,如果是两层array,每个array之间使用逻辑或,每个array自身使用逻辑与
37+ if (!is_array ($ envDesc [0 ])){
38+ $ envDesc = array ($ envDesc );
39+ }
40+ foreach ($ envDesc as $ descs ) {
41+ $ ret = false ;
42+ $ current = true ;
43+ foreach ($ descs as $ desc ) {
44+ if (!preg_match (';^(?P<env>\w+)\s+(?P<operator>\S+)(?:\s+(?P<arg>.*))?$; ' , $ desc , $ match )) {
45+ continue ;
46+ }
47+ // 目前的实现, 仅支持所有条件逻辑与
48+ $ arg = array_key_exists ('arg ' , $ match ) ? $ match ['arg ' ] : '' ;
49+ $ envName = $ match ['env ' ];
50+ $ envValue = self ::$ env ->$ envName ;
51+ $ operator = $ match ['operator ' ];
52+ switch ($ operator ) {
53+ case 'match ' :
54+ if (!preg_match (strval ($ arg ), strval ($ envValue ))) {
55+ $ current = false ;
56+ }
57+ break ;
58+ case 'eq ' :
59+ if (strval ($ envValue ) !=trim ($ arg )) {
60+ $ current = false ;
61+ }
62+ break ;
63+ case 'neq ' :
64+ if (strval ($ envValue ) ==trim ($ arg )) {
65+ $ current = false ;
66+ }
67+ break ;
68+ case '>= ' :
69+ if (floatval ($ envValue ) <floatval ($ arg )) {
70+ $ current = false ;
71+ }
72+ break ;
73+ case '<= ' :
74+ if (floatval ($ envValue ) >floatval ($ arg )) {
75+ $ current = false ;
76+ }
77+ break ;
78+ case '= ' :
79+ if (floatval ($ envValue ) !=floatval ($ arg )) {
80+ $ current = false ;
81+ }
82+ break ;
83+ case '> ' :
84+ if (floatval ($ envValue ) <=floatval ($ arg )) {
85+ $ current = false ;
86+ }
87+ break ;
88+ case '< ' :
89+ if (floatval ($ envValue ) >=floatval ($ arg )) {
90+ $ current = false ;
91+ }
92+ case 'v>= ' :
93+ if (self ::versionDiff ($ envValue , $ arg ) <0 ) {
94+ $ current = false ;
95+ }
96+ break ;
97+ case 'v<= ' :
98+ if (self ::versionDiff ($ envValue , $ arg ) >0 ) {
99+ $ current = false ;
100+ }
101+ break ;
102+ case 'v= ' :
103+ if (self ::versionDiff ($ envValue , $ arg ) !==0 ) {
104+ $ current = false ;
105+ }
106+ break ;
107+ case 'v> ' :
108+ if (self ::versionDiff ($ envValue , $ arg ) <=0 ) {
109+ $ current = false ;
110+ }
111+ break ;
112+ case 'v< ' :
113+ if (self ::versionDiff ($ envValue , $ arg ) >=0 ) {
114+ $ current = false ;
115+ }
116+ break ;
117+ case '<=% ' : # deviceId <=% 100:10 表示设备id经过运算后的对100取模小于等于10为真
118+ case '>=% ' : # deviceId >=% 100:10 表示设备id经过运算后的对100取模大于等于10为真
119+ case '>% ' : # deviceId >% 100:10 表示设备id经过运算后的对100取模大于10为真
120+ case '<% ' : # deviceId <% 100:10 表示设备id经过运算后的对100取模小于10为真
121+ if (!self ::_judgeDuration ($ envValue , $ operator , $ arg )){
122+ $ current = false ;
123+ }
124+ break ;
125+ case '~ ' : #不区分大小写
126+ if (empty ($ envValue ) || strpos (strtolower ($ envValue ), strtolower ($ arg )) === false ) {
127+ $ current = false ;
128+ }
129+ break ;
130+ case '!~ ' :#不区分大小写
131+ if (empty ($ envValue ) || strpos (strtolower ($ envValue ), strtolower ($ arg )) != false ) {
132+ $ current = false ;
133+ }
134+ break ;
135+ case 'in ' :#in操作, 后面的数据以英文逗号分开: 切记中文逗号不算分隔符号
136+ $ arg = $ arg ? trim ($ arg ) : '' ;
137+ $ elems = explode (", " , $ arg );
138+ $ elems = array_filter (array_map ('trim ' , $ elems ));
139+ if (empty ($ envValue ) || !in_array (trim (strval ($ envValue )), $ elems , TRUE )){
140+ $ current = false ;
141+ }
142+ break ;
143+ case 'notin ' :#in操作, 后面的数据以英文逗号分开: 切记中文逗号不算分隔符号
144+ $ arg = $ arg ? trim ($ arg ) : '' ;
145+ $ elems = explode (", " , $ arg );
146+ $ elems = array_filter (array_map ('trim ' , $ elems ));
147+ if (in_array (trim (strval ($ envValue )), $ elems , TRUE )){
148+ $ current = false ;
149+ }
150+ break ;
151+ default :
152+ trigger_error ('undefined operator[ ' .$ operator .'] for client env adapter ' , E_USER_ERROR );
153+ break ;
154+ }
155+ if (!$ current ){
156+ break ;
157+ }
158+ }
159+ if ($ current ){//找到一个符合的分支
160+ return TRUE ;
161+ }
162+
163+ }
164+ return $ ret ;
165+ }
166+
167+ private static function _judgeDuration ($ envValue , $ operator , $ arg ){
168+ $ ret = true ;
169+ if (empty ($ envValue )){
170+ $ ret = false ;
171+ }
172+ if ($ ret ){
173+ list ($ total , $ limit ) = explode (': ' , $ arg );
174+ $ total = intval ($ total );
175+ $ limit = intval ($ limit );
176+ $ res = 0 ;
177+ if (is_numeric ($ envValue )){
178+ $ res = intval ($ envValue );
179+ } else {
180+ $ res = crc32 ($ envValue );
181+ }
182+ if (!$ res ){
183+ $ ret = false ;
184+ }
185+ $ tmpRes = $ res % $ total ;
186+ if ($ operator == '>=% ' && $ tmpRes < $ limit ){
187+ $ ret = false ;
188+ } else if ($ operator == '<=% ' && $ tmpRes > $ limit ){
189+ $ ret = false ;
190+ } else if ($ operator == '<% ' && $ tmpRes >= $ limit ){
191+ $ ret = false ;
192+ } else if ($ operator == '>% ' && $ tmpRes <= $ limit ){
193+ $ ret = false ;
194+ }
195+ }
196+ return $ ret ;
197+ }
198+
199+
200+ private static function versionDiff ($ v1 , $ v2 ) {
201+
202+ $ i1 = explode ('. ' , $ v1 );
203+ $ i2 = explode ('. ' , $ v2 );
204+ $ l1 = count ($ i1 );
205+ $ l2 = count ($ i2 );
206+
207+ $ len = max ($ l1 , $ l2 );
208+ for ($ i = 0 ; $ i < $ len ; $ i ++) {
209+ $ p1 = isset ($ i1 [$ i ]) ? intval ($ i1 [$ i ]) : 0 ;
210+ $ p2 = isset ($ i2 [$ i ]) ? intval ($ i2 [$ i ]) : 0 ;
211+
212+ if ($ p1 > $ p2 ) {
213+ return 1 ;
214+ } elseif ($ p1 < $ p2 ) {
215+ return -1 ;
216+ }
217+ }
218+ return 0 ;
219+ }
220+
221+ }
0 commit comments