Second Street Address Line

Open to all! Ask other shopowners for help.
Post Reply
User avatar
tessthepup
Certified Developer
Posts: 383
Joined: Mon Mar 01, 2021 5:55 pm
Phoenix Version:
Has thanked: 47 times
Been thanked: 62 times

Second Street Address Line

Post by tessthepup »

Good evening everyone & a Happy New Year

I have copied/changed the includes/modules/customer_data/cd_street_address.php to make a new input for a second address line. Also created the new field in the database.

The module installs and displays fine on all pages but the data for the new address line is not saving to the database.

Is there another file somewhere that I need to add the extra line to???

Thanks


Join The Code Co-op to get access to your library in the Code Co-op Forum
User avatar
Kofod95
Senior Contributor
Posts: 748
Joined: Sat Feb 06, 2021 7:38 pm
Phoenix Version: 1.0.8.20
Has thanked: 99 times
Been thanked: 179 times

Re: Second Street Address Line

Post by Kofod95 »

Maybe a hook like one of the steps here: viewtopic.php?p=3636#p3636

Edit: link updated!

//Daniel
Last edited by Kofod95 on Wed Jan 04, 2023 10:52 pm, edited 1 time in total.
I'm not smart, but sometimes even a blind chicken can find a corn.
Here are a lot of corns: Phoenix user guide
User avatar
tessthepup
Certified Developer
Posts: 383
Joined: Mon Mar 01, 2021 5:55 pm
Phoenix Version:
Has thanked: 47 times
Been thanked: 62 times

Re: Second Street Address Line

Post by tessthepup »

Kofod95 wrote: Wed Jan 04, 2023 9:16 pm Maybe a hook like one of the steps here: memberlist.php?mode=viewprofile&u=154

//Daniel
Cheers Daniel. I will have a go tomorrow and report back
ecartz
Core Team
Posts: 3084
Joined: Tue Nov 05, 2019 6:02 pm
Phoenix Version:
Has thanked: 4 times
Been thanked: 208 times

Re: Second Street Address Line

Post by ecartz »

tessthepup wrote: Wed Jan 04, 2023 7:55 pm The module installs and displays fine on all pages but the data for the new address line is not saving to the database.
You made the new field on what table?

What's the code in the module? When does it save? Where does it save?

How do you know that it is not saving to the database? Have you looked at a row in the database that you edited since you added the module? (Best.) Or you looked in the interface and it is not appearing? Or it's not appearing in the address when you look at ...

Note that Daniel's solution fixes the field appearing correctly in the customers or address_book table but not in the orders table. It's not the right solution if the field is not saving anywhere.
User avatar
tessthepup
Certified Developer
Posts: 383
Joined: Mon Mar 01, 2021 5:55 pm
Phoenix Version:
Has thanked: 47 times
Been thanked: 62 times

Re: Second Street Address Line

Post by tessthepup »

ecartz wrote: Thu Jan 05, 2023 11:53 am
tessthepup wrote: Wed Jan 04, 2023 7:55 pm The module installs and displays fine on all pages but the data for the new address line is not saving to the database.
@ecartz

Hi, thanks for the reply
You made the new field on what table?
I added the new field to the address_book table
What's the code in the module? When does it save? Where does it save?
It does not save anywhere. I did find 2 lines I had not changed to reflect the second address line but now it's totally broken the page.

Code: Select all

