studioespresso / craft-easyaddressfield

Easy Address Field is the easiest way to add an address to your entries. Enable the fields you want for the address, automatically get the coordinates for an address and place the marker exactly where you want it.
https://plugins.craftcms.com/easy-address-field
Other
3 stars 3 forks source link

Call to undefined function GuzzleHttp\Psr7\build_query() #31

Closed vnali closed 3 years ago

vnali commented 3 years ago

Hi. i tested this plugin with a fresh install and there is an error on saving entry. Steps to reproduce: Go to add entry page change country to other than United States after saving entry, there is an error "Call to undefined function GuzzleHttp\Psr7\build_query()".

php: 7.4.20 guzzle: 7.3.0 Craft: 3.6.17 Easy Address field: 3.0.2

janhenckens commented 3 years ago

Hey @vnali, could you post a full stack trace? Not sure where this is happening in the plugin.

vnali commented 3 years ago

@janhenckens


Call to undefined function GuzzleHttp\Psr7\build_query()

1. in /var/www/html/craft2/vendor/maxh/php-nominatim/src/Nominatim.php at line 189

     *
     * @return array|\SimpleXMLElement The decoded data returned from Nominatim
     */
    public function find(QueryInterface $nRequest, array $headers = [])
    {
        $url = $this->application_url . '/' . $nRequest->getPath() . '?';
        $request = new Request('GET', $url, \array_merge($this->defaultHeaders, $headers));

        //Convert the query array to string with space replace to +
        $query = \GuzzleHttp\Psr7\build_query($nRequest->getQuery(), PHP_QUERY_RFC1738); **//<--------------------------**

        $url = $request->getUri()->withQuery($query);
        $request = $request->withUri($url);

        return $this->decodeResponse(
            $nRequest->getFormat(),
            $request,
            $this->http_client->send($request)
        );

2. in /var/www/html/craft2/vendor/studioespresso/craft-easyaddressfield/src/services/GeoLocationService.php at line 53 – maxh\Nominatim\Nominatim::find()

            ->postalCode($model->postalCode ?? '')
            ->street($model->street . ' ' . $model->street2)
            ->limit(1)
            ->polygon('geojson')
            ->addressDetails();

        $result = $nominatim->find($search); **//<------------------**
        if(empty($result)) {
            return $model;
        }

        if(isset($result[0]['lat']) && isset($result[0]['lon'])) {
            $model->longitude = $result[0]['lon'];

3. in /var/www/html/craft2/vendor/studioespresso/craft-easyaddressfield/src/services/GeoLocationService.php at line 32 – studioespresso\easyaddressfield\services\GeoLocationService::geocodeOSM()

     *
     * @return EasyAddressFieldModel
     */
    public function locate(EasyAddressFieldModel $model)
    {
        if (!$model->latitude && !$model->longitude and strlen($model->toString()) >= 2) {
            $model = $this->geocodeOSM($model); **//<-------------------------**
        }

        return $model;
    }

    private function geocodeOSM(EasyAddressFieldModel $model)

4. in /var/www/html/craft2/vendor/studioespresso/craft-easyaddressfield/src/services/FieldService.php at line 43 – studioespresso\easyaddressfield\services\GeoLocationService::locate()

            $record = new EasyAddressFieldRecord();
            $record->owner = $element->id;
            $record->site = $element->siteId;
            $record->field = $field->id;
        }

        $value = EasyAddressField::$plugin->geolocation()->locate($value); **//<------------------------------**

        $record->name = $value->name;
        $record->street = $value->street;
        $record->street2 = $value->street2;
        $record->postalCode = $value->postalCode;

5. in /var/www/html/craft2/vendor/studioespresso/craft-easyaddressfield/src/fields/EasyAddressFieldField.php at line 208 – studioespresso\easyaddressfield\services\FieldService::saveField()

    /**
     * @param ElementInterface $element
     * @param bool $isNew
     */
    public function afterElementSave(ElementInterface $element, bool $isNew)
    {
        EasyAddressField::getInstance()->field->saveField($this, $element); **//<----------------------**
        parent::afterElementSave($element, $isNew);
    }

}

