├── .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 |