├── .gitignore ├── LICENSE ├── README.md ├── UPGRADE.md ├── app ├── .htaccess ├── AppCache.php ├── AppKernel.php ├── Resources │ └── views │ │ └── base.html.twig ├── SymfonyRequirements.php ├── autoload.php ├── bootstrap.php.cache ├── check.php ├── config │ ├── config.yml │ ├── config_dev.yml │ ├── config_prod.yml │ ├── config_test.yml │ ├── parameters.yml │ ├── routing.yml │ ├── routing_dev.yml │ └── security.yml ├── console └── phpunit.xml.dist ├── composer.json ├── src ├── .htaccess └── Henter │ └── GEOBundle │ ├── Command │ ├── ImportCommand.php │ ├── geointersects.php │ └── places.json │ ├── Controller │ ├── BaseController.php │ └── PlaceController.php │ ├── DependencyInjection │ ├── Configuration.php │ └── HenterGEOExtension.php │ ├── Document │ ├── Coordinate.php │ └── Place.php │ ├── HenterGEOBundle.php │ ├── Repository │ └── PlaceRepository.php │ ├── Resources │ ├── config │ │ └── services.yml │ ├── doc │ │ └── index.rst │ ├── translations │ │ └── messages.fr.xlf │ └── views │ │ └── Place │ │ ├── box.html.twig │ │ ├── center.html.twig │ │ ├── distance.html.twig │ │ ├── geointersect.html.twig │ │ ├── geonear.html.twig │ │ ├── index.html.twig │ │ ├── near.html.twig │ │ ├── polygon.html.twig │ │ └── targets.html.twig │ ├── Twig │ └── GEOExtension.php │ └── Util │ └── LocationService.php └── web ├── .htaccess ├── app.php ├── app_dev.php ├── apple-touch-icon.png ├── config.php ├── favicon.ico └── robots.txt /.gitignore: -------------------------------------------------------------------------------- 1 | web/bundles/ 2 | web/tmp* 3 | code_check.php 4 | app/bootstrap* 5 | app/cache/* 6 | app/logs/* 7 | vendor/ 8 | composer.lock 9 | composer.phar 10 | web/js/* 11 | web/css/* 12 | web/*.log 13 | *.bak 14 | *.back 15 | *.swp 16 | *.log 17 | *~ 18 | .DS_Store 19 | .idea/ 20 | ._.DS_Store 21 | web/resize/ 22 | nbproject/ 23 | robots.txt 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2004-2013 Fabien Potencier 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | HenterGEO 2 | ========= 3 | 基于Symfony2和MongoDB的地理位置查询演示 4 | 5 | Install 6 | ------- 7 | ``` 8 | $ git clone https://github.com/henter/HenterGEO.git 9 | $ cd HenterGEO/ 10 | $ composer update 11 | $ php app/console doctrine:mongodb:schema:update 12 | $ php app/console geo:data:import 13 | ``` 14 | -------------------------------------------------------------------------------- /UPGRADE.md: -------------------------------------------------------------------------------- 1 | Symfony Standard Edition Upgrade 2 | ================================ 3 | 4 | From Symfony 2.0 to Symfony 2.1 5 | ------------------------------- 6 | 7 | ### Project Dependencies 8 | 9 | As of Symfony 2.1, project dependencies are managed by 10 | [Composer](http://getcomposer.org/): 11 | 12 | * The `bin/vendors` script can be removed as `composer.phar` does all the work 13 | now (it is recommended to install it globally on your machine). 14 | 15 | * The `deps` file need to be replaced with the `composer.json` one. 16 | 17 | * The `composer.lock` is the equivalent of the generated `deps.lock` file and 18 | it is automatically generated by Composer. 19 | 20 | Download the default 21 | [`composer.json`](https://raw.github.com/symfony/symfony-standard/2.1/composer.json) 22 | and 23 | [`composer.lock`](https://raw.github.com/symfony/symfony-standard/2.1/composer.lock) 24 | files for Symfony 2.1 and put them into the main directory of your project. If 25 | you have customized your `deps` file, move the added dependencies to the 26 | `composer.json` file (many bundles and PHP libraries are already available as 27 | Composer packages -- search for them on [Packagist](http://packagist.org/)). 28 | 29 | Remove your current `vendor` directory. 30 | 31 | Finally, run Composer: 32 | 33 | $ composer.phar install 34 | 35 | Note: You must complete the upgrade steps below so composer can successfully generate the autoload files. 36 | 37 | ### `app/autoload.php` 38 | 39 | The default `autoload.php` reads as follows (it has been simplified a lot as 40 | autoloading for libraries and bundles declared in your `composer.json` file is 41 | automatically managed by the Composer autoloader): 42 | 43 | add('', __DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs'); 54 | } 55 | 56 | AnnotationRegistry::registerLoader(array($loader, 'loadClass')); 57 | 58 | return $loader; 59 | 60 | ### `app/config/config.yml` 61 | 62 | The `framework.charset` setting must be removed. If you are not using `UTF-8` 63 | for your application, override the `getCharset()` method in your `AppKernel` 64 | class instead: 65 | 66 | class AppKernel extends Kernel 67 | { 68 | public function getCharset() 69 | { 70 | return 'ISO-8859-1'; 71 | } 72 | 73 | // ... 74 | } 75 | 76 | You might want to add the new `strict_requirements` parameter to 77 | `framework.router` (it avoids fatal errors in the production environment when 78 | a link cannot be generated): 79 | 80 | framework: 81 | router: 82 | strict_requirements: "%kernel.debug%" 83 | 84 | The `default_locale` parameter is now a setting of the main `framework` 85 | configuration (it was under the `framework.session` in 2.0): 86 | 87 | framework: 88 | default_locale: "%locale%" 89 | 90 | The `auto_start` setting under `framework.session` must be removed as it is 91 | not used anymore (the session is now always started on-demand). If 92 | `auto_start` was the only setting under the `framework.session` entry, don't 93 | remove it entirely, but set its value to `~` (`~` means `null` in YAML) 94 | instead: 95 | 96 | framework: 97 | session: ~ 98 | 99 | The `trust_proxy_headers` setting was added in the default configuration file 100 | (as it should be set to `true` when you install your application behind a 101 | reverse proxy): 102 | 103 | framework: 104 | trust_proxy_headers: false 105 | 106 | An empty `bundles` entry was added to the `assetic` configuration: 107 | 108 | assetic: 109 | bundles: [] 110 | 111 | The default `swiftmailer` configuration now has the `spool` setting configured 112 | to the `memory` type to defer email sending after the response is sent to the 113 | user (recommended for better end-user performance): 114 | 115 | swiftmailer: 116 | spool: { type: memory } 117 | 118 | The `jms_security_extra` configuration was moved to the `security.yml` 119 | configuration file. 120 | 121 | ### `app/config/config_dev.yml` 122 | 123 | An example of how to send all emails to a unique address was added: 124 | 125 | #swiftmailer: 126 | # delivery_address: me@example.com 127 | 128 | ### `app/config/config_test.yml` 129 | 130 | The `storage_id` setting must be changed to `session.storage.mock_file`: 131 | 132 | framework: 133 | session: 134 | storage_id: session.storage.mock_file 135 | 136 | ### `app/config/parameters.ini` 137 | 138 | The file has been converted to a YAML file which reads as follows: 139 | 140 | parameters: 141 | database_driver: pdo_mysql 142 | database_host: localhost 143 | database_port: ~ 144 | database_name: symfony 145 | database_user: root 146 | database_password: ~ 147 | 148 | mailer_transport: smtp 149 | mailer_host: localhost 150 | mailer_user: ~ 151 | mailer_password: ~ 152 | 153 | locale: en 154 | secret: ThisTokenIsNotSoSecretChangeIt 155 | 156 | Note that if you convert your parameters file to YAML, you must also change 157 | its reference in `app/config/config.yml`. 158 | 159 | ### `app/config/routing_dev.yml` 160 | 161 | The `_assetic` entry was removed: 162 | 163 | #_assetic: 164 | # resource: . 165 | # type: assetic 166 | 167 | ### `app/config/security.yml` 168 | 169 | Under `security.access_control`, the default rule for internal routes was changed: 170 | 171 | security: 172 | access_control: 173 | #- { path: ^/_internal/secure, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 } 174 | 175 | Under `security.providers`, the `in_memory` example was updated to the following: 176 | 177 | security: 178 | providers: 179 | in_memory: 180 | memory: 181 | users: 182 | user: { password: userpass, roles: [ 'ROLE_USER' ] } 183 | admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] } 184 | 185 | ### `app/AppKernel.php` 186 | 187 | The following bundles have been added to the list of default registered bundles: 188 | 189 | new JMS\AopBundle\JMSAopBundle(), 190 | new JMS\DiExtraBundle\JMSDiExtraBundle($this), 191 | 192 | You must also rename the DoctrineBundle from: 193 | 194 | new Symfony\Bundle\DoctrineBundle\DoctrineBundle(), 195 | 196 | to: 197 | 198 | new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(), 199 | 200 | ### `web/app.php` 201 | 202 | The default `web/app.php` file now reads as follows: 203 | 204 | register(true); 216 | */ 217 | 218 | require_once __DIR__.'/../app/AppKernel.php'; 219 | //require_once __DIR__.'/../app/AppCache.php'; 220 | 221 | $kernel = new AppKernel('prod', false); 222 | $kernel->loadClassCache(); 223 | //$kernel = new AppCache($kernel); 224 | $request = Request::createFromGlobals(); 225 | $response = $kernel->handle($request); 226 | $response->send(); 227 | $kernel->terminate($request, $response); 228 | 229 | ### `web/app_dev.php` 230 | 231 | The default `web/app_dev.php` file now reads as follows: 232 | 233 | loadClassCache(); 259 | $request = Request::createFromGlobals(); 260 | $response = $kernel->handle($request); 261 | $response->send(); 262 | $kernel->terminate($request, $response); 263 | -------------------------------------------------------------------------------- /app/.htaccess: -------------------------------------------------------------------------------- 1 | deny from all -------------------------------------------------------------------------------- /app/AppCache.php: -------------------------------------------------------------------------------- 1 | getEnvironment(), array('dev', 'test'))) { 27 | $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); 28 | $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle(); 29 | $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle(); 30 | $bundles[] = new RaulFraile\Bundle\LadybugBundle\RaulFraileLadybugBundle(); 31 | } 32 | 33 | return $bundles; 34 | } 35 | 36 | public function registerContainerConfiguration(LoaderInterface $loader) 37 | { 38 | $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/Resources/views/base.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block title %}Welcome!{% endblock %} 6 | {% block stylesheets %}{% endblock %} 7 | 8 | 9 | 10 | {% block body %}{% endblock %} 11 | {% block javascripts %}{% endblock %} 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/SymfonyRequirements.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | /* 13 | * Users of PHP 5.2 should be able to run the requirements checks. 14 | * This is why the file and all classes must be compatible with PHP 5.2+ 15 | * (e.g. not using namespaces and closures). 16 | * 17 | * ************** CAUTION ************** 18 | * 19 | * DO NOT EDIT THIS FILE as it will be overriden by Composer as part of 20 | * the installation/update process. The original file resides in the 21 | * SensioDistributionBundle. 22 | * 23 | * ************** CAUTION ************** 24 | */ 25 | 26 | /** 27 | * Represents a single PHP requirement, e.g. an installed extension. 28 | * It can be a mandatory requirement or an optional recommendation. 29 | * There is a special subclass, named PhpIniRequirement, to check a php.ini configuration. 30 | * 31 | * @author Tobias Schultze 32 | */ 33 | class Requirement 34 | { 35 | private $fulfilled; 36 | private $testMessage; 37 | private $helpText; 38 | private $helpHtml; 39 | private $optional; 40 | 41 | /** 42 | * Constructor that initializes the requirement. 43 | * 44 | * @param Boolean $fulfilled Whether the requirement is fulfilled 45 | * @param string $testMessage The message for testing the requirement 46 | * @param string $helpHtml The help text formatted in HTML for resolving the problem 47 | * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) 48 | * @param Boolean $optional Whether this is only an optional recommendation not a mandatory requirement 49 | */ 50 | public function __construct($fulfilled, $testMessage, $helpHtml, $helpText = null, $optional = false) 51 | { 52 | $this->fulfilled = (Boolean) $fulfilled; 53 | $this->testMessage = (string) $testMessage; 54 | $this->helpHtml = (string) $helpHtml; 55 | $this->helpText = null === $helpText ? strip_tags($this->helpHtml) : (string) $helpText; 56 | $this->optional = (Boolean) $optional; 57 | } 58 | 59 | /** 60 | * Returns whether the requirement is fulfilled. 61 | * 62 | * @return Boolean true if fulfilled, otherwise false 63 | */ 64 | public function isFulfilled() 65 | { 66 | return $this->fulfilled; 67 | } 68 | 69 | /** 70 | * Returns the message for testing the requirement. 71 | * 72 | * @return string The test message 73 | */ 74 | public function getTestMessage() 75 | { 76 | return $this->testMessage; 77 | } 78 | 79 | /** 80 | * Returns the help text for resolving the problem 81 | * 82 | * @return string The help text 83 | */ 84 | public function getHelpText() 85 | { 86 | return $this->helpText; 87 | } 88 | 89 | /** 90 | * Returns the help text formatted in HTML. 91 | * 92 | * @return string The HTML help 93 | */ 94 | public function getHelpHtml() 95 | { 96 | return $this->helpHtml; 97 | } 98 | 99 | /** 100 | * Returns whether this is only an optional recommendation and not a mandatory requirement. 101 | * 102 | * @return Boolean true if optional, false if mandatory 103 | */ 104 | public function isOptional() 105 | { 106 | return $this->optional; 107 | } 108 | } 109 | 110 | /** 111 | * Represents a PHP requirement in form of a php.ini configuration. 112 | * 113 | * @author Tobias Schultze 114 | */ 115 | class PhpIniRequirement extends Requirement 116 | { 117 | /** 118 | * Constructor that initializes the requirement. 119 | * 120 | * @param string $cfgName The configuration name used for ini_get() 121 | * @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false, 122 | or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement 123 | * @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. 124 | This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. 125 | Example: You require a config to be true but PHP later removes this config and defaults it to true internally. 126 | * @param string|null $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived) 127 | * @param string|null $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived) 128 | * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) 129 | * @param Boolean $optional Whether this is only an optional recommendation not a mandatory requirement 130 | */ 131 | public function __construct($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null, $optional = false) 132 | { 133 | $cfgValue = ini_get($cfgName); 134 | 135 | if (is_callable($evaluation)) { 136 | if (null === $testMessage || null === $helpHtml) { 137 | throw new InvalidArgumentException('You must provide the parameters testMessage and helpHtml for a callback evaluation.'); 138 | } 139 | 140 | $fulfilled = call_user_func($evaluation, $cfgValue); 141 | } else { 142 | if (null === $testMessage) { 143 | $testMessage = sprintf('%s %s be %s in php.ini', 144 | $cfgName, 145 | $optional ? 'should' : 'must', 146 | $evaluation ? 'enabled' : 'disabled' 147 | ); 148 | } 149 | 150 | if (null === $helpHtml) { 151 | $helpHtml = sprintf('Set %s to %s in php.ini*.', 152 | $cfgName, 153 | $evaluation ? 'on' : 'off' 154 | ); 155 | } 156 | 157 | $fulfilled = $evaluation == $cfgValue; 158 | } 159 | 160 | parent::__construct($fulfilled || ($approveCfgAbsence && false === $cfgValue), $testMessage, $helpHtml, $helpText, $optional); 161 | } 162 | } 163 | 164 | /** 165 | * A RequirementCollection represents a set of Requirement instances. 166 | * 167 | * @author Tobias Schultze 168 | */ 169 | class RequirementCollection implements IteratorAggregate 170 | { 171 | private $requirements = array(); 172 | 173 | /** 174 | * Gets the current RequirementCollection as an Iterator. 175 | * 176 | * @return Traversable A Traversable interface 177 | */ 178 | public function getIterator() 179 | { 180 | return new ArrayIterator($this->requirements); 181 | } 182 | 183 | /** 184 | * Adds a Requirement. 185 | * 186 | * @param Requirement $requirement A Requirement instance 187 | */ 188 | public function add(Requirement $requirement) 189 | { 190 | $this->requirements[] = $requirement; 191 | } 192 | 193 | /** 194 | * Adds a mandatory requirement. 195 | * 196 | * @param Boolean $fulfilled Whether the requirement is fulfilled 197 | * @param string $testMessage The message for testing the requirement 198 | * @param string $helpHtml The help text formatted in HTML for resolving the problem 199 | * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) 200 | */ 201 | public function addRequirement($fulfilled, $testMessage, $helpHtml, $helpText = null) 202 | { 203 | $this->add(new Requirement($fulfilled, $testMessage, $helpHtml, $helpText, false)); 204 | } 205 | 206 | /** 207 | * Adds an optional recommendation. 208 | * 209 | * @param Boolean $fulfilled Whether the recommendation is fulfilled 210 | * @param string $testMessage The message for testing the recommendation 211 | * @param string $helpHtml The help text formatted in HTML for resolving the problem 212 | * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) 213 | */ 214 | public function addRecommendation($fulfilled, $testMessage, $helpHtml, $helpText = null) 215 | { 216 | $this->add(new Requirement($fulfilled, $testMessage, $helpHtml, $helpText, true)); 217 | } 218 | 219 | /** 220 | * Adds a mandatory requirement in form of a php.ini configuration. 221 | * 222 | * @param string $cfgName The configuration name used for ini_get() 223 | * @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false, 224 | or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement 225 | * @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. 226 | This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. 227 | Example: You require a config to be true but PHP later removes this config and defaults it to true internally. 228 | * @param string $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived) 229 | * @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived) 230 | * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) 231 | */ 232 | public function addPhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null) 233 | { 234 | $this->add(new PhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence, $testMessage, $helpHtml, $helpText, false)); 235 | } 236 | 237 | /** 238 | * Adds an optional recommendation in form of a php.ini configuration. 239 | * 240 | * @param string $cfgName The configuration name used for ini_get() 241 | * @param Boolean|callback $evaluation Either a Boolean indicating whether the configuration should evaluate to true or false, 242 | or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement 243 | * @param Boolean $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false. 244 | This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin. 245 | Example: You require a config to be true but PHP later removes this config and defaults it to true internally. 246 | * @param string $testMessage The message for testing the requirement (when null and $evaluation is a Boolean a default message is derived) 247 | * @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a Boolean a default help is derived) 248 | * @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags) 249 | */ 250 | public function addPhpIniRecommendation($cfgName, $evaluation, $approveCfgAbsence = false, $testMessage = null, $helpHtml = null, $helpText = null) 251 | { 252 | $this->add(new PhpIniRequirement($cfgName, $evaluation, $approveCfgAbsence, $testMessage, $helpHtml, $helpText, true)); 253 | } 254 | 255 | /** 256 | * Adds a requirement collection to the current set of requirements. 257 | * 258 | * @param RequirementCollection $collection A RequirementCollection instance 259 | */ 260 | public function addCollection(RequirementCollection $collection) 261 | { 262 | $this->requirements = array_merge($this->requirements, $collection->all()); 263 | } 264 | 265 | /** 266 | * Returns both requirements and recommendations. 267 | * 268 | * @return array Array of Requirement instances 269 | */ 270 | public function all() 271 | { 272 | return $this->requirements; 273 | } 274 | 275 | /** 276 | * Returns all mandatory requirements. 277 | * 278 | * @return array Array of Requirement instances 279 | */ 280 | public function getRequirements() 281 | { 282 | $array = array(); 283 | foreach ($this->requirements as $req) { 284 | if (!$req->isOptional()) { 285 | $array[] = $req; 286 | } 287 | } 288 | 289 | return $array; 290 | } 291 | 292 | /** 293 | * Returns the mandatory requirements that were not met. 294 | * 295 | * @return array Array of Requirement instances 296 | */ 297 | public function getFailedRequirements() 298 | { 299 | $array = array(); 300 | foreach ($this->requirements as $req) { 301 | if (!$req->isFulfilled() && !$req->isOptional()) { 302 | $array[] = $req; 303 | } 304 | } 305 | 306 | return $array; 307 | } 308 | 309 | /** 310 | * Returns all optional recommmendations. 311 | * 312 | * @return array Array of Requirement instances 313 | */ 314 | public function getRecommendations() 315 | { 316 | $array = array(); 317 | foreach ($this->requirements as $req) { 318 | if ($req->isOptional()) { 319 | $array[] = $req; 320 | } 321 | } 322 | 323 | return $array; 324 | } 325 | 326 | /** 327 | * Returns the recommendations that were not met. 328 | * 329 | * @return array Array of Requirement instances 330 | */ 331 | public function getFailedRecommendations() 332 | { 333 | $array = array(); 334 | foreach ($this->requirements as $req) { 335 | if (!$req->isFulfilled() && $req->isOptional()) { 336 | $array[] = $req; 337 | } 338 | } 339 | 340 | return $array; 341 | } 342 | 343 | /** 344 | * Returns whether a php.ini configuration is not correct. 345 | * 346 | * @return Boolean php.ini configuration problem? 347 | */ 348 | public function hasPhpIniConfigIssue() 349 | { 350 | foreach ($this->requirements as $req) { 351 | if (!$req->isFulfilled() && $req instanceof PhpIniRequirement) { 352 | return true; 353 | } 354 | } 355 | 356 | return false; 357 | } 358 | 359 | /** 360 | * Returns the PHP configuration file (php.ini) path. 361 | * 362 | * @return string|false php.ini file path 363 | */ 364 | public function getPhpIniConfigPath() 365 | { 366 | return get_cfg_var('cfg_file_path'); 367 | } 368 | } 369 | 370 | /** 371 | * This class specifies all requirements and optional recommendations that 372 | * are necessary to run the Symfony Standard Edition. 373 | * 374 | * @author Tobias Schultze 375 | * @author Fabien Potencier 376 | */ 377 | class SymfonyRequirements extends RequirementCollection 378 | { 379 | const REQUIRED_PHP_VERSION = '5.3.3'; 380 | 381 | /** 382 | * Constructor that initializes the requirements. 383 | */ 384 | public function __construct() 385 | { 386 | /* mandatory requirements follow */ 387 | 388 | $installedPhpVersion = phpversion(); 389 | 390 | $this->addRequirement( 391 | version_compare($installedPhpVersion, self::REQUIRED_PHP_VERSION, '>='), 392 | sprintf('PHP version must be at least %s (%s installed)', self::REQUIRED_PHP_VERSION, $installedPhpVersion), 393 | sprintf('You are running PHP version "%s", but Symfony needs at least PHP "%s" to run. 394 | Before using Symfony, upgrade your PHP installation, preferably to the latest version.', 395 | $installedPhpVersion, self::REQUIRED_PHP_VERSION), 396 | sprintf('Install PHP %s or newer (installed version is %s)', self::REQUIRED_PHP_VERSION, $installedPhpVersion) 397 | ); 398 | 399 | $this->addRequirement( 400 | version_compare($installedPhpVersion, '5.3.16', '!='), 401 | 'PHP version must not be 5.3.16 as Symfony won\'t work properly with it', 402 | 'Install PHP 5.3.17 or newer (or downgrade to an earlier PHP version)' 403 | ); 404 | 405 | $this->addRequirement( 406 | is_dir(__DIR__.'/../vendor/composer'), 407 | 'Vendor libraries must be installed', 408 | 'Vendor libraries are missing. Install composer following instructions from http://getcomposer.org/. ' . 409 | 'Then run "php composer.phar install" to install them.' 410 | ); 411 | 412 | $baseDir = basename(__DIR__); 413 | 414 | $this->addRequirement( 415 | is_writable(__DIR__.'/cache'), 416 | "$baseDir/cache/ directory must be writable", 417 | "Change the permissions of the \"$baseDir/cache/\" directory so that the web server can write into it." 418 | ); 419 | 420 | $this->addRequirement( 421 | is_writable(__DIR__.'/logs'), 422 | "$baseDir/logs/ directory must be writable", 423 | "Change the permissions of the \"$baseDir/logs/\" directory so that the web server can write into it." 424 | ); 425 | 426 | $this->addPhpIniRequirement( 427 | 'date.timezone', true, false, 428 | 'date.timezone setting must be set', 429 | 'Set the "date.timezone" setting in php.ini* (like Europe/Paris).' 430 | ); 431 | 432 | if (version_compare($installedPhpVersion, self::REQUIRED_PHP_VERSION, '>=')) { 433 | $timezones = array(); 434 | foreach (DateTimeZone::listAbbreviations() as $abbreviations) { 435 | foreach ($abbreviations as $abbreviation) { 436 | $timezones[$abbreviation['timezone_id']] = true; 437 | } 438 | } 439 | 440 | $this->addRequirement( 441 | isset($timezones[date_default_timezone_get()]), 442 | sprintf('Configured default timezone "%s" must be supported by your installation of PHP', date_default_timezone_get()), 443 | 'Your default timezone is not supported by PHP. Check for typos in your php.ini file and have a look at the list of deprecated timezones at http://php.net/manual/en/timezones.others.php.' 444 | ); 445 | } 446 | 447 | $this->addRequirement( 448 | function_exists('json_encode'), 449 | 'json_encode() must be available', 450 | 'Install and enable the JSON extension.' 451 | ); 452 | 453 | $this->addRequirement( 454 | function_exists('session_start'), 455 | 'session_start() must be available', 456 | 'Install and enable the session extension.' 457 | ); 458 | 459 | $this->addRequirement( 460 | function_exists('ctype_alpha'), 461 | 'ctype_alpha() must be available', 462 | 'Install and enable the ctype extension.' 463 | ); 464 | 465 | $this->addRequirement( 466 | function_exists('token_get_all'), 467 | 'token_get_all() must be available', 468 | 'Install and enable the Tokenizer extension.' 469 | ); 470 | 471 | $this->addRequirement( 472 | function_exists('simplexml_import_dom'), 473 | 'simplexml_import_dom() must be available', 474 | 'Install and enable the SimpleXML extension.' 475 | ); 476 | 477 | if (function_exists('apc_store') && ini_get('apc.enabled')) { 478 | $this->addRequirement( 479 | version_compare(phpversion('apc'), '3.0.17', '>='), 480 | 'APC version must be at least 3.0.17', 481 | 'Upgrade your APC extension (3.0.17+).' 482 | ); 483 | } 484 | 485 | $this->addPhpIniRequirement('detect_unicode', false); 486 | 487 | if (extension_loaded('suhosin')) { 488 | $this->addPhpIniRequirement( 489 | 'suhosin.executor.include.whitelist', 490 | create_function('$cfgValue', 'return false !== stripos($cfgValue, "phar");'), 491 | false, 492 | 'suhosin.executor.include.whitelist must be configured correctly in php.ini', 493 | 'Add "phar" to suhosin.executor.include.whitelist in php.ini*.' 494 | ); 495 | } 496 | 497 | if (extension_loaded('xdebug')) { 498 | $this->addPhpIniRequirement( 499 | 'xdebug.show_exception_trace', false, true 500 | ); 501 | 502 | $this->addPhpIniRequirement( 503 | 'xdebug.scream', false, true 504 | ); 505 | 506 | $this->addPhpIniRecommendation( 507 | 'xdebug.max_nesting_level', 508 | create_function('$cfgValue', 'return $cfgValue > 100;'), 509 | true, 510 | 'xdebug.max_nesting_level should be above 100 in php.ini', 511 | 'Set "xdebug.max_nesting_level" to e.g. "250" in php.ini* to stop Xdebug\'s infinite recursion protection erroneously throwing a fatal error in your project.' 512 | ); 513 | } 514 | 515 | $pcreVersion = defined('PCRE_VERSION') ? (float) PCRE_VERSION : null; 516 | 517 | $this->addRequirement( 518 | null !== $pcreVersion, 519 | 'PCRE extension must be available', 520 | 'Install the PCRE extension (version 8.0+).' 521 | ); 522 | 523 | /* optional recommendations follow */ 524 | 525 | $this->addRecommendation( 526 | file_get_contents(__FILE__) === file_get_contents(__DIR__.'/../vendor/sensio/distribution-bundle/Sensio/Bundle/DistributionBundle/Resources/skeleton/app/SymfonyRequirements.php'), 527 | 'Requirements file should be up-to-date', 528 | 'Your requirements file is outdated. Run composer install and re-check your configuration.' 529 | ); 530 | 531 | $this->addRecommendation( 532 | version_compare($installedPhpVersion, '5.3.4', '>='), 533 | 'You should use at least PHP 5.3.4 due to PHP bug #52083 in earlier versions', 534 | 'Your project might malfunction randomly due to PHP bug #52083 ("Notice: Trying to get property of non-object"). Install PHP 5.3.4 or newer.' 535 | ); 536 | 537 | $this->addRecommendation( 538 | version_compare($installedPhpVersion, '5.3.8', '>='), 539 | 'When using annotations you should have at least PHP 5.3.8 due to PHP bug #55156', 540 | 'Install PHP 5.3.8 or newer if your project uses annotations.' 541 | ); 542 | 543 | $this->addRecommendation( 544 | version_compare($installedPhpVersion, '5.4.0', '!='), 545 | 'You should not use PHP 5.4.0 due to the PHP bug #61453', 546 | 'Your project might not work properly due to the PHP bug #61453 ("Cannot dump definitions which have method calls"). Install PHP 5.4.1 or newer.' 547 | ); 548 | 549 | if (null !== $pcreVersion) { 550 | $this->addRecommendation( 551 | $pcreVersion >= 8.0, 552 | sprintf('PCRE extension should be at least version 8.0 (%s installed)', $pcreVersion), 553 | 'PCRE 8.0+ is preconfigured in PHP since 5.3.2 but you are using an outdated version of it. Symfony probably works anyway but it is recommended to upgrade your PCRE extension.' 554 | ); 555 | } 556 | 557 | $this->addRecommendation( 558 | class_exists('DomDocument'), 559 | 'PHP-XML module should be installed', 560 | 'Install and enable the PHP-XML module.' 561 | ); 562 | 563 | $this->addRecommendation( 564 | function_exists('mb_strlen'), 565 | 'mb_strlen() should be available', 566 | 'Install and enable the mbstring extension.' 567 | ); 568 | 569 | $this->addRecommendation( 570 | function_exists('iconv'), 571 | 'iconv() should be available', 572 | 'Install and enable the iconv extension.' 573 | ); 574 | 575 | $this->addRecommendation( 576 | function_exists('utf8_decode'), 577 | 'utf8_decode() should be available', 578 | 'Install and enable the XML extension.' 579 | ); 580 | 581 | if (!defined('PHP_WINDOWS_VERSION_BUILD')) { 582 | $this->addRecommendation( 583 | function_exists('posix_isatty'), 584 | 'posix_isatty() should be available', 585 | 'Install and enable the php_posix extension (used to colorize the CLI output).' 586 | ); 587 | } 588 | 589 | $this->addRecommendation( 590 | class_exists('Locale'), 591 | 'intl extension should be available', 592 | 'Install and enable the intl extension (used for validators).' 593 | ); 594 | 595 | if (class_exists('Collator')) { 596 | $this->addRecommendation( 597 | null !== new Collator('fr_FR'), 598 | 'intl extension should be correctly configured', 599 | 'The intl extension does not behave properly. This problem is typical on PHP 5.3.X x64 WIN builds.' 600 | ); 601 | } 602 | 603 | if (class_exists('Locale')) { 604 | if (defined('INTL_ICU_VERSION')) { 605 | $version = INTL_ICU_VERSION; 606 | } else { 607 | $reflector = new ReflectionExtension('intl'); 608 | 609 | ob_start(); 610 | $reflector->info(); 611 | $output = strip_tags(ob_get_clean()); 612 | 613 | preg_match('/^ICU version +(?:=> )?(.*)$/m', $output, $matches); 614 | $version = $matches[1]; 615 | } 616 | 617 | $this->addRecommendation( 618 | version_compare($version, '4.0', '>='), 619 | 'intl ICU version should be at least 4+', 620 | 'Upgrade your intl extension with a newer ICU version (4+).' 621 | ); 622 | } 623 | 624 | $accelerator = 625 | (function_exists('apc_store') && ini_get('apc.enabled')) 626 | || 627 | function_exists('eaccelerator_put') && ini_get('eaccelerator.enable') 628 | || 629 | function_exists('xcache_set') 630 | ; 631 | 632 | $this->addRecommendation( 633 | $accelerator, 634 | 'a PHP accelerator should be installed', 635 | 'Install and enable a PHP accelerator like APC (highly recommended).' 636 | ); 637 | 638 | $this->addPhpIniRecommendation('short_open_tag', false); 639 | 640 | $this->addPhpIniRecommendation('magic_quotes_gpc', false, true); 641 | 642 | $this->addPhpIniRecommendation('register_globals', false, true); 643 | 644 | $this->addPhpIniRecommendation('session.auto_start', false); 645 | 646 | $this->addRecommendation( 647 | class_exists('PDO'), 648 | 'PDO should be installed', 649 | 'Install PDO (mandatory for Doctrine).' 650 | ); 651 | 652 | if (class_exists('PDO')) { 653 | $drivers = PDO::getAvailableDrivers(); 654 | $this->addRecommendation( 655 | count($drivers), 656 | sprintf('PDO should have some drivers installed (currently available: %s)', count($drivers) ? implode(', ', $drivers) : 'none'), 657 | 'Install PDO drivers (mandatory for Doctrine).' 658 | ); 659 | } 660 | } 661 | } 662 | -------------------------------------------------------------------------------- /app/autoload.php: -------------------------------------------------------------------------------- 1 | add('', __DIR__.'/../vendor/symfony/symfony/src/Symfony/Component/Locale/Resources/stubs'); 16 | } 17 | 18 | AnnotationRegistry::registerLoader(array($loader, 'loadClass')); 19 | 20 | return $loader; 21 | -------------------------------------------------------------------------------- /app/bootstrap.php.cache: -------------------------------------------------------------------------------- 1 | parameterBag = null === $parameterBag ? new ParameterBag() : $parameterBag; 118 | 119 | $this->services = array(); 120 | $this->scopes = array(); 121 | $this->scopeChildren = array(); 122 | $this->scopedServices = array(); 123 | $this->scopeStacks = array(); 124 | 125 | $this->set('service_container', $this); 126 | } 127 | 128 | 129 | public function compile() 130 | { 131 | $this->parameterBag->resolve(); 132 | 133 | $this->parameterBag = new FrozenParameterBag($this->parameterBag->all()); 134 | } 135 | 136 | 137 | public function isFrozen() 138 | { 139 | return $this->parameterBag instanceof FrozenParameterBag; 140 | } 141 | 142 | 143 | public function getParameterBag() 144 | { 145 | return $this->parameterBag; 146 | } 147 | 148 | 149 | public function getParameter($name) 150 | { 151 | return $this->parameterBag->get($name); 152 | } 153 | 154 | 155 | public function hasParameter($name) 156 | { 157 | return $this->parameterBag->has($name); 158 | } 159 | 160 | 161 | public function setParameter($name, $value) 162 | { 163 | $this->parameterBag->set($name, $value); 164 | } 165 | 166 | 167 | public function set($id, $service, $scope = self::SCOPE_CONTAINER) 168 | { 169 | if (self::SCOPE_PROTOTYPE === $scope) { 170 | throw new InvalidArgumentException('You cannot set services of scope "prototype".'); 171 | } 172 | 173 | $id = strtolower($id); 174 | 175 | if (self::SCOPE_CONTAINER !== $scope) { 176 | if (!isset($this->scopedServices[$scope])) { 177 | throw new RuntimeException('You cannot set services of inactive scopes.'); 178 | } 179 | 180 | $this->scopedServices[$scope][$id] = $service; 181 | } 182 | 183 | $this->services[$id] = $service; 184 | } 185 | 186 | 187 | public function has($id) 188 | { 189 | $id = strtolower($id); 190 | 191 | return isset($this->services[$id]) || method_exists($this, 'get'.strtr($id, array('_' => '', '.' => '_')).'Service'); 192 | } 193 | 194 | 195 | public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE) 196 | { 197 | $id = strtolower($id); 198 | 199 | if (isset($this->services[$id])) { 200 | return $this->services[$id]; 201 | } 202 | 203 | if (isset($this->loading[$id])) { 204 | throw new ServiceCircularReferenceException($id, array_keys($this->loading)); 205 | } 206 | 207 | if (method_exists($this, $method = 'get'.strtr($id, array('_' => '', '.' => '_')).'Service')) { 208 | $this->loading[$id] = true; 209 | 210 | try { 211 | $service = $this->$method(); 212 | } catch (\Exception $e) { 213 | unset($this->loading[$id]); 214 | 215 | if (isset($this->services[$id])) { 216 | unset($this->services[$id]); 217 | } 218 | 219 | throw $e; 220 | } 221 | 222 | unset($this->loading[$id]); 223 | 224 | return $service; 225 | } 226 | 227 | if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { 228 | throw new ServiceNotFoundException($id); 229 | } 230 | } 231 | 232 | 233 | public function initialized($id) 234 | { 235 | return isset($this->services[strtolower($id)]); 236 | } 237 | 238 | 239 | public function getServiceIds() 240 | { 241 | $ids = array(); 242 | $r = new \ReflectionClass($this); 243 | foreach ($r->getMethods() as $method) { 244 | if (preg_match('/^get(.+)Service$/', $method->name, $match)) { 245 | $ids[] = self::underscore($match[1]); 246 | } 247 | } 248 | 249 | return array_unique(array_merge($ids, array_keys($this->services))); 250 | } 251 | 252 | 253 | public function enterScope($name) 254 | { 255 | if (!isset($this->scopes[$name])) { 256 | throw new InvalidArgumentException(sprintf('The scope "%s" does not exist.', $name)); 257 | } 258 | 259 | if (self::SCOPE_CONTAINER !== $this->scopes[$name] && !isset($this->scopedServices[$this->scopes[$name]])) { 260 | throw new RuntimeException(sprintf('The parent scope "%s" must be active when entering this scope.', $this->scopes[$name])); 261 | } 262 | 263 | if (isset($this->scopedServices[$name])) { 264 | $services = array($this->services, $name => $this->scopedServices[$name]); 265 | unset($this->scopedServices[$name]); 266 | 267 | foreach ($this->scopeChildren[$name] as $child) { 268 | if (isset($this->scopedServices[$child])) { 269 | $services[$child] = $this->scopedServices[$child]; 270 | unset($this->scopedServices[$child]); 271 | } 272 | } 273 | 274 | $this->services = call_user_func_array('array_diff_key', $services); 275 | array_shift($services); 276 | 277 | if (!isset($this->scopeStacks[$name])) { 278 | $this->scopeStacks[$name] = new \SplStack(); 279 | } 280 | $this->scopeStacks[$name]->push($services); 281 | } 282 | 283 | $this->scopedServices[$name] = array(); 284 | } 285 | 286 | 287 | public function leaveScope($name) 288 | { 289 | if (!isset($this->scopedServices[$name])) { 290 | throw new InvalidArgumentException(sprintf('The scope "%s" is not active.', $name)); 291 | } 292 | 293 | $services = array($this->services, $this->scopedServices[$name]); 294 | unset($this->scopedServices[$name]); 295 | foreach ($this->scopeChildren[$name] as $child) { 296 | if (!isset($this->scopedServices[$child])) { 297 | continue; 298 | } 299 | 300 | $services[] = $this->scopedServices[$child]; 301 | unset($this->scopedServices[$child]); 302 | } 303 | $this->services = call_user_func_array('array_diff_key', $services); 304 | 305 | if (isset($this->scopeStacks[$name]) && count($this->scopeStacks[$name]) > 0) { 306 | $services = $this->scopeStacks[$name]->pop(); 307 | $this->scopedServices += $services; 308 | 309 | array_unshift($services, $this->services); 310 | $this->services = call_user_func_array('array_merge', $services); 311 | } 312 | } 313 | 314 | 315 | public function addScope(ScopeInterface $scope) 316 | { 317 | $name = $scope->getName(); 318 | $parentScope = $scope->getParentName(); 319 | 320 | if (self::SCOPE_CONTAINER === $name || self::SCOPE_PROTOTYPE === $name) { 321 | throw new InvalidArgumentException(sprintf('The scope "%s" is reserved.', $name)); 322 | } 323 | if (isset($this->scopes[$name])) { 324 | throw new InvalidArgumentException(sprintf('A scope with name "%s" already exists.', $name)); 325 | } 326 | if (self::SCOPE_CONTAINER !== $parentScope && !isset($this->scopes[$parentScope])) { 327 | throw new InvalidArgumentException(sprintf('The parent scope "%s" does not exist, or is invalid.', $parentScope)); 328 | } 329 | 330 | $this->scopes[$name] = $parentScope; 331 | $this->scopeChildren[$name] = array(); 332 | 333 | while ($parentScope !== self::SCOPE_CONTAINER) { 334 | $this->scopeChildren[$parentScope][] = $name; 335 | $parentScope = $this->scopes[$parentScope]; 336 | } 337 | } 338 | 339 | 340 | public function hasScope($name) 341 | { 342 | return isset($this->scopes[$name]); 343 | } 344 | 345 | 346 | public function isScopeActive($name) 347 | { 348 | return isset($this->scopedServices[$name]); 349 | } 350 | 351 | 352 | public static function camelize($id) 353 | { 354 | return preg_replace_callback('/(^|_|\.)+(.)/', function ($match) { return ('.' === $match[1] ? '_' : '').strtoupper($match[2]); }, $id); 355 | } 356 | 357 | 358 | public static function underscore($id) 359 | { 360 | return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr($id, '_', '.'))); 361 | } 362 | } 363 | } 364 | 365 | 366 | 367 | 368 | namespace Symfony\Component\HttpKernel 369 | { 370 | 371 | use Symfony\Component\HttpFoundation\Request; 372 | use Symfony\Component\HttpFoundation\Response; 373 | 374 | 375 | interface HttpKernelInterface 376 | { 377 | const MASTER_REQUEST = 1; 378 | const SUB_REQUEST = 2; 379 | 380 | 381 | public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true); 382 | } 383 | } 384 | 385 | 386 | 387 | 388 | namespace Symfony\Component\HttpKernel 389 | { 390 | 391 | use Symfony\Component\DependencyInjection\ContainerInterface; 392 | use Symfony\Component\HttpKernel\HttpKernelInterface; 393 | use Symfony\Component\HttpKernel\Bundle\BundleInterface; 394 | use Symfony\Component\Config\Loader\LoaderInterface; 395 | 396 | 397 | interface KernelInterface extends HttpKernelInterface, \Serializable 398 | { 399 | 400 | public function registerBundles(); 401 | 402 | 403 | public function registerContainerConfiguration(LoaderInterface $loader); 404 | 405 | 406 | public function boot(); 407 | 408 | 409 | public function shutdown(); 410 | 411 | 412 | public function getBundles(); 413 | 414 | 415 | public function isClassInActiveBundle($class); 416 | 417 | 418 | public function getBundle($name, $first = true); 419 | 420 | 421 | public function locateResource($name, $dir = null, $first = true); 422 | 423 | 424 | public function getName(); 425 | 426 | 427 | public function getEnvironment(); 428 | 429 | 430 | public function isDebug(); 431 | 432 | 433 | public function getRootDir(); 434 | 435 | 436 | public function getContainer(); 437 | 438 | 439 | public function getStartTime(); 440 | 441 | 442 | public function getCacheDir(); 443 | 444 | 445 | public function getLogDir(); 446 | 447 | 448 | public function getCharset(); 449 | } 450 | } 451 | 452 | 453 | 454 | 455 | namespace Symfony\Component\HttpKernel 456 | { 457 | 458 | use Symfony\Component\HttpFoundation\Request; 459 | use Symfony\Component\HttpFoundation\Response; 460 | 461 | 462 | interface TerminableInterface 463 | { 464 | 465 | public function terminate(Request $request, Response $response); 466 | } 467 | } 468 | 469 | 470 | 471 | 472 | namespace Symfony\Component\HttpKernel 473 | { 474 | 475 | use Symfony\Component\DependencyInjection\ContainerInterface; 476 | use Symfony\Component\DependencyInjection\ContainerBuilder; 477 | use Symfony\Component\DependencyInjection\Dumper\PhpDumper; 478 | use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; 479 | use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; 480 | use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; 481 | use Symfony\Component\DependencyInjection\Loader\IniFileLoader; 482 | use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; 483 | use Symfony\Component\DependencyInjection\Loader\ClosureLoader; 484 | use Symfony\Component\HttpFoundation\Request; 485 | use Symfony\Component\HttpFoundation\Response; 486 | use Symfony\Component\HttpKernel\HttpKernelInterface; 487 | use Symfony\Component\HttpKernel\Bundle\BundleInterface; 488 | use Symfony\Component\HttpKernel\Config\FileLocator; 489 | use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; 490 | use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass; 491 | use Symfony\Component\HttpKernel\Debug\ErrorHandler; 492 | use Symfony\Component\HttpKernel\Debug\ExceptionHandler; 493 | use Symfony\Component\Config\Loader\LoaderResolver; 494 | use Symfony\Component\Config\Loader\DelegatingLoader; 495 | use Symfony\Component\Config\ConfigCache; 496 | use Symfony\Component\ClassLoader\ClassCollectionLoader; 497 | use Symfony\Component\ClassLoader\DebugClassLoader; 498 | 499 | 500 | abstract class Kernel implements KernelInterface, TerminableInterface 501 | { 502 | protected $bundles; 503 | protected $bundleMap; 504 | protected $container; 505 | protected $rootDir; 506 | protected $environment; 507 | protected $debug; 508 | protected $booted; 509 | protected $name; 510 | protected $startTime; 511 | protected $classes; 512 | protected $errorReportingLevel; 513 | 514 | const VERSION = '2.1.10'; 515 | const VERSION_ID = '20110'; 516 | const MAJOR_VERSION = '2'; 517 | const MINOR_VERSION = '1'; 518 | const RELEASE_VERSION = '10'; 519 | const EXTRA_VERSION = ''; 520 | 521 | 522 | public function __construct($environment, $debug) 523 | { 524 | $this->environment = $environment; 525 | $this->debug = (Boolean) $debug; 526 | $this->booted = false; 527 | $this->rootDir = $this->getRootDir(); 528 | $this->name = $this->getName(); 529 | $this->classes = array(); 530 | 531 | if ($this->debug) { 532 | $this->startTime = microtime(true); 533 | } 534 | 535 | $this->init(); 536 | } 537 | 538 | public function init() 539 | { 540 | if ($this->debug) { 541 | ini_set('display_errors', 1); 542 | error_reporting(-1); 543 | 544 | DebugClassLoader::enable(); 545 | ErrorHandler::register($this->errorReportingLevel); 546 | if ('cli' !== php_sapi_name()) { 547 | ExceptionHandler::register(); 548 | } 549 | } else { 550 | ini_set('display_errors', 0); 551 | } 552 | } 553 | 554 | public function __clone() 555 | { 556 | if ($this->debug) { 557 | $this->startTime = microtime(true); 558 | } 559 | 560 | $this->booted = false; 561 | $this->container = null; 562 | } 563 | 564 | 565 | public function boot() 566 | { 567 | if (true === $this->booted) { 568 | return; 569 | } 570 | 571 | $this->initializeBundles(); 572 | 573 | $this->initializeContainer(); 574 | 575 | foreach ($this->getBundles() as $bundle) { 576 | $bundle->setContainer($this->container); 577 | $bundle->boot(); 578 | } 579 | 580 | $this->booted = true; 581 | } 582 | 583 | 584 | public function terminate(Request $request, Response $response) 585 | { 586 | if (false === $this->booted) { 587 | return; 588 | } 589 | 590 | if ($this->getHttpKernel() instanceof TerminableInterface) { 591 | $this->getHttpKernel()->terminate($request, $response); 592 | } 593 | } 594 | 595 | 596 | public function shutdown() 597 | { 598 | if (false === $this->booted) { 599 | return; 600 | } 601 | 602 | $this->booted = false; 603 | 604 | foreach ($this->getBundles() as $bundle) { 605 | $bundle->shutdown(); 606 | $bundle->setContainer(null); 607 | } 608 | 609 | $this->container = null; 610 | } 611 | 612 | 613 | public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) 614 | { 615 | if (false === $this->booted) { 616 | $this->boot(); 617 | } 618 | 619 | return $this->getHttpKernel()->handle($request, $type, $catch); 620 | } 621 | 622 | 623 | protected function getHttpKernel() 624 | { 625 | return $this->container->get('http_kernel'); 626 | } 627 | 628 | 629 | public function getBundles() 630 | { 631 | return $this->bundles; 632 | } 633 | 634 | 635 | public function isClassInActiveBundle($class) 636 | { 637 | foreach ($this->getBundles() as $bundle) { 638 | if (0 === strpos($class, $bundle->getNamespace())) { 639 | return true; 640 | } 641 | } 642 | 643 | return false; 644 | } 645 | 646 | 647 | public function getBundle($name, $first = true) 648 | { 649 | if (!isset($this->bundleMap[$name])) { 650 | throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, get_class($this))); 651 | } 652 | 653 | if (true === $first) { 654 | return $this->bundleMap[$name][0]; 655 | } 656 | 657 | return $this->bundleMap[$name]; 658 | } 659 | 660 | 661 | public function locateResource($name, $dir = null, $first = true) 662 | { 663 | if ('@' !== $name[0]) { 664 | throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name)); 665 | } 666 | 667 | if (false !== strpos($name, '..')) { 668 | throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name)); 669 | } 670 | 671 | $bundleName = substr($name, 1); 672 | $path = ''; 673 | if (false !== strpos($bundleName, '/')) { 674 | list($bundleName, $path) = explode('/', $bundleName, 2); 675 | } 676 | 677 | $isResource = 0 === strpos($path, 'Resources') && null !== $dir; 678 | $overridePath = substr($path, 9); 679 | $resourceBundle = null; 680 | $bundles = $this->getBundle($bundleName, false); 681 | $files = array(); 682 | 683 | foreach ($bundles as $bundle) { 684 | if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) { 685 | if (null !== $resourceBundle) { 686 | throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.', 687 | $file, 688 | $resourceBundle, 689 | $dir.'/'.$bundles[0]->getName().$overridePath 690 | )); 691 | } 692 | 693 | if ($first) { 694 | return $file; 695 | } 696 | $files[] = $file; 697 | } 698 | 699 | if (file_exists($file = $bundle->getPath().'/'.$path)) { 700 | if ($first && !$isResource) { 701 | return $file; 702 | } 703 | $files[] = $file; 704 | $resourceBundle = $bundle->getName(); 705 | } 706 | } 707 | 708 | if (count($files) > 0) { 709 | return $first && $isResource ? $files[0] : $files; 710 | } 711 | 712 | throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name)); 713 | } 714 | 715 | 716 | public function getName() 717 | { 718 | if (null === $this->name) { 719 | $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir)); 720 | } 721 | 722 | return $this->name; 723 | } 724 | 725 | 726 | public function getEnvironment() 727 | { 728 | return $this->environment; 729 | } 730 | 731 | 732 | public function isDebug() 733 | { 734 | return $this->debug; 735 | } 736 | 737 | 738 | public function getRootDir() 739 | { 740 | if (null === $this->rootDir) { 741 | $r = new \ReflectionObject($this); 742 | $this->rootDir = str_replace('\\', '/', dirname($r->getFileName())); 743 | } 744 | 745 | return $this->rootDir; 746 | } 747 | 748 | 749 | public function getContainer() 750 | { 751 | return $this->container; 752 | } 753 | 754 | 755 | public function loadClassCache($name = 'classes', $extension = '.php') 756 | { 757 | if (!$this->booted && is_file($this->getCacheDir().'/classes.map')) { 758 | ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension); 759 | } 760 | } 761 | 762 | 763 | public function setClassCache(array $classes) 764 | { 765 | file_put_contents($this->getCacheDir().'/classes.map', sprintf('debug ? $this->startTime : -INF; 772 | } 773 | 774 | 775 | public function getCacheDir() 776 | { 777 | return $this->rootDir.'/cache/'.$this->environment; 778 | } 779 | 780 | 781 | public function getLogDir() 782 | { 783 | return $this->rootDir.'/logs'; 784 | } 785 | 786 | 787 | public function getCharset() 788 | { 789 | return 'UTF-8'; 790 | } 791 | 792 | 793 | protected function initializeBundles() 794 | { 795 | $this->bundles = array(); 796 | $topMostBundles = array(); 797 | $directChildren = array(); 798 | 799 | foreach ($this->registerBundles() as $bundle) { 800 | $name = $bundle->getName(); 801 | if (isset($this->bundles[$name])) { 802 | throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name)); 803 | } 804 | $this->bundles[$name] = $bundle; 805 | 806 | if ($parentName = $bundle->getParent()) { 807 | if (isset($directChildren[$parentName])) { 808 | throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName])); 809 | } 810 | if ($parentName == $name) { 811 | throw new \LogicException(sprintf('Bundle "%s" can not extend itself.', $name)); 812 | } 813 | $directChildren[$parentName] = $name; 814 | } else { 815 | $topMostBundles[$name] = $bundle; 816 | } 817 | } 818 | 819 | if (count($diff = array_values(array_diff(array_keys($directChildren), array_keys($this->bundles))))) { 820 | throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0])); 821 | } 822 | 823 | $this->bundleMap = array(); 824 | foreach ($topMostBundles as $name => $bundle) { 825 | $bundleMap = array($bundle); 826 | $hierarchy = array($name); 827 | 828 | while (isset($directChildren[$name])) { 829 | $name = $directChildren[$name]; 830 | array_unshift($bundleMap, $this->bundles[$name]); 831 | $hierarchy[] = $name; 832 | } 833 | 834 | foreach ($hierarchy as $bundle) { 835 | $this->bundleMap[$bundle] = $bundleMap; 836 | array_pop($bundleMap); 837 | } 838 | } 839 | 840 | } 841 | 842 | 843 | protected function getContainerClass() 844 | { 845 | return $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer'; 846 | } 847 | 848 | 849 | protected function getContainerBaseClass() 850 | { 851 | return 'Container'; 852 | } 853 | 854 | 855 | protected function initializeContainer() 856 | { 857 | $class = $this->getContainerClass(); 858 | $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug); 859 | $fresh = true; 860 | if (!$cache->isFresh()) { 861 | $container = $this->buildContainer(); 862 | $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); 863 | 864 | $fresh = false; 865 | } 866 | 867 | require_once $cache; 868 | 869 | $this->container = new $class(); 870 | $this->container->set('kernel', $this); 871 | 872 | if (!$fresh && $this->container->has('cache_warmer')) { 873 | $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir')); 874 | } 875 | } 876 | 877 | 878 | protected function getKernelParameters() 879 | { 880 | $bundles = array(); 881 | foreach ($this->bundles as $name => $bundle) { 882 | $bundles[$name] = get_class($bundle); 883 | } 884 | 885 | return array_merge( 886 | array( 887 | 'kernel.root_dir' => $this->rootDir, 888 | 'kernel.environment' => $this->environment, 889 | 'kernel.debug' => $this->debug, 890 | 'kernel.name' => $this->name, 891 | 'kernel.cache_dir' => $this->getCacheDir(), 892 | 'kernel.logs_dir' => $this->getLogDir(), 893 | 'kernel.bundles' => $bundles, 894 | 'kernel.charset' => $this->getCharset(), 895 | 'kernel.container_class' => $this->getContainerClass(), 896 | ), 897 | $this->getEnvParameters() 898 | ); 899 | } 900 | 901 | 902 | protected function getEnvParameters() 903 | { 904 | $parameters = array(); 905 | foreach ($_SERVER as $key => $value) { 906 | if (0 === strpos($key, 'SYMFONY__')) { 907 | $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value; 908 | } 909 | } 910 | 911 | return $parameters; 912 | } 913 | 914 | 915 | protected function buildContainer() 916 | { 917 | foreach (array('cache' => $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) { 918 | if (!is_dir($dir)) { 919 | if (false === @mkdir($dir, 0777, true)) { 920 | throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir)); 921 | } 922 | } elseif (!is_writable($dir)) { 923 | throw new \RuntimeException(sprintf("Unable to write in the %s directory (%s)\n", $name, $dir)); 924 | } 925 | } 926 | 927 | $container = $this->getContainerBuilder(); 928 | $extensions = array(); 929 | foreach ($this->bundles as $bundle) { 930 | if ($extension = $bundle->getContainerExtension()) { 931 | $container->registerExtension($extension); 932 | $extensions[] = $extension->getAlias(); 933 | } 934 | 935 | if ($this->debug) { 936 | $container->addObjectResource($bundle); 937 | } 938 | } 939 | foreach ($this->bundles as $bundle) { 940 | $bundle->build($container); 941 | } 942 | 943 | $container->addObjectResource($this); 944 | 945 | $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions)); 946 | 947 | if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) { 948 | $container->merge($cont); 949 | } 950 | 951 | $container->addCompilerPass(new AddClassesToCachePass($this)); 952 | $container->compile(); 953 | 954 | return $container; 955 | } 956 | 957 | 958 | protected function getContainerBuilder() 959 | { 960 | return new ContainerBuilder(new ParameterBag($this->getKernelParameters())); 961 | } 962 | 963 | 964 | protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, $class, $baseClass) 965 | { 966 | $dumper = new PhpDumper($container); 967 | $content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass)); 968 | if (!$this->debug) { 969 | $content = self::stripComments($content); 970 | } 971 | 972 | $cache->write($content, $container->getResources()); 973 | } 974 | 975 | 976 | protected function getContainerLoader(ContainerInterface $container) 977 | { 978 | $locator = new FileLocator($this); 979 | $resolver = new LoaderResolver(array( 980 | new XmlFileLoader($container, $locator), 981 | new YamlFileLoader($container, $locator), 982 | new IniFileLoader($container, $locator), 983 | new PhpFileLoader($container, $locator), 984 | new ClosureLoader($container), 985 | )); 986 | 987 | return new DelegatingLoader($resolver); 988 | } 989 | 990 | 991 | public static function stripComments($source) 992 | { 993 | if (!function_exists('token_get_all')) { 994 | return $source; 995 | } 996 | 997 | $output = ''; 998 | foreach (token_get_all($source) as $token) { 999 | if (is_string($token)) { 1000 | $output .= $token; 1001 | } elseif (!in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) { 1002 | $output .= $token[1]; 1003 | } 1004 | } 1005 | 1006 | $output = preg_replace(array('/\s+$/Sm', '/\n+/S'), "\n", $output); 1007 | 1008 | return $output; 1009 | } 1010 | 1011 | public function serialize() 1012 | { 1013 | return serialize(array($this->environment, $this->debug)); 1014 | } 1015 | 1016 | public function unserialize($data) 1017 | { 1018 | list($environment, $debug) = unserialize($data); 1019 | 1020 | $this->__construct($environment, $debug); 1021 | } 1022 | } 1023 | } 1024 | 1025 | 1026 | 1027 | 1028 | namespace Symfony\Component\ClassLoader 1029 | { 1030 | 1031 | 1032 | class ApcClassLoader 1033 | { 1034 | private $prefix; 1035 | private $classFinder; 1036 | 1037 | 1038 | public function __construct($prefix, $classFinder) 1039 | { 1040 | if (!extension_loaded('apc')) { 1041 | throw new \RuntimeException('Unable to use ApcClassLoader as APC is not enabled.'); 1042 | } 1043 | 1044 | if (!method_exists($classFinder, 'findFile')) { 1045 | throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); 1046 | } 1047 | 1048 | $this->prefix = $prefix; 1049 | $this->classFinder = $classFinder; 1050 | } 1051 | 1052 | 1053 | public function register($prepend = false) 1054 | { 1055 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 1056 | } 1057 | 1058 | 1059 | public function unregister() 1060 | { 1061 | spl_autoload_unregister(array($this, 'loadClass')); 1062 | } 1063 | 1064 | 1065 | public function loadClass($class) 1066 | { 1067 | if ($file = $this->findFile($class)) { 1068 | require $file; 1069 | 1070 | return true; 1071 | } 1072 | } 1073 | 1074 | 1075 | public function findFile($class) 1076 | { 1077 | if (false === $file = apc_fetch($this->prefix.$class)) { 1078 | apc_store($this->prefix.$class, $file = $this->classFinder->findFile($class)); 1079 | } 1080 | 1081 | return $file; 1082 | } 1083 | } 1084 | } 1085 | 1086 | 1087 | 1088 | 1089 | namespace Symfony\Component\HttpKernel\Bundle 1090 | { 1091 | 1092 | use Symfony\Component\DependencyInjection\ContainerAwareInterface; 1093 | use Symfony\Component\DependencyInjection\ContainerBuilder; 1094 | use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; 1095 | 1096 | 1097 | interface BundleInterface extends ContainerAwareInterface 1098 | { 1099 | 1100 | public function boot(); 1101 | 1102 | 1103 | public function shutdown(); 1104 | 1105 | 1106 | public function build(ContainerBuilder $container); 1107 | 1108 | 1109 | public function getContainerExtension(); 1110 | 1111 | 1112 | public function getParent(); 1113 | 1114 | 1115 | public function getName(); 1116 | 1117 | 1118 | public function getNamespace(); 1119 | 1120 | 1121 | public function getPath(); 1122 | } 1123 | } 1124 | 1125 | 1126 | 1127 | 1128 | namespace Symfony\Component\DependencyInjection 1129 | { 1130 | 1131 | 1132 | abstract class ContainerAware implements ContainerAwareInterface 1133 | { 1134 | 1135 | protected $container; 1136 | 1137 | 1138 | public function setContainer(ContainerInterface $container = null) 1139 | { 1140 | $this->container = $container; 1141 | } 1142 | } 1143 | } 1144 | 1145 | 1146 | 1147 | 1148 | namespace Symfony\Component\HttpKernel\Bundle 1149 | { 1150 | 1151 | use Symfony\Component\DependencyInjection\ContainerAware; 1152 | use Symfony\Component\DependencyInjection\ContainerBuilder; 1153 | use Symfony\Component\DependencyInjection\Container; 1154 | use Symfony\Component\Console\Application; 1155 | use Symfony\Component\Finder\Finder; 1156 | 1157 | 1158 | abstract class Bundle extends ContainerAware implements BundleInterface 1159 | { 1160 | protected $name; 1161 | protected $reflected; 1162 | protected $extension; 1163 | 1164 | 1165 | public function boot() 1166 | { 1167 | } 1168 | 1169 | 1170 | public function shutdown() 1171 | { 1172 | } 1173 | 1174 | 1175 | public function build(ContainerBuilder $container) 1176 | { 1177 | } 1178 | 1179 | 1180 | public function getContainerExtension() 1181 | { 1182 | if (null === $this->extension) { 1183 | $basename = preg_replace('/Bundle$/', '', $this->getName()); 1184 | 1185 | $class = $this->getNamespace().'\\DependencyInjection\\'.$basename.'Extension'; 1186 | if (class_exists($class)) { 1187 | $extension = new $class(); 1188 | 1189 | $expectedAlias = Container::underscore($basename); 1190 | if ($expectedAlias != $extension->getAlias()) { 1191 | throw new \LogicException(sprintf( 1192 | 'The extension alias for the default extension of a '. 1193 | 'bundle must be the underscored version of the '. 1194 | 'bundle name ("%s" instead of "%s")', 1195 | $expectedAlias, $extension->getAlias() 1196 | )); 1197 | } 1198 | 1199 | $this->extension = $extension; 1200 | } else { 1201 | $this->extension = false; 1202 | } 1203 | } 1204 | 1205 | if ($this->extension) { 1206 | return $this->extension; 1207 | } 1208 | } 1209 | 1210 | 1211 | public function getNamespace() 1212 | { 1213 | if (null === $this->reflected) { 1214 | $this->reflected = new \ReflectionObject($this); 1215 | } 1216 | 1217 | return $this->reflected->getNamespaceName(); 1218 | } 1219 | 1220 | 1221 | public function getPath() 1222 | { 1223 | if (null === $this->reflected) { 1224 | $this->reflected = new \ReflectionObject($this); 1225 | } 1226 | 1227 | return dirname($this->reflected->getFileName()); 1228 | } 1229 | 1230 | 1231 | public function getParent() 1232 | { 1233 | return null; 1234 | } 1235 | 1236 | 1237 | final public function getName() 1238 | { 1239 | if (null !== $this->name) { 1240 | return $this->name; 1241 | } 1242 | 1243 | $name = get_class($this); 1244 | $pos = strrpos($name, '\\'); 1245 | 1246 | return $this->name = false === $pos ? $name : substr($name, $pos + 1); 1247 | } 1248 | 1249 | 1250 | public function registerCommands(Application $application) 1251 | { 1252 | if (!is_dir($dir = $this->getPath().'/Command')) { 1253 | return; 1254 | } 1255 | 1256 | $finder = new Finder(); 1257 | $finder->files()->name('*Command.php')->in($dir); 1258 | 1259 | $prefix = $this->getNamespace().'\\Command'; 1260 | foreach ($finder as $file) { 1261 | $ns = $prefix; 1262 | if ($relativePath = $file->getRelativePath()) { 1263 | $ns .= '\\'.strtr($relativePath, '/', '\\'); 1264 | } 1265 | $r = new \ReflectionClass($ns.'\\'.$file->getBasename('.php')); 1266 | if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract()) { 1267 | $application->add($r->newInstance()); 1268 | } 1269 | } 1270 | } 1271 | } 1272 | } 1273 | 1274 | 1275 | 1276 | 1277 | namespace Symfony\Component\Config 1278 | { 1279 | 1280 | 1281 | class ConfigCache 1282 | { 1283 | private $debug; 1284 | private $file; 1285 | 1286 | 1287 | public function __construct($file, $debug) 1288 | { 1289 | $this->file = $file; 1290 | $this->debug = (Boolean) $debug; 1291 | } 1292 | 1293 | 1294 | public function __toString() 1295 | { 1296 | return $this->file; 1297 | } 1298 | 1299 | 1300 | public function isFresh() 1301 | { 1302 | if (!is_file($this->file)) { 1303 | return false; 1304 | } 1305 | 1306 | if (!$this->debug) { 1307 | return true; 1308 | } 1309 | 1310 | $metadata = $this->file.'.meta'; 1311 | if (!is_file($metadata)) { 1312 | return false; 1313 | } 1314 | 1315 | $time = filemtime($this->file); 1316 | $meta = unserialize(file_get_contents($metadata)); 1317 | foreach ($meta as $resource) { 1318 | if (!$resource->isFresh($time)) { 1319 | return false; 1320 | } 1321 | } 1322 | 1323 | return true; 1324 | } 1325 | 1326 | 1327 | public function write($content, array $metadata = null) 1328 | { 1329 | $dir = dirname($this->file); 1330 | if (!is_dir($dir)) { 1331 | if (false === @mkdir($dir, 0777, true)) { 1332 | throw new \RuntimeException(sprintf('Unable to create the %s directory', $dir)); 1333 | } 1334 | } elseif (!is_writable($dir)) { 1335 | throw new \RuntimeException(sprintf('Unable to write in the %s directory', $dir)); 1336 | } 1337 | 1338 | $tmpFile = tempnam(dirname($this->file), basename($this->file)); 1339 | if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $this->file)) { 1340 | @chmod($this->file, 0666 & ~umask()); 1341 | } else { 1342 | throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $this->file)); 1343 | } 1344 | 1345 | if (null !== $metadata && true === $this->debug) { 1346 | $file = $this->file.'.meta'; 1347 | $tmpFile = tempnam(dirname($file), basename($file)); 1348 | if (false !== @file_put_contents($tmpFile, serialize($metadata)) && @rename($tmpFile, $file)) { 1349 | @chmod($file, 0666 & ~umask()); 1350 | } 1351 | } 1352 | } 1353 | } 1354 | } 1355 | 1356 | 1357 | 1358 | 1359 | namespace Symfony\Component\HttpKernel 1360 | { 1361 | 1362 | use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; 1363 | use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; 1364 | use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; 1365 | use Symfony\Component\HttpKernel\Event\FilterControllerEvent; 1366 | use Symfony\Component\HttpKernel\Event\FilterResponseEvent; 1367 | use Symfony\Component\HttpKernel\Event\GetResponseEvent; 1368 | use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent; 1369 | use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; 1370 | use Symfony\Component\HttpKernel\Event\PostResponseEvent; 1371 | use Symfony\Component\HttpFoundation\Request; 1372 | use Symfony\Component\HttpFoundation\Response; 1373 | use Symfony\Component\EventDispatcher\EventDispatcherInterface; 1374 | 1375 | 1376 | class HttpKernel implements HttpKernelInterface, TerminableInterface 1377 | { 1378 | protected $dispatcher; 1379 | protected $resolver; 1380 | 1381 | 1382 | public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver) 1383 | { 1384 | $this->dispatcher = $dispatcher; 1385 | $this->resolver = $resolver; 1386 | } 1387 | 1388 | 1389 | public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) 1390 | { 1391 | try { 1392 | return $this->handleRaw($request, $type); 1393 | } catch (\Exception $e) { 1394 | if (false === $catch) { 1395 | throw $e; 1396 | } 1397 | 1398 | return $this->handleException($e, $request, $type); 1399 | } 1400 | } 1401 | 1402 | 1403 | public function terminate(Request $request, Response $response) 1404 | { 1405 | $this->dispatcher->dispatch(KernelEvents::TERMINATE, new PostResponseEvent($this, $request, $response)); 1406 | } 1407 | 1408 | 1409 | private function handleRaw(Request $request, $type = self::MASTER_REQUEST) 1410 | { 1411 | $event = new GetResponseEvent($this, $request, $type); 1412 | $this->dispatcher->dispatch(KernelEvents::REQUEST, $event); 1413 | 1414 | if ($event->hasResponse()) { 1415 | return $this->filterResponse($event->getResponse(), $request, $type); 1416 | } 1417 | 1418 | if (false === $controller = $this->resolver->getController($request)) { 1419 | throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". Maybe you forgot to add the matching route in your routing configuration?', $request->getPathInfo())); 1420 | } 1421 | 1422 | $event = new FilterControllerEvent($this, $controller, $request, $type); 1423 | $this->dispatcher->dispatch(KernelEvents::CONTROLLER, $event); 1424 | $controller = $event->getController(); 1425 | 1426 | $arguments = $this->resolver->getArguments($request, $controller); 1427 | 1428 | $response = call_user_func_array($controller, $arguments); 1429 | 1430 | if (!$response instanceof Response) { 1431 | $event = new GetResponseForControllerResultEvent($this, $request, $type, $response); 1432 | $this->dispatcher->dispatch(KernelEvents::VIEW, $event); 1433 | 1434 | if ($event->hasResponse()) { 1435 | $response = $event->getResponse(); 1436 | } 1437 | 1438 | if (!$response instanceof Response) { 1439 | $msg = sprintf('The controller must return a response (%s given).', $this->varToString($response)); 1440 | 1441 | if (null === $response) { 1442 | $msg .= ' Did you forget to add a return statement somewhere in your controller?'; 1443 | } 1444 | throw new \LogicException($msg); 1445 | } 1446 | } 1447 | 1448 | return $this->filterResponse($response, $request, $type); 1449 | } 1450 | 1451 | 1452 | private function filterResponse(Response $response, Request $request, $type) 1453 | { 1454 | $event = new FilterResponseEvent($this, $request, $type, $response); 1455 | 1456 | $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); 1457 | 1458 | return $event->getResponse(); 1459 | } 1460 | 1461 | 1462 | private function handleException(\Exception $e, $request, $type) 1463 | { 1464 | $event = new GetResponseForExceptionEvent($this, $request, $type, $e); 1465 | $this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event); 1466 | 1467 | $e = $event->getException(); 1468 | 1469 | if (!$event->hasResponse()) { 1470 | throw $e; 1471 | } 1472 | 1473 | $response = $event->getResponse(); 1474 | 1475 | if ($response->headers->has('X-Status-Code')) { 1476 | $response->setStatusCode($response->headers->get('X-Status-Code')); 1477 | 1478 | $response->headers->remove('X-Status-Code'); 1479 | } elseif (!$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) { 1480 | if ($e instanceof HttpExceptionInterface) { 1481 | $response->setStatusCode($e->getStatusCode()); 1482 | $response->headers->add($e->getHeaders()); 1483 | } else { 1484 | $response->setStatusCode(500); 1485 | } 1486 | } 1487 | 1488 | try { 1489 | return $this->filterResponse($response, $request, $type); 1490 | } catch (\Exception $e) { 1491 | return $response; 1492 | } 1493 | } 1494 | 1495 | private function varToString($var) 1496 | { 1497 | if (is_object($var)) { 1498 | return sprintf('Object(%s)', get_class($var)); 1499 | } 1500 | 1501 | if (is_array($var)) { 1502 | $a = array(); 1503 | foreach ($var as $k => $v) { 1504 | $a[] = sprintf('%s => %s', $k, $this->varToString($v)); 1505 | } 1506 | 1507 | return sprintf("Array(%s)", implode(', ', $a)); 1508 | } 1509 | 1510 | if (is_resource($var)) { 1511 | return sprintf('Resource(%s)', get_resource_type($var)); 1512 | } 1513 | 1514 | if (null === $var) { 1515 | return 'null'; 1516 | } 1517 | 1518 | if (false === $var) { 1519 | return 'false'; 1520 | } 1521 | 1522 | if (true === $var) { 1523 | return 'true'; 1524 | } 1525 | 1526 | return (string) $var; 1527 | } 1528 | } 1529 | } 1530 | 1531 | 1532 | 1533 | 1534 | namespace Symfony\Bundle\FrameworkBundle 1535 | { 1536 | 1537 | use Symfony\Component\HttpFoundation\Request; 1538 | use Symfony\Component\HttpFoundation\Response; 1539 | use Symfony\Component\HttpFoundation\StreamedResponse; 1540 | use Symfony\Component\HttpKernel\HttpKernelInterface; 1541 | use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; 1542 | use Symfony\Component\DependencyInjection\ContainerInterface; 1543 | use Symfony\Component\HttpKernel\HttpKernel as BaseHttpKernel; 1544 | use Symfony\Component\EventDispatcher\EventDispatcherInterface; 1545 | 1546 | 1547 | class HttpKernel extends BaseHttpKernel 1548 | { 1549 | protected $container; 1550 | 1551 | private $esiSupport; 1552 | 1553 | public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver) 1554 | { 1555 | parent::__construct($dispatcher, $controllerResolver); 1556 | 1557 | $this->container = $container; 1558 | } 1559 | 1560 | public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) 1561 | { 1562 | $request->headers->set('X-Php-Ob-Level', ob_get_level()); 1563 | 1564 | $this->container->enterScope('request'); 1565 | $this->container->set('request', $request, 'request'); 1566 | 1567 | try { 1568 | $response = parent::handle($request, $type, $catch); 1569 | } catch (\Exception $e) { 1570 | $this->container->leaveScope('request'); 1571 | 1572 | throw $e; 1573 | } 1574 | 1575 | $this->container->leaveScope('request'); 1576 | 1577 | return $response; 1578 | } 1579 | 1580 | 1581 | public function forward($controller, array $attributes = array(), array $query = array()) 1582 | { 1583 | $attributes['_controller'] = $controller; 1584 | $subRequest = $this->container->get('request')->duplicate($query, null, $attributes); 1585 | 1586 | return $this->handle($subRequest, HttpKernelInterface::SUB_REQUEST); 1587 | } 1588 | 1589 | 1590 | public function render($controller, array $options = array()) 1591 | { 1592 | $options = array_merge(array( 1593 | 'attributes' => array(), 1594 | 'query' => array(), 1595 | 'ignore_errors' => !$this->container->getParameter('kernel.debug'), 1596 | 'alt' => array(), 1597 | 'standalone' => false, 1598 | 'comment' => '', 1599 | ), $options); 1600 | 1601 | if (!is_array($options['alt'])) { 1602 | $options['alt'] = array($options['alt']); 1603 | } 1604 | 1605 | if (null === $this->esiSupport) { 1606 | $this->esiSupport = $this->container->has('esi') && $this->container->get('esi')->hasSurrogateEsiCapability($this->container->get('request')); 1607 | } 1608 | 1609 | if ($this->esiSupport && (true === $options['standalone'] || 'esi' === $options['standalone'])) { 1610 | if (0 === strpos($controller, 'http://') || 0 === strpos($controller, 'https://')) { 1611 | $uri = $controller; 1612 | } else { 1613 | $uri = $this->generateInternalUri($controller, $options['attributes'], $options['query']); 1614 | } 1615 | 1616 | $alt = ''; 1617 | if ($options['alt']) { 1618 | if (is_string($options['alt']) && (0 === strpos($options['alt'], 'http://') || 0 === strpos($options['alt'], 'https://'))) { 1619 | $alt = $options['alt']; 1620 | } else { 1621 | $alt = $this->generateInternalUri($options['alt'][0], isset($options['alt'][1]) ? $options['alt'][1] : array(), isset($options['alt'][2]) ? $options['alt'][2] : array()); 1622 | } 1623 | } 1624 | 1625 | return $this->container->get('esi')->renderIncludeTag($uri, $alt, $options['ignore_errors'], $options['comment']); 1626 | } 1627 | 1628 | if ('js' === $options['standalone']) { 1629 | if (0 === strpos($controller, 'http://') || 0 === strpos($controller, 'https://')) { 1630 | $uri = $controller; 1631 | } else { 1632 | $uri = $this->generateInternalUri($controller, $options['attributes'], $options['query'], false); 1633 | } 1634 | $defaultContent = null; 1635 | 1636 | if ($template = $this->container->getParameter('templating.hinclude.default_template')) { 1637 | $defaultContent = $this->container->get('templating')->render($template); 1638 | } 1639 | 1640 | return $this->renderHIncludeTag($uri, $defaultContent); 1641 | } 1642 | 1643 | $request = $this->container->get('request'); 1644 | 1645 | if (0 === strpos($controller, 'http://') || 0 === strpos($controller, 'https://')) { 1646 | $subRequest = $request::create($controller, 'get', array(), $request->cookies->all(), array(), $request->server->all()); 1647 | if ($session = $request->getSession()) { 1648 | $subRequest->setSession($session); 1649 | } 1650 | } elseif (0 === strpos($controller, '/')) { 1651 | $subRequest = $request::create($request->getUriForPath($controller), 'get', array(), $request->cookies->all(), array(), $request->server->all()); 1652 | if ($session = $request->getSession()) { 1653 | $subRequest->setSession($session); 1654 | } 1655 | } else { 1656 | $options['attributes']['_controller'] = $controller; 1657 | 1658 | if (!isset($options['attributes']['_format'])) { 1659 | $options['attributes']['_format'] = $request->getRequestFormat(); 1660 | } 1661 | 1662 | $options['attributes']['_route'] = '_internal'; 1663 | $subRequest = $request->duplicate($options['query'], null, $options['attributes']); 1664 | $subRequest->setMethod('GET'); 1665 | } 1666 | 1667 | $level = ob_get_level(); 1668 | try { 1669 | $response = $this->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false); 1670 | 1671 | if (!$response->isSuccessful()) { 1672 | throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $request->getUri(), $response->getStatusCode())); 1673 | } 1674 | 1675 | if (!$response instanceof StreamedResponse) { 1676 | return $response->getContent(); 1677 | } 1678 | 1679 | $response->sendContent(); 1680 | } catch (\Exception $e) { 1681 | if ($options['alt']) { 1682 | $alt = $options['alt']; 1683 | unset($options['alt']); 1684 | $options['attributes'] = isset($alt[1]) ? $alt[1] : array(); 1685 | $options['query'] = isset($alt[2]) ? $alt[2] : array(); 1686 | 1687 | return $this->render($alt[0], $options); 1688 | } 1689 | 1690 | if (!$options['ignore_errors']) { 1691 | throw $e; 1692 | } 1693 | 1694 | while (ob_get_level() > $level) { 1695 | ob_get_clean(); 1696 | } 1697 | } 1698 | } 1699 | 1700 | 1701 | public function generateInternalUri($controller, array $attributes = array(), array $query = array(), $secure = true) 1702 | { 1703 | if (0 === strpos($controller, '/')) { 1704 | return $controller; 1705 | } 1706 | 1707 | $path = http_build_query($attributes, '', '&'); 1708 | $uri = $this->container->get('router')->generate($secure ? '_internal' : '_internal_public', array( 1709 | 'controller' => $controller, 1710 | 'path' => $path ?: 'none', 1711 | '_format' => $this->container->get('request')->getRequestFormat(), 1712 | )); 1713 | 1714 | if ($queryString = http_build_query($query, '', '&')) { 1715 | $uri .= '?'.$queryString; 1716 | } 1717 | 1718 | return $uri; 1719 | } 1720 | 1721 | 1722 | public function renderHIncludeTag($uri, $defaultContent = null) 1723 | { 1724 | return sprintf('%s', $uri, $defaultContent); 1725 | } 1726 | 1727 | public function hasEsiSupport() 1728 | { 1729 | return $this->esiSupport; 1730 | } 1731 | } 1732 | } 1733 | 1734 | 1735 | namespace { return $loader; } 1736 | -------------------------------------------------------------------------------- /app/check.php: -------------------------------------------------------------------------------- 1 | getPhpIniConfigPath(); 8 | 9 | echo "********************************\n"; 10 | echo "* *\n"; 11 | echo "* Symfony requirements check *\n"; 12 | echo "* *\n"; 13 | echo "********************************\n\n"; 14 | 15 | echo $iniPath ? sprintf("* Configuration file used by PHP: %s\n\n", $iniPath) : "* WARNING: No configuration file (php.ini) used by PHP!\n\n"; 16 | 17 | echo "** ATTENTION **\n"; 18 | echo "* The PHP CLI can use a different php.ini file\n"; 19 | echo "* than the one used with your web server.\n"; 20 | if ('\\' == DIRECTORY_SEPARATOR) { 21 | echo "* (especially on the Windows platform)\n"; 22 | } 23 | echo "* To be on the safe side, please also launch the requirements check\n"; 24 | echo "* from your web server using the web/config.php script.\n"; 25 | 26 | echo_title('Mandatory requirements'); 27 | 28 | foreach ($symfonyRequirements->getRequirements() as $req) { 29 | echo_requirement($req); 30 | } 31 | 32 | echo_title('Optional recommendations'); 33 | 34 | foreach ($symfonyRequirements->getRecommendations() as $req) { 35 | echo_requirement($req); 36 | } 37 | 38 | /** 39 | * Prints a Requirement instance 40 | */ 41 | function echo_requirement(Requirement $requirement) 42 | { 43 | $result = $requirement->isFulfilled() ? 'OK' : ($requirement->isOptional() ? 'WARNING' : 'ERROR'); 44 | echo ' ' . str_pad($result, 9); 45 | echo $requirement->getTestMessage() . "\n"; 46 | 47 | if (!$requirement->isFulfilled()) { 48 | echo sprintf(" %s\n\n", $requirement->getHelpText()); 49 | } 50 | } 51 | 52 | function echo_title($title) 53 | { 54 | echo "\n** $title **\n\n"; 55 | } 56 | -------------------------------------------------------------------------------- /app/config/config.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: parameters.yml } 3 | - { resource: security.yml } 4 | 5 | framework: 6 | #esi: ~ 7 | #translator: { fallback: "%locale%" } 8 | secret: "%secret%" 9 | router: 10 | resource: "%kernel.root_dir%/config/routing.yml" 11 | strict_requirements: "%kernel.debug%" 12 | form: true 13 | csrf_protection: true 14 | validation: { enable_annotations: true } 15 | templating: { engines: ['twig'] } #assets_version: SomeVersionScheme 16 | default_locale: "%locale%" 17 | trust_proxy_headers: false # Deprecated in 2.0; will be removed in 2.3 (used trusted_proxies instead) 18 | trusted_proxies: ~ 19 | session: ~ 20 | 21 | # Twig Configuration 22 | twig: 23 | debug: "%kernel.debug%" 24 | strict_variables: "%kernel.debug%" 25 | 26 | # Assetic Configuration 27 | assetic: 28 | debug: "%kernel.debug%" 29 | use_controller: false 30 | bundles: [ ] 31 | #java: /usr/bin/java 32 | filters: 33 | cssrewrite: ~ 34 | #closure: 35 | # jar: "%kernel.root_dir%/Resources/java/compiler.jar" 36 | #yui_css: 37 | # jar: "%kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar" 38 | 39 | # Doctrine Configuration 40 | doctrine: 41 | dbal: 42 | driver: "%database_driver%" 43 | host: "%database_host%" 44 | port: "%database_port%" 45 | dbname: "%database_name%" 46 | user: "%database_user%" 47 | password: "%database_password%" 48 | charset: UTF8 49 | 50 | orm: 51 | auto_generate_proxy_classes: "%kernel.debug%" 52 | auto_mapping: true 53 | 54 | # Swiftmailer Configuration 55 | swiftmailer: 56 | transport: "%mailer_transport%" 57 | host: "%mailer_host%" 58 | username: "%mailer_user%" 59 | password: "%mailer_password%" 60 | spool: { type: memory } 61 | 62 | 63 | doctrine_mongodb: 64 | connections: 65 | default: 66 | server: mongodb://localhost:27017 67 | options: {} 68 | default_database: "%database_name%" 69 | document_managers: 70 | default: 71 | auto_mapping: true -------------------------------------------------------------------------------- /app/config/config_dev.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: config.yml } 3 | 4 | framework: 5 | router: { resource: "%kernel.root_dir%/config/routing_dev.yml" } 6 | profiler: { only_exceptions: false } 7 | 8 | web_profiler: 9 | toolbar: true 10 | intercept_redirects: false 11 | 12 | monolog: 13 | handlers: 14 | main: 15 | type: stream 16 | path: "%kernel.logs_dir%/%kernel.environment%.log" 17 | level: debug 18 | firephp: 19 | type: firephp 20 | level: info 21 | 22 | assetic: 23 | use_controller: true 24 | 25 | #swiftmailer: 26 | # delivery_address: me@example.com 27 | -------------------------------------------------------------------------------- /app/config/config_prod.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: config.yml } 3 | 4 | #doctrine: 5 | # orm: 6 | # metadata_cache_driver: apc 7 | # result_cache_driver: apc 8 | # query_cache_driver: apc 9 | 10 | monolog: 11 | handlers: 12 | main: 13 | type: fingers_crossed 14 | action_level: error 15 | handler: nested 16 | nested: 17 | type: stream 18 | path: "%kernel.logs_dir%/%kernel.environment%.log" 19 | level: debug 20 | -------------------------------------------------------------------------------- /app/config/config_test.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: config_dev.yml } 3 | 4 | framework: 5 | test: ~ 6 | session: 7 | storage_id: session.storage.mock_file 8 | 9 | web_profiler: 10 | toolbar: false 11 | intercept_redirects: false 12 | 13 | swiftmailer: 14 | disable_delivery: true 15 | -------------------------------------------------------------------------------- /app/config/parameters.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | database_driver: pdo_mysql 3 | database_host: localhost 4 | database_port: ~ 5 | database_name: mongo_test 6 | database_user: root 7 | database_password: ~ 8 | 9 | mailer_transport: smtp 10 | mailer_host: 127.0.0.1 11 | mailer_user: ~ 12 | mailer_password: ~ 13 | 14 | locale: en 15 | secret: ThisTokenIsNotSoSecretChangeIt 16 | -------------------------------------------------------------------------------- /app/config/routing.yml: -------------------------------------------------------------------------------- 1 | # Internal routing configuration to handle ESI 2 | # ****** WARNING ****** 3 | # This route should be enabled with caution as it can open a security vulnerability 4 | # see http://symfony.com/blog/security-release-symfony-2-0-20-and-2-1-5-released for more information 5 | # ****** WARNING ****** 6 | #_internal: 7 | # resource: "@FrameworkBundle/Resources/config/routing/internal.xml" 8 | # prefix: /_internal 9 | 10 | place: 11 | resource: "@HenterGEOBundle/Controller" 12 | type: annotation 13 | prefix: / -------------------------------------------------------------------------------- /app/config/routing_dev.yml: -------------------------------------------------------------------------------- 1 | _wdt: 2 | resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml" 3 | prefix: /_wdt 4 | 5 | _profiler: 6 | resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml" 7 | prefix: /_profiler 8 | 9 | _configurator: 10 | resource: "@SensioDistributionBundle/Resources/config/routing/webconfigurator.xml" 11 | prefix: /_configurator 12 | 13 | _main: 14 | resource: routing.yml 15 | -------------------------------------------------------------------------------- /app/config/security.yml: -------------------------------------------------------------------------------- 1 | jms_security_extra: 2 | secure_all_services: false 3 | expressions: true 4 | 5 | security: 6 | encoders: 7 | Symfony\Component\Security\Core\User\User: plaintext 8 | 9 | role_hierarchy: 10 | ROLE_ADMIN: ROLE_USER 11 | ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] 12 | 13 | providers: 14 | in_memory: 15 | memory: 16 | users: 17 | user: { password: userpass, roles: [ 'ROLE_USER' ] } 18 | admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] } 19 | 20 | firewalls: 21 | dev: 22 | pattern: ^/(_(profiler|wdt)|css|images|js)/ 23 | security: false 24 | 25 | login: 26 | pattern: ^/demo/secured/login$ 27 | security: false 28 | 29 | secured_area: 30 | pattern: ^/demo/secured/ 31 | form_login: 32 | check_path: /demo/secured/login_check 33 | login_path: /demo/secured/login 34 | logout: 35 | path: /demo/secured/logout 36 | target: /demo/ 37 | #anonymous: ~ 38 | #http_basic: 39 | # realm: "Secured Demo Area" 40 | 41 | access_control: 42 | #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https } 43 | # 44 | # You must uncomment the two following rules to restrict access to paths 45 | # starting with the /_internal prefix to only localhost 46 | #- { path: ^/_internal/secure, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 } 47 | #- { path: ^/_internal/secure, roles: ROLE_NO_ACCESS } 48 | -------------------------------------------------------------------------------- /app/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | getParameterOption(array('--env', '-e'), getenv('SYMFONY_ENV') ?: 'dev'); 18 | $debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(array('--no-debug', '')) && $env !== 'prod'; 19 | 20 | $kernel = new AppKernel($env, $debug); 21 | $application = new Application($kernel); 22 | $application->run($input); 23 | -------------------------------------------------------------------------------- /app/phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | 18 | ../src/*/*Bundle/Tests 19 | ../src/*/Bundle/*Bundle/Tests 20 | 21 | 22 | 23 | 28 | 29 | 30 | 31 | ../src 32 | 33 | ../src/*/*Bundle/Resources 34 | ../src/*/*Bundle/Tests 35 | ../src/*/Bundle/*Bundle/Resources 36 | ../src/*/Bundle/*Bundle/Tests 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "symfony/framework-standard-edition", 3 | "license": "MIT", 4 | "type": "project", 5 | "description": "The \"Symfony Standard Edition\" distribution", 6 | "autoload": { 7 | "psr-0": { "": "src/" } 8 | }, 9 | "require": { 10 | "php": ">=5.3.3", 11 | "symfony/symfony": "2.1.*", 12 | "doctrine/orm": ">=2.2.3,<2.5-dev", 13 | "doctrine/doctrine-bundle": "1.1.*", 14 | "twig/extensions": "1.0.*@dev", 15 | "symfony/assetic-bundle": "2.1.*", 16 | "symfony/swiftmailer-bundle": "2.1.*", 17 | "symfony/monolog-bundle": "2.1.*", 18 | "sensio/distribution-bundle": "2.1.*", 19 | "sensio/framework-extra-bundle": "2.1.*", 20 | "sensio/generator-bundle": "2.1.*", 21 | "jms/security-extra-bundle": "1.2.*", 22 | "jms/di-extra-bundle": "1.1.*", 23 | "kriswallsmith/assetic": "1.1.*@dev", 24 | "raulfraile/ladybug-bundle": "dev-master", 25 | "doctrine/mongodb-odm-bundle": "dev-master", 26 | "doctrine/mongodb-odm": "dev-master" 27 | }, 28 | "scripts": { 29 | "post-install-cmd": [ 30 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap", 31 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache", 32 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets", 33 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile" 34 | ], 35 | "post-update-cmd": [ 36 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap", 37 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache", 38 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets", 39 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile" 40 | ] 41 | }, 42 | "extra": { 43 | "symfony-app-dir": "app", 44 | "symfony-web-dir": "web", 45 | "branch-alias": { 46 | "dev-master": "2.1-dev" 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/.htaccess: -------------------------------------------------------------------------------- 1 | deny from all -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Command/ImportCommand.php: -------------------------------------------------------------------------------- 1 | setName('geo:data:import') 24 | ->setDescription('import demo data') 25 | ; 26 | } 27 | 28 | protected function execute(InputInterface $input, OutputInterface $output) 29 | { 30 | $this->output = $output; 31 | $this->dm = $this->getContainer()->get('doctrine_mongodb')->getManager(); 32 | 33 | $this->import_data(); 34 | 35 | $this->output->writeln('导入完成'); 36 | } 37 | 38 | public function import_data(){ 39 | $data = json_decode(file_get_contents(__DIR__.'/places.json'), true); 40 | 41 | foreach($data as $k=>$v){ 42 | $new = new Place(); 43 | $coordinate = new Coordinate(); 44 | $coordinate->setLongitude($v['coordinate']['longitude']); 45 | $coordinate->setLatitude($v['coordinate']['latitude']); 46 | $new->setCoordinate($coordinate); 47 | $new->setAddress($v['address']); 48 | $new->setTitle($v['title']); 49 | 50 | $this->dm->persist($new); 51 | $this->output->writeln($v['address']); 52 | 53 | } 54 | $this->output->writeln('importing...'); 55 | $this->dm->flush($new); 56 | 57 | $this->output->writeln(' done'); 58 | return true; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Command/geointersects.php: -------------------------------------------------------------------------------- 1 | 5 | array ( 6 | '_id' => 116117, 7 | 'title' => '仅售1288元,市场价3272元的天吉大酒店豪华海鲜宴10-12人餐,赠送水果拼盘,美味共享,欢度圣诞!', 8 | 'address' => '浦东南路855号世界广场3楼', 9 | 'coordinate' => 10 | array ( 11 | 'longitude' => 121.5142, 12 | 'latitude' => 31.23253, 13 | ), 14 | ), 15 | 1 => 16 | array ( 17 | '_id' => 116111, 18 | 'title' => '仅售398元,市场价1104元的天吉大酒店4-6人套餐,赠水果拼盘,欢乐圣诞,温馨一刻!', 19 | 'address' => '浦东南路855号世界广场3楼', 20 | 'coordinate' => 21 | array ( 22 | 'longitude' => 121.5142, 23 | 'latitude' => 31.23253, 24 | ), 25 | ), 26 | 2 => 27 | array ( 28 | '_id' => 115696, 29 | 'title' => '毕业了,我们去深圳吧', 30 | 'address' => '上海 黄浦区 人民广场 南京路步行街', 31 | 'coordinate' => 32 | array ( 33 | 'longitude' => 121.474777, 34 | 'latitude' => 31.234846, 35 | ), 36 | ), 37 | 3 => 38 | array ( 39 | '_id' => 115686, 40 | 'title' => '好友会面,一起来体验瑜伽吧', 41 | 'address' => '上海 浦东新区 商城路297号申金大厦408室', 42 | 'coordinate' => 43 | array ( 44 | 'longitude' => 121.510353, 45 | 'latitude' => 31.229366, 46 | ), 47 | ), 48 | 4 => 49 | array ( 50 | '_id' => 115685, 51 | 'title' => '在自然山水中邂逅人生另一半。。上海旅游交友自驾群', 52 | 'address' => '上海 浦东新区 八佰伴 浦东南路中融国际商城7楼上海歌城', 53 | 'coordinate' => 54 | array ( 55 | 'longitude' => 121.52504, 56 | 'latitude' => 31.230747, 57 | ), 58 | ), 59 | 5 => 60 | array ( 61 | '_id' => 115683, 62 | 'title' => '魔都三国杀聚会(长期)', 63 | 'address' => '上海 黄浦区 浙江中路229号3楼365室', 64 | 'coordinate' => 65 | array ( 66 | 'longitude' => 121.478989, 67 | 'latitude' => 31.233599, 68 | ), 69 | ), 70 | 6 => 71 | array ( 72 | '_id' => 115655, 73 | 'title' => '世界末日系列--2012世界末日狂欢德啤畅饮派对', 74 | 'address' => '上海 黄浦区 人民广场 北京西路61号', 75 | 'coordinate' => 76 | array ( 77 | 'longitude' => 121.472343, 78 | 'latitude' => 31.2369, 79 | ), 80 | ), 81 | 7 => 82 | array ( 83 | '_id' => 93287, 84 | 'title' => '【上海杭州2店通用】仅售78元!市场价最高660元的上海鸿光眼镜/杭州视觉眼镜配镜套组一份(男女不限,需自取):记忆板材架/合金钢板架/记忆钛架(3选1)+卡蒂罗镜片【1.56折射率、非球面、加硬加膜】,另免费验光+免费清洗+免费校正、维修!赠送镜盒、镜布!镜片适用于近视0-800度(含)和散光0-200度(含)的用户!更有升级套组详见页面!时尚前卫,让你靓丽出行!专业眼光配镜,让您看到的世界更清晰明亮!', 85 | 'address' => '上海市黄浦区南京东路592号4楼412室(南京东路步行街李宁旗舰店楼上)', 86 | 'coordinate' => 87 | array ( 88 | 'longitude' => 121.48023, 89 | 'latitude' => 31.23576, 90 | ), 91 | ), 92 | 8 => 93 | array ( 94 | '_id' => 90463, 95 | 'title' => '仅售9.8元,市场价12.8元的牛奶棚掼奶魔方蛋糕2个,节假日通用,营养健康!爱意无限', 96 | 'address' => '黄浦区西藏中路632号', 97 | 'coordinate' => 98 | array ( 99 | 'longitude' => 121.47355, 100 | 'latitude' => 31.23817, 101 | ), 102 | ), 103 | 9 => 104 | array ( 105 | '_id' => 90460, 106 | 'title' => '【城隍庙】仅售798元!市场价1420元的兴宇大酒店8-10人套餐一份:鲍参刺肚羹+双椒焗龙虾+鲍汁扣大乌参+避风塘花蟹+沙田乳鸽+酱爆驼峰肉+深井烧鹅+辣酒煮香螺+桂花炒瑶柱+干煸四季豆+清炒时蔬+木瓜蛋挞+生煎包!邀请朋友来一起品尝这精致的美食吧!另赠送水果拼盘1份及精美八冷碟1份!', 107 | 'address' => '黄浦区人民路386号8楼', 108 | 'coordinate' => 109 | array ( 110 | 'longitude' => 121.49216, 111 | 'latitude' => 31.22945, 112 | ), 113 | ), 114 | 10 => 115 | array ( 116 | '_id' => 90455, 117 | 'title' => '【城隍庙】仅售158元!市场价478元的兴宇大酒店4人套餐一份:双椒焗龙虾+西湖牛肉羹+红烧罗汉鲍+蜜汁叉烧+素鱼翅饺+清炒时蔬!邀请朋友来一起品尝这精致的美食吧!', 118 | 'address' => '黄浦区人民路386号8楼', 119 | 'coordinate' => 120 | array ( 121 | 'longitude' => 121.49216, 122 | 'latitude' => 31.22945, 123 | ), 124 | ), 125 | 11 => 126 | array ( 127 | '_id' => 90451, 128 | 'title' => '【2店通用】仅售999元!市场价4108元的跃民大酒店10人B套餐一份:冷菜(老干妈小黄鱼+家乡咸鸡+特色鱼皮+糟三鲜+水晶肴肉+关东木耳+万年青+冰糖红枣)+热菜(清蒸大闸蟹+黄油焗龙虾+鲍汁翅肚羹+酒香蒸鲥鱼+豆豉扇贝王+黑椒牛仔粒+金牌烤鸭+ 红烧大圆蹄+小米椒仔鸡+特色鱼米之乡+龙虾泡饭+上汤时蔬+点心(麻饼)!拉手券使用时间:西藏南路店:10:30-14:00,16:00-21:00,崂山路店:10:30-14:00 ,16:00-次日凌晨03:00!', 129 | 'address' => '浦东新区崂山路585号', 130 | 'coordinate' => 131 | array ( 132 | 'longitude' => 121.52343, 133 | 'latitude' => 31.2254, 134 | ), 135 | ), 136 | 12 => 137 | array ( 138 | '_id' => 90450, 139 | 'title' => '【2店通用】仅售168元!市场价827元的跃民大酒店4-6人套餐一份:冷菜(散养鸡+本帮熏鱼+凉拌黄瓜)+热菜(香辣梭子蟹+酒香鲥鱼+清炒河虾仁+干锅牛筋+鹅肝沫炖蛋+灌汤虾球+香菇面筋煲+热炝花蛤+本帮酸辣汤+清炒时蔬)!拉手券使用时间:西藏南路店:10:30-14:00,16:00-21:00,崂山路店:10:30-14:00 ,16:00-次日凌晨03:00!', 140 | 'address' => '浦东新区崂山路585号', 141 | 'coordinate' => 142 | array ( 143 | 'longitude' => 121.52343, 144 | 'latitude' => 31.2254, 145 | ), 146 | ), 147 | 13 => 148 | array ( 149 | '_id' => 90449, 150 | 'title' => '【2店通用】仅售699元!市场价2013元的跃民大酒店10人A套餐一份:冷菜(散养鸡+水晶肴肉+本帮熏鱼+关东木耳+色拉+万年青)+热菜(葱油局龙虾+葱姜梭子蟹+金牌烤鸭+灌汤虾球+鲍汁白灵菇+干锅牛蛙+清蒸白水鱼+沙律牛排+鹅肝炖蛋+热炝花蛤+上汤杭白菜+农家老鸡汤)+点心(脆皮香蕉+麻饼)!拉手券使用时间:西藏南路店:10:30-14:00,16:00-21:00,崂山路店:10:30-14:00 ,16:00-次日凌晨03:00!', 151 | 'address' => '浦东新区崂山路585号', 152 | 'coordinate' => 153 | array ( 154 | 'longitude' => 121.52343, 155 | 'latitude' => 31.2254, 156 | ), 157 | ), 158 | 14 => 159 | array ( 160 | '_id' => 90432, 161 | 'title' => '仅售19.9元,市场价30元的芒不颠港式甜品套餐,3种套餐任选,喧闹的城市,安静的小店,一份甜品,一点舒心,你需要一个甜蜜的下午,来放松一周的辛劳,给自己一份甜蜜的犒赏!', 162 | 'address' => '浦东新区崂山路645号(近潍坊路)', 163 | 'coordinate' => 164 | array ( 165 | 'longitude' => 121.52456, 166 | 'latitude' => 31.22318, 167 | ), 168 | ), 169 | 15 => 170 | array ( 171 | '_id' => 90427, 172 | 'title' => '仅售79元,市场价198元的康骏会馆(南京东路店)按摩套组,男女不限,健康有道,骏越万里!', 173 | 'address' => '黄浦区南京东路588号丝绸商厦4楼', 174 | 'coordinate' => 175 | array ( 176 | 'longitude' => 121.48023, 177 | 'latitude' => 31.23576, 178 | ), 179 | ), 180 | 16 => 181 | array ( 182 | '_id' => 90425, 183 | 'title' => '仅售209元,市场价708元的康骏会馆(南京东路店)全身精油按摩,男女不限,健康有道,骏越万里!', 184 | 'address' => '黄浦区南京东路588号丝绸商厦4楼', 185 | 'coordinate' => 186 | array ( 187 | 'longitude' => 121.48023, 188 | 'latitude' => 31.23576, 189 | ), 190 | ), 191 | 17 => 192 | array ( 193 | '_id' => 90418, 194 | 'title' => '【人民广场】仅售9元!市场价180元的华兴少儿体验课程一人次(适合5-16周岁青少年):面塑(捏面人)/空手道(约60分钟,2选1)!拉手券仅限每周三、周五、周六、周日使用!国庆节(2012年10月3日、5日、6日、7日)不使用拉手券!', 195 | 'address' => '黄浦区北海路8号9楼D座', 196 | 'coordinate' => 197 | array ( 198 | 'longitude' => 121.48444, 199 | 'latitude' => 31.23176, 200 | ), 201 | ), 202 | 18 => 203 | array ( 204 | '_id' => 90404, 205 | 'title' => '仅售149.9元,市场价601元的安藤家日本料理4人套餐,交通便利,秉承美食烹制之精华,一脉相承之古老秘方,美味从此开始!', 206 | 'address' => '黄浦区金陵东路229号范仕达生活广场2楼', 207 | 'coordinate' => 208 | array ( 209 | 'longitude' => 121.4875, 210 | 'latitude' => 31.2303, 211 | ), 212 | ), 213 | 19 => 214 | array ( 215 | '_id' => 90402, 216 | 'title' => '仅售33元,市场价83元的中油阳光大酒店(三楼和怡中餐厅)单人套餐,物美价廉,美味地道,尽在中油阳光大酒店和怡中餐厅!', 217 | 'address' => '浦东新区东方路969号(近浦电路)', 218 | 'coordinate' => 219 | array ( 220 | 'longitude' => 121.52876, 221 | 'latitude' => 31.22204, 222 | ), 223 | ), 224 | 20 => 225 | array ( 226 | '_id' => 90377, 227 | 'title' => '仅售48元,市场价1852元的修身堂美容养生套组,赠送修身堂人体测分仪1次,要美丽,要自信,修身堂让您绽放美丽光彩!', 228 | 'address' => '浦东新区浦东南路1036号隆宇大厦801室', 229 | 'coordinate' => 230 | array ( 231 | 'longitude' => 121.5152, 232 | 'latitude' => 31.22899, 233 | ), 234 | ), 235 | 21 => 236 | array ( 237 | '_id' => 90376, 238 | 'title' => '仅售108元,市场价320元的上海源胜商务酒店客房一间入住一天,交通便利,上海源胜商务酒店,享受家的幸福!', 239 | 'address' => '黄浦区南苏州路935号正大门(黄浦区厦门路206号后门)(人民广场,南京东路,近西藏中路桥)', 240 | 'coordinate' => 241 | array ( 242 | 'longitude' => 121.47416, 243 | 'latitude' => 31.24088, 244 | ), 245 | ), 246 | 22 => 247 | array ( 248 | '_id' => 90372, 249 | 'title' => '仅售88.8元,市场价200元的重庆龙门鱼府鱼火锅4人套餐,2店通用,龙门鱼府,真正的鱼火锅,吃的就是这个味儿~', 250 | 'address' => '上海市浦东新区崂山路300号(近乳山路)', 251 | 'coordinate' => 252 | array ( 253 | 'longitude' => 121.52022, 254 | 'latitude' => 31.234, 255 | ), 256 | ), 257 | 23 => 258 | array ( 259 | '_id' => 90359, 260 | 'title' => '仅售998元,市场价3097元的中福世福汇大酒店豪华十人宴,节假日通用,美味诱惑,奢华享受', 261 | 'address' => '上海市黄浦区广东路339号3楼潮粤轩中餐厅', 262 | 'coordinate' => 263 | array ( 264 | 'longitude' => 121.48439, 265 | 'latitude' => 31.23258, 266 | ), 267 | ), 268 | 24 => 269 | array ( 270 | '_id' => 90297, 271 | 'title' => '仅售179元,酒店门市价309元的汉庭快捷酒店客房一间入住一天,含双人早餐,舒适温馨,给您家的感觉', 272 | 'address' => '浦东新区峨山路91弄38号', 273 | 'coordinate' => 274 | array ( 275 | 'longitude' => 121.53299, 276 | 'latitude' => 31.21559, 277 | ), 278 | ), 279 | 25 => 280 | array ( 281 | '_id' => 90292, 282 | 'title' => '仅售188元,酒店门市价599元的上海瑞亚臻品酒店客房入住1天,赠送矿泉水2瓶,优雅浪漫,温暖舒心', 283 | 'address' => '上海市闸北区梅园路37号', 284 | 'coordinate' => 285 | array ( 286 | 'longitude' => 121.46055, 287 | 'latitude' => 31.24134, 288 | ), 289 | ), 290 | 26 => 291 | array ( 292 | '_id' => 90282, 293 | 'title' => '仅售128元,市场价160元的常州淹城春秋乐园自由行,节假日通用,神奇淹城,梦回春秋', 294 | 'address' => '黄浦区河南南路33号', 295 | 'coordinate' => 296 | array ( 297 | 'longitude' => 121.48721, 298 | 'latitude' => 31.22902, 299 | ), 300 | ), 301 | 27 => 302 | array ( 303 | '_id' => 90281, 304 | 'title' => '仅售88元,市场价168元的常州花都温泉自由行,节假日通用,花都温泉设计透露自然与生态,隔开外面的喧闹吵杂,有着静谧的安全感,展现了休闲度假的意境,给紧张生活带来彻底的放松', 305 | 'address' => '黄浦区河南南路33号', 306 | 'coordinate' => 307 | array ( 308 | 'longitude' => 121.48721, 309 | 'latitude' => 31.22902, 310 | ), 311 | ), 312 | 28 => 313 | array ( 314 | '_id' => 90252, 315 | 'title' => '仅售29.9元,市场价50元的韩林炭烤(市百一店)现金抵用,可叠加使用,美味鲜香,尽享欢乐', 316 | 'address' => '黄浦区南京东路830号第一百货5F', 317 | 'coordinate' => 318 | array ( 319 | 'longitude' => 121.48023, 320 | 'latitude' => 31.23576, 321 | ), 322 | ), 323 | 29 => 324 | array ( 325 | '_id' => 90224, 326 | 'title' => '仅售79元,酒店门市价100元的汉庭快捷酒店钟点房一间连续入住4小时,节假日通用,舒适温馨,给您家的感觉', 327 | 'address' => '浦东新区峨山路91弄38号', 328 | 'coordinate' => 329 | array ( 330 | 'longitude' => 121.53299, 331 | 'latitude' => 31.21559, 332 | ), 333 | ), 334 | 30 => 335 | array ( 336 | '_id' => 90194, 337 | 'title' => '仅售499元,市场价1128元的南浔世家10人餐,节假日通用', 338 | 'address' => '浦东新区乳山路345号', 339 | 'coordinate' => 340 | array ( 341 | 'longitude' => 121.53027, 342 | 'latitude' => 31.23863, 343 | ), 344 | ), 345 | 31 => 346 | array ( 347 | '_id' => 90193, 348 | 'title' => '仅售69元,市场价238元的南新雅大酒店8英寸蛋糕,浓浓的芝士香味让那股温柔甜蜜肆意地在您全身每一处洋溢', 349 | 'address' => '黄浦区九江路700号南新雅大酒店', 350 | 'coordinate' => 351 | array ( 352 | 'longitude' => 121.47736, 353 | 'latitude' => 31.23435, 354 | ), 355 | ), 356 | 32 => 357 | array ( 358 | '_id' => 90187, 359 | 'title' => '仅售1298元,市场价2596元的瑞慈体检至尊套组,连锁品牌,值得信赖', 360 | 'address' => '上海市浦东南路256号华夏银行大厦3F', 361 | 'coordinate' => 362 | array ( 363 | 'longitude' => 121.50896, 364 | 'latitude' => 31.23974, 365 | ), 366 | ), 367 | 33 => 368 | array ( 369 | '_id' => 90186, 370 | 'title' => '仅售698元,市场价1269元的瑞慈体检关爱套组,连锁品牌,值得信赖', 371 | 'address' => '上海市浦东南路256号华夏银行大厦3F', 372 | 'coordinate' => 373 | array ( 374 | 'longitude' => 121.50896, 375 | 'latitude' => 31.23974, 376 | ), 377 | ), 378 | 34 => 379 | array ( 380 | '_id' => 90185, 381 | 'title' => '仅售398元,市场价1099元的俪晶酒店餐厅6-8人餐,俪晶酒店,贴心位置,赞口美味', 382 | 'address' => '黄浦区汉口路678号3楼', 383 | 'coordinate' => 384 | array ( 385 | 'longitude' => 121.47758, 386 | 'latitude' => 31.23375, 387 | ), 388 | ), 389 | 35 => 390 | array ( 391 | '_id' => 90164, 392 | 'title' => '仅售168元,市场价360元的铁道宾馆入住一晚,酒店地处与上海市中心繁华的南京东路步行街接壤的贵州路,交通极其便利', 393 | 'address' => '上海市黄浦区贵州路160号', 394 | 'coordinate' => 395 | array ( 396 | 'longitude' => 121.47606, 397 | 'latitude' => 31.2366, 398 | ), 399 | ), 400 | 36 => 401 | array ( 402 | '_id' => 90163, 403 | 'title' => '仅售158元,市场价248元的名信游船浦江游套票,游览浦江美景,享永不落幕的经典', 404 | 'address' => '黄浦区中山东二路531号', 405 | 'coordinate' => 406 | array ( 407 | 'longitude' => 121.49831, 408 | 'latitude' => 31.22743, 409 | ), 410 | ), 411 | 37 => 412 | array ( 413 | '_id' => 90152, 414 | 'title' => '仅售798元,市场价1600元的瑞慈体检豪华体检套组,连锁品牌,值得信赖', 415 | 'address' => '上海市浦东南路256号华夏银行大厦3F', 416 | 'coordinate' => 417 | array ( 418 | 'longitude' => 121.50896, 419 | 'latitude' => 31.23974, 420 | ), 421 | ), 422 | 38 => 423 | array ( 424 | '_id' => 90151, 425 | 'title' => '仅售328元,市场价630元的瑞慈体检体检套组,男女通用,连锁品牌,值得信赖', 426 | 'address' => '上海市浦东南路256号华夏银行大厦3F', 427 | 'coordinate' => 428 | array ( 429 | 'longitude' => 121.50896, 430 | 'latitude' => 31.23974, 431 | ), 432 | ), 433 | 39 => 434 | array ( 435 | '_id' => 90145, 436 | 'title' => '仅售98元,市场价238元的上海浦江之星客房一间入住一天,节假日通用,精致生活,品质享受', 437 | 'address' => '浦东新区蓝村路2号', 438 | 'coordinate' => 439 | array ( 440 | 'longitude' => 121.53301, 441 | 'latitude' => 31.21147, 442 | ), 443 | ), 444 | 40 => 445 | array ( 446 | '_id' => 90135, 447 | 'title' => '仅售198元,市场价298元的上海辰龙商务酒店客房一间入住一天,节假日通用,精致生活,品质享受', 448 | 'address' => '黄浦区牛庄路582号', 449 | 'coordinate' => 450 | array ( 451 | 'longitude' => 121.47918, 452 | 'latitude' => 31.23814, 453 | ), 454 | ), 455 | 41 => 456 | array ( 457 | '_id' => 90123, 458 | 'title' => '仅售38元,市场价50元的小梁园枫叶餐厅现金抵用,可叠加使用,精致生活,品质享受', 459 | 'address' => '黄浦区山东中路208号', 460 | 'coordinate' => 461 | array ( 462 | 'longitude' => 121.48457, 463 | 'latitude' => 31.23471, 464 | ), 465 | ), 466 | 42 => 467 | array ( 468 | '_id' => 90118, 469 | 'title' => '仅售88元,市场价128元的快乐船长浦江游船长8号特色航班散客票,节假日通用,豪华游轮格调不凡,在浦江黄金航线,尽赏上海精髓之美!', 470 | 'address' => '上海市黄浦区中山东二路531号十六铺码头B1(进入地下一层右转到底2号侯船室)', 471 | 'coordinate' => 472 | array ( 473 | 'longitude' => 121.49831, 474 | 'latitude' => 31.22743, 475 | ), 476 | ), 477 | 43 => 478 | array ( 479 | '_id' => 90108, 480 | 'title' => '仅售128元!市场价198元的浦江游览1号龙船浪漫夜游自助餐(含保险)一人次:龙船浪漫浦江夜游(约80分钟游程,每天只开一班,开航时间19:00)+浦江游览龙船自助餐!', 481 | 'address' => '上海市外马路307号', 482 | 'coordinate' => 483 | array ( 484 | 'longitude' => 121.5052, 485 | 'latitude' => 31.22162, 486 | ), 487 | ), 488 | 44 => 489 | array ( 490 | '_id' => 90104, 491 | 'title' => '仅售888元,市场价1750元的南新雅大酒店8-10人餐,赠送果盘,美味传承,各类美味轮番来袭,豪华味蕾享受', 492 | 'address' => '上海市黄浦区九江路700号南新雅大酒店二楼', 493 | 'coordinate' => 494 | array ( 495 | 'longitude' => 121.47712, 496 | 'latitude' => 31.23475, 497 | ), 498 | ), 499 | 45 => 500 | array ( 501 | '_id' => 90102, 502 | 'title' => '仅售128元,市场价228元的上海浦西万怡酒店单人豪华自助晚餐,多种口味任选,精美海量自助餐无限畅吃', 503 | 'address' => '闸北区恒丰路338号2楼', 504 | 'coordinate' => 505 | array ( 506 | 'longitude' => 121.45576, 507 | 'latitude' => 31.2431, 508 | ), 509 | ), 510 | 46 => 511 | array ( 512 | '_id' => 90053, 513 | 'title' => '仅售298元,市场价478元的南新雅大酒店4人餐,赠送果盘,美味传承,各类美味轮番来袭,豪华味蕾享受', 514 | 'address' => '上海市黄浦区九江路700号南新雅大酒店', 515 | 'coordinate' => 516 | array ( 517 | 'longitude' => 121.47705, 518 | 'latitude' => 31.23433, 519 | ), 520 | ), 521 | 47 => 522 | array ( 523 | '_id' => 90050, 524 | 'title' => '仅售378元,市场价1200元的上海吉瑞酒店公寓入住一天,赠送矿泉水2瓶', 525 | 'address' => '浦东新区浦电路110号', 526 | 'coordinate' => 527 | array ( 528 | 'longitude' => 121.5201, 529 | 'latitude' => 31.21859, 530 | ), 531 | ), 532 | 48 => 533 | array ( 534 | '_id' => 90023, 535 | 'title' => '仅售168.8元,市场价430元的台北小统一牛排馆浪漫双人餐,与爱人分享这浪漫时刻', 536 | 'address' => '九江路693号1-2楼', 537 | 'coordinate' => 538 | array ( 539 | 'longitude' => 121.4772, 540 | 'latitude' => 31.23403, 541 | ), 542 | ), 543 | 49 => 544 | array ( 545 | '_id' => 11122, 546 | 'coordinate' => 547 | array ( 548 | 'longitude' => 121.48023, 549 | 'latitude' => 31.23576, 550 | ), 551 | 'title' => '【上海杭州2店通用】仅售78元!市场价最高660元的上海鸿光眼镜/杭州视觉眼镜配镜套组一份(男女不限,需自取):记忆板材架/合金钢板架/记忆钛架(3选1)+卡蒂罗镜片【1.56折射率、非球面、加硬加膜】,另免费验光+免费清洗+免费校正、维修!赠送镜盒、镜布!镜片适用于近视0-800度(含)和散光0-200度(含)的用户!更有升级套组详见页面!时尚前卫,让你靓丽出行!专业眼光配镜,让您看到的世界更清晰明亮!', 552 | 'address' => '上海市黄浦区南京东路592号4楼412室(南京东路步行街李宁旗舰店楼上)', 553 | ), 554 | 50 => 555 | array ( 556 | '_id' => 464, 557 | 'coordinate' => 558 | array ( 559 | 'longitude' => 121.47355, 560 | 'latitude' => 31.23817, 561 | ), 562 | 'title' => '仅售9.8元,市场价12.8元的牛奶棚掼奶魔方蛋糕2个,节假日通用,营养健康!爱意无限', 563 | 'address' => '黄浦区西藏中路632号', 564 | ), 565 | 51 => 566 | array ( 567 | '_id' => 461, 568 | 'coordinate' => 569 | array ( 570 | 'longitude' => 121.49216, 571 | 'latitude' => 31.22945, 572 | ), 573 | 'title' => '【城隍庙】仅售798元!市场价1420元的兴宇大酒店8-10人套餐一份:鲍参刺肚羹+双椒焗龙虾+鲍汁扣大乌参+避风塘花蟹+沙田乳鸽+酱爆驼峰肉+深井烧鹅+辣酒煮香螺+桂花炒瑶柱+干煸四季豆+清炒时蔬+木瓜蛋挞+生煎包!邀请朋友来一起品尝这精致的美食吧!另赠送水果拼盘1份及精美八冷碟1份!', 574 | 'address' => '黄浦区人民路386号8楼', 575 | ), 576 | 52 => 577 | array ( 578 | '_id' => 456, 579 | 'coordinate' => 580 | array ( 581 | 'longitude' => 121.49216, 582 | 'latitude' => 31.22945, 583 | ), 584 | 'title' => '【城隍庙】仅售158元!市场价478元的兴宇大酒店4人套餐一份:双椒焗龙虾+西湖牛肉羹+红烧罗汉鲍+蜜汁叉烧+素鱼翅饺+清炒时蔬!邀请朋友来一起品尝这精致的美食吧!', 585 | 'address' => '黄浦区人民路386号8楼', 586 | ), 587 | 53 => 588 | array ( 589 | '_id' => 452, 590 | 'coordinate' => 591 | array ( 592 | 'longitude' => 121.52343, 593 | 'latitude' => 31.2254, 594 | ), 595 | 'title' => '【2店通用】仅售999元!市场价4108元的跃民大酒店10人B套餐一份:冷菜(老干妈小黄鱼+家乡咸鸡+特色鱼皮+糟三鲜+水晶肴肉+关东木耳+万年青+冰糖红枣)+热菜(清蒸大闸蟹+黄油焗龙虾+鲍汁翅肚羹+酒香蒸鲥鱼+豆豉扇贝王+黑椒牛仔粒+金牌烤鸭+ 红烧大圆蹄+小米椒仔鸡+特色鱼米之乡+龙虾泡饭+上汤时蔬+点心(麻饼)!拉手券使用时间:西藏南路店:10:30-14:00,16:00-21:00,崂山路店:10:30-14:00 ,16:00-次日凌晨03:00!', 596 | 'address' => '浦东新区崂山路585号', 597 | ), 598 | 54 => 599 | array ( 600 | '_id' => 451, 601 | 'coordinate' => 602 | array ( 603 | 'longitude' => 121.52343, 604 | 'latitude' => 31.2254, 605 | ), 606 | 'title' => '【2店通用】仅售168元!市场价827元的跃民大酒店4-6人套餐一份:冷菜(散养鸡+本帮熏鱼+凉拌黄瓜)+热菜(香辣梭子蟹+酒香鲥鱼+清炒河虾仁+干锅牛筋+鹅肝沫炖蛋+灌汤虾球+香菇面筋煲+热炝花蛤+本帮酸辣汤+清炒时蔬)!拉手券使用时间:西藏南路店:10:30-14:00,16:00-21:00,崂山路店:10:30-14:00 ,16:00-次日凌晨03:00!', 607 | 'address' => '浦东新区崂山路585号', 608 | ), 609 | 55 => 610 | array ( 611 | '_id' => 450, 612 | 'coordinate' => 613 | array ( 614 | 'longitude' => 121.52343, 615 | 'latitude' => 31.2254, 616 | ), 617 | 'title' => '【2店通用】仅售699元!市场价2013元的跃民大酒店10人A套餐一份:冷菜(散养鸡+水晶肴肉+本帮熏鱼+关东木耳+色拉+万年青)+热菜(葱油局龙虾+葱姜梭子蟹+金牌烤鸭+灌汤虾球+鲍汁白灵菇+干锅牛蛙+清蒸白水鱼+沙律牛排+鹅肝炖蛋+热炝花蛤+上汤杭白菜+农家老鸡汤)+点心(脆皮香蕉+麻饼)!拉手券使用时间:西藏南路店:10:30-14:00,16:00-21:00,崂山路店:10:30-14:00 ,16:00-次日凌晨03:00!', 618 | 'address' => '浦东新区崂山路585号', 619 | ), 620 | 56 => 621 | array ( 622 | '_id' => 433, 623 | 'coordinate' => 624 | array ( 625 | 'longitude' => 121.52456, 626 | 'latitude' => 31.22318, 627 | ), 628 | 'title' => '仅售19.9元,市场价30元的芒不颠港式甜品套餐,3种套餐任选,喧闹的城市,安静的小店,一份甜品,一点舒心,你需要一个甜蜜的下午,来放松一周的辛劳,给自己一份甜蜜的犒赏!', 629 | 'address' => '浦东新区崂山路645号(近潍坊路)', 630 | ), 631 | 57 => 632 | array ( 633 | '_id' => 428, 634 | 'coordinate' => 635 | array ( 636 | 'longitude' => 121.48023, 637 | 'latitude' => 31.23576, 638 | ), 639 | 'title' => '仅售79元,市场价198元的康骏会馆(南京东路店)按摩套组,男女不限,健康有道,骏越万里!', 640 | 'address' => '黄浦区南京东路588号丝绸商厦4楼', 641 | ), 642 | 58 => 643 | array ( 644 | '_id' => 426, 645 | 'coordinate' => 646 | array ( 647 | 'longitude' => 121.48023, 648 | 'latitude' => 31.23576, 649 | ), 650 | 'title' => '仅售209元,市场价708元的康骏会馆(南京东路店)全身精油按摩,男女不限,健康有道,骏越万里!', 651 | 'address' => '黄浦区南京东路588号丝绸商厦4楼', 652 | ), 653 | 59 => 654 | array ( 655 | '_id' => 419, 656 | 'coordinate' => 657 | array ( 658 | 'longitude' => 121.48444, 659 | 'latitude' => 31.23176, 660 | ), 661 | 'title' => '【人民广场】仅售9元!市场价180元的华兴少儿体验课程一人次(适合5-16周岁青少年):面塑(捏面人)/空手道(约60分钟,2选1)!拉手券仅限每周三、周五、周六、周日使用!国庆节(2012年10月3日、5日、6日、7日)不使用拉手券!', 662 | 'address' => '黄浦区北海路8号9楼D座', 663 | ), 664 | 60 => 665 | array ( 666 | '_id' => 405, 667 | 'coordinate' => 668 | array ( 669 | 'longitude' => 121.4875, 670 | 'latitude' => 31.2303, 671 | ), 672 | 'title' => '仅售149.9元,市场价601元的安藤家日本料理4人套餐,交通便利,秉承美食烹制之精华,一脉相承之古老秘方,美味从此开始!', 673 | 'address' => '黄浦区金陵东路229号范仕达生活广场2楼', 674 | ), 675 | 61 => 676 | array ( 677 | '_id' => 403, 678 | 'coordinate' => 679 | array ( 680 | 'longitude' => 121.52876, 681 | 'latitude' => 31.22204, 682 | ), 683 | 'title' => '仅售33元,市场价83元的中油阳光大酒店(三楼和怡中餐厅)单人套餐,物美价廉,美味地道,尽在中油阳光大酒店和怡中餐厅!', 684 | 'address' => '浦东新区东方路969号(近浦电路)', 685 | ), 686 | 62 => 687 | array ( 688 | '_id' => 378, 689 | 'coordinate' => 690 | array ( 691 | 'longitude' => 121.5152, 692 | 'latitude' => 31.22899, 693 | ), 694 | 'title' => '仅售48元,市场价1852元的修身堂美容养生套组,赠送修身堂人体测分仪1次,要美丽,要自信,修身堂让您绽放美丽光彩!', 695 | 'address' => '浦东新区浦东南路1036号隆宇大厦801室', 696 | ), 697 | 63 => 698 | array ( 699 | '_id' => 377, 700 | 'coordinate' => 701 | array ( 702 | 'longitude' => 121.47416, 703 | 'latitude' => 31.24088, 704 | ), 705 | 'title' => '仅售108元,市场价320元的上海源胜商务酒店客房一间入住一天,交通便利,上海源胜商务酒店,享受家的幸福!', 706 | 'address' => '黄浦区南苏州路935号正大门(黄浦区厦门路206号后门)(人民广场,南京东路,近西藏中路桥)', 707 | ), 708 | 64 => 709 | array ( 710 | '_id' => 373, 711 | 'coordinate' => 712 | array ( 713 | 'longitude' => 121.52022, 714 | 'latitude' => 31.234, 715 | ), 716 | 'title' => '仅售88.8元,市场价200元的重庆龙门鱼府鱼火锅4人套餐,2店通用,龙门鱼府,真正的鱼火锅,吃的就是这个味儿~', 717 | 'address' => '上海市浦东新区崂山路300号(近乳山路)', 718 | ), 719 | 65 => 720 | array ( 721 | '_id' => 360, 722 | 'coordinate' => 723 | array ( 724 | 'longitude' => 121.48439, 725 | 'latitude' => 31.23258, 726 | ), 727 | 'title' => '仅售998元,市场价3097元的中福世福汇大酒店豪华十人宴,节假日通用,美味诱惑,奢华享受', 728 | 'address' => '上海市黄浦区广东路339号3楼潮粤轩中餐厅', 729 | ), 730 | 66 => 731 | array ( 732 | '_id' => 298, 733 | 'coordinate' => 734 | array ( 735 | 'longitude' => 121.53299, 736 | 'latitude' => 31.21559, 737 | ), 738 | 'title' => '仅售179元,酒店门市价309元的汉庭快捷酒店客房一间入住一天,含双人早餐,舒适温馨,给您家的感觉', 739 | 'address' => '浦东新区峨山路91弄38号', 740 | ), 741 | 67 => 742 | array ( 743 | '_id' => 293, 744 | 'coordinate' => 745 | array ( 746 | 'longitude' => 121.46055, 747 | 'latitude' => 31.24134, 748 | ), 749 | 'title' => '仅售188元,酒店门市价599元的上海瑞亚臻品酒店客房入住1天,赠送矿泉水2瓶,优雅浪漫,温暖舒心', 750 | 'address' => '上海市闸北区梅园路37号', 751 | ), 752 | 68 => 753 | array ( 754 | '_id' => 283, 755 | 'coordinate' => 756 | array ( 757 | 'longitude' => 121.48721, 758 | 'latitude' => 31.22902, 759 | ), 760 | 'title' => '仅售128元,市场价160元的常州淹城春秋乐园自由行,节假日通用,神奇淹城,梦回春秋', 761 | 'address' => '黄浦区河南南路33号', 762 | ), 763 | 69 => 764 | array ( 765 | '_id' => 282, 766 | 'coordinate' => 767 | array ( 768 | 'longitude' => 121.48721, 769 | 'latitude' => 31.22902, 770 | ), 771 | 'title' => '仅售88元,市场价168元的常州花都温泉自由行,节假日通用,花都温泉设计透露自然与生态,隔开外面的喧闹吵杂,有着静谧的安全感,展现了休闲度假的意境,给紧张生活带来彻底的放松', 772 | 'address' => '黄浦区河南南路33号', 773 | ), 774 | 70 => 775 | array ( 776 | '_id' => 253, 777 | 'coordinate' => 778 | array ( 779 | 'longitude' => 121.48023, 780 | 'latitude' => 31.23576, 781 | ), 782 | 'title' => '仅售29.9元,市场价50元的韩林炭烤(市百一店)现金抵用,可叠加使用,美味鲜香,尽享欢乐', 783 | 'address' => '黄浦区南京东路830号第一百货5F', 784 | ), 785 | 71 => 786 | array ( 787 | '_id' => 225, 788 | 'coordinate' => 789 | array ( 790 | 'longitude' => 121.53299, 791 | 'latitude' => 31.21559, 792 | ), 793 | 'title' => '仅售79元,酒店门市价100元的汉庭快捷酒店钟点房一间连续入住4小时,节假日通用,舒适温馨,给您家的感觉', 794 | 'address' => '浦东新区峨山路91弄38号', 795 | ), 796 | 72 => 797 | array ( 798 | '_id' => 195, 799 | 'coordinate' => 800 | array ( 801 | 'longitude' => 121.53027, 802 | 'latitude' => 31.23863, 803 | ), 804 | 'title' => '仅售499元,市场价1128元的南浔世家10人餐,节假日通用', 805 | 'address' => '浦东新区乳山路345号', 806 | ), 807 | 73 => 808 | array ( 809 | '_id' => 194, 810 | 'coordinate' => 811 | array ( 812 | 'longitude' => 121.47736, 813 | 'latitude' => 31.23435, 814 | ), 815 | 'title' => '仅售69元,市场价238元的南新雅大酒店8英寸蛋糕,浓浓的芝士香味让那股温柔甜蜜肆意地在您全身每一处洋溢', 816 | 'address' => '黄浦区九江路700号南新雅大酒店', 817 | ), 818 | 74 => 819 | array ( 820 | '_id' => 188, 821 | 'coordinate' => 822 | array ( 823 | 'longitude' => 121.50896, 824 | 'latitude' => 31.23974, 825 | ), 826 | 'title' => '仅售1298元,市场价2596元的瑞慈体检至尊套组,连锁品牌,值得信赖', 827 | 'address' => '上海市浦东南路256号华夏银行大厦3F', 828 | ), 829 | 75 => 830 | array ( 831 | '_id' => 187, 832 | 'coordinate' => 833 | array ( 834 | 'longitude' => 121.50896, 835 | 'latitude' => 31.23974, 836 | ), 837 | 'title' => '仅售698元,市场价1269元的瑞慈体检关爱套组,连锁品牌,值得信赖', 838 | 'address' => '上海市浦东南路256号华夏银行大厦3F', 839 | ), 840 | 76 => 841 | array ( 842 | '_id' => 186, 843 | 'coordinate' => 844 | array ( 845 | 'longitude' => 121.47758, 846 | 'latitude' => 31.23375, 847 | ), 848 | 'title' => '仅售398元,市场价1099元的俪晶酒店餐厅6-8人餐,俪晶酒店,贴心位置,赞口美味', 849 | 'address' => '黄浦区汉口路678号3楼', 850 | ), 851 | 77 => 852 | array ( 853 | '_id' => 165, 854 | 'coordinate' => 855 | array ( 856 | 'longitude' => 121.47606, 857 | 'latitude' => 31.2366, 858 | ), 859 | 'title' => '仅售168元,市场价360元的铁道宾馆入住一晚,酒店地处与上海市中心繁华的南京东路步行街接壤的贵州路,交通极其便利', 860 | 'address' => '上海市黄浦区贵州路160号', 861 | ), 862 | 78 => 863 | array ( 864 | '_id' => 164, 865 | 'coordinate' => 866 | array ( 867 | 'longitude' => 121.49831, 868 | 'latitude' => 31.22743, 869 | ), 870 | 'title' => '仅售158元,市场价248元的名信游船浦江游套票,游览浦江美景,享永不落幕的经典', 871 | 'address' => '黄浦区中山东二路531号', 872 | ), 873 | 79 => 874 | array ( 875 | '_id' => 153, 876 | 'coordinate' => 877 | array ( 878 | 'longitude' => 121.50896, 879 | 'latitude' => 31.23974, 880 | ), 881 | 'title' => '仅售798元,市场价1600元的瑞慈体检豪华体检套组,连锁品牌,值得信赖', 882 | 'address' => '上海市浦东南路256号华夏银行大厦3F', 883 | ), 884 | 80 => 885 | array ( 886 | '_id' => 152, 887 | 'coordinate' => 888 | array ( 889 | 'longitude' => 121.50896, 890 | 'latitude' => 31.23974, 891 | ), 892 | 'title' => '仅售328元,市场价630元的瑞慈体检体检套组,男女通用,连锁品牌,值得信赖', 893 | 'address' => '上海市浦东南路256号华夏银行大厦3F', 894 | ), 895 | 81 => 896 | array ( 897 | '_id' => 146, 898 | 'coordinate' => 899 | array ( 900 | 'longitude' => 121.53301, 901 | 'latitude' => 31.21147, 902 | ), 903 | 'title' => '仅售98元,市场价238元的上海浦江之星客房一间入住一天,节假日通用,精致生活,品质享受', 904 | 'address' => '浦东新区蓝村路2号', 905 | ), 906 | 82 => 907 | array ( 908 | '_id' => 136, 909 | 'coordinate' => 910 | array ( 911 | 'longitude' => 121.47918, 912 | 'latitude' => 31.23814, 913 | ), 914 | 'title' => '仅售198元,市场价298元的上海辰龙商务酒店客房一间入住一天,节假日通用,精致生活,品质享受', 915 | 'address' => '黄浦区牛庄路582号', 916 | ), 917 | 83 => 918 | array ( 919 | '_id' => 124, 920 | 'coordinate' => 921 | array ( 922 | 'longitude' => 121.48457, 923 | 'latitude' => 31.23471, 924 | ), 925 | 'title' => '仅售38元,市场价50元的小梁园枫叶餐厅现金抵用,可叠加使用,精致生活,品质享受', 926 | 'address' => '黄浦区山东中路208号', 927 | ), 928 | 84 => 929 | array ( 930 | '_id' => 119, 931 | 'coordinate' => 932 | array ( 933 | 'longitude' => 121.49831, 934 | 'latitude' => 31.22743, 935 | ), 936 | 'title' => '仅售88元,市场价128元的快乐船长浦江游船长8号特色航班散客票,节假日通用,豪华游轮格调不凡,在浦江黄金航线,尽赏上海精髓之美!', 937 | 'address' => '上海市黄浦区中山东二路531号十六铺码头B1(进入地下一层右转到底2号侯船室)', 938 | ), 939 | 85 => 940 | array ( 941 | '_id' => 109, 942 | 'coordinate' => 943 | array ( 944 | 'longitude' => 121.5052, 945 | 'latitude' => 31.22162, 946 | ), 947 | 'title' => '仅售128元!市场价198元的浦江游览1号龙船浪漫夜游自助餐(含保险)一人次:龙船浪漫浦江夜游(约80分钟游程,每天只开一班,开航时间19:00)+浦江游览龙船自助餐!', 948 | 'address' => '上海市外马路307号', 949 | ), 950 | 86 => 951 | array ( 952 | '_id' => 105, 953 | 'coordinate' => 954 | array ( 955 | 'longitude' => 121.47712, 956 | 'latitude' => 31.23475, 957 | ), 958 | 'title' => '仅售888元,市场价1750元的南新雅大酒店8-10人餐,赠送果盘,美味传承,各类美味轮番来袭,豪华味蕾享受', 959 | 'address' => '上海市黄浦区九江路700号南新雅大酒店二楼', 960 | ), 961 | 87 => 962 | array ( 963 | '_id' => 103, 964 | 'coordinate' => 965 | array ( 966 | 'longitude' => 121.45576, 967 | 'latitude' => 31.2431, 968 | ), 969 | 'title' => '仅售128元,市场价228元的上海浦西万怡酒店单人豪华自助晚餐,多种口味任选,精美海量自助餐无限畅吃', 970 | 'address' => '闸北区恒丰路338号2楼', 971 | ), 972 | 88 => 973 | array ( 974 | '_id' => 54, 975 | 'coordinate' => 976 | array ( 977 | 'longitude' => 121.47705, 978 | 'latitude' => 31.23433, 979 | ), 980 | 'title' => '仅售298元,市场价478元的南新雅大酒店4人餐,赠送果盘,美味传承,各类美味轮番来袭,豪华味蕾享受', 981 | 'address' => '上海市黄浦区九江路700号南新雅大酒店', 982 | ), 983 | 89 => 984 | array ( 985 | '_id' => 51, 986 | 'coordinate' => 987 | array ( 988 | 'longitude' => 121.5201, 989 | 'latitude' => 31.21859, 990 | ), 991 | 'title' => '仅售378元,市场价1200元的上海吉瑞酒店公寓入住一天,赠送矿泉水2瓶', 992 | 'address' => '浦东新区浦电路110号', 993 | ), 994 | 90 => 995 | array ( 996 | '_id' => 24, 997 | 'coordinate' => 998 | array ( 999 | 'longitude' => 121.4772, 1000 | 'latitude' => 31.23403, 1001 | ), 1002 | 'title' => '仅售168.8元,市场价430元的台北小统一牛排馆浪漫双人餐,与爱人分享这浪漫时刻', 1003 | 'address' => '九江路693号1-2楼', 1004 | ), 1005 | ) 1006 | ; 1007 | 1008 | -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Controller/BaseController.php: -------------------------------------------------------------------------------- 1 | get('doctrine_mongodb'); 14 | } 15 | 16 | /** 17 | * @return \Doctrine\ODM\MongoDB\DocumentRepository 18 | */ 19 | public function getDMManager(){ 20 | return $this->get('doctrine_mongodb')->getManager(); 21 | } 22 | 23 | /** 24 | * @return \Doctrine\ODM\MongoDB\DocumentRepository 25 | */ 26 | public function getDoctrineManager(){ 27 | return $this->get('doctrine_mongodb'); 28 | } 29 | 30 | /** 31 | * @return \Henter\GEOBundle\Repository\PlaceRepository 32 | */ 33 | public function getPlaceRepository(){ 34 | return $this->get('doctrine_mongodb')->getRepository('HenterGEOBundle:Place'); 35 | } 36 | 37 | /** 38 | * @param string $action 39 | * @param string $value 40 | */ 41 | protected function setFlash($action, $value) 42 | { 43 | $this->get('session')->setFlash($action, $value); 44 | } 45 | 46 | 47 | } -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Controller/PlaceController.php: -------------------------------------------------------------------------------- 1 | getRequest(); 37 | 38 | $latitude = (float)$request->get('lat'); 39 | $longitude = (float)$request->get('lon'); 40 | $max = (float)$request->get('max'); 41 | $num = (float)$request->get('num'); 42 | 43 | // 2km 44 | $max = $max ?: 2/111; 45 | 46 | $repo = $this->getPlaceRepository(); 47 | 48 | if($type == 'near'){ 49 | $places = $repo->createQueryBuilder() 50 | ->field('coordinate')->near($longitude, $latitude) 51 | ->maxDistance($max) 52 | ->getQuery(); 53 | }elseif($type == 'center'){ 54 | $places = $repo->createQueryBuilder() 55 | ->field('coordinate')->withinCenter($longitude, $latitude, $max) 56 | ->getQuery(); 57 | 58 | }elseif($type == 'box'){ 59 | $latitude2 = (float)$request->get('lat2'); 60 | $longitude2 = (float)$request->get('lon2'); 61 | 62 | $places = $repo->createQueryBuilder() 63 | ->field('coordinate')->withinBox($longitude, $latitude, $longitude2, $latitude2) 64 | ->getQuery(); 65 | } 66 | 67 | $return = []; 68 | foreach($places as $place){ 69 | $item = []; 70 | $item['tiitle'] = $place->getTitle(); 71 | $item['address'] = $place->getAddress(); 72 | $item['longitude'] = $place->getCoordinate()->getLongitude(); 73 | $item['latitude'] = $place->getCoordinate()->getLatitude(); 74 | $return[] = $item; 75 | } 76 | 77 | return new JsonResponse($return); 78 | } 79 | 80 | 81 | /** 82 | * @Route("/near", name="near") 83 | * @Template() 84 | */ 85 | public function nearAction(){ 86 | $request = $this->getRequest(); 87 | 88 | $longitude = (float)$request->get('lon',121.4905); 89 | $latitude = (float)$request->get('lat',31.2646); 90 | //2km 91 | $max = (float)$request->get('max', 2); 92 | 93 | $places = $this->getPlaceRepository()->createQueryBuilder() 94 | ->field('coordinate')->near($longitude, $latitude) 95 | ->maxDistance($max/111) 96 | ->getQuery()->toarray(); 97 | 98 | return compact('places','max','longitude','latitude'); 99 | } 100 | 101 | 102 | /** 103 | * @Route("/center", name="center") 104 | * @Template() 105 | */ 106 | public function centerAction(){ 107 | $request = $this->getRequest(); 108 | 109 | $longitude = (float)$request->get('lon',121.4905); 110 | $latitude = (float)$request->get('lat',31.2646); 111 | //10km 112 | $max = (float)$request->get('max', 10); 113 | 114 | $places = $this->getPlaceRepository()->createQueryBuilder() 115 | ->field('coordinate')->withinCenter($longitude, $latitude, $max/111) 116 | ->getQuery()->toarray(); 117 | 118 | return compact('places','max','longitude','latitude'); 119 | } 120 | 121 | 122 | /** 123 | * @Route("/box", name="box") 124 | * @Template() 125 | */ 126 | public function boxAction(){ 127 | $request = $this->getRequest(); 128 | 129 | $longitude = (float)$request->get('lon',121.462035); 130 | $latitude = (float)$request->get('lat',31.237641); 131 | 132 | $longitude2 = (float)$request->get('lon2',121.522098); 133 | $latitude2 = (float)$request->get('lat2',31.215284); 134 | 135 | $places = $this->getPlaceRepository()->createQueryBuilder() 136 | ->field('coordinate')->withinBox($longitude, $latitude, $longitude2, $latitude2) 137 | ->getQuery()->toarray(); 138 | 139 | return compact('places','longitude','latitude', 'longitude2', 'latitude2'); 140 | } 141 | 142 | 143 | /** 144 | * @Route("/polygon", name="polygon") 145 | * @Template() 146 | */ 147 | public function polygonAction(){ 148 | $points = []; 149 | $points[] = [121.45183,31.243816]; 150 | $points[] = [121.533181,31.24344]; 151 | $points[] = [121.535049,31.208983]; 152 | $points[] = [121.448955,31.214913]; 153 | $points[] = [121.440619,31.228748]; 154 | 155 | $sumlon = $sumlat = 0; 156 | foreach($points as $p){ 157 | $sumlon += $p[0]; 158 | $sumlat += $p[1]; 159 | } 160 | $center = [$sumlon/count($points), $sumlat/count($points)]; 161 | 162 | $places = $this->getPlaceRepository()->createQueryBuilder() 163 | ->field('coordinate')->withinPolygon($points[0], $points[1], $points[2], $points[3], $points[4]) 164 | ->getQuery()->toarray(); 165 | 166 | return compact('places','points', 'center'); 167 | } 168 | 169 | 170 | /** 171 | * @Route("/geonear", name="geonear") 172 | * @Template() 173 | */ 174 | public function geonearAction(){ 175 | $request = $this->getRequest(); 176 | 177 | $longitude = (float)$request->get('lon',121.4905); 178 | $latitude = (float)$request->get('lat',31.2646); 179 | //2km 180 | $max = (float)$request->get('max', 2); 181 | 182 | $places = $this->getPlaceRepository()->createQueryBuilder() 183 | ->field('coordinate')->geoNear($longitude, $latitude) 184 | ->spherical(true) 185 | ->maxDistance($max/6371) 186 | ->getQuery()->toarray(); 187 | 188 | return compact('places','longitude', 'latitude', 'max'); 189 | } 190 | 191 | 192 | 193 | /** 194 | * @Route("/distance", name="distance") 195 | * @Template() 196 | */ 197 | public function distanceAction(){ 198 | $request = $this->getRequest(); 199 | 200 | $longitude = (float)$request->get('lon',121.4905); 201 | $latitude = (float)$request->get('lat',31.2646); 202 | //2km 203 | $max = (float)$request->get('max', 2); 204 | 205 | $places = $this->getPlaceRepository()->createQueryBuilder() 206 | ->field('coordinate') 207 | ->geoNear($longitude, $latitude) 208 | ->spherical(true) 209 | ->distanceMultiplier(6371) 210 | ->maxDistance($max/6371) 211 | ->limit(100) 212 | ->getQuery() 213 | ->execute() 214 | ->toArray() 215 | ; 216 | 217 | return compact('places','longitude', 'latitude', 'max'); 218 | } 219 | 220 | 221 | 222 | /** 223 | * @Route("/geointersect", name="geointersect") 224 | * @Template() 225 | */ 226 | public function geointersectAction(){ 227 | //doctrine do not support geointersect yet, coordinates below are just for demo 228 | $points = []; 229 | $points[] = [121.45183,31.243816]; 230 | $points[] = [121.533181,31.24344]; 231 | $points[] = [121.535049,31.208983]; 232 | $points[] = [121.45183,31.243816]; 233 | 234 | 235 | $places = include dirname(__DIR__).'/Command/geointersects.php'; 236 | 237 | 238 | $longitude = '121.4905'; 239 | $latitude = '31.2646'; 240 | return compact('places','points','longitude', 'latitude'); 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /src/Henter/GEOBundle/DependencyInjection/Configuration.php: -------------------------------------------------------------------------------- 1 | root('hentergeo'); 22 | 23 | // Here you should define the parameters that are allowed to 24 | // configure your bundle. See the documentation linked above for 25 | // more information on that topic. 26 | 27 | return $treeBuilder; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Henter/GEOBundle/DependencyInjection/HenterGEOExtension.php: -------------------------------------------------------------------------------- 1 | processConfiguration($configuration, $configs); 24 | 25 | $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 26 | $loader->load('services.yml'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Document/Coordinate.php: -------------------------------------------------------------------------------- 1 | latitude = $latitude; 36 | return $this; 37 | } 38 | 39 | /** 40 | * Get latitude 41 | * 42 | * @return float $latitude 43 | */ 44 | public function getLatitude() 45 | { 46 | return $this->latitude; 47 | } 48 | 49 | /** 50 | * Set longitude 51 | * 52 | * @param float $longitude 53 | * @return \Coordinate 54 | */ 55 | public function setLongitude($longitude) 56 | { 57 | $this->longitude = $longitude; 58 | return $this; 59 | } 60 | 61 | /** 62 | * Get longitude 63 | * 64 | * @return float $longitude 65 | */ 66 | public function getLongitude() 67 | { 68 | return $this->longitude; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Document/Place.php: -------------------------------------------------------------------------------- 1 | id; 56 | } 57 | 58 | /** 59 | * Set title 60 | * 61 | * @param string $title 62 | * @return \Place 63 | */ 64 | public function setTitle($title) 65 | { 66 | $this->title = $title; 67 | return $this; 68 | } 69 | 70 | /** 71 | * Get title 72 | * 73 | * @return string $title 74 | */ 75 | public function getTitle() 76 | { 77 | return $this->title; 78 | } 79 | 80 | /** 81 | * Set coordinate 82 | * 83 | * @param Henter\GEOBundle\Document\Coordinate $coordinate 84 | * @return \Place 85 | */ 86 | public function setCoordinate(\Henter\GEOBundle\Document\Coordinate $coordinate) 87 | { 88 | $this->coordinate = $coordinate; 89 | return $this; 90 | } 91 | 92 | /** 93 | * Get coordinate 94 | * 95 | * @return Henter\GEOBundle\Document\Coordinate $coordinate 96 | */ 97 | public function getCoordinate() 98 | { 99 | return $this->coordinate; 100 | } 101 | 102 | /** 103 | * Set address 104 | * 105 | * @param string $address 106 | * @return \Place 107 | */ 108 | public function setAddress($address) 109 | { 110 | $this->address = $address; 111 | return $this; 112 | } 113 | 114 | /** 115 | * Get address 116 | * 117 | * @return string $address 118 | */ 119 | public function getAddress() 120 | { 121 | return $this->address; 122 | } 123 | 124 | /** 125 | * Set distance 126 | * 127 | * @param string $distance 128 | * @return self 129 | */ 130 | public function setDistance($distance) 131 | { 132 | $this->distance = $distance; 133 | return $this; 134 | } 135 | 136 | /** 137 | * Get distance 138 | * 139 | * @return string $distance 140 | */ 141 | public function getDistance() 142 | { 143 | return $this->distance; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/Henter/GEOBundle/HenterGEOBundle.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Symfony2 is great 7 | J'aime Symfony2 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Resources/views/Place/box.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "HenterGEOBundle::Place/index.html.twig" %} 2 | {% block title %}box {{ parent() }}{% endblock %} 3 | 4 | {% block intro %} 5 |
6 |
搜索矩形
7 |
8 |