<?php
/*
  $Id$

  CE Phoenix, E-Commerce made Easy
  https://phoenixcart.org

  Copyright (c) 2021 Phoenix Cart

  Released under the GNU General Public License
*/

  class cd_second_street_address extends abstract_customer_data_module {

    const CONFIG_KEY_BASE = 'MODULE_CUSTOMER_DATA_SECOND_STREET_ADDRESS_';

    const PROVIDES = [ 'Address Line 2' ];
    const REQUIRES = [  ];

    protected function get_parameters() {
      return [
        static::CONFIG_KEY_BASE . 'STATUS' => [
          'title' => 'Enable Additional Street Address module',
          'value' => 'True',
          'desc' => 'Do you want to add the module to your shop?',
          'set_func' => "Config::select_one(['True', 'False'], ",
        ],
        static::CONFIG_KEY_BASE . 'GROUP' => [
          'title' => 'Customer data group',
          'value' => '2',
          'desc' => 'In what group should this appear?',
          'use_func' => 'customer_data_group::fetch_name',
          'set_func' => 'Config::select_customer_data_group(',
        ],
        static::CONFIG_KEY_BASE . 'REQUIRED' => [
          'title' => 'Require Street Address module (if enabled)',
          'value' => 'True',
          'desc' => 'Do you want the street address to be required in customer registration?',
          'set_func' => "Config::select_one(['True', 'False'], ",
        ],
        static::CONFIG_KEY_BASE . 'MIN_LENGTH' => [
          'title' => 'Minimum Length',
          'value' => '3',
          'desc' => 'Minimum length of street address',
        ],
        static::CONFIG_KEY_BASE . 'PAGES' => [
          'title' => 'Pages',
          'value' => 'address_book;checkout_new_address;create_account;customers',
          'desc' => 'On what pages should this appear?',
          'set_func' => 'Customers::select_pages(',
          'use_func' => 'abstract_module::list_exploded',
        ],
        static::CONFIG_KEY_BASE . 'SORT_ORDER' => [
          'title' => 'Sort Order',
          'value' => '4200',
          'desc' => 'Sort order of display. Lowest is displayed first.',
        ],
        static::CONFIG_KEY_BASE . 'TEMPLATE' => [
          'title' => 'Template',
          'value' => 'includes/modules/customer_data/cd_whole_row_input.php',
          'desc' => 'What template should be used to surround this input?',
        ],
      ];
    }

    public function get($field, &$customer_details) {
      switch ($field) {
        case 'second_street_address':
          if (!isset($customer_details[$field])) {
            $customer_details[$field] = $customer_details['second_street_address']
              ?? $customer_details['entry_second_street_address'] ?? null;
          }
          return $customer_details[$field];
      }
    }

    public function display_input($customer_details = null) {
      $label_text = ENTRY_SECOND_STREET_ADDRESS;
      $input_id = 'inputSecondStreetAddress';

      $input = new Input('second_street_address', [
        'id' => $input_id,
        'autocomplete' => 'address-line2',
        'placeholder' => ENTRY_SECOND_STREET_ADDRESS_TEXT,
      ]);

      if ($customer_details && is_array($customer_details)) {
        $input->set('value', $this->get('second_street_address', $customer_details));
      }

      if ($this->is_required()) {
        $input->require();
        $input .= FORM_REQUIRED_INPUT;
      }

      include Guarantor::ensure_global('Template')->map($this->base_constant('TEMPLATE'));
    }

    public function process(&$customer_details) {
      $customer_details['second_street_address'] = Text::input($_POST['second_street_address']);

      if ((strlen($customer_details['second_street_address']) < $this->base_constant('MIN_LENGTH'))
        && $this->is_required()
        )
      {
        $GLOBALS['messageStack']->add_classed(
          $GLOBALS['message_stack_area'] ?? 'customer_data',
          sprintf(ENTRY_STREET_ADDRESS_ERROR, $this->base_constant('MIN_LENGTH')));

        return false;
      }

      return true;
    }

    public function build_db_values(&$db_tables, $customer_details, $table = 'both') {
      Guarantor::guarantee_subarray($db_tables, 'address_book');
      $db_tables['address_book']['entry_second_street_address'] = $customer_details['second_street_address'];
    }

    public function build_db_aliases(&$db_tables, $table = 'both') {
      Guarantor::guarantee_subarray($db_tables, 'address_book');
      $db_tables['address_book']['entry_second_street_address'] = 'second_street_address';
    }

  }
How do you know that it is not saving to the database? Have you looked at a row in the database that you edited since you added the module? (Best.) Or you looked in the interface and it is not appearing? Or it's not appearing in the address when you look at ...
Check the database and nothing got saved to the field. Also before I broke the code I manually entered a value into the database and it showed in the field on the address_book etc.

Note that Daniel's solution fixes the field appearing correctly in the customers or address_book table but not in the orders table. It's not the right solution if the field is not saving anywhere.
one problem at a time ;)

Thanks

Mark
ecartz
Core Team
Posts: 3084
Joined: Tue Nov 05, 2019 6:02 pm
Phoenix Version:
Has thanked: 4 times
Been thanked: 208 times

Re: Second Street Address Line

Post by ecartz »

