├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── detect_mobile.info.yml ├── detect_mobile.links.menu.yml ├── detect_mobile.module ├── detect_mobile.routing.yml ├── detect_mobile.services.yml ├── phpunit.xml.dist ├── src ├── Detect │ └── MobileDetect.php ├── EventSubscriber │ └── MobileDetectSubscriber.php ├── Form │ └── DefaultForm.php ├── Middleware │ ├── MobileDetectManager.php │ ├── MobileDetectManagerInterface.php │ └── MobileDetectMiddleware.php ├── Plugin │ └── Block │ │ └── MobileDetectBlock.php └── Twig │ └── MobileDetectExtension.php ├── templates └── block--detect-mobile.html.twig └── tests ├── Detect └── MobileDetectTest.php └── Twig └── MobileDetectExtensionTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | /nbproject/ 4 | vendor/ 5 | composer.phar 6 | 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | detect_mobile 2 | ============= 3 | drupal 8 module for detect mobile devices. 4 | 5 | This is a lightweight mobile detection based on the [Mobile_Detect.php](http://mobiledetect.net/) library. 6 | 7 | PHP examples 8 | ------------ 9 | 10 | ### Check type device 11 | ``` php 12 | $mobileDetector = \Drupal::service('mobile_detect'); 13 | $mobileDetector->isMobile(); 14 | $mobileDetector->isTablet() 15 | ``` 16 | 17 | ### Check phone 18 | **is[iPhone|HTC|Nexus|Dell|Motorola|Samsung|Sony|Asus|Palm|Vertu|GenericPhone]** 19 | 20 | ``` php 21 | $mobileDetector->isIphone(); 22 | $mobileDetector->isHTC(); 23 | etc. 24 | ``` 25 | 26 | ### Check tablet 27 | **is[BlackBerryTablet|iPad|Kindle|SamsungTablet|HTCtablet|MotorolaTablet|AsusTablet|NookTablet|AcerTablet| 28 | YarvikTablet|GenericTablet]** 29 | 30 | ```php 31 | $mobileDetector->isIpad(); 32 | $mobileDetector->isMotorolaTablet(); 33 | etc. 34 | ``` 35 | 36 | ### Check mobile OS 37 | **is[AndroidOS|BlackBerryOS|PalmOS|SymbianOS|WindowsMobileOS|iOS|badaOS]** 38 | 39 | ```php 40 | $mobileDetector->isAndroidOS(); 41 | $mobileDetector->isIOS(); 42 | ``` 43 | 44 | Twig Helper 45 | ----------- 46 | 47 | ```jinja 48 | {% if is_mobile() %} 49 | {% if is_tablet() %} 50 | {% if is_device('iphone') %} 51 | {% if is_ios() %} 52 | {% if is_android_os() %} 53 | ``` 54 | 55 | Redirect to mobile domain 56 | ------------------------------------------------- 57 | To enable redirect use the configuration form here /admin/config/system/detect_mobile 58 | 59 | enter the domain for the desktop & mobile without 'http' for example 'example.com' 60 | 61 | TODO 62 | --------- 63 | 64 | * ~~redirect to mobile and tablet~~ 65 | * Write tests 66 | 67 | 68 | HOW TO INSTALL 69 | ------------------------------------------------- 70 | 71 | With composer: 72 | 73 | 1) add the git package to ```composer.json```: 74 | ``` json 75 | "repositories": [ 76 | ... 77 | { 78 | "type": "package", 79 | "package": { 80 | "name": "tabbabi/detect_mobile", 81 | "version": "dev-master", 82 | "type":"drupal-module", 83 | "source": { 84 | "url": "https://github.com/tabbabi/detect_mobile.git", 85 | "type": "git", 86 | "reference": "master" 87 | } 88 | } 89 | } 90 | ... 91 | ] 92 | ``` 93 | 2) require the dependencies: 94 | ``` shell 95 | composer require mobiledetect/mobiledetectlib 96 | composer require tabbabi/detect_mobile 97 | ``` 98 | 3) enable the module 99 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tabbabi/detect_mobile", 3 | "type": "drupal-module", 4 | "description": "A lightweight Drupal 8 module for mobile detection based on the Mobile_Detect.php library", 5 | "keywords": ["Drupal"], 6 | "require": { 7 | "mobiledetect/mobiledetectlib": "^2.8" 8 | }, 9 | "require-dev": { 10 | "phpunit/phpunit": "^5.7" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "629d7d9349da5f8248ae24fd6ac16449", 8 | "packages": [ 9 | { 10 | "name": "mobiledetect/mobiledetectlib", 11 | "version": "2.8.26", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/serbanghita/Mobile-Detect.git", 15 | "reference": "a0ed86c9d7c04ae27fa6418b55e3beb04dfe3297" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/a0ed86c9d7c04ae27fa6418b55e3beb04dfe3297", 20 | "reference": "a0ed86c9d7c04ae27fa6418b55e3beb04dfe3297", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.0.0" 25 | }, 26 | "require-dev": { 27 | "phpunit/phpunit": "*" 28 | }, 29 | "type": "library", 30 | "autoload": { 31 | "classmap": [ 32 | "Mobile_Detect.php" 33 | ], 34 | "psr-0": { 35 | "Detection": "namespaced/" 36 | } 37 | }, 38 | "notification-url": "https://packagist.org/downloads/", 39 | "license": [ 40 | "MIT" 41 | ], 42 | "authors": [ 43 | { 44 | "name": "Serban Ghita", 45 | "email": "serbanghita@gmail.com", 46 | "homepage": "http://mobiledetect.net", 47 | "role": "Developer" 48 | } 49 | ], 50 | "description": "Mobile_Detect is a lightweight PHP class for detecting mobile devices. It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.", 51 | "homepage": "https://github.com/serbanghita/Mobile-Detect", 52 | "keywords": [ 53 | "detect mobile devices", 54 | "mobile", 55 | "mobile detect", 56 | "mobile detector", 57 | "php mobile detect" 58 | ], 59 | "time": "2017-08-29T18:23:54+00:00" 60 | } 61 | ], 62 | "packages-dev": [ 63 | { 64 | "name": "doctrine/instantiator", 65 | "version": "1.0.5", 66 | "source": { 67 | "type": "git", 68 | "url": "https://github.com/doctrine/instantiator.git", 69 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 70 | }, 71 | "dist": { 72 | "type": "zip", 73 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 74 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 75 | "shasum": "" 76 | }, 77 | "require": { 78 | "php": ">=5.3,<8.0-DEV" 79 | }, 80 | "require-dev": { 81 | "athletic/athletic": "~0.1.8", 82 | "ext-pdo": "*", 83 | "ext-phar": "*", 84 | "phpunit/phpunit": "~4.0", 85 | "squizlabs/php_codesniffer": "~2.0" 86 | }, 87 | "type": "library", 88 | "extra": { 89 | "branch-alias": { 90 | "dev-master": "1.0.x-dev" 91 | } 92 | }, 93 | "autoload": { 94 | "psr-4": { 95 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 96 | } 97 | }, 98 | "notification-url": "https://packagist.org/downloads/", 99 | "license": [ 100 | "MIT" 101 | ], 102 | "authors": [ 103 | { 104 | "name": "Marco Pivetta", 105 | "email": "ocramius@gmail.com", 106 | "homepage": "http://ocramius.github.com/" 107 | } 108 | ], 109 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 110 | "homepage": "https://github.com/doctrine/instantiator", 111 | "keywords": [ 112 | "constructor", 113 | "instantiate" 114 | ], 115 | "time": "2015-06-14T21:17:01+00:00" 116 | }, 117 | { 118 | "name": "myclabs/deep-copy", 119 | "version": "1.7.0", 120 | "source": { 121 | "type": "git", 122 | "url": "https://github.com/myclabs/DeepCopy.git", 123 | "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" 124 | }, 125 | "dist": { 126 | "type": "zip", 127 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", 128 | "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", 129 | "shasum": "" 130 | }, 131 | "require": { 132 | "php": "^5.6 || ^7.0" 133 | }, 134 | "require-dev": { 135 | "doctrine/collections": "^1.0", 136 | "doctrine/common": "^2.6", 137 | "phpunit/phpunit": "^4.1" 138 | }, 139 | "type": "library", 140 | "autoload": { 141 | "psr-4": { 142 | "DeepCopy\\": "src/DeepCopy/" 143 | }, 144 | "files": [ 145 | "src/DeepCopy/deep_copy.php" 146 | ] 147 | }, 148 | "notification-url": "https://packagist.org/downloads/", 149 | "license": [ 150 | "MIT" 151 | ], 152 | "description": "Create deep copies (clones) of your objects", 153 | "keywords": [ 154 | "clone", 155 | "copy", 156 | "duplicate", 157 | "object", 158 | "object graph" 159 | ], 160 | "time": "2017-10-19T19:58:43+00:00" 161 | }, 162 | { 163 | "name": "phpdocumentor/reflection-common", 164 | "version": "1.0.1", 165 | "source": { 166 | "type": "git", 167 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 168 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" 169 | }, 170 | "dist": { 171 | "type": "zip", 172 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 173 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 174 | "shasum": "" 175 | }, 176 | "require": { 177 | "php": ">=5.5" 178 | }, 179 | "require-dev": { 180 | "phpunit/phpunit": "^4.6" 181 | }, 182 | "type": "library", 183 | "extra": { 184 | "branch-alias": { 185 | "dev-master": "1.0.x-dev" 186 | } 187 | }, 188 | "autoload": { 189 | "psr-4": { 190 | "phpDocumentor\\Reflection\\": [ 191 | "src" 192 | ] 193 | } 194 | }, 195 | "notification-url": "https://packagist.org/downloads/", 196 | "license": [ 197 | "MIT" 198 | ], 199 | "authors": [ 200 | { 201 | "name": "Jaap van Otterdijk", 202 | "email": "opensource@ijaap.nl" 203 | } 204 | ], 205 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 206 | "homepage": "http://www.phpdoc.org", 207 | "keywords": [ 208 | "FQSEN", 209 | "phpDocumentor", 210 | "phpdoc", 211 | "reflection", 212 | "static analysis" 213 | ], 214 | "time": "2017-09-11T18:02:19+00:00" 215 | }, 216 | { 217 | "name": "phpdocumentor/reflection-docblock", 218 | "version": "3.2.2", 219 | "source": { 220 | "type": "git", 221 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 222 | "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157" 223 | }, 224 | "dist": { 225 | "type": "zip", 226 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/4aada1f93c72c35e22fb1383b47fee43b8f1d157", 227 | "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157", 228 | "shasum": "" 229 | }, 230 | "require": { 231 | "php": ">=5.5", 232 | "phpdocumentor/reflection-common": "^1.0@dev", 233 | "phpdocumentor/type-resolver": "^0.3.0", 234 | "webmozart/assert": "^1.0" 235 | }, 236 | "require-dev": { 237 | "mockery/mockery": "^0.9.4", 238 | "phpunit/phpunit": "^4.4" 239 | }, 240 | "type": "library", 241 | "autoload": { 242 | "psr-4": { 243 | "phpDocumentor\\Reflection\\": [ 244 | "src/" 245 | ] 246 | } 247 | }, 248 | "notification-url": "https://packagist.org/downloads/", 249 | "license": [ 250 | "MIT" 251 | ], 252 | "authors": [ 253 | { 254 | "name": "Mike van Riel", 255 | "email": "me@mikevanriel.com" 256 | } 257 | ], 258 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 259 | "time": "2017-08-08T06:39:58+00:00" 260 | }, 261 | { 262 | "name": "phpdocumentor/type-resolver", 263 | "version": "0.3.0", 264 | "source": { 265 | "type": "git", 266 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 267 | "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773" 268 | }, 269 | "dist": { 270 | "type": "zip", 271 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fb3933512008d8162b3cdf9e18dba9309b7c3773", 272 | "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773", 273 | "shasum": "" 274 | }, 275 | "require": { 276 | "php": "^5.5 || ^7.0", 277 | "phpdocumentor/reflection-common": "^1.0" 278 | }, 279 | "require-dev": { 280 | "mockery/mockery": "^0.9.4", 281 | "phpunit/phpunit": "^5.2||^4.8.24" 282 | }, 283 | "type": "library", 284 | "extra": { 285 | "branch-alias": { 286 | "dev-master": "1.0.x-dev" 287 | } 288 | }, 289 | "autoload": { 290 | "psr-4": { 291 | "phpDocumentor\\Reflection\\": [ 292 | "src/" 293 | ] 294 | } 295 | }, 296 | "notification-url": "https://packagist.org/downloads/", 297 | "license": [ 298 | "MIT" 299 | ], 300 | "authors": [ 301 | { 302 | "name": "Mike van Riel", 303 | "email": "me@mikevanriel.com" 304 | } 305 | ], 306 | "time": "2017-06-03T08:32:36+00:00" 307 | }, 308 | { 309 | "name": "phpspec/prophecy", 310 | "version": "v1.7.2", 311 | "source": { 312 | "type": "git", 313 | "url": "https://github.com/phpspec/prophecy.git", 314 | "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6" 315 | }, 316 | "dist": { 317 | "type": "zip", 318 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6", 319 | "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6", 320 | "shasum": "" 321 | }, 322 | "require": { 323 | "doctrine/instantiator": "^1.0.2", 324 | "php": "^5.3|^7.0", 325 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", 326 | "sebastian/comparator": "^1.1|^2.0", 327 | "sebastian/recursion-context": "^1.0|^2.0|^3.0" 328 | }, 329 | "require-dev": { 330 | "phpspec/phpspec": "^2.5|^3.2", 331 | "phpunit/phpunit": "^4.8 || ^5.6.5" 332 | }, 333 | "type": "library", 334 | "extra": { 335 | "branch-alias": { 336 | "dev-master": "1.7.x-dev" 337 | } 338 | }, 339 | "autoload": { 340 | "psr-0": { 341 | "Prophecy\\": "src/" 342 | } 343 | }, 344 | "notification-url": "https://packagist.org/downloads/", 345 | "license": [ 346 | "MIT" 347 | ], 348 | "authors": [ 349 | { 350 | "name": "Konstantin Kudryashov", 351 | "email": "ever.zet@gmail.com", 352 | "homepage": "http://everzet.com" 353 | }, 354 | { 355 | "name": "Marcello Duarte", 356 | "email": "marcello.duarte@gmail.com" 357 | } 358 | ], 359 | "description": "Highly opinionated mocking framework for PHP 5.3+", 360 | "homepage": "https://github.com/phpspec/prophecy", 361 | "keywords": [ 362 | "Double", 363 | "Dummy", 364 | "fake", 365 | "mock", 366 | "spy", 367 | "stub" 368 | ], 369 | "time": "2017-09-04T11:05:03+00:00" 370 | }, 371 | { 372 | "name": "phpunit/php-code-coverage", 373 | "version": "4.0.8", 374 | "source": { 375 | "type": "git", 376 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 377 | "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" 378 | }, 379 | "dist": { 380 | "type": "zip", 381 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", 382 | "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", 383 | "shasum": "" 384 | }, 385 | "require": { 386 | "ext-dom": "*", 387 | "ext-xmlwriter": "*", 388 | "php": "^5.6 || ^7.0", 389 | "phpunit/php-file-iterator": "^1.3", 390 | "phpunit/php-text-template": "^1.2", 391 | "phpunit/php-token-stream": "^1.4.2 || ^2.0", 392 | "sebastian/code-unit-reverse-lookup": "^1.0", 393 | "sebastian/environment": "^1.3.2 || ^2.0", 394 | "sebastian/version": "^1.0 || ^2.0" 395 | }, 396 | "require-dev": { 397 | "ext-xdebug": "^2.1.4", 398 | "phpunit/phpunit": "^5.7" 399 | }, 400 | "suggest": { 401 | "ext-xdebug": "^2.5.1" 402 | }, 403 | "type": "library", 404 | "extra": { 405 | "branch-alias": { 406 | "dev-master": "4.0.x-dev" 407 | } 408 | }, 409 | "autoload": { 410 | "classmap": [ 411 | "src/" 412 | ] 413 | }, 414 | "notification-url": "https://packagist.org/downloads/", 415 | "license": [ 416 | "BSD-3-Clause" 417 | ], 418 | "authors": [ 419 | { 420 | "name": "Sebastian Bergmann", 421 | "email": "sb@sebastian-bergmann.de", 422 | "role": "lead" 423 | } 424 | ], 425 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 426 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 427 | "keywords": [ 428 | "coverage", 429 | "testing", 430 | "xunit" 431 | ], 432 | "time": "2017-04-02T07:44:40+00:00" 433 | }, 434 | { 435 | "name": "phpunit/php-file-iterator", 436 | "version": "1.4.2", 437 | "source": { 438 | "type": "git", 439 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 440 | "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" 441 | }, 442 | "dist": { 443 | "type": "zip", 444 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", 445 | "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", 446 | "shasum": "" 447 | }, 448 | "require": { 449 | "php": ">=5.3.3" 450 | }, 451 | "type": "library", 452 | "extra": { 453 | "branch-alias": { 454 | "dev-master": "1.4.x-dev" 455 | } 456 | }, 457 | "autoload": { 458 | "classmap": [ 459 | "src/" 460 | ] 461 | }, 462 | "notification-url": "https://packagist.org/downloads/", 463 | "license": [ 464 | "BSD-3-Clause" 465 | ], 466 | "authors": [ 467 | { 468 | "name": "Sebastian Bergmann", 469 | "email": "sb@sebastian-bergmann.de", 470 | "role": "lead" 471 | } 472 | ], 473 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 474 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 475 | "keywords": [ 476 | "filesystem", 477 | "iterator" 478 | ], 479 | "time": "2016-10-03T07:40:28+00:00" 480 | }, 481 | { 482 | "name": "phpunit/php-text-template", 483 | "version": "1.2.1", 484 | "source": { 485 | "type": "git", 486 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 487 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 488 | }, 489 | "dist": { 490 | "type": "zip", 491 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 492 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 493 | "shasum": "" 494 | }, 495 | "require": { 496 | "php": ">=5.3.3" 497 | }, 498 | "type": "library", 499 | "autoload": { 500 | "classmap": [ 501 | "src/" 502 | ] 503 | }, 504 | "notification-url": "https://packagist.org/downloads/", 505 | "license": [ 506 | "BSD-3-Clause" 507 | ], 508 | "authors": [ 509 | { 510 | "name": "Sebastian Bergmann", 511 | "email": "sebastian@phpunit.de", 512 | "role": "lead" 513 | } 514 | ], 515 | "description": "Simple template engine.", 516 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 517 | "keywords": [ 518 | "template" 519 | ], 520 | "time": "2015-06-21T13:50:34+00:00" 521 | }, 522 | { 523 | "name": "phpunit/php-timer", 524 | "version": "1.0.9", 525 | "source": { 526 | "type": "git", 527 | "url": "https://github.com/sebastianbergmann/php-timer.git", 528 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" 529 | }, 530 | "dist": { 531 | "type": "zip", 532 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 533 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 534 | "shasum": "" 535 | }, 536 | "require": { 537 | "php": "^5.3.3 || ^7.0" 538 | }, 539 | "require-dev": { 540 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 541 | }, 542 | "type": "library", 543 | "extra": { 544 | "branch-alias": { 545 | "dev-master": "1.0-dev" 546 | } 547 | }, 548 | "autoload": { 549 | "classmap": [ 550 | "src/" 551 | ] 552 | }, 553 | "notification-url": "https://packagist.org/downloads/", 554 | "license": [ 555 | "BSD-3-Clause" 556 | ], 557 | "authors": [ 558 | { 559 | "name": "Sebastian Bergmann", 560 | "email": "sb@sebastian-bergmann.de", 561 | "role": "lead" 562 | } 563 | ], 564 | "description": "Utility class for timing", 565 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 566 | "keywords": [ 567 | "timer" 568 | ], 569 | "time": "2017-02-26T11:10:40+00:00" 570 | }, 571 | { 572 | "name": "phpunit/php-token-stream", 573 | "version": "1.4.11", 574 | "source": { 575 | "type": "git", 576 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 577 | "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" 578 | }, 579 | "dist": { 580 | "type": "zip", 581 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", 582 | "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", 583 | "shasum": "" 584 | }, 585 | "require": { 586 | "ext-tokenizer": "*", 587 | "php": ">=5.3.3" 588 | }, 589 | "require-dev": { 590 | "phpunit/phpunit": "~4.2" 591 | }, 592 | "type": "library", 593 | "extra": { 594 | "branch-alias": { 595 | "dev-master": "1.4-dev" 596 | } 597 | }, 598 | "autoload": { 599 | "classmap": [ 600 | "src/" 601 | ] 602 | }, 603 | "notification-url": "https://packagist.org/downloads/", 604 | "license": [ 605 | "BSD-3-Clause" 606 | ], 607 | "authors": [ 608 | { 609 | "name": "Sebastian Bergmann", 610 | "email": "sebastian@phpunit.de" 611 | } 612 | ], 613 | "description": "Wrapper around PHP's tokenizer extension.", 614 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 615 | "keywords": [ 616 | "tokenizer" 617 | ], 618 | "time": "2017-02-27T10:12:30+00:00" 619 | }, 620 | { 621 | "name": "phpunit/phpunit", 622 | "version": "5.7.23", 623 | "source": { 624 | "type": "git", 625 | "url": "https://github.com/sebastianbergmann/phpunit.git", 626 | "reference": "78532d5269d984660080d8e0f4c99c5c2ea65ffe" 627 | }, 628 | "dist": { 629 | "type": "zip", 630 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/78532d5269d984660080d8e0f4c99c5c2ea65ffe", 631 | "reference": "78532d5269d984660080d8e0f4c99c5c2ea65ffe", 632 | "shasum": "" 633 | }, 634 | "require": { 635 | "ext-dom": "*", 636 | "ext-json": "*", 637 | "ext-libxml": "*", 638 | "ext-mbstring": "*", 639 | "ext-xml": "*", 640 | "myclabs/deep-copy": "~1.3", 641 | "php": "^5.6 || ^7.0", 642 | "phpspec/prophecy": "^1.6.2", 643 | "phpunit/php-code-coverage": "^4.0.4", 644 | "phpunit/php-file-iterator": "~1.4", 645 | "phpunit/php-text-template": "~1.2", 646 | "phpunit/php-timer": "^1.0.6", 647 | "phpunit/phpunit-mock-objects": "^3.2", 648 | "sebastian/comparator": "^1.2.4", 649 | "sebastian/diff": "^1.4.3", 650 | "sebastian/environment": "^1.3.4 || ^2.0", 651 | "sebastian/exporter": "~2.0", 652 | "sebastian/global-state": "^1.1", 653 | "sebastian/object-enumerator": "~2.0", 654 | "sebastian/resource-operations": "~1.0", 655 | "sebastian/version": "~1.0.3|~2.0", 656 | "symfony/yaml": "~2.1|~3.0" 657 | }, 658 | "conflict": { 659 | "phpdocumentor/reflection-docblock": "3.0.2" 660 | }, 661 | "require-dev": { 662 | "ext-pdo": "*" 663 | }, 664 | "suggest": { 665 | "ext-xdebug": "*", 666 | "phpunit/php-invoker": "~1.1" 667 | }, 668 | "bin": [ 669 | "phpunit" 670 | ], 671 | "type": "library", 672 | "extra": { 673 | "branch-alias": { 674 | "dev-master": "5.7.x-dev" 675 | } 676 | }, 677 | "autoload": { 678 | "classmap": [ 679 | "src/" 680 | ] 681 | }, 682 | "notification-url": "https://packagist.org/downloads/", 683 | "license": [ 684 | "BSD-3-Clause" 685 | ], 686 | "authors": [ 687 | { 688 | "name": "Sebastian Bergmann", 689 | "email": "sebastian@phpunit.de", 690 | "role": "lead" 691 | } 692 | ], 693 | "description": "The PHP Unit Testing framework.", 694 | "homepage": "https://phpunit.de/", 695 | "keywords": [ 696 | "phpunit", 697 | "testing", 698 | "xunit" 699 | ], 700 | "time": "2017-10-15T06:13:55+00:00" 701 | }, 702 | { 703 | "name": "phpunit/phpunit-mock-objects", 704 | "version": "3.4.4", 705 | "source": { 706 | "type": "git", 707 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 708 | "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" 709 | }, 710 | "dist": { 711 | "type": "zip", 712 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", 713 | "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", 714 | "shasum": "" 715 | }, 716 | "require": { 717 | "doctrine/instantiator": "^1.0.2", 718 | "php": "^5.6 || ^7.0", 719 | "phpunit/php-text-template": "^1.2", 720 | "sebastian/exporter": "^1.2 || ^2.0" 721 | }, 722 | "conflict": { 723 | "phpunit/phpunit": "<5.4.0" 724 | }, 725 | "require-dev": { 726 | "phpunit/phpunit": "^5.4" 727 | }, 728 | "suggest": { 729 | "ext-soap": "*" 730 | }, 731 | "type": "library", 732 | "extra": { 733 | "branch-alias": { 734 | "dev-master": "3.2.x-dev" 735 | } 736 | }, 737 | "autoload": { 738 | "classmap": [ 739 | "src/" 740 | ] 741 | }, 742 | "notification-url": "https://packagist.org/downloads/", 743 | "license": [ 744 | "BSD-3-Clause" 745 | ], 746 | "authors": [ 747 | { 748 | "name": "Sebastian Bergmann", 749 | "email": "sb@sebastian-bergmann.de", 750 | "role": "lead" 751 | } 752 | ], 753 | "description": "Mock Object library for PHPUnit", 754 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 755 | "keywords": [ 756 | "mock", 757 | "xunit" 758 | ], 759 | "time": "2017-06-30T09:13:00+00:00" 760 | }, 761 | { 762 | "name": "sebastian/code-unit-reverse-lookup", 763 | "version": "1.0.1", 764 | "source": { 765 | "type": "git", 766 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 767 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" 768 | }, 769 | "dist": { 770 | "type": "zip", 771 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 772 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 773 | "shasum": "" 774 | }, 775 | "require": { 776 | "php": "^5.6 || ^7.0" 777 | }, 778 | "require-dev": { 779 | "phpunit/phpunit": "^5.7 || ^6.0" 780 | }, 781 | "type": "library", 782 | "extra": { 783 | "branch-alias": { 784 | "dev-master": "1.0.x-dev" 785 | } 786 | }, 787 | "autoload": { 788 | "classmap": [ 789 | "src/" 790 | ] 791 | }, 792 | "notification-url": "https://packagist.org/downloads/", 793 | "license": [ 794 | "BSD-3-Clause" 795 | ], 796 | "authors": [ 797 | { 798 | "name": "Sebastian Bergmann", 799 | "email": "sebastian@phpunit.de" 800 | } 801 | ], 802 | "description": "Looks up which function or method a line of code belongs to", 803 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 804 | "time": "2017-03-04T06:30:41+00:00" 805 | }, 806 | { 807 | "name": "sebastian/comparator", 808 | "version": "1.2.4", 809 | "source": { 810 | "type": "git", 811 | "url": "https://github.com/sebastianbergmann/comparator.git", 812 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" 813 | }, 814 | "dist": { 815 | "type": "zip", 816 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 817 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 818 | "shasum": "" 819 | }, 820 | "require": { 821 | "php": ">=5.3.3", 822 | "sebastian/diff": "~1.2", 823 | "sebastian/exporter": "~1.2 || ~2.0" 824 | }, 825 | "require-dev": { 826 | "phpunit/phpunit": "~4.4" 827 | }, 828 | "type": "library", 829 | "extra": { 830 | "branch-alias": { 831 | "dev-master": "1.2.x-dev" 832 | } 833 | }, 834 | "autoload": { 835 | "classmap": [ 836 | "src/" 837 | ] 838 | }, 839 | "notification-url": "https://packagist.org/downloads/", 840 | "license": [ 841 | "BSD-3-Clause" 842 | ], 843 | "authors": [ 844 | { 845 | "name": "Jeff Welch", 846 | "email": "whatthejeff@gmail.com" 847 | }, 848 | { 849 | "name": "Volker Dusch", 850 | "email": "github@wallbash.com" 851 | }, 852 | { 853 | "name": "Bernhard Schussek", 854 | "email": "bschussek@2bepublished.at" 855 | }, 856 | { 857 | "name": "Sebastian Bergmann", 858 | "email": "sebastian@phpunit.de" 859 | } 860 | ], 861 | "description": "Provides the functionality to compare PHP values for equality", 862 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 863 | "keywords": [ 864 | "comparator", 865 | "compare", 866 | "equality" 867 | ], 868 | "time": "2017-01-29T09:50:25+00:00" 869 | }, 870 | { 871 | "name": "sebastian/diff", 872 | "version": "1.4.3", 873 | "source": { 874 | "type": "git", 875 | "url": "https://github.com/sebastianbergmann/diff.git", 876 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" 877 | }, 878 | "dist": { 879 | "type": "zip", 880 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", 881 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", 882 | "shasum": "" 883 | }, 884 | "require": { 885 | "php": "^5.3.3 || ^7.0" 886 | }, 887 | "require-dev": { 888 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 889 | }, 890 | "type": "library", 891 | "extra": { 892 | "branch-alias": { 893 | "dev-master": "1.4-dev" 894 | } 895 | }, 896 | "autoload": { 897 | "classmap": [ 898 | "src/" 899 | ] 900 | }, 901 | "notification-url": "https://packagist.org/downloads/", 902 | "license": [ 903 | "BSD-3-Clause" 904 | ], 905 | "authors": [ 906 | { 907 | "name": "Kore Nordmann", 908 | "email": "mail@kore-nordmann.de" 909 | }, 910 | { 911 | "name": "Sebastian Bergmann", 912 | "email": "sebastian@phpunit.de" 913 | } 914 | ], 915 | "description": "Diff implementation", 916 | "homepage": "https://github.com/sebastianbergmann/diff", 917 | "keywords": [ 918 | "diff" 919 | ], 920 | "time": "2017-05-22T07:24:03+00:00" 921 | }, 922 | { 923 | "name": "sebastian/environment", 924 | "version": "2.0.0", 925 | "source": { 926 | "type": "git", 927 | "url": "https://github.com/sebastianbergmann/environment.git", 928 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" 929 | }, 930 | "dist": { 931 | "type": "zip", 932 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", 933 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", 934 | "shasum": "" 935 | }, 936 | "require": { 937 | "php": "^5.6 || ^7.0" 938 | }, 939 | "require-dev": { 940 | "phpunit/phpunit": "^5.0" 941 | }, 942 | "type": "library", 943 | "extra": { 944 | "branch-alias": { 945 | "dev-master": "2.0.x-dev" 946 | } 947 | }, 948 | "autoload": { 949 | "classmap": [ 950 | "src/" 951 | ] 952 | }, 953 | "notification-url": "https://packagist.org/downloads/", 954 | "license": [ 955 | "BSD-3-Clause" 956 | ], 957 | "authors": [ 958 | { 959 | "name": "Sebastian Bergmann", 960 | "email": "sebastian@phpunit.de" 961 | } 962 | ], 963 | "description": "Provides functionality to handle HHVM/PHP environments", 964 | "homepage": "http://www.github.com/sebastianbergmann/environment", 965 | "keywords": [ 966 | "Xdebug", 967 | "environment", 968 | "hhvm" 969 | ], 970 | "time": "2016-11-26T07:53:53+00:00" 971 | }, 972 | { 973 | "name": "sebastian/exporter", 974 | "version": "2.0.0", 975 | "source": { 976 | "type": "git", 977 | "url": "https://github.com/sebastianbergmann/exporter.git", 978 | "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" 979 | }, 980 | "dist": { 981 | "type": "zip", 982 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", 983 | "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", 984 | "shasum": "" 985 | }, 986 | "require": { 987 | "php": ">=5.3.3", 988 | "sebastian/recursion-context": "~2.0" 989 | }, 990 | "require-dev": { 991 | "ext-mbstring": "*", 992 | "phpunit/phpunit": "~4.4" 993 | }, 994 | "type": "library", 995 | "extra": { 996 | "branch-alias": { 997 | "dev-master": "2.0.x-dev" 998 | } 999 | }, 1000 | "autoload": { 1001 | "classmap": [ 1002 | "src/" 1003 | ] 1004 | }, 1005 | "notification-url": "https://packagist.org/downloads/", 1006 | "license": [ 1007 | "BSD-3-Clause" 1008 | ], 1009 | "authors": [ 1010 | { 1011 | "name": "Jeff Welch", 1012 | "email": "whatthejeff@gmail.com" 1013 | }, 1014 | { 1015 | "name": "Volker Dusch", 1016 | "email": "github@wallbash.com" 1017 | }, 1018 | { 1019 | "name": "Bernhard Schussek", 1020 | "email": "bschussek@2bepublished.at" 1021 | }, 1022 | { 1023 | "name": "Sebastian Bergmann", 1024 | "email": "sebastian@phpunit.de" 1025 | }, 1026 | { 1027 | "name": "Adam Harvey", 1028 | "email": "aharvey@php.net" 1029 | } 1030 | ], 1031 | "description": "Provides the functionality to export PHP variables for visualization", 1032 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1033 | "keywords": [ 1034 | "export", 1035 | "exporter" 1036 | ], 1037 | "time": "2016-11-19T08:54:04+00:00" 1038 | }, 1039 | { 1040 | "name": "sebastian/global-state", 1041 | "version": "1.1.1", 1042 | "source": { 1043 | "type": "git", 1044 | "url": "https://github.com/sebastianbergmann/global-state.git", 1045 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 1046 | }, 1047 | "dist": { 1048 | "type": "zip", 1049 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 1050 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 1051 | "shasum": "" 1052 | }, 1053 | "require": { 1054 | "php": ">=5.3.3" 1055 | }, 1056 | "require-dev": { 1057 | "phpunit/phpunit": "~4.2" 1058 | }, 1059 | "suggest": { 1060 | "ext-uopz": "*" 1061 | }, 1062 | "type": "library", 1063 | "extra": { 1064 | "branch-alias": { 1065 | "dev-master": "1.0-dev" 1066 | } 1067 | }, 1068 | "autoload": { 1069 | "classmap": [ 1070 | "src/" 1071 | ] 1072 | }, 1073 | "notification-url": "https://packagist.org/downloads/", 1074 | "license": [ 1075 | "BSD-3-Clause" 1076 | ], 1077 | "authors": [ 1078 | { 1079 | "name": "Sebastian Bergmann", 1080 | "email": "sebastian@phpunit.de" 1081 | } 1082 | ], 1083 | "description": "Snapshotting of global state", 1084 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1085 | "keywords": [ 1086 | "global state" 1087 | ], 1088 | "time": "2015-10-12T03:26:01+00:00" 1089 | }, 1090 | { 1091 | "name": "sebastian/object-enumerator", 1092 | "version": "2.0.1", 1093 | "source": { 1094 | "type": "git", 1095 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1096 | "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" 1097 | }, 1098 | "dist": { 1099 | "type": "zip", 1100 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", 1101 | "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", 1102 | "shasum": "" 1103 | }, 1104 | "require": { 1105 | "php": ">=5.6", 1106 | "sebastian/recursion-context": "~2.0" 1107 | }, 1108 | "require-dev": { 1109 | "phpunit/phpunit": "~5" 1110 | }, 1111 | "type": "library", 1112 | "extra": { 1113 | "branch-alias": { 1114 | "dev-master": "2.0.x-dev" 1115 | } 1116 | }, 1117 | "autoload": { 1118 | "classmap": [ 1119 | "src/" 1120 | ] 1121 | }, 1122 | "notification-url": "https://packagist.org/downloads/", 1123 | "license": [ 1124 | "BSD-3-Clause" 1125 | ], 1126 | "authors": [ 1127 | { 1128 | "name": "Sebastian Bergmann", 1129 | "email": "sebastian@phpunit.de" 1130 | } 1131 | ], 1132 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1133 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1134 | "time": "2017-02-18T15:18:39+00:00" 1135 | }, 1136 | { 1137 | "name": "sebastian/recursion-context", 1138 | "version": "2.0.0", 1139 | "source": { 1140 | "type": "git", 1141 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1142 | "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" 1143 | }, 1144 | "dist": { 1145 | "type": "zip", 1146 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", 1147 | "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", 1148 | "shasum": "" 1149 | }, 1150 | "require": { 1151 | "php": ">=5.3.3" 1152 | }, 1153 | "require-dev": { 1154 | "phpunit/phpunit": "~4.4" 1155 | }, 1156 | "type": "library", 1157 | "extra": { 1158 | "branch-alias": { 1159 | "dev-master": "2.0.x-dev" 1160 | } 1161 | }, 1162 | "autoload": { 1163 | "classmap": [ 1164 | "src/" 1165 | ] 1166 | }, 1167 | "notification-url": "https://packagist.org/downloads/", 1168 | "license": [ 1169 | "BSD-3-Clause" 1170 | ], 1171 | "authors": [ 1172 | { 1173 | "name": "Jeff Welch", 1174 | "email": "whatthejeff@gmail.com" 1175 | }, 1176 | { 1177 | "name": "Sebastian Bergmann", 1178 | "email": "sebastian@phpunit.de" 1179 | }, 1180 | { 1181 | "name": "Adam Harvey", 1182 | "email": "aharvey@php.net" 1183 | } 1184 | ], 1185 | "description": "Provides functionality to recursively process PHP variables", 1186 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1187 | "time": "2016-11-19T07:33:16+00:00" 1188 | }, 1189 | { 1190 | "name": "sebastian/resource-operations", 1191 | "version": "1.0.0", 1192 | "source": { 1193 | "type": "git", 1194 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1195 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" 1196 | }, 1197 | "dist": { 1198 | "type": "zip", 1199 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 1200 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 1201 | "shasum": "" 1202 | }, 1203 | "require": { 1204 | "php": ">=5.6.0" 1205 | }, 1206 | "type": "library", 1207 | "extra": { 1208 | "branch-alias": { 1209 | "dev-master": "1.0.x-dev" 1210 | } 1211 | }, 1212 | "autoload": { 1213 | "classmap": [ 1214 | "src/" 1215 | ] 1216 | }, 1217 | "notification-url": "https://packagist.org/downloads/", 1218 | "license": [ 1219 | "BSD-3-Clause" 1220 | ], 1221 | "authors": [ 1222 | { 1223 | "name": "Sebastian Bergmann", 1224 | "email": "sebastian@phpunit.de" 1225 | } 1226 | ], 1227 | "description": "Provides a list of PHP built-in functions that operate on resources", 1228 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1229 | "time": "2015-07-28T20:34:47+00:00" 1230 | }, 1231 | { 1232 | "name": "sebastian/version", 1233 | "version": "2.0.1", 1234 | "source": { 1235 | "type": "git", 1236 | "url": "https://github.com/sebastianbergmann/version.git", 1237 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 1238 | }, 1239 | "dist": { 1240 | "type": "zip", 1241 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 1242 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 1243 | "shasum": "" 1244 | }, 1245 | "require": { 1246 | "php": ">=5.6" 1247 | }, 1248 | "type": "library", 1249 | "extra": { 1250 | "branch-alias": { 1251 | "dev-master": "2.0.x-dev" 1252 | } 1253 | }, 1254 | "autoload": { 1255 | "classmap": [ 1256 | "src/" 1257 | ] 1258 | }, 1259 | "notification-url": "https://packagist.org/downloads/", 1260 | "license": [ 1261 | "BSD-3-Clause" 1262 | ], 1263 | "authors": [ 1264 | { 1265 | "name": "Sebastian Bergmann", 1266 | "email": "sebastian@phpunit.de", 1267 | "role": "lead" 1268 | } 1269 | ], 1270 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1271 | "homepage": "https://github.com/sebastianbergmann/version", 1272 | "time": "2016-10-03T07:35:21+00:00" 1273 | }, 1274 | { 1275 | "name": "symfony/yaml", 1276 | "version": "v3.3.10", 1277 | "source": { 1278 | "type": "git", 1279 | "url": "https://github.com/symfony/yaml.git", 1280 | "reference": "8c7bf1e7d5d6b05a690b715729cb4cd0c0a99c46" 1281 | }, 1282 | "dist": { 1283 | "type": "zip", 1284 | "url": "https://api.github.com/repos/symfony/yaml/zipball/8c7bf1e7d5d6b05a690b715729cb4cd0c0a99c46", 1285 | "reference": "8c7bf1e7d5d6b05a690b715729cb4cd0c0a99c46", 1286 | "shasum": "" 1287 | }, 1288 | "require": { 1289 | "php": "^5.5.9|>=7.0.8" 1290 | }, 1291 | "require-dev": { 1292 | "symfony/console": "~2.8|~3.0" 1293 | }, 1294 | "suggest": { 1295 | "symfony/console": "For validating YAML files using the lint command" 1296 | }, 1297 | "type": "library", 1298 | "extra": { 1299 | "branch-alias": { 1300 | "dev-master": "3.3-dev" 1301 | } 1302 | }, 1303 | "autoload": { 1304 | "psr-4": { 1305 | "Symfony\\Component\\Yaml\\": "" 1306 | }, 1307 | "exclude-from-classmap": [ 1308 | "/Tests/" 1309 | ] 1310 | }, 1311 | "notification-url": "https://packagist.org/downloads/", 1312 | "license": [ 1313 | "MIT" 1314 | ], 1315 | "authors": [ 1316 | { 1317 | "name": "Fabien Potencier", 1318 | "email": "fabien@symfony.com" 1319 | }, 1320 | { 1321 | "name": "Symfony Community", 1322 | "homepage": "https://symfony.com/contributors" 1323 | } 1324 | ], 1325 | "description": "Symfony Yaml Component", 1326 | "homepage": "https://symfony.com", 1327 | "time": "2017-10-05T14:43:42+00:00" 1328 | }, 1329 | { 1330 | "name": "webmozart/assert", 1331 | "version": "1.2.0", 1332 | "source": { 1333 | "type": "git", 1334 | "url": "https://github.com/webmozart/assert.git", 1335 | "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" 1336 | }, 1337 | "dist": { 1338 | "type": "zip", 1339 | "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", 1340 | "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", 1341 | "shasum": "" 1342 | }, 1343 | "require": { 1344 | "php": "^5.3.3 || ^7.0" 1345 | }, 1346 | "require-dev": { 1347 | "phpunit/phpunit": "^4.6", 1348 | "sebastian/version": "^1.0.1" 1349 | }, 1350 | "type": "library", 1351 | "extra": { 1352 | "branch-alias": { 1353 | "dev-master": "1.3-dev" 1354 | } 1355 | }, 1356 | "autoload": { 1357 | "psr-4": { 1358 | "Webmozart\\Assert\\": "src/" 1359 | } 1360 | }, 1361 | "notification-url": "https://packagist.org/downloads/", 1362 | "license": [ 1363 | "MIT" 1364 | ], 1365 | "authors": [ 1366 | { 1367 | "name": "Bernhard Schussek", 1368 | "email": "bschussek@gmail.com" 1369 | } 1370 | ], 1371 | "description": "Assertions to validate method input/output with nice error messages.", 1372 | "keywords": [ 1373 | "assert", 1374 | "check", 1375 | "validate" 1376 | ], 1377 | "time": "2016-11-23T20:04:58+00:00" 1378 | } 1379 | ], 1380 | "aliases": [], 1381 | "minimum-stability": "stable", 1382 | "stability-flags": [], 1383 | "prefer-stable": false, 1384 | "prefer-lowest": false, 1385 | "platform": [], 1386 | "platform-dev": [] 1387 | } 1388 | -------------------------------------------------------------------------------- /detect_mobile.info.yml: -------------------------------------------------------------------------------- 1 | name: Detect Mobile 2 | type: module 3 | description: A wrapper around the "Mobile_Detect.php" library - Detects mobile devices using HTTP headers, proving helper functions to developers for templates. 4 | core: 8.x 5 | version: 8.x-1.0 6 | package: Layout 7 | -------------------------------------------------------------------------------- /detect_mobile.links.menu.yml: -------------------------------------------------------------------------------- 1 | detect_mobile.admin_config_detect_mobile: 2 | title: 'Detect Mobile Config Page' 3 | parent: system.admin_config_system 4 | route_name: detect_mobile.default_form 5 | weight: -50 6 | -------------------------------------------------------------------------------- /detect_mobile.module: -------------------------------------------------------------------------------- 1 | ' . t('About') . ''; 19 | $output .= '

' . t('Mobile detect') . '

'; 20 | return $output; 21 | 22 | break; 23 | } 24 | } 25 | 26 | /** 27 | * Implements hook_theme(). 28 | */ 29 | function detect_mobile_theme() { 30 | return [ 31 | 'detect_mobile_block' => [ 32 | 'variables' => [ 33 | 'title' => NULL, 34 | 'description' => NULL, 35 | 'mobile_d' => NULL, 36 | 'desktop_d' => NULL, 37 | 'http_host' => NULL, 38 | ], 39 | 'template' => 'block--detect-mobile', 40 | ], 41 | ]; 42 | } 43 | -------------------------------------------------------------------------------- /detect_mobile.routing.yml: -------------------------------------------------------------------------------- 1 | detect_mobile.default_form: 2 | path: '/admin/config/system/detect_mobile' 3 | defaults: 4 | _form: '\Drupal\detect_mobile\Form\DefaultForm' 5 | _title: 'Detect Mobile Config Page' 6 | requirements: 7 | _permission: 'administer site configuration' 8 | -------------------------------------------------------------------------------- /detect_mobile.services.yml: -------------------------------------------------------------------------------- 1 | services: 2 | mobile_detect: 3 | class: Drupal\detect_mobile\Detect\MobileDetect 4 | mobile_detect.twig.extension: 5 | class: Drupal\detect_mobile\Twig\MobileDetectExtension 6 | arguments: ["@mobile_detect"] 7 | tags: 8 | - { name: twig.extension } 9 | mobile_detect.middleware: 10 | class: Drupal\detect_mobile\Middleware\MobileDetectMiddleware 11 | arguments: ["@mobile_detect.manager", "@mobile_detect" ] 12 | tags: 13 | - { name: http_middleware, priority: 400 } 14 | mobile_detect.manager: 15 | class: Drupal\detect_mobile\Middleware\MobileDetectManager 16 | tags: 17 | - { name: backend_overridable } 18 | mobile_detect.subscriber: 19 | class: Drupal\detect_mobile\EventSubscriber\MobileDetectSubscriber 20 | tags: 21 | - { name: event_subscriber } 22 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | tests 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/Detect/MobileDetect.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class MobileDetect extends BaseMobileDetect {} -------------------------------------------------------------------------------- /src/EventSubscriber/MobileDetectSubscriber.php: -------------------------------------------------------------------------------- 1 | get('mobile_domain'); 37 | $dd = $config->get('desktop_domain'); 38 | $response = $event->getResponse(); 39 | $version = $event->getRequest()->query->get('version'); 40 | if (!empty($dd) && $version == 'desktop') { 41 | $cookie = new Cookie('site_version', 'desktop'); 42 | $response->headers->setCookie($cookie); 43 | } 44 | elseif (!empty($md) && $version == 'mobile') { 45 | $cookie = new Cookie('site_version', 'mobile'); 46 | $response->headers->setCookie($cookie); 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/Form/DefaultForm.php: -------------------------------------------------------------------------------- 1 | config('detect_mobile.default_form.settings'); 32 | $form['desktop_domain'] = [ 33 | '#type' => 'textfield', 34 | '#title' => $this->t('Desktop Domain'), 35 | '#description' => $this->t("enter the domain for the desktop without 'http' for example 'example.com'"), 36 | '#default_value' => $config->get('desktop_domain'), 37 | '#maxlength' => 32, 38 | '#size' => 32, 39 | '#weight' => '0', 40 | ]; 41 | $form['mobile_domain'] = [ 42 | '#type' => 'textfield', 43 | '#title' => $this->t('Mobile Domain'), 44 | '#description' => $this->t("enter the domain for the mobile without 'http' for example 'm.example.com'"), 45 | '#default_value' => $config->get('mobile_domain'), 46 | '#maxlength' => 32, 47 | '#size' => 32, 48 | '#weight' => '0', 49 | ]; 50 | 51 | return parent::buildForm($form, $form_state); 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | public function validateForm(array &$form, FormStateInterface $form_state) { 58 | parent::validateForm($form, $form_state); 59 | } 60 | 61 | /** 62 | * {@inheritdoc} 63 | */ 64 | public function submitForm(array &$form, FormStateInterface $form_state) { 65 | // Display result. 66 | $values = $form_state->getValues(); 67 | $this->config('detect_mobile.default_form.settings') 68 | ->set('desktop_domain', $values['desktop_domain']) 69 | ->set('mobile_domain', $values['mobile_domain']) 70 | ->save(); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/Middleware/MobileDetectManager.php: -------------------------------------------------------------------------------- 1 | MobileDetectConfig = \Drupal::config('detect_mobile.default_form.settings'); 24 | } 25 | 26 | /** 27 | * {@inheritdoc} 28 | */ 29 | public function getDesktop() { 30 | return $this->MobileDetectConfig->get('desktop_domain'); 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | public function getMobile() { 37 | return $this->MobileDetectConfig->get('mobile_domain'); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/Middleware/MobileDetectManagerInterface.php: -------------------------------------------------------------------------------- 1 | httpKernel = $http_kernel; 36 | $this->manager = $manager; 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) { 43 | $mobileDetector = \Drupal::service('mobile_detect'); 44 | $mobileDomain = $this->manager->getMobile(); 45 | $desktopDomain = $this->manager->getDesktop(); 46 | $http_host = $request->getHttpHost(); 47 | $req_uri = $request->getRequestUri(); 48 | $req_sheme = $request->getScheme(); 49 | $version = $request->query->get('version'); 50 | $site_version = $request->cookies->get('site_version'); 51 | if (!empty($mobileDomain) && $mobileDetector->isMobile() 52 | && $http_host !== $mobileDomain && $version !== 'desktop' 53 | && $site_version !== 'desktop') { 54 | return new RedirectResponse($req_sheme . '://' . $mobileDomain . $req_uri); 55 | } 56 | if (!empty($desktopDomain) && !$mobileDetector->isMobile() 57 | && $http_host !== $desktopDomain && $version !== 'mobile' 58 | && $site_version !== 'mobile') { 59 | return new RedirectResponse($req_sheme . '://' . $desktopDomain . $req_uri); 60 | } 61 | return $this->httpKernel->handle($request, $type, $catch); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/Plugin/Block/MobileDetectBlock.php: -------------------------------------------------------------------------------- 1 | 'detect_mobile_block', 24 | '#mobile_d' => $config->get('mobile_domain'), 25 | '#desktop_d' => $config->get('desktop_domain'), 26 | '#http_host' => \Drupal::request()->getHost(), 27 | ]; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/Twig/MobileDetectExtension.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class MobileDetectExtension extends \Twig_Extension 11 | { 12 | /** 13 | * @var MobileDetect 14 | */ 15 | protected $mobileDetector; 16 | 17 | /** 18 | * Constructor 19 | * @param MobileDetect $mobileDetector 20 | */ 21 | public function __construct(MobileDetect $mobileDetector) 22 | { 23 | $this->mobileDetector = $mobileDetector; 24 | } 25 | 26 | /** 27 | * Get extension twig function 28 | * @return array 29 | */ 30 | public function getFunctions() 31 | { 32 | return array( 33 | 'is_mobile' => new \Twig_Function_Function(array($this, 'isMobile')), 34 | 'is_tablet' => new \Twig_Function_Function(array($this, 'isTablet')), 35 | 'is_device' => new \Twig_Function_Function(array($this, 'isDevice')), 36 | 'is_ios' => new \Twig_Function_Function(array($this, 'isIOS')), 37 | 'is_android_os' => new \Twig_Function_Function(array($this, 'isAndroidOS')), 38 | ); 39 | } 40 | 41 | /** 42 | * Is mobile 43 | * @return boolean 44 | */ 45 | public function isMobile() 46 | { 47 | return $this->mobileDetector->isMobile(); 48 | } 49 | 50 | /** 51 | * Is tablet 52 | * @return boolean 53 | */ 54 | public function isTablet() 55 | { 56 | return $this->mobileDetector->isTablet(); 57 | } 58 | 59 | /** 60 | * Is device 61 | * @param string $deviceName is[iPhone|BlackBerry|HTC|Nexus|Dell|Motorola|Samsung|Sony|Asus|Palm|Vertu|...] 62 | * 63 | * @return boolean 64 | */ 65 | public function isDevice($deviceName) 66 | { 67 | $magicMethodName = 'is' . strtolower((string) $deviceName); 68 | 69 | return $this->mobileDetector->$magicMethodName(); 70 | } 71 | 72 | /** 73 | * Is iOS 74 | * @return boolean 75 | */ 76 | public function isIOS() 77 | { 78 | return $this->mobileDetector->isIOS(); 79 | } 80 | 81 | /** 82 | * Is Android OS 83 | * @return boolean 84 | */ 85 | public function isAndroidOS() 86 | { 87 | return $this->mobileDetector->isAndroidOS(); 88 | } 89 | 90 | /** 91 | * Extension name 92 | * @return string 93 | */ 94 | public function getName() 95 | { 96 | return 'mobile_detect.twig.extension'; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /templates/block--detect-mobile.html.twig: -------------------------------------------------------------------------------- 1 | {# 2 | /** 3 | * @file 4 | * Default theme implementation to display a block. 5 | * 6 | * Available variables: 7 | * - plugin_id: The ID of the block implementation. 8 | * - label: The configured label of the block if visible. 9 | * - configuration: A list of the block's configuration values. 10 | * - label: The configured label for the block. 11 | * - label_display: The display settings for the label. 12 | * - provider: The module or other provider that provided this block plugin. 13 | * - Block plugin specific settings will also be stored here. 14 | * - content: The content of this block. 15 | * - attributes: array of HTML attributes populated by modules, intended to 16 | * be added to the main container tag of this template. 17 | * - id: A valid HTML ID and guaranteed unique. 18 | * - title_attributes: Same as attributes, except applied to the main title 19 | * tag that appears in the template. 20 | * - content_attributes: Same as attributes, except applied to the main content 21 | * tag that appears in the template. 22 | * - title_prefix: Additional output populated by modules, intended to be 23 | * displayed in front of the main title tag that appears in the template. 24 | * - title_suffix: Additional output populated by modules, intended to be 25 | * displayed after the main title tag that appears in the template. 26 | * 27 | * @see template_preprocess_block() 28 | * 29 | * @ingroup themeable 30 | */ 31 | #} 32 | {% 33 | set classes = [ 34 | 'block', 35 | 'block-' ~ configuration.provider|clean_class, 36 | 'block-' ~ plugin_id|clean_class, 37 | ] 38 | %} 39 | 40 | {{ title_prefix }} 41 | {% if label %} 42 | {{ label }} 43 | {% endif %} 44 | {{ title_suffix }} 45 | {% block content %} 46 | 47 | {% if mobile_d == http_host %} 48 | {{ 'Desktop version'|t }} 49 | {% else %} 50 | {{ 'Mobile version'|t }} 51 | {% endif %} 52 | 53 | {% endblock %} 54 | 55 | -------------------------------------------------------------------------------- /tests/Detect/MobileDetectTest.php: -------------------------------------------------------------------------------- 1 | detectMobile = $this->createMock(MobileDetect::class); 30 | $this-> object = new MobileDetectExtension($this->detectMobile); 31 | } 32 | } 33 | --------------------------------------------------------------------------------