9 |
10 | longitude: {{ longitude }}
11 | latitude: {{ latitude }}
12 |
13 | longitude2: {{ longitude2 }}
14 | latitude2: {{ latitude2 }}
15 | 16 | 17 |

18 |
19 |
20 | {% endblock %} 21 | 22 | 23 | 24 | 25 | {% block mapjs %} 26 | 49 | {% endblock %} -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Resources/views/Place/center.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "HenterGEOBundle::Place/index.html.twig" %} 2 | {% block title %}center {{ parent() }}{% endblock %} 3 | 4 | {% block intro %} 5 |
6 |
搜索圆圈
7 |
8 |

9 | 以
10 | longitude: {{ longitude }}
11 | latitude: {{ latitude }}
12 | 为中心点,
13 | 14 | 半径{{ max }}KM
15 | 16 |

17 |
18 |
19 | {% endblock %} 20 | 21 | 22 | 23 | 24 | {% block mapjs %} 25 | 91 | {% endblock %} -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Resources/views/Place/distance.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "HenterGEOBundle::Place/index.html.twig" %} 2 | {% block title %}near {{ parent() }}{% endblock %} 3 | 4 | {% block intro %} 5 |
6 |
geoNear Distance
7 |
8 |

9 | 10 | longitude: {{ longitude }}
11 | latitude: {{ latitude }}
12 | 周边{{ max }}km 13 |