Try changing

Code: Select all

    const PROVIDES = [ 'Address Line 2' ];
to

Code: Select all

    const PROVIDES = [ 'second_street_address' ];
I'm not sure that it handles spaces (although it might), and I am sure that there is at least one place where what is given must match that.
User avatar
burt
Core Team
Posts: 4555
Joined: Tue Oct 29, 2019 9:37 am
Phoenix Version: v1.1.0.8
Has thanked: 252 times
Been thanked: 412 times

Re: Second Street Address Line

Post by burt »

This works in 1.0.8.17 for the following (you'll need to add entry_street_address_l2 to the address_book table);

1. allow admin to add street address (l2) to the relevant forms as per the usual way
2. saves the inputted data from customer
3. shows the inputted data to customer when editing an address [not sure if I tested if it saves changed data]

The issue now is how to get the "l2" inputted data to show where-ever a customers address shows. You'll need this "l2" to show in places so the customer can see their full address (eg in the checkout area, on the gdpr page) and in the admin area for the shopowner (especailly on orders page [I haven't tested that], and in the customer editing screen [I haven't tested that]).

My suggestion would be to look at address_format and try to get the $streets to pick up the relevant data. I didn't have time to look into it. Maybe Matt has a good/easy way of doing this.
You do not have the required permissions to view the files attached to this post.
I am not here to build for you.
I am here to build with you. Let's help each other.
User avatar
tessthepup
Certified Developer
Posts: 383
Joined: Mon Mar 01, 2021 5:55 pm
Phoenix Version:
Has thanked: 47 times
Been thanked: 62 times

Re: Second Street Address Line

Post by tessthepup »

@ecartz @burt

Thanks Guys

I changed the line as suggested by ecartz and that worked great and the second address line saved to the database.

Gary, your file was very helpful and also the suggestion of changing the $streets. I added $cr$second_streets after $streets in each field in the address_format table.

I also had to add the second address line to includes/modules/customer_data/cd_traditional_address.php

Code: Select all

<?php
/*
  $Id$

  CE Phoenix, E-Commerce made Easy
  https://phoenixcart.org

  Copyright (c) 2021 Phoenix Cart

  Released under the GNU General Public License
*/

  class cd_traditional_address extends abstract_module {

    const CONFIG_KEY_BASE = 'MODULE_CUSTOMER_DATA_TRADITIONAL_ADDRESS_';

    const PROVIDES = [ 'address' ];
    const REQUIRES = [ 'name', 'street_address', 'second_street_address', 'postcode', 'city', 'country' ];
    const FIELDS = [ 'name', 'street_address', 'second_street_address', 'postcode', 'city', 'country_id', 'company', 'suburb', 'state' ];

    private $active_fields;

    protected function get_parameters() {
      return [
        static::CONFIG_KEY_BASE . 'STATUS' => [
          'title' => 'Enable Traditional Address module',
          'value' => 'True',
          'desc' => 'Do you want to add the module to your shop?',
          'set_func' => "Config::select_one(['True', 'False'], ",
        ],
      ];
    }

    public function get($field, &$customer_details) {
      switch ($field) {
        case 'address':
          if (!isset($customer_details[$field])) {
            $customer_details[$field] = array_combine(
              $this->get_fields(),
              array_map(
                function ($v) use (&$customer_details) {
                  return $GLOBALS['customer_data']->get($v, $customer_details);
                },
                $this->get_fields()
              )
            );
          }

          return $customer_details[$field];
      }
    }

    public function process(&$customer_details) {
      $results = $GLOBALS['customer_data']->process($this->get_fields());
      $customer_details = array_merge($customer_details, $results);

      return !empty($results);
    }

    public function get_fields() {
      if (is_null($this->active_fields)) {
        global $customer_data;

        $customer_data->has(self::FIELDS);
        $this->active_fields = array_diff(self::FIELDS, $customer_data->get_last_missing_abilities());
      }

      return $this->active_fields;
    }

    public function get_purveyors() {
      return array_map([$GLOBALS['customer_data'], 'get_module'], $this->get_fields());
    }

    public function build_db_values(&$db_tables, $customer_details, $table = 'both') {
      foreach ($this->get_purveyors() as $purveyor) {
        $purveyor->build_db_values($db_tables, $customer_details, $table);
      }
    }

    public function build_db_aliases(&$db_tables, $table = 'both') {
      foreach ($this->get_purveyors() as $purveyor) {
        $purveyor->build_db_aliases($db_tables, $table);
      }
    }

    function format($address, $html, $boln, $eoln) {
      $address_format_id = $address['format_id'] ?? $address['address_format_id'] ?? $this->get_address_format_id($address['country_id'] ?? $address['country']['id'] ?? null);
      $address_format = $GLOBALS['db']->query("SELECT address_format AS format FROM address_format WHERE address_format_id = " . (int)$address_format_id)->fetch_assoc();

      $company = htmlspecialchars($address['company'] ?? '');
      $name = htmlspecialchars($GLOBALS['customer_data']->get('name', $address) ?? '');

      $street = htmlspecialchars($address['street_address']);
      $second_street = htmlspecialchars($address['second_street_address']);
      $suburb = htmlspecialchars($address['suburb'] ?? '');
      $city = htmlspecialchars($address['city']);
      $state = htmlspecialchars($address['state'] ?? '');
      if (!empty($address['country_id'])) {
        $country = Country::fetch_name($address['country_id']);

        if (!empty($address['zone_id'])) {
          $state = Zone::fetch_code($address['zone_id'], $address['country_id'], $state);
        }
      } elseif (!empty($address['country']) && is_array($address['country'])) {
        $country = htmlspecialchars($address['country']['title']);
      } else {
        $country = '';
      }
      $postcode = htmlspecialchars($address['postcode']);
      $zip = $postcode;

      if ($html) {
        // HTML Mode
        $HR = '<hr />';
        $hr = '<hr />';
        if ( ($boln == '') && ($eoln == "\n") ) { // Values not specified, use rational defaults
          $CR = '<br>';
          $cr = '<br>';
          $eoln = $cr;
        } else { // Use values supplied
          $CR = $eoln . $boln;
          $cr = $CR;
        }
      } else {
        // Text Mode
        $CR = $eoln;
        $cr = $CR;
        $HR = '----------------------------------------';
        $hr = '----------------------------------------';
      }

      $statecomma = '';
      $streets = $street;
      $second_streets = $second_street;
      if ('' != $suburb) {
        $streets .= $cr . $suburb;
      }
      if ('' != $state) {
        $statecomma = $state . ', ';
      }

      $fmt = $address_format['format'];
      eval("\$address = \"$fmt\";");

      if (!empty($company)) {
        $address = $company . $cr . $address;
      }

      return $address;
    }

    function get_address_format_id($country_id) {
      $address_format = $GLOBALS['db']->query("SELECT address_format_id AS format_id FROM countries WHERE countries_id = " . (int)$country_id)->fetch_assoc();

      return $address_format['format_id'] ?? '1';
    }

  }
I have check in most areas on the store front and all seems ok.

I then unfortunately had to modify catalog/includes/system/segments/checkout/insert_order.php

and add

Code: Select all

'customers_second_street_address' => $GLOBALS['customer_data']->get('second_street_address', $order->customer),
'delivery_second_street_address' => $GLOBALS['customer_data']->get('second_street_address', $order->delivery),
'billing_second_street_address' => $GLOBALS['customer_data']->get('second_street_address', $order->billing),
I then added 3 new fields to correspond to the above changes to the orders table
ecartz
Core Team
Posts: 3084
Joined: Tue Nov 05, 2019 6:02 pm
Phoenix Version:
Has thanked: 4 times
Been thanked: 208 times

Re: Second Street Address Line

Post by ecartz »

tessthepup wrote: Fri Jan 06, 2023 8:18 pm I then unfortunately had to modify catalog/includes/system/segments/checkout/insert_order.php
This is the point where you should read Daniel's link about using a hook to do that. Or actually, you should have read it before making the core changes. But since we're past that, you should read it now. You can do that entirely via hook and revert the core changes.
tessthepup wrote: Fri Jan 06, 2023 8:18 pm I also had to add the second address line to includes/modules/customer_data/cd_traditional_address.php
The suggested method here is to duplicate cd_traditional_address.php with a new name. Then uninstall the original and install your duplicate version. Then you won't get stomped by later core changes.


Join The Code Co-op to get access to your library in the Code Co-op Forum
Post Reply