6. in /var/www/html/craft2/vendor/craftcms/cms/src/base/Element.php at line 3341 – studioespresso\easyaddressfield\fields\EasyAddressFieldField::afterElementSave()

     * @inheritdoc
     */
    public function afterSave(bool $isNew)
    {
        // Tell the fields about it
        foreach ($this->fieldLayoutFields() as $field) {
            $field->afterElementSave($this, $isNew); **//<--------------------**
        }

        // Trigger an 'afterSave' event
        if ($this->hasEventHandlers(self::EVENT_AFTER_SAVE)) {
            $this->trigger(self::EVENT_AFTER_SAVE, new ModelEvent([
                'isNew' => $isNew,

7. in /var/www/html/craft2/vendor/craftcms/cms/src/elements/Entry.php at line 1573 – craft\base\Element::afterSave()

                }
            }

            $this->setDirtyAttributes($dirtyAttributes);
        }

        parent::afterSave($isNew);
    }

    /**
     * @inheritdoc
     */
    public function afterPropagate(bool $isNew)

8. in /var/www/html/craft2/vendor/craftcms/cms/src/services/Elements.php at line 2514 – craft\elements\Entry::afterSave()

            if ($trackChanges) {
                ArrayHelper::append($dirtyAttributes, ...$element->getDirtyAttributes());
                $element->setDirtyAttributes($dirtyAttributes, false);
            }

            // It is now officially saved
            $element->afterSave($isNewElement);

            // Update the element across the other sites?
            if ($propagate) {
                $element->newSiteIds = [];

                foreach ($supportedSites as $siteInfo) {

9. in /var/www/html/craft2/vendor/craftcms/cms/src/services/Elements.php at line 758 – craft\services\Elements::_saveElementInternal()

        $propagate = !$element->id || $propagate;

        // Not currently being duplicated
        $duplicateOf = $element->duplicateOf;
        $element->duplicateOf = null;

        $success = $this->_saveElementInternal($element, $runValidation, $propagate, $updateSearchIndex);
        $element->duplicateOf = $duplicateOf;
        return $success;
    }

    /**
     * Resaves all elements that match a given element query.

10. in /var/www/html/craft2/vendor/craftcms/cms/src/controllers/EntryRevisionsController.php at line 436 – craft\services\Elements::saveElement()

        if ($draft->getIsUnpublishedDraft() && $this->request->getBodyParam('propagateAll')) {
            $draft->propagateAll = true;
        }

        try {
            if (!Craft::$app->getElements()->saveElement($draft)) {
                throw new InvalidElementException($draft);
            }

            // Publish the draft (finally!)
            $newEntry = Craft::$app->getDrafts()->publishDraft($draft);
        } catch (InvalidElementException $e) {

11. craft\controllers\EntryRevisionsController::actionPublishDraft()
12. in /var/www/html/craft2/vendor/yiisoft/yii2/base/InlineAction.php at line 57 – call_user_func_array()
13. in /var/www/html/craft2/vendor/yiisoft/yii2/base/Controller.php at line 181 – yii\base\InlineAction::runWithParams()
14. in /var/www/html/craft2/vendor/craftcms/cms/src/web/Controller.php at line 190 – yii\base\Controller::runAction()
184185186187188189190191192193194195196

    /**
     * @inheritdoc
     */
    public function runAction($id, $params = [])
    {
        try {
            return parent::runAction($id, $params);
        } catch (\Throwable $e) {
            if ($this->request->getAcceptsJson()) {
                Craft::$app->getErrorHandler()->logException($e);
                if (!YII_DEBUG && !$e instanceof UserException) {
                    $message = Craft::t('app', 'A server error occurred.');
                } else {

15. in /var/www/html/craft2/vendor/yiisoft/yii2/base/Module.php at line 534 – craft\web\Controller::runAction()
16. in /var/www/html/craft2/vendor/craftcms/cms/src/web/Application.php at line 278 – yii\base\Module::runAction()

     * @param string $route
     * @param array $params
     * @return Response|null The result of the action, normalized into a Response object
     */
    public function runAction($route, $params = [])
    {
        $result = parent::runAction($route, $params);

        if ($result !== null) {
            if ($result instanceof Response) {
                return $result;
            }

17. in /var/www/html/craft2/vendor/craftcms/cms/src/web/Application.php at line 581 – craft\web\Application::runAction()

        if ($request->getIsActionRequest()) {
            $route = implode('/', $request->getActionSegments());

            try {
                Craft::debug("Route requested: '$route'", __METHOD__);
                $this->requestedRoute = $route;
                return $this->runAction($route, $_GET);
            } catch (\Throwable $e) {
                $this->_unregisterDebugModule();
                if ($e instanceof InvalidRouteException) {
                    throw new NotFoundHttpException(Craft::t('yii', 'Page not found.'), $e->getCode(), $e);
                }
                throw $e;

18. in /var/www/html/craft2/vendor/craftcms/cms/src/web/Application.php at line 257 – craft\web\Application::_processActionRequest()

            if (!$user->checkPermission('accessPlugin-' . $plugin->id)) {
                throw new ForbiddenHttpException();
            }
        }

        // If this is an action request, call the controller
        if (($response = $this->_processActionRequest($request)) !== null) {
            return $response;
        }

        // If we're still here, finally let Yii do it's thing.
        try {
            return parent::handleRequest($request);

19. in /var/www/html/craft2/vendor/yiisoft/yii2/base/Application.php at line 392 – craft\web\Application::handleRequest()
20. in /var/www/html/craft2/web/index.php at line 26 – yii\base\Application::run()

define('CRAFT_ENVIRONMENT', getenv('ENVIRONMENT') ?: 'production');
// ...

// Load and run Craft
/** @var craft\web\Application $app */
$app = require CRAFT_VENDOR_PATH . '/craftcms/cms/bootstrap/web.php';
$app->
janhenckens commented 3 years ago

That's pretty strange since the GuzzleHttp dependency should have been installed along with maxh/php-nominatim. Could you try running composer install again and if that doesn't work removing your vendor directory and then running it again?

vnali commented 3 years ago

@janhenckens /var/www/html/craft2/vendor/guzzlehttp/psr7/src was available. i also tried composer install and removing vendor and again composer install and it didn't work. i am not sure but it seems build_query is a deprecated and removed function.

janhenckens commented 3 years ago

The function does have the following doc block:

  • @deprecated build_query will be removed in guzzlehttp/psr7:2.0. Use Query::build instead.

I'll try to reproduce on guzzlehttp/psr7 2.0 and report back!

janhenckens commented 3 years ago

@vnali could you check which version for guzzlehttp/psr7 you have installed?

So guzzlehttp/psr7 2.0 was released 11 days ago, which removed the build_query function. maxhelias/php-nominatim doesn't specify which version they need so I can specify this myself and that should fix it.

But just to make sure, could you run composer show guzzlehttp/psr7 to list which package you have installed that needs 2.0?

Thanks

vnali commented 3 years ago

thanks. composer.lock shows 2.0.0 and composer shows guzzlehttp/psr7 output is:

name     : guzzlehttp/psr7
descrip. : PSR-7 message implementation that also provides common utility methods
keywords : http, message, psr-7, request, response, stream, uri, url
versions : * 2.0.0
type     : library
license  : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
homepage :
source   : []
path     : /var/www/html/craft2/vendor/guzzlehttp/psr7
names    : guzzlehttp/psr7, psr/http-factory-implementation, psr/http-message-implementation

autoload
psr-4
GuzzleHttp\Psr7\ => src/

requires
php ^7.2.5 || ^8.0
psr/http-factory ^1.0
psr/http-message ^1.0
ralouphie/getallheaders ^3.0

suggests
laminas/laminas-httphandlerrunner Emit PSR-7 responses

provides
psr/http-factory-implementation 1.0
psr/http-message-implementation 1.0
janhenckens commented 3 years ago

The nominatim package got on update to support this (https://github.com/maxhelias/php-nominatim/releases/tag/2.3.0) - Can you try running composer update to see if that fixes the error?

vnali commented 3 years ago

thanks! it works now after composer update