14 |
15 | 16 |
results
17 |
18 | {% for p in places %} 19 |

{{ p.address }}
20 | 距离{{ p.distance|distance }}米 21 |

22 | {% endfor %} 23 |
24 |
25 | {% endblock %} 26 | 27 | 28 | 29 | 30 | {% block mapjs %} 31 | 95 | {% endblock %} -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Resources/views/Place/geointersect.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "HenterGEOBundle::Place/index.html.twig" %} 2 | {% block title %}box {{ parent() }}{% endblock %} 3 | 4 | {% block intro %} 5 |
6 |
geointersect
7 |
8 |

9 |
10 | {% for p in points %} 11 | longitude: {{ p.0 }}
12 | latitude: {{ p.1 }}
13 |
14 | {% endfor %} 15 | 16 |

17 |
18 |
19 | {% endblock %} 20 | 21 | 22 | 23 | 24 | {% block mapjs %} 25 | 55 | {% endblock %} -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Resources/views/Place/geonear.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "HenterGEOBundle::Place/index.html.twig" %} 2 | {% block title %}near {{ parent() }}{% endblock %} 3 | 4 | {% block intro %} 5 |
6 |
geoNear
7 |
8 |

9 | 10 | longitude: {{ longitude }}
11 | latitude: {{ latitude }}
12 | 周边{{ max }}km 13 | 14 |

