�PNG  IHDR����Q�gAMA�� �a cHRMz&�����u0�`:�p��Q<�bKGD�������gmIDATx���w�U���ﹻ�& �^C��X(�����J I@� ���"% (** B�X� �+*�i��"]j(IH�{~�R)��[��~��>h��{�}g�y�)I�$I��j��� ������.I�$I�$�ʊ�y@�}x�.�: �$I�$I��i}��V�Z�����PC)I�$I��F� ����^��0ʐJ�$I�$�Q^���}{�"���r�=��OzI��$gR�ZeC.�IO����vH eK��X� �����$IM�px��sk�.��쒷/��&���r�[޳����<���v|�� ��.I���~�)@������$�up��dY�R�����a�$I �|�M�.�e ��Jaֶ�pS�Y�R��6j��>h�%IR��ز�� �i�f&���u�J)������M�����$I vL���i���=�H;�7UJ�,�]�,X��$I��1��AҒ�J����$ X�Y� XzI��@G����N��ҥR���T)E��@��;��]K*�M�w;#�5_�wO�n~\ DC&�$(A�5 �R�R��FkvIR���}�l��!�RytRl;��~^Ƿ�Jj� �اy�뷦BZ��Jr����&ӥ�8�P�j��w~�vn�����v ���X���^�(I;�4�R=�P[�3]J�,�]ȏ�~��:�3�?��[��� ��a��&e)`�e*����P[�4]�T��=Cq�6�R[ ~ޤ����r�XR Հg(�t�_HZ�-Hg �M�$�ãm�L5�R� �u��k�*`%C-�E6/����%[�t X.{��8�P9Z�������.vk����XŐKj����gKZ��Hg�(����aK9ڦ��mKj��Ѻm�_ \�#�$5�,)- � �61eJ�,��5m|� ��r�'��=��� ��&ڡd���%-]J �on�� X���m|�{ ��R�Ҟ����e $eڧY X��Y�����rԮ-a�7�RK�6h���>n$5A�V�ڴ�i��*�ֆ�K)���mѦ���tm�r�1p| �q:흺,)O�����i��*�ֺ�K)���ܬ�֦����K-5�r�3�>0ԔHj��Jئ�EZ��j�,%��r�e��~�/��z��%j�V��M��ڸ�mr��t)��3]J�,���T ��K֦O�vԒg��i�i��*�����bK�i�NO~�%�P��W���0=�d��i�i�������2�t�J9��J����ݕ�{�7�"I P��9�JK�Tb�u,%��r���"�6�RKU��}�Ij�2����HK�Z�XJ�,妝�� X��Y�����rP��� ެ�2�4�c��%i��^���IK|.H�,%��r�b���:XR�l��1X��4Pe/`����x��&����P��8�Pj��28��M��z���s��x���2���r�\���zR��P�z�4J����}�y���P[g=�L)��� .Q[�6Rj�Wgp ��FI�H�*-`I�����M�RaK9T��X��c�q�����*I� y���[j��E>cw%��gL�R���ԕi�F�Cj�-��ď�a`������#e~���I�� j�,%��r�,)?[gp �FI˨���mn��WX#��>mʔ X�A��� �DZf9,�nKҲz�����I��Z�XJ�,�L#��k�i��P�z�4JZF�����,�I,`���61%�2s �$���,�VO��Ϛ2��/U��FJ�fy��7����K�> X�+�6� S�TX����Ie�����JI���Lz�M�fKm ��L�RaK9�%|��4p9L�w�JI��!`N����sia���zĔ)������%-� X��M���q�>�pk�$-$�Q���2����x#�N� ؎�-�QR��}ᶦHZ�ډ��)�J�,�l#��i@y�n3������L��N`���;�nڔ X�����u����X5��p��F)��m|��^�0(��>B�H���F9(c�զE��er��JI rg��7 ��4I@z�0\�JI��������i�䵙���RR��0�s;�$�s6eJ�,�`n �䂦���0�a�)S)�A������ ���1eJ�,堌#�6�35R��I�gpN��Hu������TH���_S���ԕqV�����e `� ��&S)���>�p;S$魁eKI����uX��`I�����4��춒�o}`m�$1"��:�PI���<[�v9�^�\p��TJj�r�iRŭ ��P{#�{R2,`)e-`mgj�~�1�ϣ�L��Kam�7�&U\j�/�3mJ�,�`F��;M��'�䱀�� .KR#��)y�h�Tq�;p���cK9(���q!w�?����u�RR,n.yw�*UXj#�\�]ɱ���(q�v2=R���q����f����B#i��Jm�m�L����<]�Y����͙�#�$5� ��u�TU�7��Ӧ�X�R+q�,`I}����qL�����'���`��6�K�ͷ�6���r�,�]����0S$-���� ��[RKR3���o��iRE����|�nӦ�X�R.�(i�:�L��D�L��TJj�Y��%o�:����)�����6���r�x���zҒ��q��TJj��h㞦I���.�$Y�R.ʼ�n�GZ�\ֿ��f:%5�5 ��I�˼!�6����dK�x��m��4E�"mG�_�� �s? �.e*��?L�RfK9��%�����q�#�uh$�)�i���3U�����L�RfK9yx��m܌b�j�����8��4���$�i��1U��^@Wbm��4uJ�,�����Ҫ�A�>���_Ij�?1�v�3�2����[�gL�R��D��9�6�o�Ta�R���׿��N7%�����L�2�� NT�,`)7�&�Ɲ��L�*꽙��yp���_$���M�2�#�A�����S�,`)7�$r��k�TA���29�_���Iy�e"�|/0�t)�$�n X�T2���`Y���J���;�6��J�x"�����.e�<�`�����$)� P�I$��5�V4]���29���SRI>�~�=@j�]��l�p�2`K9Jaai�^" Ԋ��29�O�RI%��:X�V5]J��m��N9���]�H;1U���C39���NI%���Xe78�t)a��;���O��i Ҙ�>X�t�"~G>�_mn:%���|~ޅ_�+]�$�o���)�@��ǀ{hgN;�IK�6�G&�rp�)�T2�i�୦K�Ju���v*���T��=�T��O�SV�>(��~D�>d�����m�,I*��Ɛ�:���R�#��ۙNI%��D>G��.n��$�o��;�+#��R�R��!��.e�U��˽���TRI�2��8�t)1L��WϚ>IJ�a3�oF��b��u&���:�tJ*��(F7��y�0�Z�R ^�p���'Ii� ����L�24x�| X��RI%�ۄ>S1]J�y��[z��L�$�adB7��.eh4��%���%�누>W�E���Tf+3�����IR:�I�3Xה)3אO�ۦSR�O'�ٺ�)S�}"��q�O��r[B7�ϙ.edG�)^E���TR"R��t��R�ݜh���0}������<�S����ɧx�.6,)�&���)SI�p��j�'I��?���A�L�"���L����.\TZV�N���!�'I�Y.��pAS����5}� �TRbNL�3��”�d�����b�e��)��4]��Mg/S���Z{ni����,)=k����Д�d��p��ǦO��uLb7�ߛ2%lO�}u�)���K��]le�T�P��j�eS(I�Z���ִ��R�^eJ%%*�/\ Ke�̈́�-O�M�$����|.5eJ��o�s)^]oJ%%,�㚃R� <�p��LS��� �*����`GӦ�tdt<�5���o'��/�6�٧�� _��BIJ�kH��_�6%d ���rQ�b�gZ%%n�ڍ9o1mj�U�g���JR>�L�F�VӦD�B^k_���J�Dj��\����=�L���S(I������v─a���T�eZ%e�U����A�M-�0;�~˃@�i��|l�� �@S���4y���7��2��>���sX-vA�}�ϛBI���!ݎߨ����W�l�*)3{'�Y|�iS�lEڻ(��5�����K��t��SI�$��Uv0��2���,~��ԩ~�x��;�P��4��ց��C�r�O%ty�n4��25:���KM��l�D� ^���4JR������xS��ه�F_}شJ�T�S��6uj�+ﷸk�$e���Z�O%�G�*^�V2�����u3E�Mj�3��k%)ok��I]d�T����)�UR�K���DS� �7�~�m@�TJR�~�荪�f�T"�֛L�� �\���s��M��� �-0��T �K�f�J��z+��n�إK�r� �L�����&j��(��)�[�E&I����� ߴ>e �FW�_�kJR�|!���O�:5�/2跌3��T-�'|�zX�� r�yp0��J����S ~^�F�>-�2�< �`*%�ZFP�)����bS��n"���L�� :)���+pʷf(pO���3��TMW$~����>@~ū:����TA�IsV�1}�S2�<���%��ޟ�M�?@�iT ,E�ū�oz%i�~��g�|`wS(�]�oȤ��8��)�$�� �� ntu`өe�`6y�Pl� Iz�MI{�ʣ�z����ʨ�� �)IZ�2��= ld:5+���請M�$-ї���;�U�>_���g��sY��$Á����N�5��W���z�W�fIZ��)�-��y�u�XI�fp���~S*IZ��dt�;�t�>K�ū��KR�|$���#Lc�Ԁ+2�\�;kJ��`]�Y���ǔ��M1B)��U�bG"IRߊ���<x����ܾ��ӔJ�������0�Z����=��'�Y��嵤����� Le�v�e�g��)�$��z���n����V-º����^�3Ւ�o�f��#0�Tfk�^�Z�s[�*I꯳3{���)�ˬ����W�4Ւ4 �Odp��bZ��R���S��|�*I� �����5��5�#��"�&�-IvT&��/��윚Ye:��i�$ �9��{�Lk�u�R���e�[��I~�_�\��ؠ%�>�GL�$iY�8 �9ܕ��"�S���`kS.I�l���C;Ҏ4���x&�>�u_0J��Lr����<��J�2�(^��$5��L� s�=Mg�V� �~�,Ij�u��>�� 7��r2�)^=G���$�1:��3�G< �`J�3�~�&IR%�� 6���T�x�/�rIj���3�O< �ʔ&#f�_yX��J�i�ގN��Sz;�� T�x�(��i���8%���#���4 �~�AS+Ij��e���r�I�U�rIj�����3�62��v8��8�5�+Ij�A�h�K__5���X��%�n�V%Iͳ-y��|7��XV��2��v4���fzo��_6��8���"�S/I-qbf��;� Lk��F�)K���SM�$���� Ms�>K� W�N���V����}�^`��-�큧3����2Œ�Vؙ�G��d��u�,^�^m�%��6���~��N�n�&�͓��3Œ�V�Z����MsRpfE�W���%I�wd���ǀ�Lm[��7���W&�bIR��L�@Q�|�)*�� ����i ImsI�����MmKm�y��V`�i�$��G+R� 0�t�V'����!���V�)֏���28����v���U�7͒�v���H����ꦼt���x�ꗞ�T ;S���}��7�M�f���+��fIR���H��N��ZUk�U�x5��SA�Jㄌ�9��Mq��μ���AIRi|�j�5��)o����*^���'<$�T����w���I�1��hE�U�^c�_�j�?���Е$%d`z� �c�y�f��,X���O IJ�nTg����A�� �����U�XRD��������� ���}�������{�H�}��^�S,P5��V��2���\����Xx`p�Z����|Y�k:����$e�� ��~ ��@nW�L�.j�+��ϝ���Y��b퇪��bZ� �BV�u�)�u�������/IJ_ �1�[�p.p60�bC�� >|X����9�1P�:��N\�!�5�qUB}5�a5ja `ub��c�VxYt1N�0�Z����z���l4����]7­gKj�]�?�4ϻ� ���*���[��b��g$)+À���*x쳀ogO$~,5� �ز���U��S�����9���� lq3�+5�mgw@��n�p1��sso Ӻ=����|�N6 /�g(�Wv7U��;��zωM=��wk�,0���u��T��g�_��`_�P`�uz?�2�yI��!b��`�k���ĸSo��+Q���x%!\��ο����e����|�އ���ԁK��S-s6��pu���_����(ֿ�$�i+��+�T8=�e�Y;��� �צ��P�+p��h�x��WQ���v���*���|p1��. ��ά. XRk�IQ�Y�P,���d�r�Z�� |����� ��������B�%������w��P|�S5`��~́@�i�޾��� E�;��Չaw{o'�Q��?%�iL{u D��?���������N1��B��D������!�o��w�����PHRe��FZ�*�� ���k�_-~����{����E9�b-��~P�`��f��E{AܶB�J�A�FO��� wx6��R�ox�5 K5����=�W����we�������hS8 (��J���C���l�J���~ p+���F���i�;ŗo+��:�bD�#g(��C��"�wA^�� r.�F�8L;�dzd�IH�U�X��݆�Ϟ�X�g� �)I�F����q��e�m��%I�4�d�j&pp�T�{���'{�HO���x�( Rk���6^C�٫����O.�)�3�:s(��۳(Z�?~ٻ8�9�zmT"�PL�tw䥈��5��&b<8GZ-�Y��&�K�?e8,`I��6���e�����(֍x�b8�3 � `���r�����zX�j��)F�=l($I�j� �2*�(F�?h(/9ik:��I`m#�p3�Mg���L�aKj�c�/U��#�n5����S�# �������m(^)=y=đ�x8Ŭ����I���[U]����~S�цA�4�p���$-F �i(��R�,�7C�x�;X��=�c����I��>���{���Km�\ �o(T��v�2������v�x�2q�i����iDJ�N�,���Ҏ����!1f� �5quB�j��1��!�8 �r���D�Fd(���!���W���Ql��,g�S��k����L��1Bx��g'�'�՞�^���ǘ;�p����Q ���P(c���_ IRu����j�g(�W�z ����b�s�#�P�­rz�>���� k�� c&nB=�q+��ؔX���n#r5����)co���*Ũ�+G��?7��<�� |�P�����Q��ӣ'�G�����`uO�d>%M�ct�z�#�� Ԫ�����ڞ�&�7��CaQ��~N�'��-P�.�W`Oedp0�3C!IZc�I�AMP��U�ۀ5�J�<��\u~+�{�9�(Fb�b���y�A�e�B����hOS���ܳ�1� b��È���T�#��ŠyDžs�����,`5�}��D���C�-�`��̞%r&�ڙa��8�7Q����W����W����p6e7� ��Rϫ/�o����Y� ꇅ N��ܶ�ը��tc��!��L���A ���T�7�V4�J�sū� I-�0����P��x�z7�QN�F���_�i����Z�g�úW�k�G���83� ���0e�Wr9 X����]㾮݁#���Jˢ C�}0��=3�ݱ��tB��i�]�_ ��&�{�{[/�o[�~ \q�鯜�0��0��٩���|��cD��3�=4��B_b� ���RY��b$ó�BR���sf�&������l�L�X#M*��C����_�L܄:gx�)WΘs���GSb���u��L ���rF$9�'�;\4�Ɍ�q�'�n�[%p.�Q`�������u ��h���N�b`eCQyQ|���l�_���C>L���b꟟3h��Sb�� �#��x��N��xS���������s^�� 88�|�Mz�)��}:�](vbۢ�amŖ࿥� ��0)Q����7���@�0���=?^k(*�J�����}�3ib�kF�n H�jB׻���NO���� �z�� �x}�7p 0�t��f����D����X�.lw��gȔ��h�Ծ�Ų� }6�g� E� |�Lk��LZ���t��eu+=���q���\I�v0쮑�)��Q�ٵpH8�/2?Σ�o�>�J�vpp��h�������o~�f>%bM��M���}���\�//��":�PT��c(v���9v���!��g�ո��Q ��)��U�fV��G��+!� ��35{=�x\�2�+��k�i,y$���~A1��iC�6#)v��C�5�^>�+gǵ�@1�Hy٪7����u;p ps�ϰ�u���/S�� <��aʸ����Gu't�D1�ԝI��<��p��g|����6�j��'p:�tպ�h��X�{�o(7v],��*�}��6�a_����<�u`��Ȯ�r.E�;ˑ�q�io�p�R��"������26�2E�8j�� ]����U��鿍ǜ�v���D��,2���վ�8ϫ�:�e/^AQ����T�H{�WgRl���̊���2Yx���"1�Q�> �wX�Rk,O�]�Lܳ���~V<�����F���8��a��_g~�o.�XCD�?S�t���h���梫A�o�%���~K1ݵ��O1�LyZ�bJ�� E��Q���xpq�i�Cpv��a6��_�:�wejT����]����"����<��u`"���� 2>���o4��5rp"N5k��;�m���{���rZ�b������Φ${#)��`(��Ŵ�g�,;j���%�6�j���.�pyYT��?}-��kB������D���c3q����A`��N��WQ���ū2�0�/^A��Z�W%�N�Q��� ��MI�.��X#P��#����,^Eb�c&��?X�R tA�V�|Y���.�1����!�����؅�⨉ccww���>���i��v��l(J��T�~� �u`��ٵDm �q)���+���Ri�� x/�x��8cyFO�!�/���*�!/��&��,7�<.���N���,�������YDŽ�&ܑ�Q�F1�Bz��)F���P�ʛ�?5����d� �6`�����kQձ �λc�؎�%58�2��Y��&nD�_$Je4��>a��?��!� ��ͨ�|�Ȏ�WZ��S�s��v���8� �j����(�I��&��y�j� �Jb5��m��?��H������Wp��=����g}�G��3��#�|I��,5v珿�] H~�R3�@B��������[☉9Ox~��oMy�=J���;�xUVoj�� �b�U�s�l_��35�t-�(Ճɼ�RB7�U!�q��c��+�x�4�H�_�Q�o֮$[���GO<��4`��&č�\GO�c[�.[*�A�f%m��G/� ň�M�/�r ��W�/Nw~B1U3������J�?��P&���Y�� �)`�ѓ����Z�����1���p]�^l“��W#)lWZ�i����l�U�Q�u`��-����m|xĐ,������_�ƪ|9i:�_��{*(3G�ѧ}�Uo�D+�>m_�?V��Pۅ�15���&}2�|���/p�IOʵ�>���� G�Z9�cmíت�mnz��)yߐb���D�������� �>e}:�)� �r|@�R5q�V�S�����A�10�C%�E�_��'^�8c��������R��7O;�6�[���eKeP�������G������ϦX7�j���b}��OT�GO^j��n*媓����7n����GMC�� � ���t,�k31�R�b �(v�yܴ�ʭ�!��iTh8~�ZY�Z�p��(q��s���RL ?�b���}����c�Ũ�ʊGO^���!��rP�JO��1��5�MJ[��c&~������Z`"��ѓޔ����H1���C&����^|��Ш|�rʼ,�A�wĴ?�����b��5)�t��L��U��)F�|�� �&��g٣O]���oqSU����j���y(��x<��Ϳ3 ���.���FS�k���oYg�2� \_#w��j�{u'r�Q������>���o���;���%n�|�F�*�O�_��L�"�e�9um��Dds�����?.��fu�u����Qb��IW�z |4\0� s�b;�O�v��xOS�s�; G%����T4g��FR�u�rj���(֍ڑb �u�ԖK�D���u��1MK{���1^ q;�� �C=�6\8��F��R��艇�!���%\Y�Ô�U| �88�m��)֓��Nc��L�ve�� C�6z;��o&�X x5�9�:q���6�1�Z��(T����7���>C?�g�c�ļ�x�ѐ�� Z� ���o�o-�0�8j�ہ �x�,�`���'��� ��Ҕ���Oc��Rl��f��~���`�����jj�"�.N�v+���sM������_��]������Z�k��� �g( UOP���������y�εx%�pU����h�2�������(���@��il0���ݽ��QXxp�px-�N�S��( W�O+�轾 n��Fߢ����3M��<;z�)��FBZ�j����c�i��u�/�Q�oF�� �7R�¥ Z��F�L�F�~��#����ȣ��ߨ^<쩡�ݛк���v�џ)��)���M��E>ώ�x4�m#!-�m���!L;vv#~Y[��đ��K�����m����x�9.[,��U����FS �����C���VkZ ���+���ߟ�r�Y٧��IZd/�io�i$�%��͝ب_ֶX�3���ܫ��hNU �� Z����Z�g�k�=���]��=������b���b��JS[�w��j�U(��)���*I =ώ:}-蹞�l�Uj�:��1��}����M�W��m�=̛���� _�� ¾,8��{__�����m{_�P��V���K^n3�e����sw5�ӫh�#�$-�q=�A̟> ,^I}P�^�J$�qY~Q[ Xq���9�<�r�d�sߏǜs�#������%/���y����kKZ�������b��?� S�k�tc�񫝶L���&I ���W!�b �>{#�&�T.^����G��Vj�_���_R��K�p����n,b=`�ż����Y@�^՝��;z�{p�aV��Kk����QXj�/�)y� ��TI�c&F�;FB�G�7w����g� ZZD�G��!����x�� �r_�t��Ƣ!�}�i�/�V��=M����/��#��n��B8 Xx�Ы ^�@�CR�<{䤭����Y��CN��)�e���K��OSƟa $��&�g[i3�.C�6x�rOc���8�TI���;�o�� ��hH6�P�&L{�@�q��6�[���� �G��zp�^���71�j��(�l�`�J�}]���e6�X����☉#͕� ���׈$A�B1�Vj��h㭦IRs��qFBj�w�Q_7�Xk��>y"������N=�M�B0� ��,�C #�o6MR��c���0��|�$�)�ف����"1����!i���xY<���B��9mx�� ��`���,��t�A�>)5ػ�Q���?j��Q�?�cn�>Y�Z�e�� �Tis���v���h�#�� �GMމȇ���p�:���ԴVuږ�8ɼH��]C.���5C!UV;F`m�b��Bk��� ��L�TM�vP���ʍϤj�?��ԯ/Q�r1���N�B`9s"����s�� �TYs����z��� ��&�9S%U԰�> �{��<�ؿ���SM���xB��|H�\3�@!U�|�� �k']������$U�+>��� |�HHM����Lޢ�?��V9i�D!-�@��x�� �TI���î�%�6Z��*��9X�@HMW#�?��n�N� ,o�e6�?tQw��ڱ�.�]-����y����'�:mW�0#!�J82qF�jH -`�ѓ�&��M��0����u� Uγmxϵ��^-��_�\�]����)@0R���t.8�/?ٰ�C��Y]�x���}=sD3�o��j�ަ���Ы�N���uS%U��}Ԥw��HH�>ڗ�jܷ_3gN �����q7�[q���2�l���a���*����A�r���Ǔ��Ԗ+p�8���/��R��GM�� ]j�a����c�d(�JhWko�6��ڎb�j�]i���5���Bj�����3+�3�!\j��1�����U�Z���L��s��L�T�v8�HHmup<��U���\��GMމ�3�R+��w4R�����6�j� XW�M�T!��u(�*!��Pz�,����#���Sq���*�8?vww )kO���a��$�[&��?�*�bB�X� �@���%�����8�]�=���R�r)kO��w�0j��i��M�Tq�� ng$�2\�q�8f�:���e�N1�R�xr<��5 ������;��M��p^�@;��7]R��ꎾ�JtER�.�/(5�v3�R[�@=�h�l����?����l�@;���.���[]�Q*�Z\�4��"1P�'Y��w��x��# ���ǀg���{��5�i��_IUR���z�RɞsyS5q�E����=�@�Y���っ �����v�k��6 ��&��5�1E�o0�|�kp�c��#�j=`�D���WRU�����j̟���J'P� �����w2 �S� �v�:��p�g�3Rv�},�#�����8�b��Z~�&��(F�=�i�><�>gK�M���Jj����0�@H%��,����W�΃�7�R) "�>c�,����� x�ix������ј���^ ��aܖ>�H[�i.UI�Hc �U�1=y�W\���=��S*���G���R~�)AF���=�`�&�����2��h`�D�z���T��󑓶�����J+����?�W+}��C�%��P:|�0H���܆��}-�<;O����C[�~o.��$~��i�}��~�HQ�� �Tv�X������Έ�r=b}$��v����i�z�L��4�:�ȰT|4�~����*��!o�X�QR6��L�k+�#������t/g �lԁߖ����[��Jڶ_N$�k���������*"�.� ���x���s��xX���7jRVbA��A�ʯKҎ��U3����)�zS�NN �_�'��s�?f����)��6������X���!%s�s�A���kʱ>���qƷ�b ��h�g� %n���� �~p�1RE��GM���HH�=�������B�Jiy[<�5 ���ǁJҖ�����g�K���R��*�倳��e��~�HUy��)A���g,K)`�V�w6bRR:��q����L#\�r���cl��K��/�$�s�h�*$�� ������6�����덤�� ����KԖc� 3��Z�9��=�Ɣ�=o>�X � �Ώ�"1�� )a��`�S��JJ�6�k<��U�������-]�� b�m`��{r�y;����T���u��_GR5���*�%6�do�#XRg#���-!nl��$u�3��A�� L+Q{��9�x~�a-�|�H� �vbq[\�NJT%�]���rO8,��E�-F�����w)+?(Y{�Lz�n6����׀��?C������R�~�,)m�䎧�R�7���cww����qpW�ڳ=i.��U`Xf�F�b=�V��LJ��H^LI}��%�} ��|��w���� aG�$�,��^�R^�6 k2�^B�{7��t�������V�%@G�q� p�%R�zģN_ ��HHI[7�ֱ�>(��<�c e�{%kϊ����P�+��SL'�T�cM���J����WR���m ���ŏ�"�w)qc e�f�꒵i?��b7�b����(�'�"��2r%��������~�HUS�1���\<��(`�1�W����x��9�=�8HY9��m:X��1�8�b��g�����D1��u ���~|H��;K��-��U�ep�,,� C�1 RV.���M�R�5�άh����,�t��W�O8W���C�$ XRV�sQS]3G�J|�1��2����� [�v�M� ������:��k�#����~tH�3�0Rf-�����HYݺ-`I�9�%l�I��D�T�m\ ����S�{]��9�gO���ڒ�M���NCV\��G��*����2���J�R�Ũ;�R��ҏ^���ڽ�̱�mq�1E�u?�To�3I���)��y^��#�j�J�w���^�Ń�j��^�v����vl����B_��⋌�P�4x>0$�c>���K†A�ļ9s_V���jT��t0l�#������m��>E��-�,�,�x�,��-�W��)������سo&�9�6�R�E XR.6b���Xw�+)G���A�����E�v�L�)�͞K4�$p=�Ũ��i_ѱ�O�j��b�� HY����/���+@�θH9޼]�N�ԥ��%n�{����� �&zjT�?�� �Ty) s^�U��L�����lb�,�P�iTf�^���<À�]������� ��62R^V��7)S!nl�l��S�6~�͝�V�}�-=%*� ʻ>���G�� ���������D��nK��<��y��&>L����Py7'r=Hj���� ���9��V`[c"�*��^�8H��pc�����O�8�b�nU�`4���J��ȪA�Ƌ#��1_\ XϘH��PR���gi�k(�~G�~��0��D���A���A����_2�p�|�J�묭a����2���\N�C�r�]����M���_0 �^T��%e#����vD��^��%��x��y-n���}�-E�\�3�aS%�yN!�r_��{ �)s���A��w ���ڼp1pEAk�~v�<�:`'ӭ^�5 �����A�r���X�������OI驻��T �(��dk�)�_�\<��w���^��W�I��"�RFj3��V# ���M<,o�J��.H��#�\�SK���s]���� )��9> P��u�������A�*�B�Y�]����y�B�"�l�\�ey��� ��hH���*t��b�K)3��� IK�Z��򹞋X�jN�� �n� �*n>k�]��X�_��d�!�ry��BH� � ]��*R�� ��0(#'�7 ������%es9??��ښFC��,ՁQP��������j�����AR��J�\Ρw� �K��#��j���ah�g�w�;�2$�l*�)� ��%���Xq5�!U᢯�6Re] |�0����[�_�����_64�c�h�&�_}��i�L8K��Eg�Ҏ�7 M��/�\`|.p,�~`�a���=�BR?x�ܐrQ���8K� XR���2M�8�f ?�`s�gW�S%�"� ������Ԉ 7R%���$� N������}��?QL1|-э�ټwI�Z��%���pv�L���3Hk>,I����m�g�W���7{��E�� x�PHx�7�3R�����A�� ���@R�S�� CC���� �������!\ȟ���5I��XR^Z���xHл�$Q[��ŝ�40 (�>�+� �_C ���>���BR�t��<,T�r�T �������{���O�����/�H��+˟Pl6 I ���B)/�V���C��<6���a��2����~�����(�XwV4�g�n���XR� ϱ5�ǀHٻ?tw�똤Eyxp���{�#���WK��� �q����G%5���]�,���(�0ӈH����� HZ���])ג=K1j��&��G(FbM�@����)%�I` XR�����g ʔ�� KZ�G(v��P,�<`�[� K���n^ ��SJR���sAʠ�5xՅF`�0&R�b�V� ��t��x�:Ea�UE�/{�f��i�2;.I����A��wW8��/��t�T�x�A��GOo��N�?�G���}�l L�(���n�����`�Zv?���p�B��8K�_g�����I�+ܗ � #��i��?���ޙ�.��) p����$�u�tc �~DžfՈE�o3��l/)I-U�?a�ԅ�^��j�x�A�r����A�� ΧX��������}�DmZ@QLےbTXGd�.^|x�KHR{���|Ε�W_h]�� ���I��J`[�G9�{��)�.y�)�� ��<���D�*��zk�(ּ���Ya����O���8S����?��2-��� ������H13����#pK"���I`]`O� ��h�&=�S���F1Z�/Ie����D1R�W�a�"t'�x?!)Ou:��1 ��|��6��gt\s�����7�=�z_;�ؠ��>�0X Y��A1]q�p?�p�_���k+J*��Y�@HI>�^��?�g�t.06R�n ��,��`�� ��?)�;p pSF9����Z����X���L�����BJP�W���j���gQ|�&)7!�� Hj��Q��t���<| ؅��W�5 x �W��� �� HIz�Y���oV���M�G�P��� Hj��n`+�\�(d��N���W)F+I�rS�[���|��/a�����`K��|�ͻ�0Hj�{�R,���Q=��\� (F�}\�W�������R)A�g��SG`I��s�n���AR�=|�8�$}�G(v��C��$)s���� FBJ�?]�_�u XRv�ύ��6z�� �Ũ�G[��3��6-�T9�H��z��p����W�̞ú������� X�����g�큽�=�7C�u������fzI���$��)�k�i���^q��k��-) � ���0H*�N` �QZ��k�k]/���t���nn���sI�^Gu't=��7$�� Z;�{���8�^��jB��%� ��IItR�QS7�[�ϭ���3 �$�_���O�Q�J`7�!�]���W��"��W,)�����Iy �W��� �AJA�;K���WG��`IY�{8���k$I�$�^��%����9�.�^(`��N|���LJ�%�@�$I�}ֽp���=FB*�xN��=gI?Q{٥�4B)m���w �$I���gc~d��Z@G�9K��� X�?7)a�K�%�݅K�$IZ��-`I���p����C ������U��6�$I��\0��>!��9�k}��� Xa� ����II�S���0H�$I �H ?1R��.�Ч�j���:�4~R�w���@p�$I����r��A*�u��}��W�j�WFPJ����$I�➓/���6#!�� L�Ӿ��+ X36�x�8J �|+L;v���$I���o�4����3���0����1�R2�0��M� I�$-E}��@����,pS�^ޟR[���/����s¹'��0H�$IKyf��Ÿ���f�������VO�π�FT*�����a$I��>��H��e��~����V���Y/3�R�/�)��>d$I��>2��8`Cj���w�,n@�FU*�9tt�f$I��~<;��=�/4RD~����@��� X��-�ѕ�z��ἱI�$��:� ԍ��R �a�@��b X��{��+�Qx��u�q�$I�Л�z�o���� /~3\8����ڒ���4B������N7�$IҀ���j �V]n1�8H�$I��YFBj�3��̚�̵���ja ����p���p��� �$I���s/3R� Ӻ�-�Yj+L;�.0�R�́��I�$�A���v?� #!5�"��aʄ��j}���U���Km�ɽ��H�$Ij��C���Ys?h$I��Dl8�4��3���.��v�}���m���7�UiI=�&�=0L�g0$I��4���: ���emb�e��`���� e�Qbm�0u�? �$I�T!Sƍ'�-���s��v�)s#C��0�:�XB���2���a� w I�$�zbww�{�."p��Pz�O� �=�Ɔ�\����[� �����o($I������aw]�`���E���).K���v�i�:�L�*#gР7[��$I�����yG���PI=@��R� �4�y��R~�̮�´cg I�$I/<�t�P�ͽ ��h�Dg�o� 94����Z^k盇�΄8��I���56��^�W�$I�^�0���̜�N�?4*�H`237}g��+h���x�o��q)��SJ@p|�`�� �$I��%>������-�h���O�0e�O�>��\ԣNߌZ��D6��R�=K ����~n($I�$��y�3��D>o4�b#px�2���$��yڪt���z���W���~a�� �$I��~?�x<��e{W���g��ô�{�x$/�=�{t�G�0�7��e���a���B�$IҀ�yG��^S�卆�"puS��3��*�E=洣��,`9�>��'���Bww�pH�$IZ��ݑ�nC�㧄���Pc�_9��sO gw����J=l1�:mKB�>�����Ab<4L�p���$I�����b �o1Z���Q�@8�5�b�̍ S'�F���,�F��e���,^I�$Ij���E�dù{�l4� �8�Ys_�s� Z8.��x �m"+{~��?q,��Z D�!I�$��ϻ�'|X�h��B�)=��…'�]��M�>��5��� r�g���otԎ 獽�PH�$Ij����IP���hh)n#�cÔq���A'�ug5qw���U�&r�F|1��E%I�$%����]��!'�3�AFD/;C�k_`�9��� �v�!ٴt�PV�;��x`�'��*b�Qa� w I�$I�x�5� �����FC�3D����_��~��A�_�#O݆���Dv��V?<���q�w�+I�$I�{��=�Z�8"�.#RI���Y�yj���Ǫ����=f�D�l�9�%�M�,�����a8$I�$��Yw�i[�7�ݍFe�$�s��1��ՋBV�A?�`�]#!��oz����4zjLJ���o8$I�$%�@3j�A��a4��(�o�� �;�p,,dya�=��F9ً[��LS���PH�$IJ�Y�Љ+3��> 5"���3�9�aZ�<ñh!�{T�pB�G��k��j}��S�p��� �$I��lvF��.���F$I� ��z<� '\���K*qq��.f�<���2�Y�!�S"-\I�$I��Yw�č��jF$ w9��� \ߪB�.�1�v!Ʊ���?+��r�:�^�!I�$�BϹ�B� ����H��"�B�;L��'G[ 4�U�����#5>�੐�)|#�o0��aڱ���$I���>�}��k&�1`U#�V��?��Ys��V x���>�{t���1�[�I~D���&(I�$I/{��H�0fw�"�q"���y�%��4����� I�X�y�E~��M�3 8Xψ��L}q�������E�$I���[�> �nD�?~�s����f��� �����]o�΁� �cT��6"?'�_�Ἣ� �$I��>�~��.f�|'!������N�?�⟩����0��G KkX�Z�E��]�ޡ;�����/����&�?k�� O�ۘH�$IR��������ۀw�XӨ��<�7@��P��nS��04�a����Ӷ�p�.��:��@���\IWQ�J6�s�S%I�$���e��5��ڑ���v`�3:���x'�;��w��q_�vp�gHyX�Z� ��3�gЂ7{{���E�����uԹ�n�±��}�$I�$��������8t;b|��5��91n��ء����Q"�P������6���O�5�i���� }�i�R�̈́���%�Q�̄p!�I䮢�]��������O{�H�$IR�ϻ�9��s֧�� a=`-� aB\X��0"+5"C�1�H�b?߮����3x��3�&�g�ş�g��g����l��_���h�����Z^,`5�?���ߎ��vĸ%�̀M!�OZC2#0x ����LJ��0�� �G�w����$I�$I�}�<�{Eb�+y���;�iI,`����ܚ��F�����:�5��ܛ�A�8���-O�-|�8�K�7��s�|#�Z8�a&�>���<��a&����/V��tb�t��L��ʌI�$I�$I�$I�$I�$I�$IRj���D��D�%tEXtdate:create2022-05-31T04:40:26+00:00�!Î%tEXtdate:modify2022-05-31T04:40:26+00:00�|{2IEND�B`�Mini Shell

HOME


Mini Shell 1.0
DIR:/home/sarvhitkariparkashan.in/www/wp-content/plugins/woocommerce/includes/
Upload File :
Current File : //home/sarvhitkariparkashan.in/www/wp-content/plugins/woocommerce/includes/class-wc-checkout.php
<?php
/**
 * Checkout functionality
 *
 * The WooCommerce checkout class handles the checkout process, collecting user data and processing the payment.
 *
 * @package WooCommerce\Classes
 * @version 3.4.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * Checkout class.
 */
class WC_Checkout {

	/**
	 * The single instance of the class.
	 *
	 * @var WC_Checkout|null
	 */
	protected static $instance = null;

	/**
	 * Checkout fields are stored here.
	 *
	 * @var array|null
	 */
	protected $fields = null;

	/**
	 * Holds posted data for backwards compatibility.
	 *
	 * @var array
	 */
	protected $legacy_posted_data = array();

	/**
	 * Caches customer object. @see get_value.
	 *
	 * @var WC_Customer
	 */
	private $logged_in_customer = null;

	/**
	 * Gets the main WC_Checkout Instance.
	 *
	 * @since 2.1
	 * @static
	 * @return WC_Checkout Main instance
	 */
	public static function instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();

			// Hook in actions once.
			add_action( 'woocommerce_checkout_billing', array( self::$instance, 'checkout_form_billing' ) );
			add_action( 'woocommerce_checkout_shipping', array( self::$instance, 'checkout_form_shipping' ) );

			/**
			 * Runs once when the WC_Checkout class is first instantiated.
			 *
			 * @since 3.0.0 or earlier
			 */
			do_action( 'woocommerce_checkout_init', self::$instance );
		}
		return self::$instance;
	}

	/**
	 * See if variable is set. Used to support legacy public variables which are no longer defined.
	 *
	 * @param string $key Key.
	 * @return bool
	 */
	public function __isset( $key ) {
		return in_array(
			$key,
			array(
				'enable_signup',
				'enable_guest_checkout',
				'must_create_account',
				'checkout_fields',
				'posted',
				'shipping_method',
				'payment_method',
				'customer_id',
				'shipping_methods',
			),
			true
		);
	}

	/**
	 * Sets the legacy public variables for backwards compatibility.
	 *
	 * @param string $key   Key.
	 * @param mixed  $value Value.
	 */
	public function __set( $key, $value ) {
		switch ( $key ) {
			case 'enable_signup':
				$bool_value = wc_string_to_bool( $value );

				if ( $bool_value !== $this->is_registration_enabled() ) {
					remove_filter( 'woocommerce_checkout_registration_enabled', '__return_true', 0 );
					remove_filter( 'woocommerce_checkout_registration_enabled', '__return_false', 0 );
					add_filter( 'woocommerce_checkout_registration_enabled', $bool_value ? '__return_true' : '__return_false', 0 );
				}
				break;
			case 'enable_guest_checkout':
				$bool_value = wc_string_to_bool( $value );

				if ( $bool_value === $this->is_registration_required() ) {
					remove_filter( 'woocommerce_checkout_registration_required', '__return_true', 0 );
					remove_filter( 'woocommerce_checkout_registration_required', '__return_false', 0 );
					add_filter( 'woocommerce_checkout_registration_required', $bool_value ? '__return_false' : '__return_true', 0 );
				}
				break;
			case 'checkout_fields':
				$this->fields = $value;
				break;
			case 'shipping_methods':
				WC()->session->set( 'chosen_shipping_methods', $value );
				break;
			case 'posted':
				$this->legacy_posted_data = $value;
				break;
		}
	}

	/**
	 * Gets the legacy public variables for backwards compatibility.
	 *
	 * @param string $key Key.
	 * @return array|string
	 */
	public function __get( $key ) {
		if ( in_array( $key, array( 'posted', 'shipping_method', 'payment_method' ), true ) && empty( $this->legacy_posted_data ) ) {
			$this->legacy_posted_data = $this->get_posted_data();
		}

		switch ( $key ) {
			case 'enable_signup':
				return $this->is_registration_enabled();
			case 'enable_guest_checkout':
				return ! $this->is_registration_required();
			case 'must_create_account':
				return $this->is_registration_required() && ! is_user_logged_in();
			case 'checkout_fields':
				return $this->get_checkout_fields();
			case 'posted':
				wc_doing_it_wrong( 'WC_Checkout->posted', 'Use $_POST directly.', '3.0.0' );
				return $this->legacy_posted_data;
			case 'shipping_method':
				return $this->legacy_posted_data['shipping_method'];
			case 'payment_method':
				return $this->legacy_posted_data['payment_method'];
			case 'customer_id':
				/**
				 * Provides an opportunity to modify the customer ID associated with the current checkout process.
				 *
				 * @since 3.0.0 or earlier
				 *
				 * @param int The current user's ID (this may be 0 if no user is logged in).
				 */
				return apply_filters( 'woocommerce_checkout_customer_id', get_current_user_id() );
			case 'shipping_methods':
				return (array) WC()->session->get( 'chosen_shipping_methods' );
		}
	}

	/**
	 * Cloning is forbidden.
	 */
	public function __clone() {
		wc_doing_it_wrong( __FUNCTION__, __( 'Cloning is forbidden.', 'woocommerce' ), '2.1' );
	}

	/**
	 * Unserializing instances of this class is forbidden.
	 */
	public function __wakeup() {
		wc_doing_it_wrong( __FUNCTION__, __( 'Unserializing instances of this class is forbidden.', 'woocommerce' ), '2.1' );
	}

	/**
	 * Is registration required to checkout?
	 *
	 * @since  3.0.0
	 * @return boolean
	 */
	public function is_registration_required() {
		/**
		 * Controls if registration is required in order for checkout to be completed.
		 *
		 * @since 3.0.0
		 *
		 * @param bool $checkout_registration_required If customers must be registered to checkout.
		 */
		return apply_filters( 'woocommerce_checkout_registration_required', 'yes' !== get_option( 'woocommerce_enable_guest_checkout' ) );
	}

	/**
	 * Is registration enabled on the checkout page?
	 *
	 * @since  3.0.0
	 * @return boolean
	 */
	public function is_registration_enabled() {
		/**
		 * Determines if customer registration is enabled during checkout.
		 *
		 * @since 3.0.0
		 *
		 * @param bool $checkout_registration_enabled If checkout registration is enabled.
		 */
		return apply_filters( 'woocommerce_checkout_registration_enabled', 'yes' === get_option( 'woocommerce_enable_signup_and_login_from_checkout' ) );
	}

	/**
	 * Get an array of checkout fields.
	 *
	 * @param  string $fieldset to get.
	 * @return array
	 */
	public function get_checkout_fields( $fieldset = '' ) {
		if ( ! is_null( $this->fields ) ) {
			return $fieldset ? $this->fields[ $fieldset ] : $this->fields;
		}

		// Fields are based on billing/shipping country. Grab those values but ensure they are valid for the store before using.
		$billing_country   = $this->get_value( 'billing_country' );
		$billing_country   = empty( $billing_country ) ? WC()->countries->get_base_country() : $billing_country;
		$allowed_countries = WC()->countries->get_allowed_countries();

		if ( ! array_key_exists( $billing_country, $allowed_countries ) ) {
			$billing_country = current( array_keys( $allowed_countries ) );
		}

		$shipping_country  = $this->get_value( 'shipping_country' );
		$shipping_country  = empty( $shipping_country ) ? WC()->countries->get_base_country() : $shipping_country;
		$allowed_countries = WC()->countries->get_shipping_countries();

		if ( ! array_key_exists( $shipping_country, $allowed_countries ) ) {
			$shipping_country = current( array_keys( $allowed_countries ) );
		}

		$this->fields = array(
			'billing'  => WC()->countries->get_address_fields(
				$billing_country,
				'billing_'
			),
			'shipping' => WC()->countries->get_address_fields(
				$shipping_country,
				'shipping_'
			),
			'account'  => array(),
			'order'    => array(
				'order_comments' => array(
					'type'        => 'textarea',
					'class'       => array( 'notes' ),
					'label'       => __( 'Order notes', 'woocommerce' ),
					'placeholder' => esc_attr__(
						'Notes about your order, e.g. special notes for delivery.',
						'woocommerce'
					),
				),
			),
		);

		if ( 'no' === get_option( 'woocommerce_registration_generate_username' ) ) {
			$this->fields['account']['account_username'] = array(
				'type'         => 'text',
				'label'        => __( 'Account username', 'woocommerce' ),
				'required'     => true,
				'placeholder'  => esc_attr__( 'Username', 'woocommerce' ),
				'autocomplete' => 'username',
			);
		}

		if ( 'no' === get_option( 'woocommerce_registration_generate_password' ) ) {
			$this->fields['account']['account_password'] = array(
				'type'         => 'password',
				'label'        => __( 'Create account password', 'woocommerce' ),
				'required'     => true,
				'placeholder'  => esc_attr__( 'Password', 'woocommerce' ),
				'autocomplete' => 'new-password',
			);
		}

		/**
		 * Sets the fields used during checkout.
		 *
		 * @since 3.0.0 or earlier
		 *
		 * @param array[] $checkout_fields
		 */
		$this->fields = apply_filters( 'woocommerce_checkout_fields', $this->fields );

		foreach ( $this->fields as $field_type => $fields ) {
			// Sort each of the checkout field sections based on priority.
			uasort( $this->fields[ $field_type ], 'wc_checkout_fields_uasort_comparison' );

			// Add accessibility labels to fields that have placeholders.
			foreach ( $fields as $single_field_type => $field ) {
				if ( empty( $field['label'] ) && ! empty( $field['placeholder'] ) ) {
					$this->fields[ $field_type ][ $single_field_type ]['label']       = $field['placeholder'];
					$this->fields[ $field_type ][ $single_field_type ]['label_class'] = array( 'screen-reader-text' );
				}
			}
		}

		return $fieldset ? $this->fields[ $fieldset ] : $this->fields;
	}

	/**
	 * When we process the checkout, lets ensure cart items are rechecked to prevent checkout.
	 */
	public function check_cart_items() {
		/**
		 * Provides an opportunity to check cart items before checkout. This generally occurs during checkout validation.
		 *
		 * @see WC_Checkout::validate_checkout()
		 * @since 3.0.0 or earlier
		 */
		do_action( 'woocommerce_check_cart_items' );
	}

	/**
	 * Output the billing form.
	 */
	public function checkout_form_billing() {
		wc_get_template( 'checkout/form-billing.php', array( 'checkout' => $this ) );
	}

	/**
	 * Output the shipping form.
	 */
	public function checkout_form_shipping() {
		wc_get_template( 'checkout/form-shipping.php', array( 'checkout' => $this ) );
	}

	/**
	 * Create an order. Error codes:
	 *      520 - Cannot insert order into the database.
	 *      521 - Cannot get order after creation.
	 *      522 - Cannot update order.
	 *      525 - Cannot create line item.
	 *      526 - Cannot create fee item.
	 *      527 - Cannot create shipping item.
	 *      528 - Cannot create tax item.
	 *      529 - Cannot create coupon item.
	 *
	 * @throws Exception When checkout validation fails.
	 * @param  array $data Posted data.
	 * @return int|WP_ERROR
	 */
	public function create_order( $data ) {
		/**
		 * Gives plugins an opportunity to create a new order themselves.
		 *
		 * @since 3.0.0 or earlier
		 *
		 * @param int|null    $order_id Can be set to an order ID to short-circuit the default order creation process.
		 * @param WC_Checkout $checkout Reference to the current WC_Checkout instance.
		 */
		$order_id = apply_filters( 'woocommerce_create_order', null, $this );
		if ( $order_id ) {
			return $order_id;
		}

		try {
			$order_id           = absint( WC()->session->get( 'order_awaiting_payment' ) );
			$cart_hash          = WC()->cart->get_cart_hash();
			$available_gateways = WC()->payment_gateways->get_available_payment_gateways();
			$order              = $order_id ? wc_get_order( $order_id ) : null;

			/**
			 * If there is an order pending payment, we can resume it here so
			 * long as it has not changed. If the order has changed, i.e.
			 * different items or cost, create a new order. We use a hash to
			 * detect changes which is based on cart items + order total.
			 */
			if ( $order && $order->has_cart_hash( $cart_hash ) && $order->has_status( array( 'pending', 'failed' ) ) ) {
				/**
				 * Indicates that we are resuming checkout for an existing order (which is pending payment, and which
				 * has not changed since it was added to the current shopping session).
				 *
				 * @since 3.0.0 or earlier
				 *
				 * @param int $order_id The ID of the order being resumed.
				 */
				do_action( 'woocommerce_resume_order', $order_id );

				// Remove all items - we will re-add them later.
				$order->remove_order_items();
			} else {
				$order = new WC_Order();
			}

			$fields_prefix = array(
				'shipping' => true,
				'billing'  => true,
			);

			$shipping_fields = array(
				'shipping_method' => true,
				'shipping_total'  => true,
				'shipping_tax'    => true,
			);
			foreach ( $data as $key => $value ) {
				if ( is_callable( array( $order, "set_{$key}" ) ) ) {
					$order->{"set_{$key}"}( $value );
					// Store custom fields prefixed with wither shipping_ or billing_. This is for backwards compatibility with 2.6.x.
				} elseif ( isset( $fields_prefix[ current( explode( '_', $key ) ) ] ) ) {
					if ( ! isset( $shipping_fields[ $key ] ) ) {
						$order->update_meta_data( '_' . $key, $value );
					}
				}
			}

			if ( isset( $data['billing_email'] ) ) {
				$order->hold_applied_coupons( $data['billing_email'] );
			}

			$order->set_created_via( 'checkout' );
			$order->set_cart_hash( $cart_hash );
			/**
			 * This action is documented in woocommerce/includes/class-wc-checkout.php
			 *
			 * @since 3.0.0 or earlier
			 */
			$order->set_customer_id( apply_filters( 'woocommerce_checkout_customer_id', get_current_user_id() ) );
			$order->set_currency( get_woocommerce_currency() );
			$order->set_prices_include_tax( 'yes' === get_option( 'woocommerce_prices_include_tax' ) );
			$order->set_customer_ip_address( WC_Geolocation::get_ip_address() );
			$order->set_customer_user_agent( wc_get_user_agent() );
			$order->set_customer_note( isset( $data['order_comments'] ) ? $data['order_comments'] : '' );
			$order->set_payment_method( isset( $available_gateways[ $data['payment_method'] ] ) ? $available_gateways[ $data['payment_method'] ] : $data['payment_method'] );
			$this->set_data_from_cart( $order );

			/**
			 * Action hook to adjust order before save.
			 *
			 * @since 3.0.0
			 */
			do_action( 'woocommerce_checkout_create_order', $order, $data );

			// Save the order.
			$order_id = $order->save();

			/**
			 * Action hook fired after an order is created used to add custom meta to the order.
			 *
			 * @since 3.0.0
			 */
			do_action( 'woocommerce_checkout_update_order_meta', $order_id, $data );

			/**
			 * Action hook fired after an order is created.
			 *
			 * @since 4.3.0
			 */
			do_action( 'woocommerce_checkout_order_created', $order );

			return $order_id;
		} catch ( Exception $e ) {
			if ( $order && $order instanceof WC_Order ) {
				$order->get_data_store()->release_held_coupons( $order );
				/**
				 * Action hook fired when an order is discarded due to Exception.
				 *
				 * @since 4.3.0
				 */
				do_action( 'woocommerce_checkout_order_exception', $order );
			}
			return new WP_Error( 'checkout-error', $e->getMessage() );
		}
	}

	/**
	 * Copy line items, tax, totals data from cart to order.
	 *
	 * @param WC_Order $order Order object.
	 *
	 * @throws Exception When unable to create order.
	 */
	public function set_data_from_cart( &$order ) {
		$order_vat_exempt = WC()->cart->get_customer()->get_is_vat_exempt() ? 'yes' : 'no';
		$order->add_meta_data( 'is_vat_exempt', $order_vat_exempt, true );
		$order->set_shipping_total( WC()->cart->get_shipping_total() );
		$order->set_discount_total( WC()->cart->get_discount_total() );
		$order->set_discount_tax( WC()->cart->get_discount_tax() );
		$order->set_cart_tax( WC()->cart->get_cart_contents_tax() + WC()->cart->get_fee_tax() );
		$order->set_shipping_tax( WC()->cart->get_shipping_tax() );
		$order->set_total( WC()->cart->get_total( 'edit' ) );
		$this->create_order_line_items( $order, WC()->cart );
		$this->create_order_fee_lines( $order, WC()->cart );
		$this->create_order_shipping_lines( $order, WC()->session->get( 'chosen_shipping_methods' ), WC()->shipping()->get_packages() );
		$this->create_order_tax_lines( $order, WC()->cart );
		$this->create_order_coupon_lines( $order, WC()->cart );
	}
	/**
	 * Add line items to the order.
	 *
	 * @param WC_Order $order Order instance.
	 * @param WC_Cart  $cart  Cart instance.
	 */
	public function create_order_line_items( &$order, $cart ) {
		foreach ( $cart->get_cart() as $cart_item_key => $values ) {
			/**
			 * Filter hook to get initial item object.
			 *
			 * @since 3.1.0
			 */
			$item                       = apply_filters( 'woocommerce_checkout_create_order_line_item_object', new WC_Order_Item_Product(), $cart_item_key, $values, $order );
			$product                    = $values['data'];
			$item->legacy_values        = $values; // @deprecated 4.4.0 For legacy actions.
			$item->legacy_cart_item_key = $cart_item_key; // @deprecated 4.4.0 For legacy actions.
			$item->set_props(
				array(
					'quantity'     => $values['quantity'],
					'variation'    => $values['variation'],
					'subtotal'     => $values['line_subtotal'],
					'total'        => $values['line_total'],
					'subtotal_tax' => $values['line_subtotal_tax'],
					'total_tax'    => $values['line_tax'],
					'taxes'        => $values['line_tax_data'],
				)
			);

			if ( $product ) {
				$item->set_props(
					array(
						'name'         => $product->get_name(),
						'tax_class'    => $product->get_tax_class(),
						'product_id'   => $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id(),
						'variation_id' => $product->is_type( 'variation' ) ? $product->get_id() : 0,
					)
				);
			}

			$item->set_backorder_meta();

			/**
			 * Action hook to adjust item before save.
			 *
			 * @since 3.0.0
			 */
			do_action( 'woocommerce_checkout_create_order_line_item', $item, $cart_item_key, $values, $order );

			// Add item to order and save.
			$order->add_item( $item );
		}
	}

	/**
	 * Add fees to the order.
	 *
	 * @param WC_Order $order Order instance.
	 * @param WC_Cart  $cart  Cart instance.
	 */
	public function create_order_fee_lines( &$order, $cart ) {
		foreach ( $cart->get_fees() as $fee_key => $fee ) {
			$item                 = new WC_Order_Item_Fee();
			$item->legacy_fee     = $fee; // @deprecated 4.4.0 For legacy actions.
			$item->legacy_fee_key = $fee_key; // @deprecated 4.4.0 For legacy actions.
			$item->set_props(
				array(
					'name'      => $fee->name,
					'tax_class' => $fee->taxable ? $fee->tax_class : 0,
					'amount'    => $fee->amount,
					'total'     => $fee->total,
					'total_tax' => $fee->tax,
					'taxes'     => array(
						'total' => $fee->tax_data,
					),
				)
			);

			/**
			 * Action hook to adjust item before save.
			 *
			 * @since 3.0.0
			 */
			do_action( 'woocommerce_checkout_create_order_fee_item', $item, $fee_key, $fee, $order );

			// Add item to order and save.
			$order->add_item( $item );
		}
	}

	/**
	 * Add shipping lines to the order.
	 *
	 * @param WC_Order $order                   Order Instance.
	 * @param array    $chosen_shipping_methods Chosen shipping methods.
	 * @param array    $packages                Packages.
	 */
	public function create_order_shipping_lines( &$order, $chosen_shipping_methods, $packages ) {
		foreach ( $packages as $package_key => $package ) {
			if ( isset( $chosen_shipping_methods[ $package_key ], $package['rates'][ $chosen_shipping_methods[ $package_key ] ] ) ) {
				$shipping_rate            = $package['rates'][ $chosen_shipping_methods[ $package_key ] ];
				$item                     = new WC_Order_Item_Shipping();
				$item->legacy_package_key = $package_key; // @deprecated 4.4.0 For legacy actions.
				$item->set_props(
					array(
						'method_title' => $shipping_rate->label,
						'method_id'    => $shipping_rate->method_id,
						'instance_id'  => $shipping_rate->instance_id,
						'total'        => wc_format_decimal( $shipping_rate->cost ),
						'taxes'        => array(
							'total' => $shipping_rate->taxes,
						),
					)
				);

				foreach ( $shipping_rate->get_meta_data() as $key => $value ) {
					$item->add_meta_data( $key, $value, true );
				}

				/**
				 * Action hook to adjust item before save.
				 *
				 * @since 3.0.0
				 */
				do_action( 'woocommerce_checkout_create_order_shipping_item', $item, $package_key, $package, $order );

				// Add item to order and save.
				$order->add_item( $item );
			}
		}
	}

	/**
	 * Add tax lines to the order.
	 *
	 * @param WC_Order $order Order instance.
	 * @param WC_Cart  $cart  Cart instance.
	 */
	public function create_order_tax_lines( &$order, $cart ) {
		foreach ( array_keys( $cart->get_cart_contents_taxes() + $cart->get_shipping_taxes() + $cart->get_fee_taxes() ) as $tax_rate_id ) {
			/**
			 * Controls the zero rate tax ID.
			 *
			 * An order item tax will not be created for this ID (which by default is 'zero-rated').
			 *
			 * @since 3.0.0 or earlier
			 *
			 * @param string $tax_rate_id The ID of the zero rate tax.
			 */
			if ( $tax_rate_id && apply_filters( 'woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated' ) !== $tax_rate_id ) {
				$item = new WC_Order_Item_Tax();
				$item->set_props(
					array(
						'rate_id'            => $tax_rate_id,
						'tax_total'          => $cart->get_tax_amount( $tax_rate_id ),
						'shipping_tax_total' => $cart->get_shipping_tax_amount( $tax_rate_id ),
						'rate_code'          => WC_Tax::get_rate_code( $tax_rate_id ),
						'label'              => WC_Tax::get_rate_label( $tax_rate_id ),
						'compound'           => WC_Tax::is_compound( $tax_rate_id ),
						'rate_percent'       => WC_Tax::get_rate_percent_value( $tax_rate_id ),
					)
				);

				/**
				 * Action hook to adjust item before save.
				 *
				 * @since 3.0.0
				 */
				do_action( 'woocommerce_checkout_create_order_tax_item', $item, $tax_rate_id, $order );

				// Add item to order and save.
				$order->add_item( $item );
			}
		}
	}

	/**
	 * Add coupon lines to the order.
	 *
	 * @param WC_Order $order Order instance.
	 * @param WC_Cart  $cart  Cart instance.
	 */
	public function create_order_coupon_lines( &$order, $cart ) {
		foreach ( $cart->get_coupons() as $code => $coupon ) {
			$item = new WC_Order_Item_Coupon();
			$item->set_props(
				array(
					'code'         => $code,
					'discount'     => $cart->get_coupon_discount_amount( $code ),
					'discount_tax' => $cart->get_coupon_discount_tax_amount( $code ),
				)
			);

			$coupon_info = $coupon->get_short_info();
			$item->add_meta_data( 'coupon_info', $coupon_info );

			/**
			 * Action hook to adjust item before save.
			 *
			 * @since 3.0.0
			 */
			do_action( 'woocommerce_checkout_create_order_coupon_item', $item, $code, $coupon, $order );

			// Add item to order and save.
			$order->add_item( $item );
		}
	}

	/**
	 * See if a fieldset should be skipped.
	 *
	 * @since 3.0.0
	 * @param string $fieldset_key Fieldset key.
	 * @param array  $data         Posted data.
	 * @return bool
	 */
	protected function maybe_skip_fieldset( $fieldset_key, $data ) {
		if ( 'shipping' === $fieldset_key && ( ! $data['ship_to_different_address'] || ! WC()->cart->needs_shipping_address() ) ) {
			return true;
		}

		if ( 'account' === $fieldset_key && ( is_user_logged_in() || ( ! $this->is_registration_required() && empty( $data['createaccount'] ) ) ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Get posted data from the checkout form.
	 *
	 * @since  3.1.0
	 * @return array of data.
	 */
	public function get_posted_data() {
		// phpcs:disable WordPress.Security.NonceVerification.Missing
		$data = array(
			'terms'                              => (int) isset( $_POST['terms'] ),
			'terms-field'                        => (int) isset( $_POST['terms-field'] ),
			'createaccount'                      => (int) ( $this->is_registration_enabled() ? ! empty( $_POST['createaccount'] ) : false ),
			'payment_method'                     => isset( $_POST['payment_method'] ) ? wc_clean( wp_unslash( $_POST['payment_method'] ) ) : '',
			'shipping_method'                    => isset( $_POST['shipping_method'] ) ? wc_clean( wp_unslash( $_POST['shipping_method'] ) ) : '',
			'ship_to_different_address'          => ! empty( $_POST['ship_to_different_address'] ) && ! wc_ship_to_billing_address_only(),
			'woocommerce_checkout_update_totals' => isset( $_POST['woocommerce_checkout_update_totals'] ),
		);
		// phpcs:enable WordPress.Security.NonceVerification.Missing

		$skipped        = array();
		$form_was_shown = isset( $_POST['woocommerce-process-checkout-nonce'] ); // phpcs:disable WordPress.Security.NonceVerification.Missing

		foreach ( $this->get_checkout_fields() as $fieldset_key => $fieldset ) {
			if ( $this->maybe_skip_fieldset( $fieldset_key, $data ) ) {
				$skipped[] = $fieldset_key;
				continue;
			}

			foreach ( $fieldset as $key => $field ) {
				$type = sanitize_title( isset( $field['type'] ) ? $field['type'] : 'text' );

				if ( isset( $_POST[ $key ] ) && '' !== $_POST[ $key ] ) { // phpcs:disable WordPress.Security.NonceVerification.Missing
					$value = wp_unslash( $_POST[ $key ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
				} elseif ( isset( $field['default'] ) && 'checkbox' !== $type && ! $form_was_shown ) {
					$value = $field['default'];
				} else {
					$value = '';
				}

				if ( '' !== $value ) {
					switch ( $type ) {
						case 'checkbox':
							$value = 1;
							break;
						case 'multiselect':
							$value = implode( ', ', wc_clean( $value ) );
							break;
						case 'textarea':
							$value = wc_sanitize_textarea( $value );
							break;
						case 'password':
							if ( $data['createaccount'] && 'account_password' === $key ) {
								$value = wp_slash( $value ); // Passwords are encrypted with slashes on account creation, so we need to slash here too.
							}
							break;
						default:
							$value = wc_clean( $value );
							break;
					}
				}

				$data[ $key ] = apply_filters( 'woocommerce_process_checkout_' . $type . '_field', apply_filters( 'woocommerce_process_checkout_field_' . $key, $value ) );
			}
		}

		if ( in_array( 'shipping', $skipped, true ) && ( WC()->cart->needs_shipping_address() || wc_ship_to_billing_address_only() ) ) {
			foreach ( $this->get_checkout_fields( 'shipping' ) as $key => $field ) {
				$data[ $key ] = isset( $data[ 'billing_' . substr( $key, 9 ) ] ) ? $data[ 'billing_' . substr( $key, 9 ) ] : '';
			}
		}

		// BW compatibility.
		$this->legacy_posted_data = $data;

		return apply_filters( 'woocommerce_checkout_posted_data', $data );
	}

	/**
	 * Validates the posted checkout data based on field properties.
	 *
	 * @since  3.0.0
	 * @param  array    $data   An array of posted data.
	 * @param  WP_Error $errors Validation error.
	 */
	protected function validate_posted_data( &$data, &$errors ) {
		foreach ( $this->get_checkout_fields() as $fieldset_key => $fieldset ) {
			$validate_fieldset = true;
			if ( $this->maybe_skip_fieldset( $fieldset_key, $data ) ) {
				$validate_fieldset = false;
			}

			foreach ( $fieldset as $key => $field ) {
				if ( ! isset( $data[ $key ] ) ) {
					continue;
				}
				$required    = ! empty( $field['required'] );
				$format      = array_filter( isset( $field['validate'] ) ? (array) $field['validate'] : array() );
				$field_label = isset( $field['label'] ) ? $field['label'] : '';

				if ( $validate_fieldset &&
					( isset( $field['type'] ) && 'country' === $field['type'] && '' !== $data[ $key ] ) &&
					! WC()->countries->country_exists( $data[ $key ] ) ) {
						/* translators: ISO 3166-1 alpha-2 country code */
						$errors->add( $key . '_validation', sprintf( __( "'%s' is not a valid country code.", 'woocommerce' ), $data[ $key ] ) );
				}

				switch ( $fieldset_key ) {
					case 'shipping':
						/* translators: %s: field name */
						$field_label = sprintf( _x( 'Shipping %s', 'checkout-validation', 'woocommerce' ), $field_label );
						break;
					case 'billing':
						/* translators: %s: field name */
						$field_label = sprintf( _x( 'Billing %s', 'checkout-validation', 'woocommerce' ), $field_label );
						break;
				}

				if ( in_array( 'postcode', $format, true ) ) {
					$country      = isset( $data[ $fieldset_key . '_country' ] ) ? $data[ $fieldset_key . '_country' ] : WC()->customer->{"get_{$fieldset_key}_country"}();
					$data[ $key ] = wc_format_postcode( $data[ $key ], $country );

					if ( $validate_fieldset && '' !== $data[ $key ] && ! WC_Validation::is_postcode( $data[ $key ], $country ) ) {
						switch ( $country ) {
							case 'IE':
								/* translators: %1$s: field name, %2$s finder.eircode.ie URL */
								$postcode_validation_notice = sprintf( __( '%1$s is not valid. You can look up the correct Eircode <a target="_blank" href="%2$s">here</a>.', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>', 'https://finder.eircode.ie' );
								break;
							default:
								/* translators: %s: field name */
								$postcode_validation_notice = sprintf( __( '%s is not a valid postcode / ZIP.', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>' );
						}
						$errors->add( $key . '_validation', apply_filters( 'woocommerce_checkout_postcode_validation_notice', $postcode_validation_notice, $country, $data[ $key ] ), array( 'id' => $key ) );
					}
				}

				if ( in_array( 'phone', $format, true ) ) {
					if ( $validate_fieldset && '' !== $data[ $key ] && ! WC_Validation::is_phone( $data[ $key ] ) ) {
						/* translators: %s: phone number */
						$errors->add( $key . '_validation', sprintf( __( '%s is not a valid phone number.', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>' ), array( 'id' => $key ) );
					}
				}

				if ( in_array( 'email', $format, true ) && '' !== $data[ $key ] ) {
					$email_is_valid = is_email( $data[ $key ] );
					$data[ $key ]   = sanitize_email( $data[ $key ] );

					if ( $validate_fieldset && ! $email_is_valid ) {
						/* translators: %s: email address */
						$errors->add( $key . '_validation', sprintf( __( '%s is not a valid email address.', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>' ), array( 'id' => $key ) );
						continue;
					}
				}

				if ( '' !== $data[ $key ] && in_array( 'state', $format, true ) ) {
					$country      = isset( $data[ $fieldset_key . '_country' ] ) ? $data[ $fieldset_key . '_country' ] : WC()->customer->{"get_{$fieldset_key}_country"}();
					$valid_states = WC()->countries->get_states( $country );

					if ( ! empty( $valid_states ) && is_array( $valid_states ) && count( $valid_states ) > 0 ) {
						$valid_state_values = array_map( 'wc_strtoupper', array_flip( array_map( 'wc_strtoupper', $valid_states ) ) );
						$data[ $key ]       = wc_strtoupper( $data[ $key ] );

						if ( isset( $valid_state_values[ $data[ $key ] ] ) ) {
							// With this part we consider state value to be valid as well, convert it to the state key for the valid_states check below.
							$data[ $key ] = $valid_state_values[ $data[ $key ] ];
						}

						if ( $validate_fieldset && ! in_array( $data[ $key ], $valid_state_values, true ) ) {
							/* translators: 1: state field 2: valid states */
							$errors->add( $key . '_validation', sprintf( __( '%1$s is not valid. Please enter one of the following: %2$s', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>', implode( ', ', $valid_states ) ), array( 'id' => $key ) );
						}
					}
				}

				if ( $validate_fieldset && $required && '' === $data[ $key ] ) {
					/* translators: %s: field name */
					$errors->add( $key . '_required', apply_filters( 'woocommerce_checkout_required_field_notice', sprintf( __( '%s is a required field.', 'woocommerce' ), '<strong>' . esc_html( $field_label ) . '</strong>' ), $field_label, $key ), array( 'id' => $key ) );
				}
			}
		}
	}

	/**
	 * Validates that the checkout has enough info to proceed.
	 *
	 * @since  3.0.0
	 * @param  array    $data   An array of posted data.
	 * @param  WP_Error $errors Validation errors.
	 */
	protected function validate_checkout( &$data, &$errors ) {
		$this->validate_posted_data( $data, $errors );
		$this->check_cart_items();

		// phpcs:ignore WordPress.Security.NonceVerification.Missing
		if ( empty( $data['woocommerce_checkout_update_totals'] ) && empty( $data['terms'] ) && ! empty( $data['terms-field'] ) ) {
			$errors->add( 'terms', __( 'Please read and accept the terms and conditions to proceed with your order.', 'woocommerce' ) );
		}

		if ( WC()->cart->needs_shipping() ) {
			$shipping_country = isset( $data['shipping_country'] ) ? $data['shipping_country'] : WC()->customer->get_shipping_country();

			if ( empty( $shipping_country ) ) {
				$errors->add( 'shipping', __( 'Please enter an address to continue.', 'woocommerce' ) );
			} elseif ( ! in_array( $shipping_country, array_keys( WC()->countries->get_shipping_countries() ), true ) ) {
				if ( WC()->countries->country_exists( $shipping_country ) ) {
					/* translators: %s: shipping location (prefix e.g. 'to' + ISO 3166-1 alpha-2 country code) */
					$errors->add( 'shipping', sprintf( __( 'Unfortunately <strong>we do not ship %s</strong>. Please enter an alternative shipping address.', 'woocommerce' ), WC()->countries->shipping_to_prefix() . ' ' . $shipping_country ) );
				}
			} else {
				$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );

				foreach ( WC()->shipping()->get_packages() as $i => $package ) {
					if ( ! isset( $chosen_shipping_methods[ $i ], $package['rates'][ $chosen_shipping_methods[ $i ] ] ) ) {
						$errors->add( 'shipping', __( 'No shipping method has been selected. Please double check your address, or contact us if you need any help.', 'woocommerce' ) );
					}
				}
			}
		}

		if ( WC()->cart->needs_payment() ) {
			$available_gateways = WC()->payment_gateways->get_available_payment_gateways();

			if ( ! isset( $available_gateways[ $data['payment_method'] ] ) ) {
				$errors->add( 'payment', __( 'Invalid payment method.', 'woocommerce' ) );
			} else {
				$available_gateways[ $data['payment_method'] ]->validate_fields();
			}
		}

		do_action( 'woocommerce_after_checkout_validation', $data, $errors );
	}

	/**
	 * Set address field for customer.
	 *
	 * @since 3.0.7
	 * @param string $field String to update.
	 * @param string $key   Field key.
	 * @param array  $data  Array of data to get the value from.
	 */
	protected function set_customer_address_fields( $field, $key, $data ) {
		$billing_value  = null;
		$shipping_value = null;

		if ( isset( $data[ "billing_{$field}" ] ) && is_callable( array( WC()->customer, "set_billing_{$field}" ) ) ) {
			$billing_value  = $data[ "billing_{$field}" ];
			$shipping_value = $data[ "billing_{$field}" ];
		}

		if ( isset( $data[ "shipping_{$field}" ] ) && is_callable( array( WC()->customer, "set_shipping_{$field}" ) ) ) {
			$shipping_value = $data[ "shipping_{$field}" ];
		}

		if ( ! is_null( $billing_value ) && is_callable( array( WC()->customer, "set_billing_{$field}" ) ) ) {
			WC()->customer->{"set_billing_{$field}"}( $billing_value );
		}

		if ( ! is_null( $shipping_value ) && is_callable( array( WC()->customer, "set_shipping_{$field}" ) ) ) {
			WC()->customer->{"set_shipping_{$field}"}( $shipping_value );
		}
	}

	/**
	 * Update customer and session data from the posted checkout data.
	 *
	 * @since 3.0.0
	 * @param array $data Posted data.
	 */
	protected function update_session( $data ) {
		// Update both shipping and billing to the passed billing address first if set.
		$address_fields = array(
			'first_name',
			'last_name',
			'company',
			'email',
			'phone',
			'address_1',
			'address_2',
			'city',
			'postcode',
			'state',
			'country',
		);

		array_walk( $address_fields, array( $this, 'set_customer_address_fields' ), $data );
		WC()->customer->save();

		// Update customer shipping and payment method to posted method.
		$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );

		if ( is_array( $data['shipping_method'] ) ) {
			foreach ( $data['shipping_method'] as $i => $value ) {
				if ( ! is_string( $value ) ) {
					continue;
				}
				$chosen_shipping_methods[ $i ] = $value;
			}
		}

		WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
		WC()->session->set( 'chosen_payment_method', $data['payment_method'] );

		// Update cart totals now we have customer address.
		WC()->cart->calculate_totals();
	}


	/**
	 * Process an order that does require payment.
	 *
	 * @since 3.0.0
	 * @param int    $order_id       Order ID.
	 * @param string $payment_method Payment method.
	 */
	protected function process_order_payment( $order_id, $payment_method ) {
		$available_gateways = WC()->payment_gateways->get_available_payment_gateways();

		if ( ! isset( $available_gateways[ $payment_method ] ) ) {
			return;
		}

		// Store Order ID in session so it can be re-used after payment failure.
		WC()->session->set( 'order_awaiting_payment', $order_id );

		// We save the session early because if the payment gateway hangs
		// the request will never finish, thus the session data will neved be saved,
		// and this can lead to duplicate orders if the user submits the order again.
		WC()->session->save_data();

		// Process Payment.
		$result = $available_gateways[ $payment_method ]->process_payment( $order_id );

		// Redirect to success/confirmation/payment page.
		if ( isset( $result['result'] ) && 'success' === $result['result'] ) {
			$result['order_id'] = $order_id;

			$result = apply_filters( 'woocommerce_payment_successful_result', $result, $order_id );

			if ( ! wp_doing_ajax() ) {
				// phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
				wp_redirect( $result['redirect'] );
				exit;
			}

			wp_send_json( $result );
		}
	}

	/**
	 * Process an order that doesn't require payment.
	 *
	 * @since 3.0.0
	 * @param int $order_id Order ID.
	 */
	protected function process_order_without_payment( $order_id ) {
		$order = wc_get_order( $order_id );
		$order->payment_complete();
		wc_empty_cart();

		if ( ! wp_doing_ajax() ) {
			wp_safe_redirect(
				apply_filters( 'woocommerce_checkout_no_payment_needed_redirect', $order->get_checkout_order_received_url(), $order )
			);
			exit;
		}

		wp_send_json(
			array(
				'result'   => 'success',
				'redirect' => apply_filters( 'woocommerce_checkout_no_payment_needed_redirect', $order->get_checkout_order_received_url(), $order ),
			)
		);
	}

	/**
	 * Create a new customer account if needed.
	 *
	 * @throws Exception When not able to create customer.
	 * @param array $data Posted data.
	 */
	protected function process_customer( $data ) {
		/**
		 * This action is documented in woocommerce/includes/class-wc-checkout.php
		 *
		 * @since 3.0.0 or earlier
		 */
		$customer_id = apply_filters( 'woocommerce_checkout_customer_id', get_current_user_id() );

		if ( ! is_user_logged_in() && ( $this->is_registration_required() || ! empty( $data['createaccount'] ) ) ) {
			$username    = ! empty( $data['account_username'] ) ? $data['account_username'] : '';
			$password    = ! empty( $data['account_password'] ) ? $data['account_password'] : '';
			$customer_id = wc_create_new_customer(
				$data['billing_email'],
				$username,
				$password,
				array(
					'first_name' => ! empty( $data['billing_first_name'] ) ? $data['billing_first_name'] : '',
					'last_name'  => ! empty( $data['billing_last_name'] ) ? $data['billing_last_name'] : '',
				)
			);

			if ( is_wp_error( $customer_id ) ) {
				throw new Exception( $customer_id->get_error_message() );
			}

			wc_set_customer_auth_cookie( $customer_id );

			// As we are now logged in, checkout will need to refresh to show logged in data.
			WC()->session->set( 'reload_checkout', true );

			// Also, recalculate cart totals to reveal any role-based discounts that were unavailable before registering.
			WC()->cart->calculate_totals();
		}

		// On multisite, ensure user exists on current site, if not add them before allowing login.
		if ( $customer_id && is_multisite() && is_user_logged_in() && ! is_user_member_of_blog() ) {
			add_user_to_blog( get_current_blog_id(), $customer_id, 'customer' );
		}

		// Add customer info from other fields.
		if ( $customer_id && apply_filters( 'woocommerce_checkout_update_customer_data', true, $this ) ) {
			$customer = new WC_Customer( $customer_id );

			if ( ! empty( $data['billing_first_name'] ) && '' === $customer->get_first_name() ) {
				$customer->set_first_name( $data['billing_first_name'] );
			}

			if ( ! empty( $data['billing_last_name'] ) && '' === $customer->get_last_name() ) {
				$customer->set_last_name( $data['billing_last_name'] );
			}

			// If the display name is an email, update to the user's full name.
			if ( is_email( $customer->get_display_name() ) ) {
				$customer->set_display_name( $customer->get_first_name() . ' ' . $customer->get_last_name() );
			}

			foreach ( $data as $key => $value ) {
				// Use setters where available.
				if ( is_callable( array( $customer, "set_{$key}" ) ) ) {
					$customer->{"set_{$key}"}( $value );

					// Store custom fields prefixed with wither shipping_ or billing_.
				} elseif ( 0 === stripos( $key, 'billing_' ) || 0 === stripos( $key, 'shipping_' ) ) {
					$customer->update_meta_data( $key, $value );
				}
			}

			/**
			 * Action hook to adjust customer before save.
			 *
			 * @since 3.0.0
			 */
			do_action( 'woocommerce_checkout_update_customer', $customer, $data );

			$customer->save();
		}

		do_action( 'woocommerce_checkout_update_user_meta', $customer_id, $data );
	}

	/**
	 * If checkout failed during an AJAX call, send failure response.
	 */
	protected function send_ajax_failure_response() {
		if ( wp_doing_ajax() ) {
			// Only print notices if not reloading the checkout, otherwise they're lost in the page reload.
			if ( ! isset( WC()->session->reload_checkout ) ) {
				$messages = wc_print_notices( true );
			}

			$response = array(
				'result'   => 'failure',
				'messages' => isset( $messages ) ? $messages : '',
				'refresh'  => isset( WC()->session->refresh_totals ),
				'reload'   => isset( WC()->session->reload_checkout ),
			);

			unset( WC()->session->refresh_totals, WC()->session->reload_checkout );

			wp_send_json( $response );
		}
	}

	/**
	 * Process the checkout after the confirm order button is pressed.
	 *
	 * @throws Exception When validation fails.
	 */
	public function process_checkout() {
		try {
			$nonce_value    = wc_get_var( $_REQUEST['woocommerce-process-checkout-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // phpcs:ignore
			$expiry_message = sprintf(
				/* translators: %s: shop cart url */
				__( 'Sorry, your session has expired. <a href="%s" class="wc-backward">Return to shop</a>', 'woocommerce' ),
				esc_url( wc_get_page_permalink( 'shop' ) )
			);

			if ( empty( $nonce_value ) || ! wp_verify_nonce( $nonce_value, 'woocommerce-process_checkout' ) ) {
				// If the cart is empty, the nonce check failed because of session expiry.
				if ( WC()->cart->is_empty() ) {
					throw new Exception( $expiry_message );
				}

				WC()->session->set( 'refresh_totals', true );
				throw new Exception( __( 'We were unable to process your order, please try again.', 'woocommerce' ) );
			}

			wc_maybe_define_constant( 'WOOCOMMERCE_CHECKOUT', true );
			wc_set_time_limit( 0 );

			do_action( 'woocommerce_before_checkout_process' );

			if ( WC()->cart->is_empty() ) {
				throw new Exception( $expiry_message );
			}

			do_action( 'woocommerce_checkout_process' );

			$errors      = new WP_Error();
			$posted_data = $this->get_posted_data();

			// Update session for customer and totals.
			$this->update_session( $posted_data );

			// Validate posted data and cart items before proceeding.
			$this->validate_checkout( $posted_data, $errors );

			foreach ( $errors->errors as $code => $messages ) {
				$data = $errors->get_error_data( $code );
				foreach ( $messages as $message ) {
					wc_add_notice( $message, 'error', $data );
				}
			}

			if ( empty( $posted_data['woocommerce_checkout_update_totals'] ) && 0 === wc_notice_count( 'error' ) ) {
				$this->process_customer( $posted_data );
				$order_id = $this->create_order( $posted_data );
				$order    = wc_get_order( $order_id );

				if ( is_wp_error( $order_id ) ) {
					throw new Exception( $order_id->get_error_message() );
				}

				if ( ! $order ) {
					throw new Exception( __( 'Unable to create order.', 'woocommerce' ) );
				}

				do_action( 'woocommerce_checkout_order_processed', $order_id, $posted_data, $order );

				/**
				 * Note that woocommerce_cart_needs_payment is only used in
				 * WC_Checkout::process_checkout() to keep backwards compatibility.
				 * Use woocommerce_order_needs_payment instead.
				 *
				 * Note that at this point you can't rely on the Cart Object anymore,
				 * since it could be empty see:
				 * https://github.com/woocommerce/woocommerce/issues/24631
				 */
				if ( apply_filters( 'woocommerce_cart_needs_payment', $order->needs_payment(), WC()->cart ) ) {
					$this->process_order_payment( $order_id, $posted_data['payment_method'] );
				} else {
					$this->process_order_without_payment( $order_id );
				}
			}
		} catch ( Exception $e ) {
			wc_add_notice( $e->getMessage(), 'error' );
		}
		$this->send_ajax_failure_response();
	}

	/**
	 * Get a posted address field after sanitization and validation.
	 *
	 * @param string $key  Field key.
	 * @param string $type Type of address; 'billing' or 'shipping'.
	 * @return string
	 */
	public function get_posted_address_data( $key, $type = 'billing' ) {
		if ( 'billing' === $type || false === $this->legacy_posted_data['ship_to_different_address'] ) {
			$return = isset( $this->legacy_posted_data[ 'billing_' . $key ] ) ? $this->legacy_posted_data[ 'billing_' . $key ] : '';
		} else {
			$return = isset( $this->legacy_posted_data[ 'shipping_' . $key ] ) ? $this->legacy_posted_data[ 'shipping_' . $key ] : '';
		}
		return $return;
	}

	/**
	 * Gets the value either from POST, or from the customer object. Sets the default values in checkout fields.
	 *
	 * @param string $input Name of the input we want to grab data for. e.g. billing_country.
	 * @return string The default value.
	 */
	public function get_value( $input ) {
		// If the form was posted, get the posted value. This will only tend to happen when JavaScript is disabled client side.
		if ( ! empty( $_POST[ $input ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
			return wc_clean( wp_unslash( $_POST[ $input ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
		}

		// Allow 3rd parties to short circuit the logic and return their own default value.
		$value = apply_filters( 'woocommerce_checkout_get_value', null, $input );

		if ( ! is_null( $value ) ) {
			return $value;
		}

		/**
		 * For logged in customers, pull data from their account rather than the session which may contain incomplete data.
		 * Another reason is that WC sets shipping address to the billing address on the checkout updates unless the
		 * "ship to another address" box is checked. @see issue #20975.
		 */
		$customer_object = false;

		if ( is_user_logged_in() ) {
			// Load customer object, but keep it cached to avoid reloading it multiple times.
			if ( is_null( $this->logged_in_customer ) ) {
				$this->logged_in_customer = new WC_Customer( get_current_user_id(), true );
			}
			$customer_object = $this->logged_in_customer;
		}

		if ( ! $customer_object ) {
			$customer_object = WC()->customer;
		}

		if ( is_callable( array( $customer_object, "get_$input" ) ) ) {
			$value = $customer_object->{"get_$input"}();
		} elseif ( $customer_object->meta_exists( $input ) ) {
			$value = $customer_object->get_meta( $input, true );
		}

		if ( '' === $value ) {
			$value = null;
		}

		return apply_filters( 'default_checkout_' . $input, $value, $input );
	}
}