classes/XLite/Model/Profile.php line 65

Open in your IDE?
  1. <?php
  2. /**
  3.  * Copyright (c) 2011-present Qualiteam software Ltd. All rights reserved.
  4.  * See https://www.x-cart.com/license-agreement.html for license details.
  5.  */
  6. namespace XLite\Model;
  7. use ApiPlatform\Core\Annotation as ApiPlatform;
  8. use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
  9. use Doctrine\ORM\Mapping as ORM;
  10. use XCart\Framework\ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\IntegerDateFilter;
  11. use XLite\API\Endpoint\Profile\DTO\ProfileInput as Input;
  12. use XLite\API\Endpoint\Profile\DTO\ProfileOutput as Output;
  13. /**
  14.  * The "profile" model class
  15.  *
  16.  * @ORM\Entity
  17.  * @ORM\Table  (name="profiles",
  18.  *      indexes={
  19.  *          @ORM\Index (name="login", columns={"login"}),
  20.  *          @ORM\Index (name="order_id", columns={"order_id"}),
  21.  *          @ORM\Index (name="password", columns={"password"}),
  22.  *          @ORM\Index (name="access_level", columns={"access_level"}),
  23.  *          @ORM\Index (name="first_login", columns={"first_login"}),
  24.  *          @ORM\Index (name="last_login", columns={"last_login"}),
  25.  *          @ORM\Index (name="status", columns={"status"})
  26.  *      }
  27.  * )
  28.  * @ApiPlatform\ApiResource(
  29.  *     input=Input::class,
  30.  *     output=Output::class,
  31.  *     itemOperations={
  32.  *          "get"={
  33.  *              "method"="GET",
  34.  *              "path"="/profiles/{profile_id}.{_format}",
  35.  *              "identifiers"={"profile_id"},
  36.  *              "requirements"={"profile_id"="\d+"}
  37.  *          },
  38.  *          "put"={
  39.  *              "method"="PUT",
  40.  *              "path"="/profiles/{profile_id}.{_format}",
  41.  *              "identifiers"={"profile_id"},
  42.  *              "requirements"={"profile_id"="\d+"}
  43.  *          },
  44.  *          "delete"={
  45.  *              "method"="DELETE",
  46.  *              "path"="/profiles/{profile_id}.{_format}",
  47.  *              "identifiers"={"profile_id"},
  48.  *              "requirements"={"profile_id"="\d+"}
  49.  *          }
  50.  *     },
  51.  *     collectionOperations={
  52.  *          "get"={
  53.  *              "method"="GET",
  54.  *              "path"="/profiles.{_format}",
  55.  *              "identifiers"={"profile_id"}
  56.  *          },
  57.  *          "post"={
  58.  *              "method"="POST",
  59.  *              "path"="/profiles.{_format}",
  60.  *              "identifiers"={"profile_id"},
  61.  *              "controller"="xcart.api.profile.controller"
  62.  *          }
  63.  *     }
  64.  * )
  65.  * @ApiPlatform\ApiFilter(IntegerDateFilter::class, properties={"first_login", "added"})
  66.  * @ApiPlatform\ApiFilter(SearchFilter::class, properties={"login"="partial", "searchFakeField"="partial"})
  67.  */
  68. class Profile extends \XLite\Model\AEntity
  69. {
  70.     /**
  71.      * Status codes
  72.      */
  73.     public const STATUS_ENABLED  'E';
  74.     public const STATUS_DISABLED 'D';
  75.     /**
  76.      * Merge flags
  77.      */
  78.     public const MERGE_ALL       3;
  79.     public const MERGE_ADDRESSES 1;
  80.     public const MERGE_ORDERS    2;
  81.     /**
  82.      * Profile unique ID
  83.      *
  84.      * @var integer
  85.      *
  86.      * @ORM\Id
  87.      * @ORM\GeneratedValue (strategy="AUTO")
  88.      * @ORM\Column         (type="integer")
  89.      */
  90.     protected $profile_id;
  91.     /**
  92.      * Old Login (e-mail)
  93.      *
  94.      * @var string
  95.      */
  96.     protected $oldLogin '';
  97.     /**
  98.      * Login (e-mail)
  99.      *
  100.      * @var string
  101.      *
  102.      * @ORM\Column (type="string", length=128)
  103.      */
  104.     protected $login '';
  105.     /**
  106.      * Password
  107.      *
  108.      * @var string
  109.      *
  110.      * @ORM\Column (type="string")
  111.      */
  112.     protected $password '';
  113.     /**
  114.      * Password hint
  115.      *
  116.      * @var string
  117.      *
  118.      * @ORM\Column (type="string", length=128)
  119.      */
  120.     protected $password_hint '';
  121.     /**
  122.      * Password hint answer
  123.      *
  124.      * @var string
  125.      *
  126.      * @ORM\Column (type="string", length=128)
  127.      */
  128.     protected $password_hint_answer '';
  129.     /**
  130.      * Password reset key (for 'Forgot password')
  131.      *
  132.      * @var string
  133.      *
  134.      * @ORM\Column (type="string")
  135.      */
  136.     protected $passwordResetKey '';
  137.     /**
  138.      * Timestamp of reset key creation date
  139.      *
  140.      * @var integer
  141.      *
  142.      * @ORM\Column (type="integer")
  143.      */
  144.     protected $passwordResetKeyDate 0;
  145.     /**
  146.      * Access level
  147.      *
  148.      * @var integer
  149.      *
  150.      * @ORM\Column (type="integer")
  151.      */
  152.     protected $access_level 0;
  153.     /**
  154.      * Timestamp of profile creation date
  155.      *
  156.      * @var integer
  157.      *
  158.      * @ORM\Column (type="integer")
  159.      */
  160.     protected $added 0;
  161.     /**
  162.      * Timestamp of first login event
  163.      *
  164.      * @var integer
  165.      *
  166.      * @ORM\Column (type="integer")
  167.      */
  168.     protected $first_login 0;
  169.     /**
  170.      * Timestamp of last login event
  171.      *
  172.      * @var integer
  173.      *
  174.      * @ORM\Column (type="integer")
  175.      */
  176.     protected $last_login 0;
  177.     /**
  178.      * Profile status
  179.      *
  180.      * @var string
  181.      *
  182.      * @ORM\Column (type="string", options={ "fixed": true }, length=1)
  183.      */
  184.     protected $status self::STATUS_ENABLED;
  185.     /**
  186.      * Status comment (reason)
  187.      *
  188.      * @var string
  189.      *
  190.      * @ORM\Column (type="string", length=255)
  191.      */
  192.     protected $statusComment '';
  193.     /**
  194.      * Referer
  195.      *
  196.      * @var string
  197.      *
  198.      * @ORM\Column (type="string", length=255)
  199.      */
  200.     protected $referer '';
  201.     /**
  202.      * Relation to a order
  203.      *
  204.      * @var \XLite\Model\Order
  205.      *
  206.      * @ORM\OneToOne   (targetEntity="XLite\Model\Order")
  207.      * @ORM\JoinColumn (name="order_id", referencedColumnName="order_id", onDelete="CASCADE")
  208.      */
  209.     protected $order;
  210.     /**
  211.      * Relation to an event
  212.      *
  213.      * @var \XLite\Model\OrderHistoryEvents
  214.      *
  215.      * @ORM\OneToMany   (targetEntity="XLite\Model\OrderHistoryEvents", mappedBy="author")
  216.      * @ORM\JoinColumn (name="event_id", referencedColumnName="event_id", onDelete="CASCADE")
  217.      */
  218.     protected $event;
  219.     /**
  220.      * Language code
  221.      *
  222.      * @var string
  223.      *
  224.      * @ORM\Column (type="string", length=2)
  225.      */
  226.     protected $language '';
  227.     /**
  228.      * Last selected shipping id
  229.      *
  230.      * @var integer
  231.      *
  232.      * @ORM\Column (type="integer", nullable=true)
  233.      */
  234.     protected $last_shipping_id;
  235.     /**
  236.      * Last selected payment id
  237.      *
  238.      * @var integer
  239.      *
  240.      * @ORM\Column (type="integer", nullable=true)
  241.      */
  242.     protected $last_payment_id;
  243.     /**
  244.      * Membership: many-to-one relation with memberships table
  245.      *
  246.      * @var \Doctrine\Common\Collections\ArrayCollection
  247.      *
  248.      * @ORM\ManyToOne  (targetEntity="XLite\Model\Membership")
  249.      * @ORM\JoinColumn (name="membership_id", referencedColumnName="membership_id", onDelete="SET NULL")
  250.      */
  251.     protected $membership;
  252.     /**
  253.      * Pending membership: many-to-one relation with memberships table
  254.      *
  255.      * @var \Doctrine\Common\Collections\ArrayCollection
  256.      *
  257.      * @ORM\ManyToOne  (targetEntity="XLite\Model\Membership")
  258.      * @ORM\JoinColumn (name="pending_membership_id", referencedColumnName="membership_id", onDelete="SET NULL")
  259.      */
  260.     protected $pending_membership;
  261.     /**
  262.      * Address book: one-to-many relation with address book entity
  263.      *
  264.      * @var \Doctrine\Common\Collections\ArrayCollection
  265.      *
  266.      * @ORM\OneToMany (targetEntity="XLite\Model\Address", mappedBy="profile", cascade={"all"})
  267.      */
  268.     protected $addresses;
  269.     /**
  270.      * Roles
  271.      *
  272.      * @var \Doctrine\Common\Collections\Collection
  273.      *
  274.      * @ORM\ManyToMany (targetEntity="XLite\Model\Role", mappedBy="profiles", cascade={"merge","detach","persist"})
  275.      */
  276.     protected $roles;
  277.     /**
  278.      * The count of orders placed by the user
  279.      *
  280.      * @var integer
  281.      */
  282.     protected $orders_count null;
  283.     /**
  284.      * Flag of anonymous profile (used for checkout process only)
  285.      *
  286.      * @var boolean
  287.      *
  288.      * @ORM\Column (type="boolean")
  289.      */
  290.     protected $anonymous false;
  291.     /**
  292.      * Flag if the user needs to change the password.
  293.      * The customers only
  294.      *
  295.      * @var boolean
  296.      *
  297.      * @ORM\Column (type="boolean")
  298.      */
  299.     protected $forceChangePassword false;
  300.     /**
  301.      * Date of last login attempt
  302.      *
  303.      * @var integer
  304.      *
  305.      * @ORM\Column (type="integer", options={ "unsigned": true })
  306.      */
  307.     protected $dateOfLoginAttempt 0;
  308.     /**
  309.      * Count of login attempt
  310.      *
  311.      * @var integer
  312.      *
  313.      * @ORM\Column (type="integer")
  314.      */
  315.     protected $countOfLoginAttempts 0;
  316.     /**
  317.      * Fake field for search
  318.      *
  319.      * @var string
  320.      *
  321.      * @ORM\Column (type="text", nullable=true)
  322.      */
  323.     protected $searchFakeField;
  324.     /**
  325.      * Flag to exporting entities
  326.      *
  327.      * @var boolean
  328.      *
  329.      * @ORM\Column (type="boolean")
  330.      */
  331.     protected $xcPendingExport false;
  332.     /**
  333.      * Checkout email
  334.      *
  335.      * @var string
  336.      *
  337.      * @ORM\Column (type="string")
  338.      */
  339.     protected $lastCheckoutEmail '';
  340.     /**
  341.      * Set referer
  342.      *
  343.      * @param string $value Value
  344.      *
  345.      * @return void
  346.      */
  347.     public function setReferer($value)
  348.     {
  349.         $this->referer substr($value0255);
  350.     }
  351.     /**
  352.      * Set membership
  353.      *
  354.      * @param \XLite\Model\Membership $membership Membership OPTIONAL
  355.      *
  356.      * @return void
  357.      */
  358.     public function setMembership(\XLite\Model\Membership $membership null)
  359.     {
  360.         $this->membership $membership;
  361.     }
  362.     /**
  363.      * Set pending membership
  364.      *
  365.      * @param \XLite\Model\Membership $pendingMembership Pending membership OPTIONAL
  366.      *
  367.      * @return void
  368.      */
  369.     public function setPendingMembership(\XLite\Model\Membership $pendingMembership null)
  370.     {
  371.         $this->pending_membership $pendingMembership;
  372.     }
  373.     /**
  374.      * Get membership Id
  375.      *
  376.      * @return integer
  377.      */
  378.     public function getMembershipId()
  379.     {
  380.         return $this->getMembership() ? $this->getMembership()->getMembershipId() : null;
  381.     }
  382.     /**
  383.      * Get pending membership Id
  384.      *
  385.      * @return integer
  386.      */
  387.     public function getPendingMembershipId()
  388.     {
  389.         return $this->getPendingMembership() ? $this->getPendingMembership()->getMembershipId() : null;
  390.     }
  391.     /**
  392.      * Get name
  393.      *
  394.      * @param boolean $useDefault Administrator|Customer if missing OPTIONAL
  395.      * @param boolean $shortName FirstName only OPTIONAL
  396.      *
  397.      * @return string
  398.      */
  399.     public function getName($useDefault true$shortName false)
  400.     {
  401.         $address $this->getBillingAddress() ?: $this->getShippingAddress();
  402.         if ($address) {
  403.             if ($shortName && $address->getFirstname()) {
  404.                 return trim($address->getFirstname());
  405.             } elseif ($address->getFirstname() || $address->getLastname()) {
  406.                 return trim($address->getFirstname() . ' ' $address->getLastname());
  407.             }
  408.         }
  409.         return $this->getNameFromDefaultAddress() ? $this->getNameFromDefaultAddress() : ($useDefault $this->getDefaultName() : '');
  410.     }
  411.     /**
  412.      * Get default name from address
  413.      *
  414.      * @return string
  415.      */
  416.     public function getNameFromDefaultAddress()
  417.     {
  418.         if (count($this->getAddresses())) {
  419.             foreach ($this->getAddresses() as $address) {
  420.                 $result trim($address->getFirstname() . ' ' $address->getLastname());
  421.                 break;
  422.             }
  423.         } else {
  424.             $result false;
  425.         }
  426.         return $result;
  427.     }
  428.     /**
  429.      * Get default name
  430.      *
  431.      * @return string
  432.      */
  433.     protected function getDefaultName()
  434.     {
  435.         return $this->isAdmin()
  436.             ? static::t('na_admin')
  437.             : static::t('na_customer');
  438.     }
  439.     /**
  440.      * Returns billing address
  441.      *
  442.      * @return \XLite\Model\Address
  443.      */
  444.     public function getBillingAddress()
  445.     {
  446.         return $this->getAddressByType(\XLite\Model\Address::BILLING);
  447.     }
  448.     /**
  449.      * Returns shipping address
  450.      *
  451.      * @return \XLite\Model\Address
  452.      */
  453.     public function getShippingAddress()
  454.     {
  455.         return $this->getAddressByType(\XLite\Model\Address::SHIPPING);
  456.     }
  457.     /**
  458.      * Switches current billing address to a new one
  459.      *
  460.      * @param \XLite\Model\Address $new
  461.      */
  462.     public function setBillingAddress($new)
  463.     {
  464.         $current $this->getBillingAddress();
  465.         if ($current && $current->getUniqueIdentifier() == $new->getUniqueIdentifier()) {
  466.             return;
  467.         }
  468.         $this->setAddress('billing'$new);
  469.     }
  470.     /**
  471.      * Switches current shipping address to a new one
  472.      *
  473.      * @param \XLite\Model\Address $new
  474.      */
  475.     public function setShippingAddress($new)
  476.     {
  477.         $current $this->getShippingAddress();
  478.         if ($current && $current->getUniqueIdentifier() == $new->getUniqueIdentifier()) {
  479.             return;
  480.         }
  481.         $this->setAddress('shipping'$new);
  482.     }
  483.     /**
  484.      * Set current address by type
  485.      *
  486.      * @param string $type
  487.      * @param \XLite\Model\Address $new
  488.      */
  489.     protected function setAddress($type$new)
  490.     {
  491.         $current = ($type == 'shipping')
  492.             ? $this->getShippingAddress()
  493.             : $this->getBillingAddress();
  494.         if ($current && $current->getUniqueIdentifier() == $new->getUniqueIdentifier()) {
  495.             return;
  496.         }
  497.         $useAsOtherType \XLite\Core\Session::getInstance()->same_address ?? null;
  498.         // Disable current address
  499.         if ($current) {
  500.             if ($current->getIsWork()) {
  501.                 $this->getAddresses()->removeElement($current);
  502.                 \XLite\Core\Database::getEM()->remove($current);
  503.             }
  504.             $useAsOtherType = ($type == 'shipping')
  505.                 ? $current->getIsBilling()
  506.                 : $current->getIsShipping();
  507.             $current->setIsShipping(false);
  508.             $current->setIsBilling(false);
  509.         }
  510.         // Check if new address is not assigned to this profile
  511.         $addToProfile true;
  512.         foreach ($this->getAddresses() as $profileAddress) {
  513.             if ($profileAddress->getUniqueIdentifier() == $new->getUniqueIdentifier()) {
  514.                 $addToProfile false;
  515.             }
  516.         }
  517.         if ($addToProfile) {
  518.             $this->addAddresses($new);
  519.             $new->setProfile($this);
  520.         }
  521.         if ($type == 'shipping') {
  522.             $new->setIsShipping(true);
  523.             if ($useAsOtherType !== null && $current && !$current->getIsWork()) {
  524.                 $new->setIsBilling($useAsOtherType);
  525.             }
  526.         } else {
  527.             $new->setIsBilling(true);
  528.             if ($useAsOtherType !== null && $current && !$current->getIsWork()) {
  529.                 $new->setIsShipping($useAsOtherType);
  530.             }
  531.         }
  532.     }
  533.     /**
  534.      * Returns first available address
  535.      *
  536.      * @return \XLite\Model\Address
  537.      */
  538.     public function getFirstAddress()
  539.     {
  540.         $result null;
  541.         foreach ($this->getAddresses() as $address) {
  542.             $result $address;
  543.             break;
  544.         }
  545.         return $result;
  546.     }
  547.     /**
  548.      * Has tax exemption
  549.      *
  550.      * @return boolean
  551.      */
  552.     public function hasTaxExemption()
  553.     {
  554.         return false;
  555.     }
  556.     /**
  557.      * Returns the number of orders places by the user
  558.      *
  559.      * @return integer
  560.      */
  561.     public function getOrdersCount()
  562.     {
  563.         if ($this->orders_count === null) {
  564.             $cnd = new \XLite\Core\CommonCell();
  565.             $cnd->profile $this;
  566.             $this->orders_count \XLite\Core\Database::getRepo('XLite\Model\Order')->search($cndtrue);
  567.         }
  568.         return $this->orders_count;
  569.     }
  570.     /**
  571.      * Check if profile is enabled
  572.      *
  573.      * @return boolean
  574.      */
  575.     public function isEnabled()
  576.     {
  577.         return strtoupper($this->getStatus()) === static::STATUS_ENABLED;
  578.     }
  579.     /**
  580.      * Check if profile is disabled
  581.      *
  582.      * @return bool
  583.      */
  584.     public function isDisabled(): bool
  585.     {
  586.         return strtoupper($this->getStatus()) === static::STATUS_DISABLED;
  587.     }
  588.     /**
  589.      * Enable user profile
  590.      *
  591.      * @return void
  592.      */
  593.     public function enable()
  594.     {
  595.         $this->setStatus(static::STATUS_ENABLED);
  596.     }
  597.     /**
  598.      * Disable user profile
  599.      *
  600.      * @return void
  601.      */
  602.     public function disable()
  603.     {
  604.         $this->setStatus(static::STATUS_DISABLED);
  605.     }
  606.     /**
  607.      * Returns true if profile has an administrator access level
  608.      *
  609.      * @return boolean
  610.      */
  611.     public function isAdmin()
  612.     {
  613.         return $this->getAccessLevel() >= \XLite\Core\Auth::getInstance()->getAdminAccessLevel();
  614.     }
  615.     /**
  616.      * Create an entity profile in the database
  617.      *
  618.      * @return boolean
  619.      */
  620.     public function create()
  621.     {
  622.         $this->prepareCreate();
  623.         return parent::create();
  624.     }
  625.     /**
  626.      * Update an entity in the database
  627.      *
  628.      * @param boolean $cloneMode Clone mode OPTIONAL
  629.      *
  630.      * @return boolean
  631.      */
  632.     public function update($cloneMode false)
  633.     {
  634.         // Check if user with specified e-mail address is already exists
  635.         $exists $cloneMode
  636.             null
  637.             \XLite\Core\Database::getRepo('XLite\Model\Profile')->checkRegisteredUserWithSameLogin($this);
  638.         if ($exists) {
  639.             $this->addErrorEmailExists();
  640.             $result false;
  641.         } else {
  642.             $this->updateSearchFakeField();
  643.             // Do an entity update
  644.             $result parent::update();
  645.         }
  646.         return $result;
  647.     }
  648.     /**
  649.      * Delete an entity profile from the database
  650.      *
  651.      * @return boolean
  652.      */
  653.     public function delete()
  654.     {
  655.         // Check if the deleted profile is a last admin profile
  656.         if ($this->isAdmin() && \XLite\Core\Database::getRepo('XLite\Model\Profile')->findCountOfAdminAccounts() == 1) {
  657.             $result false;
  658.             \XLite\Core\TopMessage::addError('The only remaining active administrator profile cannot be deleted.');
  659.         } else {
  660.             $result parent::delete();
  661.         }
  662.         return $result;
  663.     }
  664.     /**
  665.      * Check if billing and shipping addresses are equal or not
  666.      * TODO: review method after implementing at one-step-checkout
  667.      *
  668.      * @return boolean
  669.      */
  670.     public function isSameAddress()
  671.     {
  672.         $result false;
  673.         $billingAddress $this->getBillingAddress();
  674.         $shippingAddress $this->getShippingAddress();
  675.         if ($billingAddress !== null && $shippingAddress !== null) {
  676.             $result true;
  677.             if ($billingAddress->getAddressId() != $shippingAddress->getAddressId()) {
  678.                 $addressFields $billingAddress->getAvailableAddressFields();
  679.                 foreach ($addressFields as $name) {
  680.                     $methodName 'get' \Includes\Utils\Converter::convertToUpperCamelCase($name);
  681.                     // Compare field values of billing and shipping addresses
  682.                     if ($billingAddress->$methodName() != $shippingAddress->$methodName()) {
  683.                         $result false;
  684.                         break;
  685.                     }
  686.                 }
  687.             }
  688.         }
  689.         return $result;
  690.     }
  691.     /**
  692.      * Check - billing and shipping addresses are equal or not
  693.      *
  694.      * @param boolean $strict Flag: true - both billing and shipping addresses must be defined OPTIONAL
  695.      *
  696.      * @return boolean
  697.      */
  698.     public function isEqualAddress($strict false)
  699.     {
  700.         $billingAddress $this->getBillingAddress();
  701.         $shippingAddress $this->getShippingAddress();
  702.         $result $billingAddress !== null && $shippingAddress !== null;
  703.         return $strict
  704.             $result && $billingAddress->getAddressId() == $shippingAddress->getAddressId()
  705.             : !$result || $billingAddress->getAddressId() == $shippingAddress->getAddressId();
  706.     }
  707.     /**
  708.      * Clone
  709.      *
  710.      * @return \XLite\Model\Profile
  711.      */
  712.     public function cloneEntity()
  713.     {
  714.         $newProfile parent::cloneEntity();
  715.         $newProfile->setMembership($this->getMembership());
  716.         $newProfile->setPendingMembership($this->getPendingMembership());
  717.         $newProfile->setPassword('');
  718.         $billingAddress $this->getBillingAddress();
  719.         if ($billingAddress !== null) {
  720.             $newBillingAddress $billingAddress->cloneEntity();
  721.             $newBillingAddress->setProfile($newProfile);
  722.             $newProfile->addAddresses($newBillingAddress);
  723.         }
  724.         $shippingAddress $this->getShippingAddress();
  725.         if (
  726.             $shippingAddress
  727.             && (!$billingAddress
  728.                 || $billingAddress->getAddressId() != $shippingAddress->getAddressId()
  729.                 || $billingAddress->getAddressId() === null
  730.                 || $shippingAddress->getAddressId() === null
  731.             )
  732.         ) {
  733.             $newShippingAddress $shippingAddress->cloneEntity();
  734.             $newShippingAddress->setProfile($newProfile);
  735.             $newProfile->addAddresses($newShippingAddress);
  736.         }
  737.         return $newProfile;
  738.     }
  739.     /**
  740.      * Constructor
  741.      *
  742.      * @param array $data Entity properties OPTIONAL
  743.      */
  744.     public function __construct(array $data = [])
  745.     {
  746.         $this->addresses = new \Doctrine\Common\Collections\ArrayCollection();
  747.         $this->roles     = new \Doctrine\Common\Collections\ArrayCollection();
  748.         parent::__construct($data);
  749.     }
  750.     /**
  751.      * Get language code
  752.      *
  753.      * @param boolean $isCreateMode Flag to get original entity language OPTIONAL
  754.      *
  755.      * @return string
  756.      */
  757.     public function getLanguage($isCreateMode false)
  758.     {
  759.         return $isCreateMode
  760.             $this->getLanguageForCreateProfile()
  761.             : $this->checkForActiveLanguage($this->language);
  762.     }
  763.     /**
  764.      * Define the language code for created profile
  765.      *
  766.      * @return string
  767.      */
  768.     protected function getLanguageForCreateProfile()
  769.     {
  770.         return $this->language;
  771.     }
  772.     /**
  773.      * Check if the language code is in the active languages list
  774.      * If customer language is not used right now, the default customer language code is used
  775.      *
  776.      * @param string $languageCode Language code
  777.      *
  778.      * @return string
  779.      */
  780.     protected function checkForActiveLanguage($languageCode)
  781.     {
  782.         $result $languageCode;
  783.         $langs \XLite\Core\Database::getRepo('XLite\Model\Language')->findActiveLanguages();
  784.         if (!empty($langs)) {
  785.             $resultModel \Includes\Utils\ArrayManager::searchInObjectsArray(
  786.                 $langs,
  787.                 'getCode',
  788.                 $result
  789.             );
  790.             if ($resultModel === null) {
  791.                 $result \XLite\Core\Config::getInstance()->General->default_language;
  792.             }
  793.         }
  794.         return $result;
  795.     }
  796.     /**
  797.      * Set order
  798.      *
  799.      * @param \XLite\Model\Order $order Order OPTIONAL
  800.      *
  801.      * @return void
  802.      */
  803.     public function setOrder(\XLite\Model\Order $order null)
  804.     {
  805.         $this->order $order;
  806.     }
  807.     /**
  808.      * Get password hash algorithm
  809.      *
  810.      * @return string
  811.      */
  812.     public function getPasswordAlgo()
  813.     {
  814.         $parts explode(':'$this->getPassword(), 2);
  815.         return count($parts) === 'MD5' $parts[0];
  816.     }
  817.     /**
  818.      * Merge profile with another profile
  819.      *
  820.      * @param \XLite\Model\Profile $profile Profile
  821.      * @param integer              $flag    Peration flag OPTIONAL
  822.      *
  823.      * @return integer
  824.      */
  825.     public function mergeWithProfile(\XLite\Model\Profile $profile$flag self::MERGE_ALL)
  826.     {
  827.         $result 0;
  828.         // Addresses
  829.         if ($flag & static::MERGE_ADDRESSES) {
  830.             foreach ($profile->getAddresses() as $address) {
  831.                 $found false;
  832.                 foreach ($this->getAddresses() as $a) {
  833.                     if ($a->isEqualAddress($address)) {
  834.                         $found true;
  835.                         break;
  836.                     }
  837.                 }
  838.                 if (!$found) {
  839.                     $address $address->cloneEntity();
  840.                     $this->addAddresses($address);
  841.                     $address->setProfile($this);
  842.                 }
  843.             }
  844.             $result |= static::MERGE_ADDRESSES;
  845.         }
  846.         // Orders
  847.         if ($flag & static::MERGE_ORDERS) {
  848.             $cnd = new \XLite\Core\CommonCell();
  849.             $cnd->profile $profile;
  850.             foreach (\XLite\Core\Database::getRepo('XLite\Model\Order')->search($cnd) as $order) {
  851.                 $order->setOrigProfile($this);
  852.             }
  853.             $result |= static::MERGE_ORDERS;
  854.         }
  855.         return $result;
  856.     }
  857.     /**
  858.      * Prepare object for its creation in the database
  859.      *
  860.      * @return void
  861.      */
  862.     protected function prepareCreate()
  863.     {
  864.     }
  865.     /**
  866.      * Update field for search optimization
  867.      *
  868.      * @return void
  869.      */
  870.     public function updateSearchFakeField()
  871.     {
  872.         $searchFakeFieldParts = [];
  873.         foreach ($this->getAddresses() as $address) {
  874.             $searchFakeFieldParts[] = trim($address->getFirstname() . ' ' $address->getLastname() . ' ' $address->getFirstname());
  875.         }
  876.         $searchFakeFieldParts[] = $this->getLogin();
  877.         $this->setSearchFakeField(implode(';'$searchFakeFieldParts));
  878.     }
  879.     /**
  880.      * Returns address by its type (shipping or billing)
  881.      *
  882.      * @param string $atype Address type: b - billing, s - shipping OPTIONAL
  883.      *
  884.      * @return \XLite\Model\Address
  885.      */
  886.     protected function getAddressByType($atype \XLite\Model\Address::BILLING)
  887.     {
  888.         $result null;
  889.         foreach ($this->getAddresses() ?: [] as $address) {
  890.             if (
  891.                 ($atype === \XLite\Model\Address::BILLING && $address->getIsBilling())
  892.                 || ($atype === \XLite\Model\Address::SHIPPING && $address->getIsShipping())
  893.             ) {
  894.                 // Select address if its type is same as a requested type...
  895.                 $result $address;
  896.                 break;
  897.             }
  898.         }
  899.         return $result;
  900.     }
  901.     /**
  902.      * Add error top message 'Email already exists...'
  903.      *
  904.      * @return void
  905.      */
  906.     protected function addErrorEmailExists()
  907.     {
  908.         \XLite\Core\TopMessage::addError('This e-mail address is already in use by another user.');
  909.     }
  910.     // {{{ Roles
  911.     /**
  912.      * Check - specified permission is allowed or not
  913.      *
  914.      * @param string $code Permission code
  915.      *
  916.      * @return boolean
  917.      */
  918.     public function isPermissionAllowed($code)
  919.     {
  920.         $result false;
  921.         if (count($this->getRoles())) {
  922.             foreach ($this->getRoles() as $role) {
  923.                 if ($role->isPermissionAllowed($code)) {
  924.                     $result true;
  925.                     break;
  926.                 }
  927.             }
  928.         } elseif (\XLite\Core\Database::getRepo('XLite\Model\Role')->count() === 0) {
  929.             $result true;
  930.         }
  931.         return $result;
  932.     }
  933.     // }}}
  934.     /**
  935.      * Get profile_id
  936.      *
  937.      * @return integer
  938.      */
  939.     public function getProfileId(): ?int
  940.     {
  941.         return $this->profile_id;
  942.     }
  943.     public function setProfileId(int $profileId): static
  944.     {
  945.         $this->profile_id $profileId;
  946.         return $this;
  947.     }
  948.     /**
  949.      * Set login
  950.      *
  951.      * @param string $login
  952.      * @return Profile
  953.      */
  954.     public function setLogin($login)
  955.     {
  956.         $this->oldLogin $this->login;
  957.         $this->login $login;
  958.         return $this;
  959.     }
  960.     /**
  961.      * Get oldLogin
  962.      *
  963.      * @return string
  964.      */
  965.     public function getOldLogin()
  966.     {
  967.         return $this->oldLogin;
  968.     }
  969.     /**
  970.      * Get login
  971.      *
  972.      * @return string
  973.      */
  974.     public function getLogin(): string
  975.     {
  976.         return $this->login;
  977.     }
  978.     /**
  979.      * Set password
  980.      *
  981.      * @param string $password
  982.      * @return Profile
  983.      */
  984.     public function setPassword($password)
  985.     {
  986.         $this->password $password;
  987.         return $this;
  988.     }
  989.     /**
  990.      * Get password
  991.      *
  992.      * @return string
  993.      */
  994.     public function getPassword()
  995.     {
  996.         return $this->password;
  997.     }
  998.     /**
  999.      * Set password_hint
  1000.      *
  1001.      * @param string $passwordHint
  1002.      * @return Profile
  1003.      */
  1004.     public function setPasswordHint($passwordHint)
  1005.     {
  1006.         $this->password_hint $passwordHint;
  1007.         return $this;
  1008.     }
  1009.     /**
  1010.      * Get password_hint
  1011.      *
  1012.      * @return string
  1013.      */
  1014.     public function getPasswordHint()
  1015.     {
  1016.         return $this->password_hint;
  1017.     }
  1018.     /**
  1019.      * Set password_hint_answer
  1020.      *
  1021.      * @param string $passwordHintAnswer
  1022.      * @return Profile
  1023.      */
  1024.     public function setPasswordHintAnswer($passwordHintAnswer)
  1025.     {
  1026.         $this->password_hint_answer $passwordHintAnswer;
  1027.         return $this;
  1028.     }
  1029.     /**
  1030.      * Get password_hint_answer
  1031.      *
  1032.      * @return string
  1033.      */
  1034.     public function getPasswordHintAnswer()
  1035.     {
  1036.         return $this->password_hint_answer;
  1037.     }
  1038.     /**
  1039.      * Set passwordResetKey
  1040.      *
  1041.      * @param string $passwordResetKey
  1042.      * @return Profile
  1043.      */
  1044.     public function setPasswordResetKey($passwordResetKey)
  1045.     {
  1046.         $this->passwordResetKey $passwordResetKey;
  1047.         return $this;
  1048.     }
  1049.     /**
  1050.      * Get passwordResetKey
  1051.      *
  1052.      * @return string
  1053.      */
  1054.     public function getPasswordResetKey()
  1055.     {
  1056.         return $this->passwordResetKey;
  1057.     }
  1058.     /**
  1059.      * Set passwordResetKeyDate
  1060.      *
  1061.      * @param integer $passwordResetKeyDate
  1062.      * @return Profile
  1063.      */
  1064.     public function setPasswordResetKeyDate($passwordResetKeyDate)
  1065.     {
  1066.         $this->passwordResetKeyDate $passwordResetKeyDate;
  1067.         return $this;
  1068.     }
  1069.     /**
  1070.      * Get passwordResetKeyDate
  1071.      *
  1072.      * @return integer
  1073.      */
  1074.     public function getPasswordResetKeyDate()
  1075.     {
  1076.         return $this->passwordResetKeyDate;
  1077.     }
  1078.     /**
  1079.      * Set access_level
  1080.      *
  1081.      * @param integer $accessLevel
  1082.      * @return Profile
  1083.      */
  1084.     public function setAccessLevel($accessLevel)
  1085.     {
  1086.         $this->access_level $accessLevel;
  1087.         return $this;
  1088.     }
  1089.     /**
  1090.      * Get access_level
  1091.      *
  1092.      * @return integer
  1093.      */
  1094.     public function getAccessLevel()
  1095.     {
  1096.         return $this->access_level;
  1097.     }
  1098.     /**
  1099.      * Set added
  1100.      *
  1101.      * @param integer $added
  1102.      * @return Profile
  1103.      */
  1104.     public function setAdded($added)
  1105.     {
  1106.         $this->added $added;
  1107.         return $this;
  1108.     }
  1109.     /**
  1110.      * Get added
  1111.      *
  1112.      * @return integer
  1113.      */
  1114.     public function getAdded()
  1115.     {
  1116.         return $this->added;
  1117.     }
  1118.     /**
  1119.      * Set first_login
  1120.      *
  1121.      * @param integer $firstLogin
  1122.      * @return Profile
  1123.      */
  1124.     public function setFirstLogin($firstLogin)
  1125.     {
  1126.         $this->first_login $firstLogin;
  1127.         return $this;
  1128.     }
  1129.     /**
  1130.      * Get first_login
  1131.      *
  1132.      * @return integer
  1133.      */
  1134.     public function getFirstLogin()
  1135.     {
  1136.         return $this->first_login;
  1137.     }
  1138.     /**
  1139.      * Set last_login
  1140.      *
  1141.      * @param integer $lastLogin
  1142.      * @return Profile
  1143.      */
  1144.     public function setLastLogin($lastLogin)
  1145.     {
  1146.         $this->last_login $lastLogin;
  1147.         return $this;
  1148.     }
  1149.     /**
  1150.      * Get last_login
  1151.      *
  1152.      * @return integer
  1153.      */
  1154.     public function getLastLogin()
  1155.     {
  1156.         return $this->last_login;
  1157.     }
  1158.     /**
  1159.      * Set status
  1160.      *
  1161.      * @param string $status
  1162.      * @return Profile
  1163.      */
  1164.     public function setStatus($status)
  1165.     {
  1166.         $this->status $status;
  1167.         return $this;
  1168.     }
  1169.     /**
  1170.      * Get status
  1171.      *
  1172.      * @return string
  1173.      */
  1174.     public function getStatus()
  1175.     {
  1176.         return $this->status;
  1177.     }
  1178.     /**
  1179.      * Set statusComment
  1180.      *
  1181.      * @param string $statusComment
  1182.      * @return Profile
  1183.      */
  1184.     public function setStatusComment($statusComment)
  1185.     {
  1186.         $this->statusComment $statusComment;
  1187.         return $this;
  1188.     }
  1189.     /**
  1190.      * Get statusComment
  1191.      *
  1192.      * @return string
  1193.      */
  1194.     public function getStatusComment()
  1195.     {
  1196.         return $this->statusComment;
  1197.     }
  1198.     /**
  1199.      * Get referer
  1200.      *
  1201.      * @return string
  1202.      */
  1203.     public function getReferer()
  1204.     {
  1205.         return $this->referer;
  1206.     }
  1207.     /**
  1208.      * Set language
  1209.      *
  1210.      * @param string $language
  1211.      * @return Profile
  1212.      */
  1213.     public function setLanguage($language)
  1214.     {
  1215.         $this->language $language;
  1216.         return $this;
  1217.     }
  1218.     /**
  1219.      * Set last_shipping_id
  1220.      *
  1221.      * @param integer $lastShippingId
  1222.      * @return Profile
  1223.      */
  1224.     public function setLastShippingId($lastShippingId)
  1225.     {
  1226.         $this->last_shipping_id $lastShippingId;
  1227.         return $this;
  1228.     }
  1229.     /**
  1230.      * Get last_shipping_id
  1231.      *
  1232.      * @return integer
  1233.      */
  1234.     public function getLastShippingId()
  1235.     {
  1236.         return $this->last_shipping_id;
  1237.     }
  1238.     /**
  1239.      * Set last_payment_id
  1240.      *
  1241.      * @param integer $lastPaymentId
  1242.      * @return Profile
  1243.      */
  1244.     public function setLastPaymentId($lastPaymentId)
  1245.     {
  1246.         $this->last_payment_id $lastPaymentId;
  1247.         return $this;
  1248.     }
  1249.     /**
  1250.      * Get last_payment_id
  1251.      *
  1252.      * @return integer
  1253.      */
  1254.     public function getLastPaymentId()
  1255.     {
  1256.         return $this->last_payment_id;
  1257.     }
  1258.     /**
  1259.      * Set anonymous
  1260.      *
  1261.      * @param boolean $anonymous
  1262.      * @return Profile
  1263.      */
  1264.     public function setAnonymous($anonymous)
  1265.     {
  1266.         $this->anonymous $anonymous;
  1267.         return $this;
  1268.     }
  1269.     /**
  1270.      * Get anonymous
  1271.      *
  1272.      * @return boolean
  1273.      */
  1274.     public function getAnonymous()
  1275.     {
  1276.         return $this->anonymous;
  1277.     }
  1278.     /**
  1279.      * Set forceChangePassword
  1280.      *
  1281.      * @param boolean $forceChangePassword
  1282.      * @return Profile
  1283.      */
  1284.     public function setForceChangePassword($forceChangePassword)
  1285.     {
  1286.         $this->forceChangePassword $forceChangePassword;
  1287.         return $this;
  1288.     }
  1289.     /**
  1290.      * Get forceChangePassword
  1291.      *
  1292.      * @return boolean
  1293.      */
  1294.     public function getForceChangePassword()
  1295.     {
  1296.         return $this->forceChangePassword;
  1297.     }
  1298.     /**
  1299.      * Set dateOfLoginAttempt
  1300.      *
  1301.      * @param integer $dateOfLoginAttempt
  1302.      * @return Profile
  1303.      */
  1304.     public function setDateOfLoginAttempt($dateOfLoginAttempt)
  1305.     {
  1306.         $this->dateOfLoginAttempt $dateOfLoginAttempt;
  1307.         return $this;
  1308.     }
  1309.     /**
  1310.      * Get dateOfLoginAttempt
  1311.      *
  1312.      * @return integer
  1313.      */
  1314.     public function getDateOfLoginAttempt()
  1315.     {
  1316.         return $this->dateOfLoginAttempt;
  1317.     }
  1318.     /**
  1319.      * Set countOfLoginAttempts
  1320.      *
  1321.      * @param integer $countOfLoginAttempts
  1322.      * @return Profile
  1323.      */
  1324.     public function setCountOfLoginAttempts($countOfLoginAttempts)
  1325.     {
  1326.         $this->countOfLoginAttempts $countOfLoginAttempts;
  1327.         return $this;
  1328.     }
  1329.     /**
  1330.      * Get countOfLoginAttempts
  1331.      *
  1332.      * @return integer
  1333.      */
  1334.     public function getCountOfLoginAttempts()
  1335.     {
  1336.         return $this->countOfLoginAttempts;
  1337.     }
  1338.     /**
  1339.      * Set searchFakeField
  1340.      *
  1341.      * @param string $searchFakeField
  1342.      * @return Profile
  1343.      */
  1344.     public function setSearchFakeField($searchFakeField)
  1345.     {
  1346.         $this->searchFakeField $searchFakeField;
  1347.         return $this;
  1348.     }
  1349.     /**
  1350.      * Get searchFakeField
  1351.      *
  1352.      * @return string
  1353.      */
  1354.     public function getSearchFakeField()
  1355.     {
  1356.         return $this->searchFakeField;
  1357.     }
  1358.     /**
  1359.      * Set xcPendingExport
  1360.      *
  1361.      * @param boolean $xcPendingExport
  1362.      * @return Profile
  1363.      */
  1364.     public function setXcPendingExport($xcPendingExport)
  1365.     {
  1366.         $this->xcPendingExport $xcPendingExport;
  1367.         return $this;
  1368.     }
  1369.     /**
  1370.      * Get xcPendingExport
  1371.      *
  1372.      * @return boolean
  1373.      */
  1374.     public function getXcPendingExport()
  1375.     {
  1376.         return $this->xcPendingExport;
  1377.     }
  1378.     /**
  1379.      * Get order
  1380.      *
  1381.      * @return \XLite\Model\Order
  1382.      */
  1383.     public function getOrder()
  1384.     {
  1385.         return $this->order;
  1386.     }
  1387.     /**
  1388.      * Add event
  1389.      *
  1390.      * @param \XLite\Model\OrderHistoryEvents $event
  1391.      * @return Profile
  1392.      */
  1393.     public function addEvent(\XLite\Model\OrderHistoryEvents $event)
  1394.     {
  1395.         $this->event[] = $event;
  1396.         return $this;
  1397.     }
  1398.     /**
  1399.      * Get event
  1400.      *
  1401.      * @return \Doctrine\Common\Collections\Collection
  1402.      */
  1403.     public function getEvent()
  1404.     {
  1405.         return $this->event;
  1406.     }
  1407.     /**
  1408.      * Get membership
  1409.      *
  1410.      * @return \XLite\Model\Membership
  1411.      */
  1412.     public function getMembership()
  1413.     {
  1414.         return $this->membership;
  1415.     }
  1416.     /**
  1417.      * Get pending_membership
  1418.      *
  1419.      * @return \XLite\Model\Membership
  1420.      */
  1421.     public function getPendingMembership()
  1422.     {
  1423.         return $this->pending_membership;
  1424.     }
  1425.     /**
  1426.      * Add addresses
  1427.      *
  1428.      * @param \XLite\Model\Address $addresses
  1429.      * @return Profile
  1430.      */
  1431.     public function addAddresses(\XLite\Model\Address $addresses)
  1432.     {
  1433.         $this->addresses[] = $addresses;
  1434.         return $this;
  1435.     }
  1436.     /**
  1437.      * Get addresses
  1438.      *
  1439.      * @return \Doctrine\Common\Collections\Collection
  1440.      */
  1441.     public function getAddresses()
  1442.     {
  1443.         return $this->addresses;
  1444.     }
  1445.     /**
  1446.      * Add roles
  1447.      *
  1448.      * @param \XLite\Model\Role $roles
  1449.      * @return Profile
  1450.      */
  1451.     public function addRoles(\XLite\Model\Role $roles)
  1452.     {
  1453.         $this->roles[] = $roles;
  1454.         return $this;
  1455.     }
  1456.     /**
  1457.      * Get roles
  1458.      *
  1459.      * @return \Doctrine\Common\Collections\Collection
  1460.      */
  1461.     public function getRoles()
  1462.     {
  1463.         return $this->roles;
  1464.     }
  1465.     /**
  1466.      * @return string
  1467.      */
  1468.     public function getEmail()
  1469.     {
  1470.         return $this->getLastCheckoutEmail()
  1471.             ?: $this->getLogin();
  1472.     }
  1473.     /**
  1474.      * @return string
  1475.      */
  1476.     public function getLastCheckoutEmail()
  1477.     {
  1478.         return $this->lastCheckoutEmail;
  1479.     }
  1480.     /**
  1481.      * @param string $lastCheckoutEmail
  1482.      *
  1483.      * @return $this
  1484.      */
  1485.     public function setLastCheckoutEmail($lastCheckoutEmail)
  1486.     {
  1487.         $this->lastCheckoutEmail $lastCheckoutEmail;
  1488.         return $this;
  1489.     }
  1490.     /**
  1491.      * @return string
  1492.      */
  1493.     public function getSalt(): string
  1494.     {
  1495.         return implode('', [$this->login$this->password]);
  1496.     }
  1497. }