15 |
16 |
17 | {% endblock %} 18 | 19 | 20 | 21 | 22 | {% block mapjs %} 23 | 87 | {% endblock %} -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Resources/views/Place/index.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | {% block title %}HenterGEO test{% endblock %} 52 | 53 | 54 |
55 |
56 | 57 | {% block intro %} 58 |
59 |
get point(click)
60 |
61 |

62 | longitude:
63 | latitude:
64 |

65 | 66 |
67 |
68 | 69 | 70 | {% endblock %} 71 | 72 | 73 |
74 |
demo
75 |
76 |

near

77 |

center

78 |

box

79 |

polygon

80 |

geonear

81 |

distance

82 | 83 | 84 |
85 |
86 | 87 |
受火星坐标影响,百度地图上显示的点与真实地理位置有偏差。
88 |
89 | 90 | 91 | 92 | 93 | 94 | {% block mapjs %} 95 | 146 | {% endblock %} 147 | 148 | 149 | -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Resources/views/Place/near.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "HenterGEOBundle::Place/index.html.twig" %} 2 | {% block title %}near {{ parent() }}{% endblock %} 3 | 4 | {% block intro %} 5 |
6 |
搜索周边
7 |
8 |

9 | 以
10 | longitude: {{ longitude }}
11 | latitude: {{ latitude }}
12 | 为当前位置,
13 | 14 | 周边100条记录
15 | 16 |

17 |
18 |
19 | {% endblock %} 20 | 21 | 22 | 23 | 24 | {% block mapjs %} 25 | 88 | {% endblock %} -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Resources/views/Place/polygon.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "HenterGEOBundle::Place/index.html.twig" %} 2 | {% block title %}polygon {{ parent() }}{% endblock %} 3 | 4 | {% block intro %} 5 |
6 |
搜索多边形
7 |
8 |

9 |
10 | {% for p in points %} 11 | longitude: {{ p.0 }}
12 | latitude: {{ p.1 }}
13 |
14 | {% endfor %} 15 | 16 | 17 |

18 |
19 |
20 | {% endblock %} 21 | 22 | 23 | 24 | 25 | {% block mapjs %} 26 | 46 | {% endblock %} -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Resources/views/Place/targets.html.twig: -------------------------------------------------------------------------------- 1 | 2 | function addCustomLayer(longitude, latitude, title, address){ 3 | var point = new BMap.Point(longitude, latitude); 4 | var marker = new BMap.Marker(point); // 创建标注 5 | map.addOverlay(marker); // 将标注添加到地图中 6 | 7 | marker.addEventListener("click", function(){ 8 | 9 | var opts = { 10 | width : 250, // 信息窗口宽度 11 | height: 100, // 信息窗口高度 12 | title : title // 信息窗口标题 13 | } 14 | var infoWindow = new BMap.InfoWindow(address, opts); // 创建信息窗口对象 15 | map.openInfoWindow(infoWindow, map.getCenter()); // 打开信息窗口 16 | }); 17 | } 18 | 19 | {% for p in places %} 20 | addCustomLayer({{ p.coordinate|coordinate('lon') }}, {{ p.coordinate|coordinate('lat') }}, '{{ p.coordinate.longitude }}, {{ p.coordinate.latitude }}', '{{ p.address }}'); 21 | {% endfor %} -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Twig/GEOExtension.php: -------------------------------------------------------------------------------- 1 | container = $container; 19 | } 20 | 21 | public function getFilters() 22 | { 23 | return array( 24 | 'distance' => new \Twig_Filter_Method($this, 'distanceFilter'), 25 | 'coordinate' => new \Twig_Filter_Method($this, 'coordinateFilter'), 26 | 'lon' => new \Twig_Filter_Method($this, 'lonFilter'), 27 | 'lat' => new \Twig_Filter_Method($this, 'latFilter'), 28 | ); 29 | } 30 | public function getName() 31 | { 32 | return 'geo_extension'; 33 | } 34 | 35 | public function distanceFilter($dis, $precision = 2){ 36 | return round($dis*1000, $precision); 37 | } 38 | 39 | public function coordinateFilter(Coordinate $coordinate, $type = null){ 40 | list($lon, $lat) = $this->container->get('geo.location')->WGStoGCJ($coordinate->getLongitude(), $coordinate->getLatitude()); 41 | $coordinate->setLatitude($lat); 42 | $coordinate->setLongitude($lon); 43 | 44 | if($type == 'lat') 45 | return $lat; 46 | 47 | if($type == 'lon') 48 | return $lon; 49 | 50 | return $coordinate; 51 | } 52 | public function lonFilter($lon){ 53 | list($lon, $lat) = $this->container->get('geo.location')->WGStoGCJ($lon, '31.2'); 54 | 55 | return $lon; 56 | } 57 | public function latFilter($lat){ 58 | list($lon, $lat) = $this->container->get('geo.location')->WGStoGCJ('121.4', $lat); 59 | 60 | return $lat; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Henter/GEOBundle/Util/LocationService.php: -------------------------------------------------------------------------------- 1 | isOutChina($lon, $lat)){ 22 | return [$lon, $lat]; 23 | } 24 | 25 | $offsetLon = $this->convertLon($lon - 105.0, $lat - 35.0); 26 | $offsetLat = $this->convertLat($lon - 105.0, $lat - 35.0); 27 | 28 | $radLat = $lat / 180.0 * M_PI; 29 | $magic = sin($radLat); 30 | $magic = 1 - self::M_EE * $magic * $magic; 31 | $sqrtMagic = sqrt($magic); 32 | 33 | $offsetLon = ($offsetLon * 180.0) / 34 | (self::M_A / $sqrtMagic * cos($radLat) * M_PI); 35 | 36 | $offsetLat = ($offsetLat * 180.0) / 37 | ((self::M_A * (1 - self::M_EE)) / ($magic * $sqrtMagic) * M_PI); 38 | 39 | return [$lon + $offsetLon, $lat + $offsetLat]; 40 | } 41 | 42 | public function isOutChina($lon, $lat){ 43 | if ($lon < 72.004 || $lon > 137.8347){ 44 | return true; 45 | } 46 | 47 | if ($lat < 0.8293 || $lat > 55.8271){ 48 | return true; 49 | } 50 | 51 | return false; 52 | } 53 | 54 | protected function convertLon($x, $y){ 55 | $ret = 300.0 + $x + 2.0 * $y + 0.1 * $x * $x + 56 | 0.1 * $x * $y + 0.1 * sqrt(abs($x)); 57 | 58 | $ret += (20.0 * sin(6.0 * $x * M_PI) + 59 | 20.0 * sin(2.0 * $x * M_PI)) * 2.0 / 3.0; 60 | 61 | $ret += (20.0 * sin($x * M_PI) + 62 | 40.0 * sin($x / 3.0 * M_PI)) * 2.0 / 3.0; 63 | 64 | $ret += (150.0 * sin($x / 12.0 * M_PI) + 65 | 300.0 * sin($x / 30.0 * M_PI)) * 2.0 / 3.0; 66 | 67 | return $ret; 68 | } 69 | 70 | protected function convertLat($x, $y){ 71 | $ret = -100.0 + 2.0 * $x + 3.0 * $y + 0.2 * $y * $y + 72 | 0.1 * $x * $y + 0.2 * sqrt(abs($x)); 73 | 74 | $ret += (20.0 * sin(6.0 * $x * M_PI) + 75 | 20.0 * sin(2.0 * $x * M_PI)) * 2.0 / 3.0; 76 | 77 | $ret += (20.0 * sin($y * M_PI) + 78 | 40.0 * sin($y / 3.0 * M_PI)) * 2.0 / 3.0; 79 | 80 | $ret += (160.0 * sin($y / 12.0 * M_PI) + 81 | 320 * sin($y * M_PI / 30.0)) * 2.0 / 3.0; 82 | 83 | return $ret; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /web/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | RewriteEngine On 3 | 4 | # 5 | # RewriteBase / 6 | # 7 | 8 | RewriteCond %{REQUEST_FILENAME} !-f 9 | RewriteRule ^(.*)$ app.php [QSA,L] 10 | 11 | -------------------------------------------------------------------------------- /web/app.php: -------------------------------------------------------------------------------- 1 | register(true); 13 | */ 14 | 15 | require_once __DIR__.'/../app/AppKernel.php'; 16 | //require_once __DIR__.'/../app/AppCache.php'; 17 | 18 | $kernel = new AppKernel('prod', false); 19 | $kernel->loadClassCache(); 20 | //$kernel = new AppCache($kernel); 21 | $request = Request::createFromGlobals(); 22 | $response = $kernel->handle($request); 23 | $response->send(); 24 | $kernel->terminate($request, $response); 25 | -------------------------------------------------------------------------------- /web/app_dev.php: -------------------------------------------------------------------------------- 1 | loadClassCache(); 24 | $request = Request::createFromGlobals(); 25 | $response = $kernel->handle($request); 26 | $response->send(); 27 | $kernel->terminate($request, $response); 28 | -------------------------------------------------------------------------------- /web/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henter/HenterGEO/8dd268967714534282870fd3191cd7224627f43b/web/apple-touch-icon.png -------------------------------------------------------------------------------- /web/config.php: -------------------------------------------------------------------------------- 1 | getFailedRequirements(); 20 | $minorProblems = $symfonyRequirements->getFailedRecommendations(); 21 | 22 | ?> 23 | 24 | 25 | 26 | 27 | 28 | Symfony Configuration 29 | 30 | 31 |
32 |
33 |
34 | 37 | 38 |
39 |

Welcome!

40 |

Welcome to your new Symfony project.

41 |

42 | This script will guide you through the basic configuration of your project. 43 | You can also do the same by editing the ‘app/config/parameters.yml’ file directly. 44 |

45 | 46 | 47 |

Major problems

48 |

Major problems have been detected and must be fixed before continuing:

49 |
    50 | 51 |
  1. getHelpHtml() ?>
  2. 52 | 53 |
54 | 55 | 56 | 57 |

Recommendations

58 |

59 | Additionally, toTo enhance your Symfony experience, 60 | it’s recommended that you fix the following: 61 |

62 |
    63 | 64 |
  1. getHelpHtml() ?>
  2. 65 | 66 |
67 | 68 | 69 | hasPhpIniConfigIssue()): ?> 70 |

* 71 | getPhpIniConfigPath()): ?> 72 | Changes to the php.ini file must be done in "getPhpIniConfigPath() ?>". 73 | 74 | To change settings, create a "php.ini". 75 | 76 |

77 | 78 | 79 | 80 |

Your configuration looks good to run Symfony.

81 | 82 | 83 | 92 |
93 |
94 |
95 |
Symfony Standard Edition
96 |
97 | 98 | 99 | -------------------------------------------------------------------------------- /web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henter/HenterGEO/8dd268967714534282870fd3191cd7224627f43b/web/favicon.ico -------------------------------------------------------------------------------- /web/robots.txt: -------------------------------------------------------------------------------- 1 | # www.robotstxt.org/ 2 | # www.google.com/support/webmasters/bin/answer.py?hl=en&answer=156449 3 | 4 | User-agent: * 5 | --------------------------------------------------------------------------------