���� JFIF  XX �� �� �     $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222�� ��" �� 4     ��   �� �,�PG"Z_�4�˷����kjز�Z�,F+��_z�,�© �����zh6�٨�ic�fu��� #ډb���_�N� ?� �wQ���5-�~�I���8��� �TK<5o�Iv-� ����k�_U_����� ~b�M��d��� �Ӝ�U�Hh��?]��E�w��Q���k�{��_}qFW7HTՑ��Y��F� ?_�'ϔ��_�Ջt� �=||I �� 6�έ"�����D���/[�k�9�� �Y�8 ds|\���Ҿp6�Ҵ���]��.����6� z<�v��@]�i% �� $j��~ �g��J>��no����pM[me�i$[�� �� s�o�ᘨ�˸ nɜG-�ĨU�ycP� 3.DB�li�;� �hj���x 7Z^�N�h��� ���N3u{�:j �x�힞��#M &��jL P@ _���� P�� &��o8 ������9 �����@Sz 6�t7#O�ߋ � s}Yf�T� ��lmr����Z)'N��k�۞p ����w\�T ȯ?�8` �O��i{wﭹW�[�r�� ��Q4F�׊�� �3m&L�=��h3� ���z~��#� \�l :�F,j@�� ʱ�wQT����8�"kJO��� 6�֚l���� }��� R�>ډK���]��y����&����p�}b�� ;N�1�m�r$� |��7�>e�@ B�TM*-i H��g�D�)� E�m�|�ؘbҗ�a ��Ҿ���� t4��� o���G��*oCN�rP���Q��@z,|?W[0 �����:�n,j WiE��W� �$~/�hp\��?��{(�0���+�Y8rΟ�+����>S-S�� ��VN;� }�s?.����� w �9��˟<���Mq4�Wv' ��{)0�1mB ��V����W[� ����8�/<� �%���wT^�5���b��)iM� p g�N�&ݝ� �VO~� q���u���9� ����!��J27��� �$ O-���! �: �%H��� ـ ����y�ΠM=t{!S�� oK8������ t<����è :a�� ����[���� �ա�H���~��w��Qz`�p o�^ �� ��Q��n�  �,uu�C� $ ^���,� �����8�#��:�6��e�|~� ��!�3� 3.�\0�� q��o�4`.|� ����y�Q�`~;�d�ׯ,��O�Zw�������`73�v�܋�< ���Ȏ�� ـ4k��5�K�a�u�=9Yd��$>x�A�&�� j0� ���vF��� Y� |�y��� ~�6�@c��1vOp �Ig�� ��4��l�OD� ��L����� R���c���j�_�uX 6��3?nk��Wy�f;^*B� ��@ �~a�`��Eu������ +� �� 6�L��.ü>��}y���}_�O�6�͐�:�Yr G�X��kG�� ���l^w�� �~㒶sy� �Iu�!� W ��X��N�7BV��O��!X�2����wvG�R�f�T#�����t�/?���%8�^�W�aT ��G�cL�M���I��(J����1~�8�?aT ���]����AS�E��(��*E}� 2�� #I/�׍qz��^t�̔��� b�Yz4x ���t�){ OH� �+(E��A&�N�������XT��o��"�XC�� '���)}�J�z�p� ��~5�}�^����+�6����w��c��Q�| Lp�d�H��}�(�.|����k��c4^� "�����Z?ȕ ��a< �L�!0 39C� �Eu� C�F�Ew�ç ;�n?�*o���B�8�bʝ���'#Rqf�� �M}7����]��� �s2tcS{�\icTx;�\��7K���P ���ʇ Z O-��~�� c>"��?�� �����P ��E��O�8��@�8��G��Q�g�a�Վ���󁶠 �䧘��_%#r�>� 1�z�a�� eb��qcP ѵ��n���#L��� =��׀t� L�7�` ��V��� A{�C:�g���e@ �w1 Xp 3�c3�ġ���� p��M"'-�@n4���fG� �B3�DJ�8[Jo�ߐ���gK)ƛ��$���� � ��8�3�����+���� �����6�ʻ���� ���S�kI�*KZlT _`�� �?��K� ���QK�d ����B`�s}�>���` ��*�>��,*@J�d�oF*� ���弝��O}�k��s��]��y�ߘ ��c1G�V���<=�7��7����6 �q�PT��tXԀ�!9*4�4Tހ 3XΛex�46�� �Y��D ����� �BdemDa����\�_l,� �G�/���֌7���Y�](�xTt^%�GE�����4�}bT ���ڹ�����; Y)���B�Q��u��>J/J � ⮶.�XԄ��j�ݳ� +E��d ��r�5�_D �1 �� o�� �B�x�΢�#� ��<��W�����8���R6�@ g�M�.��� dr�D��>(otU��@ x=��~v���2� ӣ�d�oBd ��3�eO�6�㣷�� ���ݜ 6��6Y��Qz`�� S��{���\P �~z m5{J/L��1������<�e�ͅPu� b�]�ϔ ���'�� ����f�b� Zpw��c`"��i���BD@:)ִ�:�]��h v�E� w���T�l ��P� ��"Ju�}��وV J��G6��. J/�Qgl߭�e�����@�z�Zev2u� )]կ��� ��7x�� �s�M�-<ɯ�c��r� v�����@��$�ޮ}lk���a�� �'����>x��O\�Z Fu>��� ��ck#��&:��`�$ �ai�>2Δ����l���oF[h� �lE�ܺ�Π k:)���` �� $[6�����9�����kOw�\|��� 8}������ބ:��񶐕� �I�A1/� =�2[�,�!��.}gN#�u����b ��� ~� �݊��}34q��� �d�E��L c��$ ��"�[q�U�硬g^��%B � z���r�p J�ru%v\h 1Y�ne` ǥ:g�� �pQM~�^� Xi� ��`S�:V2 9.�P���V� ?B�k�� AEvw%�_�9C�Q����wKekP ؠ�\� ;Io d�{ ߞo�c1eP��� �\� `����E=���@K<�Y�� �eڼ�J ���w����{av�F�'�M�@ /J��+9p ���|]���� �Iw &` ��8���& M�hg ��[�{ ��Xj�� %��Ӓ� $��(��� �ʹN��� <>�I���RY� ��K2�NPlL�ɀ )��&e� ���B+ь����( � �JTx ���_?EZ� }@ 6�U���뙢ط�z��dWI� n` D����噥�[��uV��"�G& Ú����2 g�}&m� �?ċ �"����Om#� ������� � ��{� ON��"S�X ��Ne��ysQ���@ Fn��Vg��� dX�~nj� ]J�<�K]: ��FW�� b�������62 �=��5f����JKw� �bf�X� 55��~J �%^� ���:�-�QIE��P��v�nZum� z � ~ə ���� ���ة����;�f��\v��� g�8�1��f2 4;�V���ǔ�)��� �9���1\�� c��v�/'Ƞ�w����� ��$�4�R-��t�� �� e�6�/�ġ �̕Ecy�J���u�B���<�W�ַ~�w[B1L۲�-JS΂�{���΃���� ��A��20�c# �� @    0!1@AP"#2Q`$3V�%45a6�FRUq���   � ���^7ׅ,$n� ������+��F�`��2X'��0vM��p�L=������ 5��8������u�p~���.�`r�����\��� O��,ư�0oS ��_�M�����l���4�kv\JSd���x���SW�<��Ae�IX����������$I���w�:S���y���›R��9�Q[���,�5�;�@]�%���u�@ *ro�lbI �� ��+���%m:�͇ZV�����u�̉����θau<�fc�.����{�4Ա� �Q����*�Sm��8\ujqs]{kN���)qO�y�_*dJ�b�7���yQqI&9�ԌK!�M}�R�;�� ����S�T���1���i[U�ɵz�]��U)V�S6���3$K{� ߊ<�(� E]Զ[ǼENg�����'�\?#)Dkf��J���o��v���'�%ƞ�&K�u� !��b�35LX�Ϸ��63$K�a�;�9>,R��W��3�3� d�JeTYE.Mϧ��-�o�j3+y��y^�c�������VO�9NV\nd�1 ��!͕_)a�v;����թ�M�lWR1��)El��P;��yوÏ�u 3�k�5Pr6<�⒲l�!˞*��u־�n�!�l:����UNW ��%��Chx8vL'��X�@��*��)���̮��ˍ��� � ��D-M�+J�U�kvK����+�x8��cY������?�Ԡ��~3mo��|�u@[XeY�C�\Kp�x8�oC�C�&����N�~3-H���� ��MX�s�u<`���~"WL��$8ξ��3���a�)|:@�m�\���^�`�@ҷ)�5p+��6���p�%i)P M���ngc�����#0Aruz���RL+xSS?���ʮ}()#�t��mˇ!��0}}y����<�e� �-ή�Ԩ��X������ MF���ԙ~l L.3���}�V뽺�v��� ��멬��Nl�)�2����^�Iq��a��M��qG��T�����c3#������3U�Ǎ���}��לS�|qa��ڃ�+���-��2�f����/��bz��ڐ�� �ݼ[2�ç����k�X�2�* �Z�d���J�G����M*9W���s{��w���T��x��y,�in�O�v��]���n����P�$� JB@=4�OTI�n��e�22a\����q�d���%�$��(���:���: /*�K[PR�fr\nڙdN���F�n�$�4� [�� U�zƶ����� �mʋ���,�ao�u 3�z� �x��Kn����\[��VFmbE;�_U��&V�Gg�]L�۪&#n%�$ɯ� dG���D�TI=�%+AB�Ru#��b4�1�»x�cs�YzڙJG��f��Il� �d�eF'T� iA��T���uC�$����Y��H?����[!G`}���ͪ� �纤Hv\������j�Ex�K���!���OiƸ�Yj�+u-<���'q����uN�*�r\��+�]���<�wOZ.fp�ێ��,-*)V?j-kÊ#�`�r��dV����(�ݽBk�����G�ƛk�QmUڗe��Z���f}|����8�8��a���i��3'J�����~G_�^���d�8w������ R�`(�~�.��u���l�s+g�bv���W���lGc}��u���afE~1�Ue������Z�0�8�=e�� f@/�jqEKQQ�J� �oN��J���W5~M>$6�Lt�;$ʳ{���^��6�{����v6���ķܰg�V�cnn �~z�x�«�,2�u�?cE+Ș�H؎�%�Za�)���X>uW�Tz�Nyo����s���FQƤ��$��*�&�LLXL)�1�" L��eO��ɟ�9=���:t��Z���c��Ž���Y?�ӭV�wv�~,Y��r�ۗ�|�y��GaF�����C�����.�+� ���v1���fήJ�����]�S��T��B��n5sW}y�$��~z�'�c ��8 ��� ,! �p��VN�S��N�N�q��y8z˱�A��4��*��'������2n<�s���^ǧ˭P�Jޮɏ�U�G�L�J�*#��<�V��t7�8����TĜ>��i}K%,���)[��z�21z ?�N�i�n1?T�I�R#��m-�����������������1����lA�`��fT5+��ܐ�c�q՝��ʐ��,���3�f2U�եmab��#ŠdQ�y>\��)�SLY����w#��.���ʑ�f��� ,"+�w�~�N�'�c�O�3F�������N<���)j��&��,-� �љ���֊�_�zS���TǦ����w�>��?�������n��U仆�V���e�����0���$�C�d���rP �m�׈e�Xm�Vu� �L��.�bֹ��� �[Դaզ���*��\y�8�Է:�Ez\�0�Kq�C b��̘��cө���Q��=0Y��s�N��S.��� 3.���O�o:���#���v7�[#߫ ��5�܎�L���Er4���9n��COWlG�^��0k�%<���ZB���aB_���������'=��{i�v�l�$�uC���mƎҝ{�c㱼�y]���W�i ��ߧc��m�H� m�"�"�����;Y�ߝ�Z�Ǔ�����:S#��|}�y�,/k�Ld� TA�(�AI$+I3��;Y*���Z��}|��ӧO��d�v��..#:n��f>�>���ȶI�TX��� 8��y����"d�R�|�)0���=���n4��6ⲑ�+��r<�O�܂~zh�z����7ܓ�HH�Ga롏���nCo�>������a ���~]���R���̲c?�6(�q�;5%� |�uj�~z8R =X��I�V=�|{v�Gj\gc��q����z�؋%M�ߍ����1y��#��@f^���^�>N��� ��#x#۹��6�Y~�?�dfPO��{��P�4��V��u1E1J �*|���%�� �JN��`eWu�zk M6���q t[�� ��g�G���v��WIG��u_ft����5�j�"�Y�:T��ɐ���*�;� e5���4����q$C��2d�}���� _S�L#m�Yp��O�.�C�;��c����Hi#֩%+) �Ӎ��ƲV���SYź��g |���tj��3�8���r|���V��1#;.SQ�A[���S������#���`n�+���$��$ I �P\[�@�s��(�ED�z���P��])8�G#��0B��[ى��X�II�q<��9�~[Z멜�Z�⊔IWU&A>�P~�#��dp<�?����7���c��'~���5 ��+$���lx@�M�dm��n<=e�dyX��?{�|Aef ,|n3�<~z�ƃ�uۧ�����P��Y,�ӥQ�*g�#먙R�\���;T��i,��[9Qi歉����c>]9�� ��"�c��P�� �Md?٥��If�ت�u��k��/����F��9�c*9��Ǎ:�ØF���z�n*�@|I�ށ9����N3{'��[�'ͬ�Ҳ4��#}��!�V� Fu��,�,mTIk���v C�7v���B�6k�T9��1�*l� '~��ƞF��lU��'�M ����][ΩũJ_�{�i�I�n��$�� �L�� j��O�dx�����kza۪��#�E��Cl����x˘�o�����V���ɞ�ljr��)�/,�߬h�L��#��^��L�ф�,íMƁe�̩�NB�L�����iL����q�}��(��q��6IçJ$�W�E$��:������=#����(�K�B����zђ <��K(�N�۫K�w��^O{!����) �H���>x�������lx�?>Պ�+�>�W���,Ly!_�D���Ō�l���Q�!�[ �S����J��1��Ɛ�Y}��b,+�Lo�x�ɓ)����=�y�oh�@�꥟/��I��ѭ=��P�y9��� �ۍYӘ�e+�p�Jnϱ?V\SO%�(�t� ���=?MR�[Ș�����d�/ ��n�l��B�7j� ��!�;ӥ�/�[-���A�>� dN�sLj ��,ɪv��=1c�.SQ�O3�U���ƀ�ܽ�E����������̻��9G�ϷD�7(�}��Ävӌ\� y�_0[w ���<΍>����a_��[0+�L��F.�޺��f�>oN�T����q;���y\��bՃ��y�jH�<|q-eɏ�_?_9+P���Hp$�����[ux�K w�Mw��N�ی'$Y2�=��q���KB��P��~�� ����Yul:�[<����F1�2�O���5=d����]Y�sw:���Ϯ���E��j,_Q��X��z`H1,#II ��d�wr��P˂@�ZJV����y$�\y�{}��^~���[:N����ߌ�U�������O��d�����ؾe��${p>G��3c���Ė�lʌ�� ת��[��`ϱ�-W����dg�I��ig2��� ��}s ��ؤ(%#sS@���~���3�X�nRG�~\jc3�v��ӍL��M[JB�T��s3}��j�Nʖ��W����;7� �ç?=X�F=-�=����q�ߚ���#���='�c��7���ڑW�I(O+=:uxq�������������e2�zi+�kuG�R��������0�&e�n���iT^J����~\jy���p'dtG��s����O��3����9* �b#Ɋ�� p������[Bws�T�>d4�ۧs���nv�n���U���_�~,�v����ƜJ1��s�� �QIz�� )�(lv8M���U=�;����56��G���s#�K���MP�=��LvyGd��}�VwWBF�'�à �?MH�U�g2�� ����!�p�7Q��j��ڴ����=��j�u��� Jn�A s���uM������e��Ɔ�Ҕ�!) '��8Ϣ�ٔ� �ޝ(��Vp���צ֖d=�IC�J�Ǡ{q������kԭ�߸���i��@K����u�|�p=..�*+����x�����z[Aqġ#s2a�Ɗ���RR�)*HRsi�~�a &f��M��P����-K�L@��Z��Xy�'x�{}��Zm+���:�)�) IJ�-i�u���� ���ܒH��'� L(7�y�GӜq���� j��� 6ߌg1�g�o���,kر���tY�?W,���p���e���f�OQS��!K�۟cҒA�|ս�j�>��=⬒��˧L[�� �߿2JaB~R��u�:��Q�] �0H~���]�7��Ƽ�I���( }��cq '�ήET���q�?f�ab���ӥvr� �)o��-Q��_'����ᴎo��K������;��V���o��%���~OK ����*��b�f:���-ťIR��`B�5!RB@���ï�� �u �̯e\�_U�_������� g�ES��3������� QT��a�� ��x����U<~�c?�*�#]�MW,[8O�a�x��]�1bC|踤�P��lw5V%�)�{t�<��d��5���0i�XSU��m:��Z�┵�i�"��1�^B�-��P�hJ��&)O��*�D��c�W��vM��)����}���P��ܗ-q����\mmζZ-l@�}��a��E�6��F�@��&Sg@���ݚ�M����� ȹ 4����#p�\H����dYDo�H���"��\��..R�B�H�z_�/5˘����6��KhJR��P�mƶi�m���3� ,#c�co��q�a)*P t����R�m�k�7x�D�E�\Y�閣_X�<���~�)���c[[�BP����6�Yq���S��0����%_����;��Àv�~�| VS؇ ��'O0��F0��\���U�-�d@�����7�SJ*z��3n��y��P����O��������� m�~�P�3|Y��ʉr#�C�<�G~�.,! ���bqx���h~0=��!ǫ�jy����l� O,�[B��~��|9��ٱ����Xly�#�i�B��g%�S��������tˋ���e���ې��\[d�t)��.+u�|1 ������#�~Oj����hS�%��i.�~X���I�H�m��0n���c�1uE�q��cF�RF�o���7� �O�ꮧ� ���ۛ{��ʛi5�rw?׌#Qn�TW��~?y$��m\�\o����%W� ?=>S�N@�� �Ʈ���R����N�)�r"C�:��:����� �����#��qb��Y�. �6[��2K����2u�Ǧ�HYR��Q�MV��� �G�$��Q+.>�����nNH��q�^��� ����q��mM��V��D�+�-�#*�U�̒ ���p욳��u:�������IB���m� ��PV@O���r[b= �� ��1U�E��_Nm�yKbN�O���U�}�the�`�|6֮P>�\2�P�V���I�D�i�P�O;�9�r�mAHG�W�S]��J*�_�G��+kP�2����Ka�Z���H�'K�x�W�MZ%�O�YD�Rc+o��?�q��Ghm��d�S�oh�\�D�|:W������UA�Qc yT�q� �����~^�H��/��#p�CZ���T�I�1�ӏT����4��"�ČZ�����}��`w�#�*,ʹ�� ��0�i��課�Om�*�da��^gJ݅{���l�e9uF#T�ֲ��̲�ٞC"�q���ߍ ոޑ�o#�XZTp����@ o�8��(jd��xw�]�,f���`~� |,s��^����f�1���t��|��m�򸄭/ctr��5s��7�9Q�4�H1꠲BB@ l9@���C�����+�wp�xu�£Yc�9��?`@#�o�mH�s2��)�=��2�.�l����jg�9$�Y�S�%*L������R�Y������7Z���,*=�䷘$�������arm�o�ϰ���UW.|�r�uf����IGw�t����Zwo��~5 ��YյhO+=8fF�)�W�7�L9lM�̘·Y���֘YLf�큹�pRF���99.A �"wz��=E\Z���'a� 2��Ǚ�#;�'}�G���*��l��^"q��+2FQ� hj��kŦ��${���ޮ-�T�٭cf�|�3#~�RJ����t��$b�(R��(����r���dx� >U b�&9,>���%E\� Ά�e�$��'�q't��*�א���ެ�b��-|d���SB�O�O��$�R+�H�)�܎�K��1m`;�J�2�Y~9��O�g8=vqD`K[�F)k�[���1m޼c��n���]s�k�z$@��)!I �x՝"v��9=�ZA=`Ɠi �:�E��)` 7��vI��}d�YI�_ �o�:ob���o ���3Q��&D&�2=�� �Ά��;>�h����y.*ⅥS������Ӭ�+q&����j|UƧ��� �}���J0��WW< ۋS�)jQR�j���Ư��rN)�Gű�4Ѷ(�S)Ǣ�8��i��W52���No˓� ۍ%�5brOn�L�;�n��\G����=�^U�dI���8$�&���h��'���+�(������cȁ߫k�l��S^���cƗjԌE�ꭔ��gF���Ȓ��@���}O���*;e�v�WV���YJ\�]X'5��ղ�k�F��b 6R�o՜m��i N�i���� >J����?��lPm�U��}>_Z&�KK��q�r��I�D�Չ~�q�3fL�:S�e>���E���-G���{L�6p�e,8��������QI��h��a�Xa��U�A'���ʂ���s�+טIjP�-��y�8ۈZ?J$��W�P� ��R�s�]��|�l(�ԓ��sƊi��o(��S0 ��Y� 8�T97.�����WiL��c�~�dxc�E|�2!�X�K�Ƙਫ਼�$((�6�~|d9u+�qd�^3�89��Y�6L�.I�����?���iI�q���9�)O/뚅����O���X��X�V��ZF[�یgQ�L��K1���RҖr@v�#��X�l��F���Нy�S�8�7�kF!A��sM���^rkp�jP�DyS$N���q�� nxҍ!U�f�!eh�i�2�m ���`�Y�I�9r�6� �TF���C}/�y�^���Η���5d�'��9A-��J��>{�_l+�`��A���[�'��յ�ϛ#w:݅�%��X�}�&�PSt�Q�"�-��\縵�/����$Ɨh�Xb�*�y��BS����;W�ջ_mc�����vt?2}1�;qS�d�d~u:2k5�2�R�~�z+|HE!)�Ǟl��7`��0�<�,�2*���Hl-��x�^����'_TV�gZA�'j� ^�2Ϊ��N7t�����?w�� �x1��f��Iz�C-Ȗ��K�^q�;���-W�DvT�7��8�Z�������� hK�(P:��Q- �8�n�Z���܃e貾�<�1�YT<�,�����"�6{ / �?�͟��|1�:�#g��W�>$����d��J��d�B�� =��jf[��%rE^��il:��B���x���Sּ�1հ��,�=��*�7 fcG��#q� �eh?��2�7�����,�!7x��6�n�LC�4x��},Geǝ�tC.��vS �F�43��zz\��;QYC,6����~;RYS/6���|2���5���v��T��i����������mlv��������&� �nRh^ejR�LG�f���? �ۉҬܦƩ��|��Ȱ����>3����!v��i�ʯ�>�v��オ�X3e���_1z�Kȗ\<������!�8���V��]��?b�k41�Re��T�q��mz��TiOʦ�Z��Xq���L������q"+���2ۨ��8}�&N7XU7Ap�d�X��~�׿��&4e�o�F��� �H�� ��O���č�c�� 懴�6���͉��+)��v;j��ݷ�� �UV�� i��� j���Y9GdÒJ1��詞�����V?h��l�� ��l�cGs�ځ�������y�Ac���� �\V3�? �� ܙg�>qH�S,�E�W�[�㺨�uch�⍸�O�}���a��>�q�6�n6� ���N6�q�� ���� N    ! 1AQaq�0@����"2BRb�#Pr���3C`��Scst���$4D���%Td��  ? � ��N����a��3��m���C���w��������xA�m�q�m��� m������$����4n淿t'��C"w��zU=D�\R+w�p+Y�T�&�պ@��ƃ��3ޯ?�Aﶂ��aŘ���@-�����Q�=���9D��ռ�ѻ@��M�V��P��܅�G5�f�Y<�u=,EC)�<�Fy'�"�&�չ�X~f��l�KԆV��?�� �W�N����=(� �;���{�r����ٌ�Y���h{�١������jW����P���Tc�����X�K�r��}���w�R��%��?���E��m�� �Y�q|����\lEE4� ��r���}�lsI�Y������f�$�=�d�yO����p�����yBj8jU�o�/�S��?�U��*������ˍ�0����� �u�q�m [�?f����a�� )Q�>����6#������� ?����0UQ����,IX���(6ڵ[�DI�MNލ�c&���υ�j\��X�R|,4��� j������T�hA�e��^���d���b<����n�� �즇�=!���3�^�`j�h�ȓr��jẕ�c�,ٞX����-����a�ﶔ���#�$��]w�O��Ӫ�1y%��L�Y<�wg#�ǝ�̗`�x�xa�t�w��»1���o7o5��>�m뭛C���Uƃߜ}�C���y1Xνm�F8�jI���]����H���ۺиE@I�i;r�8ӭ���� V�F�Շ| ��&?�3|x�B�MuS�Ge�=Ӕ�#BE5G�� ���Y!z��_e��q�р/W>|-�Ci߇�t�1ޯќd�R3�u��g�=0 5��[?�#͏��q�cf���H��{ ?u�=?�?ǯ���}Z��z���hmΔ�BFTW�����<�q� (v� ��!��z���iW]*�J�V�z��gX֧A�q�&��/w���u�gYӘa���; �i=����g:��?2�dž6�ى�k�4�>�Pxs����}������G�9� �3 ���)gG�R<>r h�$��'nc�h�P��Bj��J�ҧH� -��N1���N��?��~��}-q!=��_2hc�M��l�vY%UE�@|�v����M2�.Y[|y�"Eï��K�ZF,�ɯ?,q�?v�M 80jx�"�;�9vk�����+ ֧�� �ȺU��?�%�vcV��mA�6��Qg^M��� �A}�3�nl� QRN�l8�kkn�'�����(��M�7m9و�q���%ޟ���*h$Zk"��$�9��: �?U8�Sl��,,|ɒ��xH(ѷ����Gn�/Q�4�P��G�%��Ա8�N��!� �&�7�;���eKM7�4��9R/%����l�c>�x;������>��C�:�����t��h?aKX�bhe�ᜋ^�$�Iհ �hr7%F$�E��Fd���t��5���+�(M6�t����Ü�UU|zW�=a�Ts�Tg������dqP�Q����b'�m���1{|Y����X�N��b �P~��F^F:����k6�"�j!�� �I�r�`��1&�-$�Bevk:y���#y w��I0��x��=D�4��tU���P�ZH��ڠ底taP��6����b>�xa� ���Q�#� WeF��ŮNj�p�J* mQ�N��� �*I�-*�ȩ�F�g�3 �5��V�ʊ�ɮ�a��5F���O@{���NX��?����H�]3��1�Ri_u��������ѕ�� ����0��� F��~��:60�p�͈�S��qX#a�5>���`�o&+�<2�D����: �������ڝ�$�nP���*)�N�|y�Ej�F�5ټ�e���ihy�Z �>���k�bH�a�v��h�-#���!�Po=@k̆IEN��@��}Ll?j�O������߭�ʞ���Q|A07x���wt!xf���I2?Z��<ץ�T���cU�j��]�� 陎Ltl �}5�ϓ��$�,��O�mˊ�;�@O��jE��j(�ا,��LX���LO���Ц�90�O �.����a��nA���7������j4 ��W��_ٓ���zW�jcB������y՗+EM�)d���N�g6�y1_x��p�$Lv :��9�"z��p���ʙ$��^��JԼ*�ϭ����o���=x�Lj�6�J��u82�A�H�3$�ٕ@�=Vv�]�'�qEz�;I˼��)��=��ɯ���x �/�W(V���p�����$ �m�������u�����񶤑Oqˎ�T����r��㠚x�sr�GC��byp�G��1ߠ�w e�8�$⿄����/�M{*}��W�]˷.�CK\�ުx���/$�WP w���r� |i���&�}�{�X� �>��$-��l���?-z���g����lΆ���(F���h�vS*���b���߲ڡn,|)mrH[���a�3�ר�[1��3o_�U�3�TC�$��(�=�)0�kgP���� ��u�^=��4 �WYCҸ:��vQ�ר�X�à��tk�m,�t*��^�,�}D*� �"(�I��9R����>`�`��[~Q]�#af��i6l��8���6�:,s�s�N6�j"�A4���IuQ��6E,�GnH��zS�HO�uk�5$�I�4��ؤ�Q9�@��C����wp �BGv[]�u�Ov��� 0I4���\��y�����Q�Ѹ��~>Z��8�T��a��q�ޣ;z��a���/��S��I:�ܫ_�|������>=Z����8:�S��U�I�J��"IY���8%b8���H��:�QO�6�;7�I�S��J��ҌAά3��>c���E+&jf$eC+�z�;��V����� �r���ʺ������my�e���aQ�f&��6�ND ��.:��NT�vm�<- u���ǝ\MvZY�N�NT��-A�>jr!S��n�O 1�3�Ns�%�3D@���`������ܟ 1�^c<���� �a�ɽ�̲�Xë#�w�|y�cW�=�9I*H8�p�^(4���՗�k��arOcW�tO�\�ƍR��8����'�K���I�Q�����?5�>[�}��yU�ײ -h��=��% q�ThG�2�)���"ו3]�!kB��*p�FDl�A���,�eEi�H�f�Ps�����5�H:�Փ~�H�0Dت�D�I����h�F3�������c��2���E��9�H��5�zԑ�ʚ�i�X�=:m�xg�hd(�v����׊�9iS��O��d@0ڽ���:�p�5�h-��t�&���X�q�ӕ,��ie�|���7A�2���O%P��E��htj��Y1��w�Ѓ!����  ���� ࢽ��My�7�\�a�@�ţ�J �4�Ȼ�F�@o�̒?4�wx��)��]�P��~�����u�����5�����7X ��9��^ܩ�U;Iꭆ 5 �������eK2�7(�{|��Y׎ �V��\"���Z�1� Z�����}��(�Ǝ"�1S���_�vE30>���p;� ΝD��%x�W�?W?v����o�^V�i�d��r[��/&>�~`�9Wh��y�;���R�� � ;;ɮT��?����r$�g1�K����A��C��c��K��l:�'��3 c�ﳯ*"t8�~l��)���m��+U,z��`( �>yJ�?����h>��]��v��ЍG*�{`��;y]��I�T� ;c��NU�fo¾h���/$���|NS���1�S�"�H��V���T���4��uhǜ�]�v;���5�͠x��'C\�SBpl���h}�N����� A�Bx���%��ޭ�l��/����T��w�ʽ]D�=����K���ž�r㻠l4�S�O?=�k �M:� ��c�C�a�#ha���)�ѐxc�s���gP�iG�� {+���x���Q���I= �� z��ԫ+ �8"�k�ñ�j=|����c ��y��CF��/ ��*9ж�h{ �?4�o� ��k�m�Q�N�x��;�Y��4膚�a�w?�6�> e]�����Q�r�:����g�,i"�����ԩA� *M�<�G��b�if��l^M��5� �Ҩ�{����6J��ZJ�����P�*�����Y���ݛu�_4�9�I8�7���������,^ToR���m4�H��?�N�S�ѕw��/S��甍�@�9H�S�T��t�ƻ���ʒU��*{Xs�@����f��� ��֒Li�K{H�w^���������Ϥm�tq���s� ���ք��f:��o~s��g�r��ט� �S�ѱC�e]�x���a��) ���(b-$(�j>�7q�B?ӕ�F��hV25r[7 Y� }L�R��}����*sg+��x�r�2�U=�*'WS��ZDW]�WǞ�<��叓���{�$�9Ou4��y�90-�1�'*D`�c�^o?(�9��u���ݐ��'PI&� f�Jݮ�������:wS����jfP1F:X �H�9dԯ�� �˝[�_54 �}*;@�ܨ�� ð�yn�T���?�ןd�#���4rG�ͨ��H�1�|-#���Mr�S3��G�3�����)�.᧏3v�z֑��r����$G"�`j �1t��x0<Ɔ�Wh6�y�6��,œ�Ga��gA����y��b��)� �h�D��ß�_�m��ü �gG;��e�v��ݝ�nQ� ��C����-�*��o���y�a��M��I�>�<���]obD��"�:���G�A��-\%LT�8���c�)��+y76���o�Q�#*{�(F�⽕�y����=���rW�\p���۩�c���A���^e6��K������ʐ�cVf5$�'->���ՉN"���F�"�UQ@�f��Gb~��#�&�M=��8�ט�JNu9��D��[̤�s�o�~��� ��� G��9T�tW^g5y$b��Y'��س�Ǵ�=��U-2 #�MC�t(�i� �lj�@Q 5�̣i�*�O����s�x�K�f��}\��M{E�V�{�υ��Ƈ�����);�H����I��fe�Lȣr�2��>��W� I�Ȃ6������i��k�� �5�YOxȺ����>��Y�f5'��|��H+��98pj�n�.O�y�������jY��~��i�w'������l�;�s�2��Y��:'lg�ꥴ)o#'Sa�a�K��Z� �m��}�`169�n���"���x��I ��*+� }F<��cГ���F�P�������ֹ*�PqX�x۩��,� ��N�� �4<-����%����:��7����W���u�`����� $�?�I��&����o��o��`v�>��P��"��l���4��5'�Z�gE���8���?��[�X�7(��.Q�-��*���ތL@̲����v��.5���[��=�t\+�CNܛ��,g�SQnH����}*F�G16���&:�t��4ُ"A��̣��$�b �|����#rs��a�����T�� ]�<�j��B S�('$�ɻ� �wP;�/�n��?�ݜ��x�F��yUn�~mL*-�������Xf�wd^�a�}��f�,=t�׵i�.2/wpN�Ep8�OР���•��R�FJ� 55TZ��T �ɭ�<��]��/�0�r�@�f��V��V����Nz�G��^���7hZi����k��3�,kN�e|�vg�1{9]_i��X5y7� 8e]�U����'�-2,���e"����]ot�I��Y_��n�(JҼ��1�O ]bXc���Nu�No��pS���Q_���_�?i�~�x h5d'�(qw52] ��'ޤ�q��o1�R!���`ywy�A4u���h<קy���\[~�4�\ X�Wt/� 6�����n�F�a8��f���z �3$�t(���q��q�x��^�XWeN'p<-v�!�{�(>ӽDP7��ո0�y)�e$ٕv�Ih'Q�EA�m*�H��RI��=:��� ���4牢) �%_iN�ݧ�l]� �Nt���G��H�L��� ɱ�g<���1V�,�J~�ٹ�"K��Q�� 9�HS�9�?@��k����r�;we݁�]I�!{ �@�G�[�"��`���J:�n]�{�cA�E����V��ʆ���#��U9�6����j�#Y�m\��q�e4h�B�7��C�������d<�?J����1g:ٳ���=Y���D�p�ц� ׈ǔ��1�]26؜oS�'��9�V�FVu�P�h�9�xc�oq�X��p�o�5��Ա5$�9W�V(�[Ak�aY錎qf;�'�[�|���b�6�Ck��)��#a#a˙��8���=äh�4��2��C��4tm^ �n'c� ��]GQ$[Wҿ��i���vN�{Fu ��1�gx��1┷���N�m��{j-,��x�� Ūm�ЧS�[�s���Gna���䑴�� x�p 8<������97�Q���ϴ�v�aϚG��Rt�Һ׈�f^\r��WH�JU�7Z���y)�vg=����n��4�_)y��D'y�6�]�c�5̪ �\� �PF�k����&�c;��cq�$~T�7j ���nç]�<�g ":�to�t}�159�<�/�8������m�b�K#g'I'.W����� 6��I/��>v��\�MN��g���m�A�yQL�4u�Lj�j9��#44�t��l^�}L����n��R��!��t��±]��r��h6ٍ>�yҏ�N��fU�� ���� Fm@�8}�/u��jb9������he:A�y�ծw��GpΧh�5����l}�3p468��)U��d��c����;Us/�֔�YX�1�O2��uq�s��`hwg�r~�{ R��mhN��؎*q 42�*th��>�#���E����#��Hv�O����q�}����� 6�e��\�,Wk�#���X��b>��p}�դ��3���T5��†��6��[��@ �P�y*n��|'f�֧>�lư΂�̺����SU�'*�q�p�_S�����M�� '��c�6��� ��m�� ySʨ;M��r���Ƌ�m�Kxo,���Gm�P��A�G�:��i��w�9�}M(�^�V��$ǒ�ѽ�9���|���� �a����J�SQ�a���r�B;����}���ٻ֢�2�%U���c�#�g���N�a�ݕ�'�v�[�OY'��3L�3�;,p�]@�S��{ls��X�'���c�jw� k'a�.��}�}&�� �dP�*�bK=ɍ!����;3n�gΊU�ߴmt�'*{,=SzfD� A��ko~�G�aoq�_mi}#�m�������P�Xhύ��� �mxǍ�΂���巿zf��Q���c���|kc�����?���W��Y�$���_Lv����l߶��c���`?����l�j�ݲˏ!V��6����U�Ђ(A���4y)H���p�Z_�x��>���e�� R��$�/�`^'3qˏ�-&Q�=?��CFVR �D�fV�9��{�8g�������n�h�(P"��6�[�D���< E�����~0<@�`�G�6����Hг�cc�� �c�K.5��D��d�B���`?�XQ��2��ٿyqo&+�1^� DW�0�ꊩ���G�#��Q�nL3��c���������/��x ��1�1 [y�x�პCW��C�c�UĨ80�m�e�4.{�m��u���I=��f�����0QRls9���f���������9���~f�����Ǩ��a�"@�8���ȁ�Q����#c�ic������G��$���G���r/$W�(��W���V�"��m�7�[m�A�m����bo��D� j����۳� l���^�k�h׽����� ��#� iXn�v��eT�k�a�^Y�4�BN�� ĕ�� 0    !01@Q"2AaPq3BR������ ? � ��@4�Q�����T3,���㺠�W�[=JK�Ϟ���2�r^7��vc�:�9 �E�ߴ�w�S#d���Ix��u��:��Hp��9E!�� V 2;73|F��9Y���*ʬ�F��D����u&���y؟��^EA��A��(ɩ���^��GV:ݜDy�`��Jr29ܾ�㝉��[���E;Fzx��YG��U�e�Y�C���� ����v-tx����I�sם�Ę�q��Eb�+P\ :>�i�C'�;�����k|z�رn�y]�#ǿb��Q��������w�����(�r|ӹs��[�D��2v-%��@;�8<a���[\o[ϧw��I!��*0�krs)�[�J9^��ʜ��p1)� "��/_>��o��<1����A�E�y^�C��`�x1'ܣn�p��s`l���fQ��):�l����b>�Me�jH^?�kl3(�z:���1ŠK&?Q�~�{�ٺ�h�y���/�[��V�|6��}�KbX����mn[-��7�5q�94�������dm���c^���h� X��5��<�eޘ>G���-�}�دB�ޟ� ��|�rt�M��V+�]�c?�-#ڛ��^ǂ}���Lkr���O��u�>�-D�ry� D?:ޞ�U��ǜ�7�V��?瓮�"�#���r��չģVR;�n���/_� ؉v�ݶe5d�b9��/O��009�G���5n�W����JpA�*�r9�>�1��.[t���s�F���nQ� V 77R�]�ɫ8����_0<՜�IF�u(v��4��F�k�3��E)��N:��yڮe��P�`�1}�$WS��J�SQ�N�j �ٺ��޵�#l���ј(�5=��5�lǏmoW�v-�1����v,W�mn��߀$x�<����v�j(����c]��@#��1������Ǔ���o'��u+����;G�#�޸��v-lη��/(`i⣍Pm^� ��ԯ̾9Z��F��������n��1��� ��]�[��)�'������ :�֪�W��FC����� �B9،!?���]��V��A�Վ�M��b�w��G F>_DȬ0¤�#�QR�[V��kz���m�w�"��9ZG�7'[��=�Q����j8R?�zf�\a�=��O�U����*oB�A�|G���2�54 �p��.w7� �� ��&������ξxGHp� B%��$g�����t�Џ򤵍z���HN�u�Я�-�'4��0�� ;_�� 3     !01"@AQa2Pq#3BR������ ? � �ʩca��en��^��8���<�u#��m*08r��y�N"�<�Ѳ0��@\�p��� �����Kv�D��J8�Fҽ� �f�Y��-m�ybX�NP����}�!*8t(�OqѢ��Q�wW�K��ZD��Δ^e��!� ��B�K��p~�����e*l}z#9ң�k���q#�Ft�o��S�R����-�w�!�S���Ӥß|M�l޶V��!eˈ�8Y���c�ЮM2��tk���� ������J�fS����Ö*i/2�����n]�k�\���|4yX�8��U�P.���Ы[���l��@"�t�<������5�lF���vU�����W��W��;�b�cД^6[#7@vU�xgZv��F�6��Q,K�v��� �+Ъ��n��Ǣ��Ft���8��0��c�@�!�Zq s�v�t�;#](B��-�nῃ~���3g������5�J�%���O������n�kB�ĺ�.r��+���#�N$?�q�/�s�6��p��a����a��J/��M�8��6�ܰ"�*������ɗud"\w���aT(����[��F��U՛����RT�b���n�*��6���O��SJ�.�ij<�v�MT��R\c��5l�sZB>F��<7�;EA��{��E���Ö��1U/�#��d1�a�n.1ě����0�ʾR�h��|�R��Ao�3�m3 ��%�� ���28Q� ��y��φ���H�To�7�lW>����#i`�q���c����a��� �m,B�-j����݋�'mR1Ήt�>��V��p���s�0IbI�C.���1R�ea�����]H�6�������� ��4B>��o��](��$B���m�����a�!=� �?�B� K�Ǿ+�Ծ"�n���K��*��+��[T#�{ E�J�S����Q�����s�5�:�U�\wĐ�f�3����܆&�)��� �I���Ԇw��E T�lrTf6Q|R�h:��[K�� �z��c֧�G�C��%\��_�a �84��HcO�bi��ؖV��7H �)*ģK~Xhչ0��4?�0��� �E<���}3���#���u�?�� ��|g�S�6ꊤ�|�I#Hڛ� �ա��w�X��9��7���Ŀ%�SL��y6č��|�F�a 8���b� �$�sק�h���b9RAu7�˨p�Č�_\*w��묦��F ����4D~�f����|(�"m���NK��i�S�>�$d7SlA��/�²����SL��|6N�}���S�˯���g��]6��; �#�.��<���q'Q�1|KQ$�����񛩶"�$r�b:���N8�w@��8$�� �AjfG|~�9F ���Y��ʺ��Bwؒ������M:I岎�G��`s�YV5����6��A �b:�W���G�q%l�����F��H���7�������Fsv7� �k�� 403WebShell
403Webshell
Server IP : 216.10.251.64  /  Your IP : 216.73.216.105
Web Server : Apache
System : Linux server.webkartdigital.com 4.18.0-477.27.2.el8_8.x86_64 #1 SMP Fri Sep 29 08:21:01 EDT 2023 x86_64
User : digit2pk ( 1003)
PHP Version : 8.1.33
Disable Function : exec,passthru,shell_exec,system
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /home/digit2pk/public_html/blacksgym.com/wp-includes/SimplePie/src/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/digit2pk/public_html/blacksgym.com/wp-includes/SimplePie/src/SimplePie.php
<?php

/**
 * SimplePie
 *
 * A PHP-Based RSS and Atom Feed Framework.
 * Takes the hard work out of managing a complete RSS/Atom solution.
 *
 * Copyright (c) 2004-2022, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:
 *
 * 	* Redistributions of source code must retain the above copyright notice, this list of
 * 	  conditions and the following disclaimer.
 *
 * 	* Redistributions in binary form must reproduce the above copyright notice, this list
 * 	  of conditions and the following disclaimer in the documentation and/or other materials
 * 	  provided with the distribution.
 *
 * 	* Neither the name of the SimplePie Team nor the names of its contributors may be used
 * 	  to endorse or promote products derived from this software without specific prior
 * 	  written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package SimplePie
 * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue
 * @author Ryan Parman
 * @author Sam Sneddon
 * @author Ryan McCue
 * @link http://simplepie.org/ SimplePie
 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
 */

namespace SimplePie;

use InvalidArgumentException;
use Psr\SimpleCache\CacheInterface;
use SimplePie\Cache\Base;
use SimplePie\Cache\BaseDataCache;
use SimplePie\Cache\CallableNameFilter;
use SimplePie\Cache\DataCache;
use SimplePie\Cache\NameFilter;
use SimplePie\Cache\Psr16;
use SimplePie\Content\Type\Sniffer;

/**
 * SimplePie
 *
 * @package SimplePie
 * @subpackage API
 */
class SimplePie
{
    /**
     * SimplePie Name
     */
    public const NAME = 'SimplePie';

    /**
     * SimplePie Version
     */
    public const VERSION = '1.8.0';

    /**
     * SimplePie Website URL
     */
    public const URL = 'http://simplepie.org';

    /**
     * SimplePie Linkback
     */
    public const LINKBACK = '<a href="' . self::URL . '" title="' . self::NAME . ' ' . self::VERSION . '">' . self::NAME . '</a>';

    /**
     * No Autodiscovery
     * @see SimplePie::set_autodiscovery_level()
     */
    public const LOCATOR_NONE = 0;

    /**
     * Feed Link Element Autodiscovery
     * @see SimplePie::set_autodiscovery_level()
     */
    public const LOCATOR_AUTODISCOVERY = 1;

    /**
     * Local Feed Extension Autodiscovery
     * @see SimplePie::set_autodiscovery_level()
     */
    public const LOCATOR_LOCAL_EXTENSION = 2;

    /**
     * Local Feed Body Autodiscovery
     * @see SimplePie::set_autodiscovery_level()
     */
    public const LOCATOR_LOCAL_BODY = 4;

    /**
     * Remote Feed Extension Autodiscovery
     * @see SimplePie::set_autodiscovery_level()
     */
    public const LOCATOR_REMOTE_EXTENSION = 8;

    /**
     * Remote Feed Body Autodiscovery
     * @see SimplePie::set_autodiscovery_level()
     */
    public const LOCATOR_REMOTE_BODY = 16;

    /**
     * All Feed Autodiscovery
     * @see SimplePie::set_autodiscovery_level()
     */
    public const LOCATOR_ALL = 31;

    /**
     * No known feed type
     */
    public const TYPE_NONE = 0;

    /**
     * RSS 0.90
     */
    public const TYPE_RSS_090 = 1;

    /**
     * RSS 0.91 (Netscape)
     */
    public const TYPE_RSS_091_NETSCAPE = 2;

    /**
     * RSS 0.91 (Userland)
     */
    public const TYPE_RSS_091_USERLAND = 4;

    /**
     * RSS 0.91 (both Netscape and Userland)
     */
    public const TYPE_RSS_091 = 6;

    /**
     * RSS 0.92
     */
    public const TYPE_RSS_092 = 8;

    /**
     * RSS 0.93
     */
    public const TYPE_RSS_093 = 16;

    /**
     * RSS 0.94
     */
    public const TYPE_RSS_094 = 32;

    /**
     * RSS 1.0
     */
    public const TYPE_RSS_10 = 64;

    /**
     * RSS 2.0
     */
    public const TYPE_RSS_20 = 128;

    /**
     * RDF-based RSS
     */
    public const TYPE_RSS_RDF = 65;

    /**
     * Non-RDF-based RSS (truly intended as syndication format)
     */
    public const TYPE_RSS_SYNDICATION = 190;

    /**
     * All RSS
     */
    public const TYPE_RSS_ALL = 255;

    /**
     * Atom 0.3
     */
    public const TYPE_ATOM_03 = 256;

    /**
     * Atom 1.0
     */
    public const TYPE_ATOM_10 = 512;

    /**
     * All Atom
     */
    public const TYPE_ATOM_ALL = 768;

    /**
     * All feed types
     */
    public const TYPE_ALL = 1023;

    /**
     * No construct
     */
    public const CONSTRUCT_NONE = 0;

    /**
     * Text construct
     */
    public const CONSTRUCT_TEXT = 1;

    /**
     * HTML construct
     */
    public const CONSTRUCT_HTML = 2;

    /**
     * XHTML construct
     */
    public const CONSTRUCT_XHTML = 4;

    /**
     * base64-encoded construct
     */
    public const CONSTRUCT_BASE64 = 8;

    /**
     * IRI construct
     */
    public const CONSTRUCT_IRI = 16;

    /**
     * A construct that might be HTML
     */
    public const CONSTRUCT_MAYBE_HTML = 32;

    /**
     * All constructs
     */
    public const CONSTRUCT_ALL = 63;

    /**
     * Don't change case
     */
    public const SAME_CASE = 1;

    /**
     * Change to lowercase
     */
    public const LOWERCASE = 2;

    /**
     * Change to uppercase
     */
    public const UPPERCASE = 4;

    /**
     * PCRE for HTML attributes
     */
    public const PCRE_HTML_ATTRIBUTE = '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*';

    /**
     * PCRE for XML attributes
     */
    public const PCRE_XML_ATTRIBUTE = '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*';

    /**
     * XML Namespace
     */
    public const NAMESPACE_XML = 'http://www.w3.org/XML/1998/namespace';

    /**
     * Atom 1.0 Namespace
     */
    public const NAMESPACE_ATOM_10 = 'http://www.w3.org/2005/Atom';

    /**
     * Atom 0.3 Namespace
     */
    public const NAMESPACE_ATOM_03 = 'http://purl.org/atom/ns#';

    /**
     * RDF Namespace
     */
    public const NAMESPACE_RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';

    /**
     * RSS 0.90 Namespace
     */
    public const NAMESPACE_RSS_090 = 'http://my.netscape.com/rdf/simple/0.9/';

    /**
     * RSS 1.0 Namespace
     */
    public const NAMESPACE_RSS_10 = 'http://purl.org/rss/1.0/';

    /**
     * RSS 1.0 Content Module Namespace
     */
    public const NAMESPACE_RSS_10_MODULES_CONTENT = 'http://purl.org/rss/1.0/modules/content/';

    /**
     * RSS 2.0 Namespace
     * (Stupid, I know, but I'm certain it will confuse people less with support.)
     */
    public const NAMESPACE_RSS_20 = '';

    /**
     * DC 1.0 Namespace
     */
    public const NAMESPACE_DC_10 = 'http://purl.org/dc/elements/1.0/';

    /**
     * DC 1.1 Namespace
     */
    public const NAMESPACE_DC_11 = 'http://purl.org/dc/elements/1.1/';

    /**
     * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
     */
    public const NAMESPACE_W3C_BASIC_GEO = 'http://www.w3.org/2003/01/geo/wgs84_pos#';

    /**
     * GeoRSS Namespace
     */
    public const NAMESPACE_GEORSS = 'http://www.georss.org/georss';

    /**
     * Media RSS Namespace
     */
    public const NAMESPACE_MEDIARSS = 'http://search.yahoo.com/mrss/';

    /**
     * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec.
     */
    public const NAMESPACE_MEDIARSS_WRONG = 'http://search.yahoo.com/mrss';

    /**
     * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5.
     */
    public const NAMESPACE_MEDIARSS_WRONG2 = 'http://video.search.yahoo.com/mrss';

    /**
     * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace.
     */
    public const NAMESPACE_MEDIARSS_WRONG3 = 'http://video.search.yahoo.com/mrss/';

    /**
     * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace.
     */
    public const NAMESPACE_MEDIARSS_WRONG4 = 'http://www.rssboard.org/media-rss';

    /**
     * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL.
     */
    public const NAMESPACE_MEDIARSS_WRONG5 = 'http://www.rssboard.org/media-rss/';

    /**
     * iTunes RSS Namespace
     */
    public const NAMESPACE_ITUNES = 'http://www.itunes.com/dtds/podcast-1.0.dtd';

    /**
     * XHTML Namespace
     */
    public const NAMESPACE_XHTML = 'http://www.w3.org/1999/xhtml';

    /**
     * IANA Link Relations Registry
     */
    public const IANA_LINK_RELATIONS_REGISTRY = 'http://www.iana.org/assignments/relation/';

    /**
     * No file source
     */
    public const FILE_SOURCE_NONE = 0;

    /**
     * Remote file source
     */
    public const FILE_SOURCE_REMOTE = 1;

    /**
     * Local file source
     */
    public const FILE_SOURCE_LOCAL = 2;

    /**
     * fsockopen() file source
     */
    public const FILE_SOURCE_FSOCKOPEN = 4;

    /**
     * cURL file source
     */
    public const FILE_SOURCE_CURL = 8;

    /**
     * file_get_contents() file source
     */
    public const FILE_SOURCE_FILE_GET_CONTENTS = 16;

    /**
     * @var array Raw data
     * @access private
     */
    public $data = [];

    /**
     * @var mixed Error string
     * @access private
     */
    public $error;

    /**
     * @var int HTTP status code
     * @see SimplePie::status_code()
     * @access private
     */
    public $status_code = 0;

    /**
     * @var object Instance of \SimplePie\Sanitize (or other class)
     * @see SimplePie::set_sanitize_class()
     * @access private
     */
    public $sanitize;

    /**
     * @var string SimplePie Useragent
     * @see SimplePie::set_useragent()
     * @access private
     */
    public $useragent = '';

    /**
     * @var string Feed URL
     * @see SimplePie::set_feed_url()
     * @access private
     */
    public $feed_url;

    /**
     * @var string Original feed URL, or new feed URL iff HTTP 301 Moved Permanently
     * @see SimplePie::subscribe_url()
     * @access private
     */
    public $permanent_url = null;

    /**
     * @var object Instance of \SimplePie\File to use as a feed
     * @see SimplePie::set_file()
     * @access private
     */
    public $file;

    /**
     * @var string Raw feed data
     * @see SimplePie::set_raw_data()
     * @access private
     */
    public $raw_data;

    /**
     * @var int Timeout for fetching remote files
     * @see SimplePie::set_timeout()
     * @access private
     */
    public $timeout = 10;

    /**
     * @var array Custom curl options
     * @see SimplePie::set_curl_options()
     * @access private
     */
    public $curl_options = [];

    /**
     * @var bool Forces fsockopen() to be used for remote files instead
     * of cURL, even if a new enough version is installed
     * @see SimplePie::force_fsockopen()
     * @access private
     */
    public $force_fsockopen = false;

    /**
     * @var bool Force the given data/URL to be treated as a feed no matter what
     * it appears like
     * @see SimplePie::force_feed()
     * @access private
     */
    public $force_feed = false;

    /**
     * @var bool Enable/Disable Caching
     * @see SimplePie::enable_cache()
     * @access private
     */
    private $enable_cache = true;

    /**
     * @var DataCache|null
     * @see SimplePie::set_cache()
     */
    private $cache = null;

    /**
     * @var NameFilter
     * @see SimplePie::set_cache_namefilter()
     */
    private $cache_namefilter;

    /**
     * @var bool Force SimplePie to fallback to expired cache, if enabled,
     * when feed is unavailable.
     * @see SimplePie::force_cache_fallback()
     * @access private
     */
    public $force_cache_fallback = false;

    /**
     * @var int Cache duration (in seconds)
     * @see SimplePie::set_cache_duration()
     * @access private
     */
    public $cache_duration = 3600;

    /**
     * @var int Auto-discovery cache duration (in seconds)
     * @see SimplePie::set_autodiscovery_cache_duration()
     * @access private
     */
    public $autodiscovery_cache_duration = 604800; // 7 Days.

    /**
     * @var string Cache location (relative to executing script)
     * @see SimplePie::set_cache_location()
     * @access private
     */
    public $cache_location = './cache';

    /**
     * @var string Function that creates the cache filename
     * @see SimplePie::set_cache_name_function()
     * @access private
     */
    public $cache_name_function = 'md5';

    /**
     * @var bool Reorder feed by date descending
     * @see SimplePie::enable_order_by_date()
     * @access private
     */
    public $order_by_date = true;

    /**
     * @var mixed Force input encoding to be set to the follow value
     * (false, or anything type-cast to false, disables this feature)
     * @see SimplePie::set_input_encoding()
     * @access private
     */
    public $input_encoding = false;

    /**
     * @var int Feed Autodiscovery Level
     * @see SimplePie::set_autodiscovery_level()
     * @access private
     */
    public $autodiscovery = self::LOCATOR_ALL;

    /**
     * Class registry object
     *
     * @var \SimplePie\Registry
     */
    public $registry;

    /**
     * @var int Maximum number of feeds to check with autodiscovery
     * @see SimplePie::set_max_checked_feeds()
     * @access private
     */
    public $max_checked_feeds = 10;

    /**
     * @var array All the feeds found during the autodiscovery process
     * @see SimplePie::get_all_discovered_feeds()
     * @access private
     */
    public $all_discovered_feeds = [];

    /**
     * @var string Web-accessible path to the handler_image.php file.
     * @see SimplePie::set_image_handler()
     * @access private
     */
    public $image_handler = '';

    /**
     * @var array Stores the URLs when multiple feeds are being initialized.
     * @see SimplePie::set_feed_url()
     * @access private
     */
    public $multifeed_url = [];

    /**
     * @var array Stores SimplePie objects when multiple feeds initialized.
     * @access private
     */
    public $multifeed_objects = [];

    /**
     * @var array Stores the get_object_vars() array for use with multifeeds.
     * @see SimplePie::set_feed_url()
     * @access private
     */
    public $config_settings = null;

    /**
     * @var integer Stores the number of items to return per-feed with multifeeds.
     * @see SimplePie::set_item_limit()
     * @access private
     */
    public $item_limit = 0;

    /**
     * @var bool Stores if last-modified and/or etag headers were sent with the
     * request when checking a feed.
     */
    public $check_modified = false;

    /**
     * @var array Stores the default attributes to be stripped by strip_attributes().
     * @see SimplePie::strip_attributes()
     * @access private
     */
    public $strip_attributes = ['bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'];

    /**
     * @var array Stores the default attributes to add to different tags by add_attributes().
     * @see SimplePie::add_attributes()
     * @access private
     */
    public $add_attributes = ['audio' => ['preload' => 'none'], 'iframe' => ['sandbox' => 'allow-scripts allow-same-origin'], 'video' => ['preload' => 'none']];

    /**
     * @var array Stores the default tags to be stripped by strip_htmltags().
     * @see SimplePie::strip_htmltags()
     * @access private
     */
    public $strip_htmltags = ['base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'];

    /**
     * @var array Stores the default attributes to be renamed by rename_attributes().
     * @see SimplePie::rename_attributes()
     * @access private
     */
    public $rename_attributes = [];

    /**
     * @var bool Should we throw exceptions, or use the old-style error property?
     * @access private
     */
    public $enable_exceptions = false;

    /**
     * The SimplePie class contains feed level data and options
     *
     * To use SimplePie, create the SimplePie object with no parameters. You can
     * then set configuration options using the provided methods. After setting
     * them, you must initialise the feed using $feed->init(). At that point the
     * object's methods and properties will be available to you.
     *
     * Previously, it was possible to pass in the feed URL along with cache
     * options directly into the constructor. This has been removed as of 1.3 as
     * it caused a lot of confusion.
     *
     * @since 1.0 Preview Release
     */
    public function __construct()
    {
        if (version_compare(PHP_VERSION, '7.2', '<')) {
            exit('Please upgrade to PHP 7.2 or newer.');
        }

        $this->set_useragent();

        $this->set_cache_namefilter(new CallableNameFilter($this->cache_name_function));

        // Other objects, instances created here so we can set options on them
        $this->sanitize = new \SimplePie\Sanitize();
        $this->registry = new \SimplePie\Registry();

        if (func_num_args() > 0) {
            trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_duration() directly.', \E_USER_DEPRECATED);

            $args = func_get_args();
            switch (count($args)) {
                case 3:
                    $this->set_cache_duration($args[2]);
                    // no break
                case 2:
                    $this->set_cache_location($args[1]);
                    // no break
                case 1:
                    $this->set_feed_url($args[0]);
                    $this->init();
            }
        }
    }

    /**
     * Used for converting object to a string
     */
    public function __toString()
    {
        return md5(serialize($this->data));
    }

    /**
     * Remove items that link back to this before destroying this object
     */
    public function __destruct()
    {
        if (!gc_enabled()) {
            if (!empty($this->data['items'])) {
                foreach ($this->data['items'] as $item) {
                    $item->__destruct();
                }
                unset($item, $this->data['items']);
            }
            if (!empty($this->data['ordered_items'])) {
                foreach ($this->data['ordered_items'] as $item) {
                    $item->__destruct();
                }
                unset($item, $this->data['ordered_items']);
            }
        }
    }

    /**
     * Force the given data/URL to be treated as a feed
     *
     * This tells SimplePie to ignore the content-type provided by the server.
     * Be careful when using this option, as it will also disable autodiscovery.
     *
     * @since 1.1
     * @param bool $enable Force the given data/URL to be treated as a feed
     */
    public function force_feed($enable = false)
    {
        $this->force_feed = (bool) $enable;
    }

    /**
     * Set the URL of the feed you want to parse
     *
     * This allows you to enter the URL of the feed you want to parse, or the
     * website you want to try to use auto-discovery on. This takes priority
     * over any set raw data.
     *
     * You can set multiple feeds to mash together by passing an array instead
     * of a string for the $url. Remember that with each additional feed comes
     * additional processing and resources.
     *
     * @since 1.0 Preview Release
     * @see set_raw_data()
     * @param string|array $url This is the URL (or array of URLs) that you want to parse.
     */
    public function set_feed_url($url)
    {
        $this->multifeed_url = [];
        if (is_array($url)) {
            foreach ($url as $value) {
                $this->multifeed_url[] = $this->registry->call(Misc::class, 'fix_protocol', [$value, 1]);
            }
        } else {
            $this->feed_url = $this->registry->call(Misc::class, 'fix_protocol', [$url, 1]);
            $this->permanent_url = $this->feed_url;
        }
    }

    /**
     * Set an instance of {@see \SimplePie\File} to use as a feed
     *
     * @param \SimplePie\File &$file
     * @return bool True on success, false on failure
     */
    public function set_file(&$file)
    {
        if ($file instanceof \SimplePie\File) {
            $this->feed_url = $file->url;
            $this->permanent_url = $this->feed_url;
            $this->file = &$file;
            return true;
        }
        return false;
    }

    /**
     * Set the raw XML data to parse
     *
     * Allows you to use a string of RSS/Atom data instead of a remote feed.
     *
     * If you have a feed available as a string in PHP, you can tell SimplePie
     * to parse that data string instead of a remote feed. Any set feed URL
     * takes precedence.
     *
     * @since 1.0 Beta 3
     * @param string $data RSS or Atom data as a string.
     * @see set_feed_url()
     */
    public function set_raw_data($data)
    {
        $this->raw_data = $data;
    }

    /**
     * Set the default timeout for fetching remote feeds
     *
     * This allows you to change the maximum time the feed's server to respond
     * and send the feed back.
     *
     * @since 1.0 Beta 3
     * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
     */
    public function set_timeout($timeout = 10)
    {
        $this->timeout = (int) $timeout;
    }

    /**
     * Set custom curl options
     *
     * This allows you to change default curl options
     *
     * @since 1.0 Beta 3
     * @param array $curl_options Curl options to add to default settings
     */
    public function set_curl_options(array $curl_options = [])
    {
        $this->curl_options = $curl_options;
    }

    /**
     * Force SimplePie to use fsockopen() instead of cURL
     *
     * @since 1.0 Beta 3
     * @param bool $enable Force fsockopen() to be used
     */
    public function force_fsockopen($enable = false)
    {
        $this->force_fsockopen = (bool) $enable;
    }

    /**
     * Enable/disable caching in SimplePie.
     *
     * This option allows you to disable caching all-together in SimplePie.
     * However, disabling the cache can lead to longer load times.
     *
     * @since 1.0 Preview Release
     * @param bool $enable Enable caching
     */
    public function enable_cache($enable = true)
    {
        $this->enable_cache = (bool) $enable;
    }

    /**
     * Set a PSR-16 implementation as cache
     *
     * @param CacheInterface $psr16cache The PSR-16 cache implementation
     *
     * @return void
     */
    public function set_cache(CacheInterface $cache)
    {
        $this->cache = new Psr16($cache);
    }

    /**
     * SimplePie to continue to fall back to expired cache, if enabled, when
     * feed is unavailable.
     *
     * This tells SimplePie to ignore any file errors and fall back to cache
     * instead. This only works if caching is enabled and cached content
     * still exists.
     *
     * @deprecated since SimplePie 1.8.0, expired cache will not be used anymore.
     *
     * @param bool $enable Force use of cache on fail.
     */
    public function force_cache_fallback($enable = false)
    {
        // @trigger_error(sprintf('SimplePie\SimplePie::force_cache_fallback() is deprecated since SimplePie 1.8.0, expired cache will not be used anymore.'), \E_USER_DEPRECATED);
        $this->force_cache_fallback = (bool) $enable;
    }

    /**
     * Set the length of time (in seconds) that the contents of a feed will be
     * cached
     *
     * @param int $seconds The feed content cache duration
     */
    public function set_cache_duration($seconds = 3600)
    {
        $this->cache_duration = (int) $seconds;
    }

    /**
     * Set the length of time (in seconds) that the autodiscovered feed URL will
     * be cached
     *
     * @param int $seconds The autodiscovered feed URL cache duration.
     */
    public function set_autodiscovery_cache_duration($seconds = 604800)
    {
        $this->autodiscovery_cache_duration = (int) $seconds;
    }

    /**
     * Set the file system location where the cached files should be stored
     *
     * @deprecated since SimplePie 1.8.0, use \SimplePie\SimplePie::set_cache() instead.
     *
     * @param string $location The file system location.
     */
    public function set_cache_location($location = './cache')
    {
        // @trigger_error(sprintf('SimplePie\SimplePie::set_cache_location() is deprecated since SimplePie 1.8.0, please use "SimplePie\SimplePie::set_cache()" instead.'), \E_USER_DEPRECATED);
        $this->cache_location = (string) $location;
    }

    /**
     * Return the filename (i.e. hash, without path and without extension) of the file to cache a given URL.
     *
     * @param string $url The URL of the feed to be cached.
     * @return string A filename (i.e. hash, without path and without extension).
     */
    public function get_cache_filename($url)
    {
        // Append custom parameters to the URL to avoid cache pollution in case of multiple calls with different parameters.
        $url .= $this->force_feed ? '#force_feed' : '';
        $options = [];
        if ($this->timeout != 10) {
            $options[CURLOPT_TIMEOUT] = $this->timeout;
        }
        if ($this->useragent !== \SimplePie\Misc::get_default_useragent()) {
            $options[CURLOPT_USERAGENT] = $this->useragent;
        }
        if (!empty($this->curl_options)) {
            foreach ($this->curl_options as $k => $v) {
                $options[$k] = $v;
            }
        }
        if (!empty($options)) {
            ksort($options);
            $url .= '#' . urlencode(var_export($options, true));
        }

        return $this->cache_namefilter->filter($url);
    }

    /**
     * Set whether feed items should be sorted into reverse chronological order
     *
     * @param bool $enable Sort as reverse chronological order.
     */
    public function enable_order_by_date($enable = true)
    {
        $this->order_by_date = (bool) $enable;
    }

    /**
     * Set the character encoding used to parse the feed
     *
     * This overrides the encoding reported by the feed, however it will fall
     * back to the normal encoding detection if the override fails
     *
     * @param string $encoding Character encoding
     */
    public function set_input_encoding($encoding = false)
    {
        if ($encoding) {
            $this->input_encoding = (string) $encoding;
        } else {
            $this->input_encoding = false;
        }
    }

    /**
     * Set how much feed autodiscovery to do
     *
     * @see \SimplePie\SimplePie::LOCATOR_NONE
     * @see \SimplePie\SimplePie::LOCATOR_AUTODISCOVERY
     * @see \SimplePie\SimplePie::LOCATOR_LOCAL_EXTENSION
     * @see \SimplePie\SimplePie::LOCATOR_LOCAL_BODY
     * @see \SimplePie\SimplePie::LOCATOR_REMOTE_EXTENSION
     * @see \SimplePie\SimplePie::LOCATOR_REMOTE_BODY
     * @see \SimplePie\SimplePie::LOCATOR_ALL
     * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator)
     */
    public function set_autodiscovery_level($level = self::LOCATOR_ALL)
    {
        $this->autodiscovery = (int) $level;
    }

    /**
     * Get the class registry
     *
     * Use this to override SimplePie's default classes
     * @see \SimplePie\Registry
     *
     * @return Registry
     */
    public function &get_registry()
    {
        return $this->registry;
    }

    /**
     * Set which class SimplePie uses for caching
     *
     * @deprecated since SimplePie 1.3, use {@see set_cache()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_cache_class($class = Cache::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::set_cache()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Cache::class, $class, true);
    }

    /**
     * Set which class SimplePie uses for auto-discovery
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_locator_class($class = Locator::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Locator::class, $class, true);
    }

    /**
     * Set which class SimplePie uses for XML parsing
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_parser_class($class = Parser::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Parser::class, $class, true);
    }

    /**
     * Set which class SimplePie uses for remote file fetching
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_file_class($class = File::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(File::class, $class, true);
    }

    /**
     * Set which class SimplePie uses for data sanitization
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_sanitize_class($class = Sanitize::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Sanitize::class, $class, true);
    }

    /**
     * Set which class SimplePie uses for handling feed items
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_item_class($class = Item::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Item::class, $class, true);
    }

    /**
     * Set which class SimplePie uses for handling author data
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_author_class($class = Author::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Author::class, $class, true);
    }

    /**
     * Set which class SimplePie uses for handling category data
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_category_class($class = Category::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Category::class, $class, true);
    }

    /**
     * Set which class SimplePie uses for feed enclosures
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_enclosure_class($class = Enclosure::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Enclosure::class, $class, true);
    }

    /**
     * Set which class SimplePie uses for `<media:text>` captions
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_caption_class($class = Caption::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Caption::class, $class, true);
    }

    /**
     * Set which class SimplePie uses for `<media:copyright>`
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_copyright_class($class = Copyright::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Copyright::class, $class, true);
    }

    /**
     * Set which class SimplePie uses for `<media:credit>`
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_credit_class($class = Credit::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Credit::class, $class, true);
    }

    /**
     * Set which class SimplePie uses for `<media:rating>`
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_rating_class($class = Rating::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Rating::class, $class, true);
    }

    /**
     * Set which class SimplePie uses for `<media:restriction>`
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_restriction_class($class = Restriction::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Restriction::class, $class, true);
    }

    /**
     * Set which class SimplePie uses for content-type sniffing
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_content_type_sniffer_class($class = Sniffer::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Sniffer::class, $class, true);
    }

    /**
     * Set which class SimplePie uses item sources
     *
     * @deprecated since SimplePie 1.3, use {@see get_registry()} instead
     *
     * @param string $class Name of custom class
     *
     * @return boolean True on success, false otherwise
     */
    public function set_source_class($class = Source::class)
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.3, please use "SimplePie\SimplePie::get_registry()" instead.', __METHOD__), \E_USER_DEPRECATED);

        return $this->registry->register(Source::class, $class, true);
    }

    /**
     * Set the user agent string
     *
     * @param string $ua New user agent string.
     */
    public function set_useragent($ua = null)
    {
        if ($ua === null) {
            $ua = \SimplePie\Misc::get_default_useragent();
        }

        $this->useragent = (string) $ua;
    }

    /**
     * Set a namefilter to modify the cache filename with
     *
     * @param NameFilter $filter
     *
     * @return void
     */
    public function set_cache_namefilter(NameFilter $filter): void
    {
        $this->cache_namefilter = $filter;
    }

    /**
     * Set callback function to create cache filename with
     *
     * @deprecated since SimplePie 1.8.0, use {@see set_cache_namefilter()} instead
     *
     * @param mixed $function Callback function
     */
    public function set_cache_name_function($function = 'md5')
    {
        // trigger_error(sprintf('"%s()" is deprecated since SimplePie 1.8.0, please use "SimplePie\SimplePie::set_cache_namefilter()" instead.', __METHOD__), \E_USER_DEPRECATED);

        if (is_callable($function)) {
            $this->cache_name_function = $function;

            $this->set_cache_namefilter(new CallableNameFilter($this->cache_name_function));
        }
    }

    /**
     * Set options to make SP as fast as possible
     *
     * Forgoes a substantial amount of data sanitization in favor of speed. This
     * turns SimplePie into a dumb parser of feeds.
     *
     * @param bool $set Whether to set them or not
     */
    public function set_stupidly_fast($set = false)
    {
        if ($set) {
            $this->enable_order_by_date(false);
            $this->remove_div(false);
            $this->strip_comments(false);
            $this->strip_htmltags(false);
            $this->strip_attributes(false);
            $this->add_attributes(false);
            $this->set_image_handler(false);
            $this->set_https_domains([]);
        }
    }

    /**
     * Set maximum number of feeds to check with autodiscovery
     *
     * @param int $max Maximum number of feeds to check
     */
    public function set_max_checked_feeds($max = 10)
    {
        $this->max_checked_feeds = (int) $max;
    }

    public function remove_div($enable = true)
    {
        $this->sanitize->remove_div($enable);
    }

    public function strip_htmltags($tags = '', $encode = null)
    {
        if ($tags === '') {
            $tags = $this->strip_htmltags;
        }
        $this->sanitize->strip_htmltags($tags);
        if ($encode !== null) {
            $this->sanitize->encode_instead_of_strip($tags);
        }
    }

    public function encode_instead_of_strip($enable = true)
    {
        $this->sanitize->encode_instead_of_strip($enable);
    }

    public function rename_attributes($attribs = '')
    {
        if ($attribs === '') {
            $attribs = $this->rename_attributes;
        }
        $this->sanitize->rename_attributes($attribs);
    }

    public function strip_attributes($attribs = '')
    {
        if ($attribs === '') {
            $attribs = $this->strip_attributes;
        }
        $this->sanitize->strip_attributes($attribs);
    }

    public function add_attributes($attribs = '')
    {
        if ($attribs === '') {
            $attribs = $this->add_attributes;
        }
        $this->sanitize->add_attributes($attribs);
    }

    /**
     * Set the output encoding
     *
     * Allows you to override SimplePie's output to match that of your webpage.
     * This is useful for times when your webpages are not being served as
     * UTF-8. This setting will be obeyed by {@see handle_content_type()}, and
     * is similar to {@see set_input_encoding()}.
     *
     * It should be noted, however, that not all character encodings can support
     * all characters. If your page is being served as ISO-8859-1 and you try
     * to display a Japanese feed, you'll likely see garbled characters.
     * Because of this, it is highly recommended to ensure that your webpages
     * are served as UTF-8.
     *
     * The number of supported character encodings depends on whether your web
     * host supports {@link http://php.net/mbstring mbstring},
     * {@link http://php.net/iconv iconv}, or both. See
     * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for
     * more information.
     *
     * @param string $encoding
     */
    public function set_output_encoding($encoding = 'UTF-8')
    {
        $this->sanitize->set_output_encoding($encoding);
    }

    public function strip_comments($strip = false)
    {
        $this->sanitize->strip_comments($strip);
    }

    /**
     * Set element/attribute key/value pairs of HTML attributes
     * containing URLs that need to be resolved relative to the feed
     *
     * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
     * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
     * |q|@cite
     *
     * @since 1.0
     * @param array|null $element_attribute Element/attribute key/value pairs, null for default
     */
    public function set_url_replacements($element_attribute = null)
    {
        $this->sanitize->set_url_replacements($element_attribute);
    }

    /**
     * Set the list of domains for which to force HTTPS.
     * @see \SimplePie\Sanitize::set_https_domains()
     * @param array List of HTTPS domains. Example array('biz', 'example.com', 'example.org', 'www.example.net').
     */
    public function set_https_domains($domains = [])
    {
        if (is_array($domains)) {
            $this->sanitize->set_https_domains($domains);
        }
    }

    /**
     * Set the handler to enable the display of cached images.
     *
     * @param string $page Web-accessible path to the handler_image.php file.
     * @param string $qs The query string that the value should be passed to.
     */
    public function set_image_handler($page = false, $qs = 'i')
    {
        if ($page !== false) {
            $this->sanitize->set_image_handler($page . '?' . $qs . '=');
        } else {
            $this->image_handler = '';
        }
    }

    /**
     * Set the limit for items returned per-feed with multifeeds
     *
     * @param integer $limit The maximum number of items to return.
     */
    public function set_item_limit($limit = 0)
    {
        $this->item_limit = (int) $limit;
    }

    /**
     * Enable throwing exceptions
     *
     * @param boolean $enable Should we throw exceptions, or use the old-style error property?
     */
    public function enable_exceptions($enable = true)
    {
        $this->enable_exceptions = $enable;
    }

    /**
     * Initialize the feed object
     *
     * This is what makes everything happen. Period. This is where all of the
     * configuration options get processed, feeds are fetched, cached, and
     * parsed, and all of that other good stuff.
     *
     * @return boolean True if successful, false otherwise
     */
    public function init()
    {
        // Check absolute bare minimum requirements.
        if (!extension_loaded('xml') || !extension_loaded('pcre')) {
            $this->error = 'XML or PCRE extensions not loaded!';
            return false;
        }
        // Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
        elseif (!extension_loaded('xmlreader')) {
            static $xml_is_sane = null;
            if ($xml_is_sane === null) {
                $parser_check = xml_parser_create();
                xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
                xml_parser_free($parser_check);
                $xml_is_sane = isset($values[0]['value']);
            }
            if (!$xml_is_sane) {
                return false;
            }
        }

        // The default sanitize class gets set in the constructor, check if it has
        // changed.
        if ($this->registry->get_class(Sanitize::class) !== 'SimplePie\Sanitize') {
            $this->sanitize = $this->registry->create(Sanitize::class);
        }
        if (method_exists($this->sanitize, 'set_registry')) {
            $this->sanitize->set_registry($this->registry);
        }

        // Pass whatever was set with config options over to the sanitizer.
        // Pass the classes in for legacy support; new classes should use the registry instead
        $this->sanitize->pass_cache_data(
            $this->enable_cache,
            $this->cache_location,
            $this->cache_namefilter,
            $this->registry->get_class(Cache::class),
            $this->cache
        );
        $this->sanitize->pass_file_data($this->registry->get_class(File::class), $this->timeout, $this->useragent, $this->force_fsockopen, $this->curl_options);

        if (!empty($this->multifeed_url)) {
            $i = 0;
            $success = 0;
            $this->multifeed_objects = [];
            $this->error = [];
            foreach ($this->multifeed_url as $url) {
                $this->multifeed_objects[$i] = clone $this;
                $this->multifeed_objects[$i]->set_feed_url($url);
                $single_success = $this->multifeed_objects[$i]->init();
                $success |= $single_success;
                if (!$single_success) {
                    $this->error[$i] = $this->multifeed_objects[$i]->error();
                }
                $i++;
            }
            return (bool) $success;
        } elseif ($this->feed_url === null && $this->raw_data === null) {
            return false;
        }

        $this->error = null;
        $this->data = [];
        $this->check_modified = false;
        $this->multifeed_objects = [];
        $cache = false;

        if ($this->feed_url !== null) {
            $parsed_feed_url = $this->registry->call(Misc::class, 'parse_url', [$this->feed_url]);

            // Decide whether to enable caching
            if ($this->enable_cache && $parsed_feed_url['scheme'] !== '') {
                $cache = $this->get_cache($this->feed_url);
            }

            // Fetch the data via \SimplePie\File into $this->raw_data
            if (($fetched = $this->fetch_data($cache)) === true) {
                return true;
            } elseif ($fetched === false) {
                return false;
            }

            [$headers, $sniffed] = $fetched;
        }

        // Empty response check
        if (empty($this->raw_data)) {
            $this->error = "A feed could not be found at `$this->feed_url`. Empty body.";
            $this->registry->call(Misc::class, 'error', [$this->error, E_USER_NOTICE, __FILE__, __LINE__]);
            return false;
        }

        // Set up array of possible encodings
        $encodings = [];

        // First check to see if input has been overridden.
        if ($this->input_encoding !== false) {
            $encodings[] = strtoupper($this->input_encoding);
        }

        $application_types = ['application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity'];
        $text_types = ['text/xml', 'text/xml-external-parsed-entity'];

        // RFC 3023 (only applies to sniffed content)
        if (isset($sniffed)) {
            if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml') {
                if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset)) {
                    $encodings[] = strtoupper($charset[1]);
                }
                $encodings = array_merge($encodings, $this->registry->call(Misc::class, 'xml_encoding', [$this->raw_data, &$this->registry]));
                $encodings[] = 'UTF-8';
            } elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml') {
                if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset)) {
                    $encodings[] = strtoupper($charset[1]);
                }
                $encodings[] = 'US-ASCII';
            }
            // Text MIME-type default
            elseif (substr($sniffed, 0, 5) === 'text/') {
                $encodings[] = 'UTF-8';
            }
        }

        // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
        $encodings = array_merge($encodings, $this->registry->call(Misc::class, 'xml_encoding', [$this->raw_data, &$this->registry]));
        $encodings[] = 'UTF-8';
        $encodings[] = 'ISO-8859-1';

        // There's no point in trying an encoding twice
        $encodings = array_unique($encodings);

        // Loop through each possible encoding, till we return something, or run out of possibilities
        foreach ($encodings as $encoding) {
            // Change the encoding to UTF-8 (as we always use UTF-8 internally)
            if ($utf8_data = $this->registry->call(Misc::class, 'change_encoding', [$this->raw_data, $encoding, 'UTF-8'])) {
                // Create new parser
                $parser = $this->registry->create(Parser::class);

                // If it's parsed fine
                if ($parser->parse($utf8_data, 'UTF-8', $this->permanent_url)) {
                    $this->data = $parser->get_data();
                    if (!($this->get_type() & ~self::TYPE_NONE)) {
                        $this->error = "A feed could not be found at `$this->feed_url`. This does not appear to be a valid RSS or Atom feed.";
                        $this->registry->call(Misc::class, 'error', [$this->error, E_USER_NOTICE, __FILE__, __LINE__]);
                        return false;
                    }

                    if (isset($headers)) {
                        $this->data['headers'] = $headers;
                    }
                    $this->data['build'] = \SimplePie\Misc::get_build();

                    // Cache the file if caching is enabled
                    $this->data['cache_expiration_time'] = $this->cache_duration + time();
                    if ($cache && !$cache->set_data($this->get_cache_filename($this->feed_url), $this->data, $this->cache_duration)) {
                        trigger_error("$this->cache_location is not writable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
                    }
                    return true;
                }
            }
        }

        if (isset($parser)) {
            // We have an error, just set \SimplePie\Misc::error to it and quit
            $this->error = $this->feed_url;
            $this->error .= sprintf(' is invalid XML, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
        } else {
            $this->error = 'The data could not be converted to UTF-8.';
            if (!extension_loaded('mbstring') && !extension_loaded('iconv') && !class_exists('\UConverter')) {
                $this->error .= ' You MUST have either the iconv, mbstring or intl (PHP 5.5+) extension installed and enabled.';
            } else {
                $missingExtensions = [];
                if (!extension_loaded('iconv')) {
                    $missingExtensions[] = 'iconv';
                }
                if (!extension_loaded('mbstring')) {
                    $missingExtensions[] = 'mbstring';
                }
                if (!class_exists('\UConverter')) {
                    $missingExtensions[] = 'intl (PHP 5.5+)';
                }
                $this->error .= ' Try installing/enabling the ' . implode(' or ', $missingExtensions) . ' extension.';
            }
        }

        $this->registry->call(Misc::class, 'error', [$this->error, E_USER_NOTICE, __FILE__, __LINE__]);

        return false;
    }

    /**
     * Fetch the data via \SimplePie\File
     *
     * If the data is already cached, attempt to fetch it from there instead
     * @param Base|DataCache|false $cache Cache handler, or false to not load from the cache
     * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type
     */
    protected function fetch_data(&$cache)
    {
        if (is_object($cache) && $cache instanceof Base) {
            // @trigger_error(sprintf('Providing $cache as "\SimplePie\Cache\Base" in %s() is deprecated since SimplePie 1.8.0, please provide "\SimplePie\Cache\DataCache" implementation instead.', __METHOD__), \E_USER_DEPRECATED);
            $cache = new BaseDataCache($cache);
        }

        if ($cache !== false && !$cache instanceof DataCache) {
            throw new InvalidArgumentException(sprintf(
                '%s(): Argument #1 ($cache) must be of type %s|false',
                __METHOD__,
                DataCache::class
            ), 1);
        }

        $cacheKey = $this->get_cache_filename($this->feed_url);

        // If it's enabled, use the cache
        if ($cache) {
            // Load the Cache
            $this->data = $cache->get_data($cacheKey, []);

            if (!empty($this->data)) {
                // If the cache is for an outdated build of SimplePie
                if (!isset($this->data['build']) || $this->data['build'] !== \SimplePie\Misc::get_build()) {
                    $cache->delete_data($cacheKey);
                    $this->data = [];
                }
                // If we've hit a collision just rerun it with caching disabled
                elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url) {
                    $cache = false;
                    $this->data = [];
                }
                // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
                elseif (isset($this->data['feed_url'])) {
                    // Do not need to do feed autodiscovery yet.
                    if ($this->data['feed_url'] !== $this->data['url']) {
                        $this->set_feed_url($this->data['feed_url']);
                        $this->data['url'] = $this->data['feed_url'];

                        $cache->set_data($this->get_cache_filename($this->feed_url), $this->data, $this->autodiscovery_cache_duration);

                        return $this->init();
                    }

                    $cache->delete_data($this->get_cache_filename($this->feed_url));
                    $this->data = [];
                }
                // Check if the cache has been updated
                elseif (isset($this->data['cache_expiration_time']) && $this->data['cache_expiration_time'] > time()) {
                    // Want to know if we tried to send last-modified and/or etag headers
                    // when requesting this file. (Note that it's up to the file to
                    // support this, but we don't always send the headers either.)
                    $this->check_modified = true;
                    if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag'])) {
                        $headers = [
                            'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
                        ];
                        if (isset($this->data['headers']['last-modified'])) {
                            $headers['if-modified-since'] = $this->data['headers']['last-modified'];
                        }
                        if (isset($this->data['headers']['etag'])) {
                            $headers['if-none-match'] = $this->data['headers']['etag'];
                        }

                        $file = $this->registry->create(File::class, [$this->feed_url, $this->timeout / 10, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options]);
                        $this->status_code = $file->status_code;

                        if ($file->success) {
                            if ($file->status_code === 304) {
                                // Set raw_data to false here too, to signify that the cache
                                // is still valid.
                                $this->raw_data = false;
                                $cache->set_data($cacheKey, $this->data, $this->cache_duration);
                                return true;
                            }
                        } else {
                            $this->check_modified = false;
                            if ($this->force_cache_fallback) {
                                $cache->set_data($cacheKey, $this->data, $this->cache_duration);
                                return true;
                            }

                            unset($file);
                        }
                    }
                }
                // If the cache is still valid, just return true
                else {
                    $this->raw_data = false;
                    return true;
                }
            }
            // If the cache is empty
            else {
                $this->data = [];
            }
        }

        // If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
        if (!isset($file)) {
            if ($this->file instanceof \SimplePie\File && $this->file->url === $this->feed_url) {
                $file = &$this->file;
            } else {
                $headers = [
                    'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
                ];
                $file = $this->registry->create(File::class, [$this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options]);
            }
        }
        $this->status_code = $file->status_code;

        // If the file connection has an error, set SimplePie::error to that and quit
        if (!$file->success && !($file->method & self::FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300))) {
            $this->error = $file->error;
            return !empty($this->data);
        }

        if (!$this->force_feed) {
            // Check if the supplied URL is a feed, if it isn't, look for it.
            $locate = $this->registry->create(Locator::class, [&$file, $this->timeout, $this->useragent, $this->max_checked_feeds, $this->force_fsockopen, $this->curl_options]);

            if (!$locate->is_feed($file)) {
                $copyStatusCode = $file->status_code;
                $copyContentType = $file->headers['content-type'];
                try {
                    $microformats = false;
                    if (class_exists('DOMXpath') && function_exists('Mf2\parse')) {
                        $doc = new \DOMDocument();
                        @$doc->loadHTML($file->body);
                        $xpath = new \DOMXpath($doc);
                        // Check for both h-feed and h-entry, as both a feed with no entries
                        // and a list of entries without an h-feed wrapper are both valid.
                        $query = '//*[contains(concat(" ", @class, " "), " h-feed ") or '.
                            'contains(concat(" ", @class, " "), " h-entry ")]';
                        $result = $xpath->query($query);
                        $microformats = $result->length !== 0;
                    }
                    // Now also do feed discovery, but if microformats were found don't
                    // overwrite the current value of file.
                    $discovered = $locate->find(
                        $this->autodiscovery,
                        $this->all_discovered_feeds
                    );
                    if ($microformats) {
                        if ($hub = $locate->get_rel_link('hub')) {
                            $self = $locate->get_rel_link('self');
                            $this->store_links($file, $hub, $self);
                        }
                        // Push the current file onto all_discovered feeds so the user can
                        // be shown this as one of the options.
                        if (isset($this->all_discovered_feeds)) {
                            $this->all_discovered_feeds[] = $file;
                        }
                    } else {
                        if ($discovered) {
                            $file = $discovered;
                        } else {
                            // We need to unset this so that if SimplePie::set_file() has
                            // been called that object is untouched
                            unset($file);
                            $this->error = "A feed could not be found at `$this->feed_url`; the status code is `$copyStatusCode` and content-type is `$copyContentType`";
                            $this->registry->call(Misc::class, 'error', [$this->error, E_USER_NOTICE, __FILE__, __LINE__]);
                            return false;
                        }
                    }
                } catch (\SimplePie\Exception $e) {
                    // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
                    unset($file);
                    // This is usually because DOMDocument doesn't exist
                    $this->error = $e->getMessage();
                    $this->registry->call(Misc::class, 'error', [$this->error, E_USER_NOTICE, $e->getFile(), $e->getLine()]);
                    return false;
                }

                if ($cache) {
                    $this->data = [
                        'url' => $this->feed_url,
                        'feed_url' => $file->url,
                        'build' => \SimplePie\Misc::get_build(),
                        'cache_expiration_time' => $this->cache_duration + time(),
                    ];

                    if (!$cache->set_data($cacheKey, $this->data, $this->cache_duration)) {
                        trigger_error("$this->cache_location is not writable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
                    }
                }
            }
            $this->feed_url = $file->url;
            $locate = null;
        }

        $this->raw_data = $file->body;
        $this->permanent_url = $file->permanent_url;
        $headers = $file->headers;
        $sniffer = $this->registry->create(Sniffer::class, [&$file]);
        $sniffed = $sniffer->get_type();

        return [$headers, $sniffed];
    }

    /**
     * Get the error message for the occurred error
     *
     * @return string|array Error message, or array of messages for multifeeds
     */
    public function error()
    {
        return $this->error;
    }

    /**
     * Get the last HTTP status code
     *
     * @return int Status code
     */
    public function status_code()
    {
        return $this->status_code;
    }

    /**
     * Get the raw XML
     *
     * This is the same as the old `$feed->enable_xml_dump(true)`, but returns
     * the data instead of printing it.
     *
     * @return string|boolean Raw XML data, false if the cache is used
     */
    public function get_raw_data()
    {
        return $this->raw_data;
    }

    /**
     * Get the character encoding used for output
     *
     * @since Preview Release
     * @return string
     */
    public function get_encoding()
    {
        return $this->sanitize->output_encoding;
    }

    /**
     * Send the content-type header with correct encoding
     *
     * This method ensures that the SimplePie-enabled page is being served with
     * the correct {@link http://www.iana.org/assignments/media-types/ mime-type}
     * and character encoding HTTP headers (character encoding determined by the
     * {@see set_output_encoding} config option).
     *
     * This won't work properly if any content or whitespace has already been
     * sent to the browser, because it relies on PHP's
     * {@link http://php.net/header header()} function, and these are the
     * circumstances under which the function works.
     *
     * Because it's setting these settings for the entire page (as is the nature
     * of HTTP headers), this should only be used once per page (again, at the
     * top).
     *
     * @param string $mime MIME type to serve the page as
     */
    public function handle_content_type($mime = 'text/html')
    {
        if (!headers_sent()) {
            $header = "Content-type: $mime;";
            if ($this->get_encoding()) {
                $header .= ' charset=' . $this->get_encoding();
            } else {
                $header .= ' charset=UTF-8';
            }
            header($header);
        }
    }

    /**
     * Get the type of the feed
     *
     * This returns a \SimplePie\SimplePie::TYPE_* constant, which can be tested against
     * using {@link http://php.net/language.operators.bitwise bitwise operators}
     *
     * @since 0.8 (usage changed to using constants in 1.0)
     * @see \SimplePie\SimplePie::TYPE_NONE Unknown.
     * @see \SimplePie\SimplePie::TYPE_RSS_090 RSS 0.90.
     * @see \SimplePie\SimplePie::TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape).
     * @see \SimplePie\SimplePie::TYPE_RSS_091_USERLAND RSS 0.91 (Userland).
     * @see \SimplePie\SimplePie::TYPE_RSS_091 RSS 0.91.
     * @see \SimplePie\SimplePie::TYPE_RSS_092 RSS 0.92.
     * @see \SimplePie\SimplePie::TYPE_RSS_093 RSS 0.93.
     * @see \SimplePie\SimplePie::TYPE_RSS_094 RSS 0.94.
     * @see \SimplePie\SimplePie::TYPE_RSS_10 RSS 1.0.
     * @see \SimplePie\SimplePie::TYPE_RSS_20 RSS 2.0.x.
     * @see \SimplePie\SimplePie::TYPE_RSS_RDF RDF-based RSS.
     * @see \SimplePie\SimplePie::TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format).
     * @see \SimplePie\SimplePie::TYPE_RSS_ALL Any version of RSS.
     * @see \SimplePie\SimplePie::TYPE_ATOM_03 Atom 0.3.
     * @see \SimplePie\SimplePie::TYPE_ATOM_10 Atom 1.0.
     * @see \SimplePie\SimplePie::TYPE_ATOM_ALL Any version of Atom.
     * @see \SimplePie\SimplePie::TYPE_ALL Any known/supported feed type.
     * @return int \SimplePie\SimplePie::TYPE_* constant
     */
    public function get_type()
    {
        if (!isset($this->data['type'])) {
            $this->data['type'] = self::TYPE_ALL;
            if (isset($this->data['child'][self::NAMESPACE_ATOM_10]['feed'])) {
                $this->data['type'] &= self::TYPE_ATOM_10;
            } elseif (isset($this->data['child'][self::NAMESPACE_ATOM_03]['feed'])) {
                $this->data['type'] &= self::TYPE_ATOM_03;
            } elseif (isset($this->data['child'][self::NAMESPACE_RDF]['RDF'])) {
                if (isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_10]['channel'])
                || isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_10]['image'])
                || isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_10]['item'])
                || isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_10]['textinput'])) {
                    $this->data['type'] &= self::TYPE_RSS_10;
                }
                if (isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_090]['channel'])
                || isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_090]['image'])
                || isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_090]['item'])
                || isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][self::NAMESPACE_RSS_090]['textinput'])) {
                    $this->data['type'] &= self::TYPE_RSS_090;
                }
            } elseif (isset($this->data['child'][self::NAMESPACE_RSS_20]['rss'])) {
                $this->data['type'] &= self::TYPE_RSS_ALL;
                if (isset($this->data['child'][self::NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version'])) {
                    switch (trim($this->data['child'][self::NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version'])) {
                        case '0.91':
                            $this->data['type'] &= self::TYPE_RSS_091;
                            if (isset($this->data['child'][self::NAMESPACE_RSS_20]['rss'][0]['child'][self::NAMESPACE_RSS_20]['skiphours']['hour'][0]['data'])) {
                                switch (trim($this->data['child'][self::NAMESPACE_RSS_20]['rss'][0]['child'][self::NAMESPACE_RSS_20]['skiphours']['hour'][0]['data'])) {
                                    case '0':
                                        $this->data['type'] &= self::TYPE_RSS_091_NETSCAPE;
                                        break;

                                    case '24':
                                        $this->data['type'] &= self::TYPE_RSS_091_USERLAND;
                                        break;
                                }
                            }
                            break;

                        case '0.92':
                            $this->data['type'] &= self::TYPE_RSS_092;
                            break;

                        case '0.93':
                            $this->data['type'] &= self::TYPE_RSS_093;
                            break;

                        case '0.94':
                            $this->data['type'] &= self::TYPE_RSS_094;
                            break;

                        case '2.0':
                            $this->data['type'] &= self::TYPE_RSS_20;
                            break;
                    }
                }
            } else {
                $this->data['type'] = self::TYPE_NONE;
            }
        }
        return $this->data['type'];
    }

    /**
     * Get the URL for the feed
     *
     * When the 'permanent' mode is enabled, returns the original feed URL,
     * except in the case of an `HTTP 301 Moved Permanently` status response,
     * in which case the location of the first redirection is returned.
     *
     * When the 'permanent' mode is disabled (default),
     * may or may not be different from the URL passed to {@see set_feed_url()},
     * depending on whether auto-discovery was used, and whether there were
     * any redirects along the way.
     *
     * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.)
     * @todo Support <itunes:new-feed-url>
     * @todo Also, |atom:link|@rel=self
     * @param bool $permanent Permanent mode to return only the original URL or the first redirection
     * iff it is a 301 redirection
     * @return string|null
     */
    public function subscribe_url($permanent = false)
    {
        if ($permanent) {
            if ($this->permanent_url !== null) {
                // sanitize encodes ampersands which are required when used in a url.
                return str_replace(
                    '&amp;',
                    '&',
                    $this->sanitize(
                        $this->permanent_url,
                        self::CONSTRUCT_IRI
                    )
                );
            }
        } else {
            if ($this->feed_url !== null) {
                return str_replace(
                    '&amp;',
                    '&',
                    $this->sanitize(
                        $this->feed_url,
                        self::CONSTRUCT_IRI
                    )
                );
            }
        }
        return null;
    }

    /**
     * Get data for an feed-level element
     *
     * This method allows you to get access to ANY element/attribute that is a
     * sub-element of the opening feed tag.
     *
     * The return value is an indexed array of elements matching the given
     * namespace and tag name. Each element has `attribs`, `data` and `child`
     * subkeys. For `attribs` and `child`, these contain namespace subkeys.
     * `attribs` then has one level of associative name => value data (where
     * `value` is a string) after the namespace. `child` has tag-indexed keys
     * after the namespace, each member of which is an indexed array matching
     * this same format.
     *
     * For example:
     * <pre>
     * // This is probably a bad example because we already support
     * // <media:content> natively, but it shows you how to parse through
     * // the nodes.
     * $group = $item->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'group');
     * $content = $group[0]['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['content'];
     * $file = $content[0]['attribs']['']['url'];
     * echo $file;
     * </pre>
     *
     * @since 1.0
     * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
     * @param string $namespace The URL of the XML namespace of the elements you're trying to access
     * @param string $tag Tag name
     * @return array
     */
    public function get_feed_tags($namespace, $tag)
    {
        $type = $this->get_type();
        if ($type & self::TYPE_ATOM_10) {
            if (isset($this->data['child'][self::NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag])) {
                return $this->data['child'][self::NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
            }
        }
        if ($type & self::TYPE_ATOM_03) {
            if (isset($this->data['child'][self::NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag])) {
                return $this->data['child'][self::NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
            }
        }
        if ($type & self::TYPE_RSS_RDF) {
            if (isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag])) {
                return $this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
            }
        }
        if ($type & self::TYPE_RSS_SYNDICATION) {
            if (isset($this->data['child'][self::NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag])) {
                return $this->data['child'][self::NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
            }
        }
        return null;
    }

    /**
     * Get data for an channel-level element
     *
     * This method allows you to get access to ANY element/attribute in the
     * channel/header section of the feed.
     *
     * See {@see SimplePie::get_feed_tags()} for a description of the return value
     *
     * @since 1.0
     * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
     * @param string $namespace The URL of the XML namespace of the elements you're trying to access
     * @param string $tag Tag name
     * @return array
     */
    public function get_channel_tags($namespace, $tag)
    {
        $type = $this->get_type();
        if ($type & self::TYPE_ATOM_ALL) {
            if ($return = $this->get_feed_tags($namespace, $tag)) {
                return $return;
            }
        }
        if ($type & self::TYPE_RSS_10) {
            if ($channel = $this->get_feed_tags(self::NAMESPACE_RSS_10, 'channel')) {
                if (isset($channel[0]['child'][$namespace][$tag])) {
                    return $channel[0]['child'][$namespace][$tag];
                }
            }
        }
        if ($type & self::TYPE_RSS_090) {
            if ($channel = $this->get_feed_tags(self::NAMESPACE_RSS_090, 'channel')) {
                if (isset($channel[0]['child'][$namespace][$tag])) {
                    return $channel[0]['child'][$namespace][$tag];
                }
            }
        }
        if ($type & self::TYPE_RSS_SYNDICATION) {
            if ($channel = $this->get_feed_tags(self::NAMESPACE_RSS_20, 'channel')) {
                if (isset($channel[0]['child'][$namespace][$tag])) {
                    return $channel[0]['child'][$namespace][$tag];
                }
            }
        }
        return null;
    }

    /**
     * Get data for an channel-level element
     *
     * This method allows you to get access to ANY element/attribute in the
     * image/logo section of the feed.
     *
     * See {@see SimplePie::get_feed_tags()} for a description of the return value
     *
     * @since 1.0
     * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
     * @param string $namespace The URL of the XML namespace of the elements you're trying to access
     * @param string $tag Tag name
     * @return array
     */
    public function get_image_tags($namespace, $tag)
    {
        $type = $this->get_type();
        if ($type & self::TYPE_RSS_10) {
            if ($image = $this->get_feed_tags(self::NAMESPACE_RSS_10, 'image')) {
                if (isset($image[0]['child'][$namespace][$tag])) {
                    return $image[0]['child'][$namespace][$tag];
                }
            }
        }
        if ($type & self::TYPE_RSS_090) {
            if ($image = $this->get_feed_tags(self::NAMESPACE_RSS_090, 'image')) {
                if (isset($image[0]['child'][$namespace][$tag])) {
                    return $image[0]['child'][$namespace][$tag];
                }
            }
        }
        if ($type & self::TYPE_RSS_SYNDICATION) {
            if ($image = $this->get_channel_tags(self::NAMESPACE_RSS_20, 'image')) {
                if (isset($image[0]['child'][$namespace][$tag])) {
                    return $image[0]['child'][$namespace][$tag];
                }
            }
        }
        return null;
    }

    /**
     * Get the base URL value from the feed
     *
     * Uses `<xml:base>` if available, otherwise uses the first link in the
     * feed, or failing that, the URL of the feed itself.
     *
     * @see get_link
     * @see subscribe_url
     *
     * @param array $element
     * @return string
     */
    public function get_base($element = [])
    {
        if (!empty($element['xml_base_explicit']) && isset($element['xml_base'])) {
            return $element['xml_base'];
        } elseif ($this->get_link() !== null) {
            return $this->get_link();
        }

        return $this->subscribe_url();
    }

    /**
     * Sanitize feed data
     *
     * @access private
     * @see \SimplePie\Sanitize::sanitize()
     * @param string $data Data to sanitize
     * @param int $type One of the \SimplePie\SimplePie::CONSTRUCT_* constants
     * @param string $base Base URL to resolve URLs against
     * @return string Sanitized data
     */
    public function sanitize($data, $type, $base = '')
    {
        try {
            return $this->sanitize->sanitize($data, $type, $base);
        } catch (\SimplePie\Exception $e) {
            if (!$this->enable_exceptions) {
                $this->error = $e->getMessage();
                $this->registry->call(Misc::class, 'error', [$this->error, E_USER_WARNING, $e->getFile(), $e->getLine()]);
                return '';
            }

            throw $e;
        }
    }

    /**
     * Get the title of the feed
     *
     * Uses `<atom:title>`, `<title>` or `<dc:title>`
     *
     * @since 1.0 (previously called `get_feed_title` since 0.8)
     * @return string|null
     */
    public function get_title()
    {
        if ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'title')) {
            return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$return[0]['attribs']]), $this->get_base($return[0]));
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_03, 'title')) {
            return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$return[0]['attribs']]), $this->get_base($return[0]));
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_RSS_10, 'title')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_RSS_090, 'title')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_RSS_20, 'title')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_11, 'title')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_10, 'title')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        }

        return null;
    }

    /**
     * Get a category for the feed
     *
     * @since Unknown
     * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1
     * @return \SimplePie\Category|null
     */
    public function get_category($key = 0)
    {
        $categories = $this->get_categories();
        if (isset($categories[$key])) {
            return $categories[$key];
        }

        return null;
    }

    /**
     * Get all categories for the feed
     *
     * Uses `<atom:category>`, `<category>` or `<dc:subject>`
     *
     * @since Unknown
     * @return array|null List of {@see \SimplePie\Category} objects
     */
    public function get_categories()
    {
        $categories = [];

        foreach ((array) $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'category') as $category) {
            $term = null;
            $scheme = null;
            $label = null;
            if (isset($category['attribs']['']['term'])) {
                $term = $this->sanitize($category['attribs']['']['term'], self::CONSTRUCT_TEXT);
            }
            if (isset($category['attribs']['']['scheme'])) {
                $scheme = $this->sanitize($category['attribs']['']['scheme'], self::CONSTRUCT_TEXT);
            }
            if (isset($category['attribs']['']['label'])) {
                $label = $this->sanitize($category['attribs']['']['label'], self::CONSTRUCT_TEXT);
            }
            $categories[] = $this->registry->create(Category::class, [$term, $scheme, $label]);
        }
        foreach ((array) $this->get_channel_tags(self::NAMESPACE_RSS_20, 'category') as $category) {
            // This is really the label, but keep this as the term also for BC.
            // Label will also work on retrieving because that falls back to term.
            $term = $this->sanitize($category['data'], self::CONSTRUCT_TEXT);
            if (isset($category['attribs']['']['domain'])) {
                $scheme = $this->sanitize($category['attribs']['']['domain'], self::CONSTRUCT_TEXT);
            } else {
                $scheme = null;
            }
            $categories[] = $this->registry->create(Category::class, [$term, $scheme, null]);
        }
        foreach ((array) $this->get_channel_tags(self::NAMESPACE_DC_11, 'subject') as $category) {
            $categories[] = $this->registry->create(Category::class, [$this->sanitize($category['data'], self::CONSTRUCT_TEXT), null, null]);
        }
        foreach ((array) $this->get_channel_tags(self::NAMESPACE_DC_10, 'subject') as $category) {
            $categories[] = $this->registry->create(Category::class, [$this->sanitize($category['data'], self::CONSTRUCT_TEXT), null, null]);
        }

        if (!empty($categories)) {
            return array_unique($categories);
        }

        return null;
    }

    /**
     * Get an author for the feed
     *
     * @since 1.1
     * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1
     * @return \SimplePie\Author|null
     */
    public function get_author($key = 0)
    {
        $authors = $this->get_authors();
        if (isset($authors[$key])) {
            return $authors[$key];
        }

        return null;
    }

    /**
     * Get all authors for the feed
     *
     * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
     *
     * @since 1.1
     * @return array|null List of {@see \SimplePie\Author} objects
     */
    public function get_authors()
    {
        $authors = [];
        foreach ((array) $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'author') as $author) {
            $name = null;
            $uri = null;
            $email = null;
            if (isset($author['child'][self::NAMESPACE_ATOM_10]['name'][0]['data'])) {
                $name = $this->sanitize($author['child'][self::NAMESPACE_ATOM_10]['name'][0]['data'], self::CONSTRUCT_TEXT);
            }
            if (isset($author['child'][self::NAMESPACE_ATOM_10]['uri'][0]['data'])) {
                $uri = $this->sanitize($author['child'][self::NAMESPACE_ATOM_10]['uri'][0]['data'], self::CONSTRUCT_IRI, $this->get_base($author['child'][self::NAMESPACE_ATOM_10]['uri'][0]));
            }
            if (isset($author['child'][self::NAMESPACE_ATOM_10]['email'][0]['data'])) {
                $email = $this->sanitize($author['child'][self::NAMESPACE_ATOM_10]['email'][0]['data'], self::CONSTRUCT_TEXT);
            }
            if ($name !== null || $email !== null || $uri !== null) {
                $authors[] = $this->registry->create(Author::class, [$name, $uri, $email]);
            }
        }
        if ($author = $this->get_channel_tags(self::NAMESPACE_ATOM_03, 'author')) {
            $name = null;
            $url = null;
            $email = null;
            if (isset($author[0]['child'][self::NAMESPACE_ATOM_03]['name'][0]['data'])) {
                $name = $this->sanitize($author[0]['child'][self::NAMESPACE_ATOM_03]['name'][0]['data'], self::CONSTRUCT_TEXT);
            }
            if (isset($author[0]['child'][self::NAMESPACE_ATOM_03]['url'][0]['data'])) {
                $url = $this->sanitize($author[0]['child'][self::NAMESPACE_ATOM_03]['url'][0]['data'], self::CONSTRUCT_IRI, $this->get_base($author[0]['child'][self::NAMESPACE_ATOM_03]['url'][0]));
            }
            if (isset($author[0]['child'][self::NAMESPACE_ATOM_03]['email'][0]['data'])) {
                $email = $this->sanitize($author[0]['child'][self::NAMESPACE_ATOM_03]['email'][0]['data'], self::CONSTRUCT_TEXT);
            }
            if ($name !== null || $email !== null || $url !== null) {
                $authors[] = $this->registry->create(Author::class, [$name, $url, $email]);
            }
        }
        foreach ((array) $this->get_channel_tags(self::NAMESPACE_DC_11, 'creator') as $author) {
            $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], self::CONSTRUCT_TEXT), null, null]);
        }
        foreach ((array) $this->get_channel_tags(self::NAMESPACE_DC_10, 'creator') as $author) {
            $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], self::CONSTRUCT_TEXT), null, null]);
        }
        foreach ((array) $this->get_channel_tags(self::NAMESPACE_ITUNES, 'author') as $author) {
            $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], self::CONSTRUCT_TEXT), null, null]);
        }

        if (!empty($authors)) {
            return array_unique($authors);
        }

        return null;
    }

    /**
     * Get a contributor for the feed
     *
     * @since 1.1
     * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1
     * @return \SimplePie\Author|null
     */
    public function get_contributor($key = 0)
    {
        $contributors = $this->get_contributors();
        if (isset($contributors[$key])) {
            return $contributors[$key];
        }

        return null;
    }

    /**
     * Get all contributors for the feed
     *
     * Uses `<atom:contributor>`
     *
     * @since 1.1
     * @return array|null List of {@see \SimplePie\Author} objects
     */
    public function get_contributors()
    {
        $contributors = [];
        foreach ((array) $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'contributor') as $contributor) {
            $name = null;
            $uri = null;
            $email = null;
            if (isset($contributor['child'][self::NAMESPACE_ATOM_10]['name'][0]['data'])) {
                $name = $this->sanitize($contributor['child'][self::NAMESPACE_ATOM_10]['name'][0]['data'], self::CONSTRUCT_TEXT);
            }
            if (isset($contributor['child'][self::NAMESPACE_ATOM_10]['uri'][0]['data'])) {
                $uri = $this->sanitize($contributor['child'][self::NAMESPACE_ATOM_10]['uri'][0]['data'], self::CONSTRUCT_IRI, $this->get_base($contributor['child'][self::NAMESPACE_ATOM_10]['uri'][0]));
            }
            if (isset($contributor['child'][self::NAMESPACE_ATOM_10]['email'][0]['data'])) {
                $email = $this->sanitize($contributor['child'][self::NAMESPACE_ATOM_10]['email'][0]['data'], self::CONSTRUCT_TEXT);
            }
            if ($name !== null || $email !== null || $uri !== null) {
                $contributors[] = $this->registry->create(Author::class, [$name, $uri, $email]);
            }
        }
        foreach ((array) $this->get_channel_tags(self::NAMESPACE_ATOM_03, 'contributor') as $contributor) {
            $name = null;
            $url = null;
            $email = null;
            if (isset($contributor['child'][self::NAMESPACE_ATOM_03]['name'][0]['data'])) {
                $name = $this->sanitize($contributor['child'][self::NAMESPACE_ATOM_03]['name'][0]['data'], self::CONSTRUCT_TEXT);
            }
            if (isset($contributor['child'][self::NAMESPACE_ATOM_03]['url'][0]['data'])) {
                $url = $this->sanitize($contributor['child'][self::NAMESPACE_ATOM_03]['url'][0]['data'], self::CONSTRUCT_IRI, $this->get_base($contributor['child'][self::NAMESPACE_ATOM_03]['url'][0]));
            }
            if (isset($contributor['child'][self::NAMESPACE_ATOM_03]['email'][0]['data'])) {
                $email = $this->sanitize($contributor['child'][self::NAMESPACE_ATOM_03]['email'][0]['data'], self::CONSTRUCT_TEXT);
            }
            if ($name !== null || $email !== null || $url !== null) {
                $contributors[] = $this->registry->create(Author::class, [$name, $url, $email]);
            }
        }

        if (!empty($contributors)) {
            return array_unique($contributors);
        }

        return null;
    }

    /**
     * Get a single link for the feed
     *
     * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
     * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1
     * @param string $rel The relationship of the link to return
     * @return string|null Link URL
     */
    public function get_link($key = 0, $rel = 'alternate')
    {
        $links = $this->get_links($rel);
        if (isset($links[$key])) {
            return $links[$key];
        }

        return null;
    }

    /**
     * Get the permalink for the item
     *
     * Returns the first link available with a relationship of "alternate".
     * Identical to {@see get_link()} with key 0
     *
     * @see get_link
     * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
     * @internal Added for parity between the parent-level and the item/entry-level.
     * @return string|null Link URL
     */
    public function get_permalink()
    {
        return $this->get_link(0);
    }

    /**
     * Get all links for the feed
     *
     * Uses `<atom:link>` or `<link>`
     *
     * @since Beta 2
     * @param string $rel The relationship of links to return
     * @return array|null Links found for the feed (strings)
     */
    public function get_links($rel = 'alternate')
    {
        if (!isset($this->data['links'])) {
            $this->data['links'] = [];
            if ($links = $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'link')) {
                foreach ($links as $link) {
                    if (isset($link['attribs']['']['href'])) {
                        $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
                        $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], self::CONSTRUCT_IRI, $this->get_base($link));
                    }
                }
            }
            if ($links = $this->get_channel_tags(self::NAMESPACE_ATOM_03, 'link')) {
                foreach ($links as $link) {
                    if (isset($link['attribs']['']['href'])) {
                        $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
                        $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], self::CONSTRUCT_IRI, $this->get_base($link));
                    }
                }
            }
            if ($links = $this->get_channel_tags(self::NAMESPACE_RSS_10, 'link')) {
                $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], self::CONSTRUCT_IRI, $this->get_base($links[0]));
            }
            if ($links = $this->get_channel_tags(self::NAMESPACE_RSS_090, 'link')) {
                $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], self::CONSTRUCT_IRI, $this->get_base($links[0]));
            }
            if ($links = $this->get_channel_tags(self::NAMESPACE_RSS_20, 'link')) {
                $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], self::CONSTRUCT_IRI, $this->get_base($links[0]));
            }

            $keys = array_keys($this->data['links']);
            foreach ($keys as $key) {
                if ($this->registry->call(Misc::class, 'is_isegment_nz_nc', [$key])) {
                    if (isset($this->data['links'][self::IANA_LINK_RELATIONS_REGISTRY . $key])) {
                        $this->data['links'][self::IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][self::IANA_LINK_RELATIONS_REGISTRY . $key]);
                        $this->data['links'][$key] = &$this->data['links'][self::IANA_LINK_RELATIONS_REGISTRY . $key];
                    } else {
                        $this->data['links'][self::IANA_LINK_RELATIONS_REGISTRY . $key] = &$this->data['links'][$key];
                    }
                } elseif (substr($key, 0, 41) === self::IANA_LINK_RELATIONS_REGISTRY) {
                    $this->data['links'][substr($key, 41)] = &$this->data['links'][$key];
                }
                $this->data['links'][$key] = array_unique($this->data['links'][$key]);
            }
        }

        if (isset($this->data['headers']['link'])) {
            $link_headers = $this->data['headers']['link'];
            if (is_array($link_headers)) {
                $link_headers = implode(',', $link_headers);
            }
            // https://datatracker.ietf.org/doc/html/rfc8288
            if (is_string($link_headers) &&
                preg_match_all('/<(?P<uri>[^>]+)>\s*;\s*rel\s*=\s*(?P<quote>"?)' . preg_quote($rel) . '(?P=quote)\s*(?=,|$)/i', $link_headers, $matches)) {
                return $matches['uri'];
            }
        }

        if (isset($this->data['links'][$rel])) {
            return $this->data['links'][$rel];
        }

        return null;
    }

    public function get_all_discovered_feeds()
    {
        return $this->all_discovered_feeds;
    }

    /**
     * Get the content for the item
     *
     * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`,
     * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>`
     *
     * @since 1.0 (previously called `get_feed_description()` since 0.8)
     * @return string|null
     */
    public function get_description()
    {
        if ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'subtitle')) {
            return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$return[0]['attribs']]), $this->get_base($return[0]));
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_03, 'tagline')) {
            return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$return[0]['attribs']]), $this->get_base($return[0]));
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_RSS_10, 'description')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_RSS_090, 'description')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_RSS_20, 'description')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_HTML, $this->get_base($return[0]));
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_11, 'description')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_10, 'description')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_ITUNES, 'summary')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_HTML, $this->get_base($return[0]));
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_ITUNES, 'subtitle')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_HTML, $this->get_base($return[0]));
        }

        return null;
    }

    /**
     * Get the copyright info for the feed
     *
     * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>`
     *
     * @since 1.0 (previously called `get_feed_copyright()` since 0.8)
     * @return string|null
     */
    public function get_copyright()
    {
        if ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'rights')) {
            return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$return[0]['attribs']]), $this->get_base($return[0]));
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_03, 'copyright')) {
            return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$return[0]['attribs']]), $this->get_base($return[0]));
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_RSS_20, 'copyright')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_11, 'rights')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_10, 'rights')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        }

        return null;
    }

    /**
     * Get the language for the feed
     *
     * Uses `<language>`, `<dc:language>`, or @xml_lang
     *
     * @since 1.0 (previously called `get_feed_language()` since 0.8)
     * @return string|null
     */
    public function get_language()
    {
        if ($return = $this->get_channel_tags(self::NAMESPACE_RSS_20, 'language')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_11, 'language')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_DC_10, 'language')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        } elseif (isset($this->data['child'][self::NAMESPACE_ATOM_10]['feed'][0]['xml_lang'])) {
            return $this->sanitize($this->data['child'][self::NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], self::CONSTRUCT_TEXT);
        } elseif (isset($this->data['child'][self::NAMESPACE_ATOM_03]['feed'][0]['xml_lang'])) {
            return $this->sanitize($this->data['child'][self::NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], self::CONSTRUCT_TEXT);
        } elseif (isset($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['xml_lang'])) {
            return $this->sanitize($this->data['child'][self::NAMESPACE_RDF]['RDF'][0]['xml_lang'], self::CONSTRUCT_TEXT);
        } elseif (isset($this->data['headers']['content-language'])) {
            return $this->sanitize($this->data['headers']['content-language'], self::CONSTRUCT_TEXT);
        }

        return null;
    }

    /**
     * Get the latitude coordinates for the item
     *
     * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
     *
     * Uses `<geo:lat>` or `<georss:point>`
     *
     * @since 1.0
     * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
     * @link http://www.georss.org/ GeoRSS
     * @return string|null
     */
    public function get_latitude()
    {
        if ($return = $this->get_channel_tags(self::NAMESPACE_W3C_BASIC_GEO, 'lat')) {
            return (float) $return[0]['data'];
        } elseif (($return = $this->get_channel_tags(self::NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) {
            return (float) $match[1];
        }

        return null;
    }

    /**
     * Get the longitude coordinates for the feed
     *
     * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
     *
     * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
     *
     * @since 1.0
     * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
     * @link http://www.georss.org/ GeoRSS
     * @return string|null
     */
    public function get_longitude()
    {
        if ($return = $this->get_channel_tags(self::NAMESPACE_W3C_BASIC_GEO, 'long')) {
            return (float) $return[0]['data'];
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_W3C_BASIC_GEO, 'lon')) {
            return (float) $return[0]['data'];
        } elseif (($return = $this->get_channel_tags(self::NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) {
            return (float) $match[2];
        }

        return null;
    }

    /**
     * Get the feed logo's title
     *
     * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title.
     *
     * Uses `<image><title>` or `<image><dc:title>`
     *
     * @return string|null
     */
    public function get_image_title()
    {
        if ($return = $this->get_image_tags(self::NAMESPACE_RSS_10, 'title')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        } elseif ($return = $this->get_image_tags(self::NAMESPACE_RSS_090, 'title')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        } elseif ($return = $this->get_image_tags(self::NAMESPACE_RSS_20, 'title')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        } elseif ($return = $this->get_image_tags(self::NAMESPACE_DC_11, 'title')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        } elseif ($return = $this->get_image_tags(self::NAMESPACE_DC_10, 'title')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_TEXT);
        }

        return null;
    }

    /**
     * Get the feed logo's URL
     *
     * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to
     * have a "feed logo" URL. This points directly to the image itself.
     *
     * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
     * `<image><title>` or `<image><dc:title>`
     *
     * @return string|null
     */
    public function get_image_url()
    {
        if ($return = $this->get_channel_tags(self::NAMESPACE_ITUNES, 'image')) {
            return $this->sanitize($return[0]['attribs']['']['href'], self::CONSTRUCT_IRI);
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'logo')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0]));
        } elseif ($return = $this->get_channel_tags(self::NAMESPACE_ATOM_10, 'icon')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0]));
        } elseif ($return = $this->get_image_tags(self::NAMESPACE_RSS_10, 'url')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0]));
        } elseif ($return = $this->get_image_tags(self::NAMESPACE_RSS_090, 'url')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0]));
        } elseif ($return = $this->get_image_tags(self::NAMESPACE_RSS_20, 'url')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0]));
        }

        return null;
    }


    /**
     * Get the feed logo's link
     *
     * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This
     * points to a human-readable page that the image should link to.
     *
     * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
     * `<image><title>` or `<image><dc:title>`
     *
     * @return string|null
     */
    public function get_image_link()
    {
        if ($return = $this->get_image_tags(self::NAMESPACE_RSS_10, 'link')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0]));
        } elseif ($return = $this->get_image_tags(self::NAMESPACE_RSS_090, 'link')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0]));
        } elseif ($return = $this->get_image_tags(self::NAMESPACE_RSS_20, 'link')) {
            return $this->sanitize($return[0]['data'], self::CONSTRUCT_IRI, $this->get_base($return[0]));
        }

        return null;
    }

    /**
     * Get the feed logo's link
     *
     * RSS 2.0 feeds are allowed to have a "feed logo" width.
     *
     * Uses `<image><width>` or defaults to 88 if no width is specified and
     * the feed is an RSS 2.0 feed.
     *
     * @return int|null
     */
    public function get_image_width()
    {
        if ($return = $this->get_image_tags(self::NAMESPACE_RSS_20, 'width')) {
            return intval($return[0]['data']);
        } elseif ($this->get_type() & self::TYPE_RSS_SYNDICATION && $this->get_image_tags(self::NAMESPACE_RSS_20, 'url')) {
            return 88;
        }

        return null;
    }

    /**
     * Get the feed logo's height
     *
     * RSS 2.0 feeds are allowed to have a "feed logo" height.
     *
     * Uses `<image><height>` or defaults to 31 if no height is specified and
     * the feed is an RSS 2.0 feed.
     *
     * @return int|null
     */
    public function get_image_height()
    {
        if ($return = $this->get_image_tags(self::NAMESPACE_RSS_20, 'height')) {
            return intval($return[0]['data']);
        } elseif ($this->get_type() & self::TYPE_RSS_SYNDICATION && $this->get_image_tags(self::NAMESPACE_RSS_20, 'url')) {
            return 31;
        }

        return null;
    }

    /**
     * Get the number of items in the feed
     *
     * This is well-suited for {@link http://php.net/for for()} loops with
     * {@see get_item()}
     *
     * @param int $max Maximum value to return. 0 for no limit
     * @return int Number of items in the feed
     */
    public function get_item_quantity($max = 0)
    {
        $max = (int) $max;
        $qty = count($this->get_items());
        if ($max === 0) {
            return $qty;
        }

        return ($qty > $max) ? $max : $qty;
    }

    /**
     * Get a single item from the feed
     *
     * This is better suited for {@link http://php.net/for for()} loops, whereas
     * {@see get_items()} is better suited for
     * {@link http://php.net/foreach foreach()} loops.
     *
     * @see get_item_quantity()
     * @since Beta 2
     * @param int $key The item that you want to return. Remember that arrays begin with 0, not 1
     * @return \SimplePie\Item|null
     */
    public function get_item($key = 0)
    {
        $items = $this->get_items();
        if (isset($items[$key])) {
            return $items[$key];
        }

        return null;
    }

    /**
     * Get all items from the feed
     *
     * This is better suited for {@link http://php.net/for for()} loops, whereas
     * {@see get_items()} is better suited for
     * {@link http://php.net/foreach foreach()} loops.
     *
     * @see get_item_quantity
     * @since Beta 2
     * @param int $start Index to start at
     * @param int $end Number of items to return. 0 for all items after `$start`
     * @return \SimplePie\Item[]|null List of {@see \SimplePie\Item} objects
     */
    public function get_items($start = 0, $end = 0)
    {
        if (!isset($this->data['items'])) {
            if (!empty($this->multifeed_objects)) {
                $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
                if (empty($this->data['items'])) {
                    return [];
                }
                return $this->data['items'];
            }
            $this->data['items'] = [];
            if ($items = $this->get_feed_tags(self::NAMESPACE_ATOM_10, 'entry')) {
                $keys = array_keys($items);
                foreach ($keys as $key) {
                    $this->data['items'][] = $this->registry->create(Item::class, [$this, $items[$key]]);
                }
            }
            if ($items = $this->get_feed_tags(self::NAMESPACE_ATOM_03, 'entry')) {
                $keys = array_keys($items);
                foreach ($keys as $key) {
                    $this->data['items'][] = $this->registry->create(Item::class, [$this, $items[$key]]);
                }
            }
            if ($items = $this->get_feed_tags(self::NAMESPACE_RSS_10, 'item')) {
                $keys = array_keys($items);
                foreach ($keys as $key) {
                    $this->data['items'][] = $this->registry->create(Item::class, [$this, $items[$key]]);
                }
            }
            if ($items = $this->get_feed_tags(self::NAMESPACE_RSS_090, 'item')) {
                $keys = array_keys($items);
                foreach ($keys as $key) {
                    $this->data['items'][] = $this->registry->create(Item::class, [$this, $items[$key]]);
                }
            }
            if ($items = $this->get_channel_tags(self::NAMESPACE_RSS_20, 'item')) {
                $keys = array_keys($items);
                foreach ($keys as $key) {
                    $this->data['items'][] = $this->registry->create(Item::class, [$this, $items[$key]]);
                }
            }
        }

        if (empty($this->data['items'])) {
            return [];
        }

        if ($this->order_by_date) {
            if (!isset($this->data['ordered_items'])) {
                $this->data['ordered_items'] = $this->data['items'];
                usort($this->data['ordered_items'], [get_class($this), 'sort_items']);
            }
            $items = $this->data['ordered_items'];
        } else {
            $items = $this->data['items'];
        }
        // Slice the data as desired
        if ($end === 0) {
            return array_slice($items, $start);
        }

        return array_slice($items, $start, $end);
    }

    /**
     * Set the favicon handler
     *
     * @deprecated Use your own favicon handling instead
     */
    public function set_favicon_handler($page = false, $qs = 'i')
    {
        trigger_error('Favicon handling has been removed, please use your own handling', \E_USER_DEPRECATED);
        return false;
    }

    /**
     * Get the favicon for the current feed
     *
     * @deprecated Use your own favicon handling instead
     */
    public function get_favicon()
    {
        trigger_error('Favicon handling has been removed, please use your own handling', \E_USER_DEPRECATED);

        if (($url = $this->get_link()) !== null) {
            return 'https://www.google.com/s2/favicons?domain=' . urlencode($url);
        }

        return false;
    }

    /**
     * Magic method handler
     *
     * @param string $method Method name
     * @param array $args Arguments to the method
     * @return mixed
     */
    public function __call($method, $args)
    {
        if (strpos($method, 'subscribe_') === 0) {
            trigger_error('subscribe_*() has been deprecated, implement the callback yourself', \E_USER_DEPRECATED);
            return '';
        }
        if ($method === 'enable_xml_dump') {
            trigger_error('enable_xml_dump() has been deprecated, use get_raw_data() instead', \E_USER_DEPRECATED);
            return false;
        }

        $class = get_class($this);
        $trace = debug_backtrace(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
        $file = $trace[0]['file'];
        $line = $trace[0]['line'];
        throw new SimplePieException("Call to undefined method $class::$method() in $file on line $line");
    }

    /**
     * Sorting callback for items
     *
     * @access private
     * @param SimplePie $a
     * @param SimplePie $b
     * @return boolean
     */
    public static function sort_items($a, $b)
    {
        $a_date = $a->get_date('U');
        $b_date = $b->get_date('U');
        if ($a_date && $b_date) {
            return $a_date > $b_date ? -1 : 1;
        }
        // Sort items without dates to the top.
        if ($a_date) {
            return 1;
        }
        if ($b_date) {
            return -1;
        }
        return 0;
    }

    /**
     * Merge items from several feeds into one
     *
     * If you're merging multiple feeds together, they need to all have dates
     * for the items or else SimplePie will refuse to sort them.
     *
     * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings
     * @param array $urls List of SimplePie feed objects to merge
     * @param int $start Starting item
     * @param int $end Number of items to return
     * @param int $limit Maximum number of items per feed
     * @return array
     */
    public static function merge_items($urls, $start = 0, $end = 0, $limit = 0)
    {
        if (is_array($urls) && sizeof($urls) > 0) {
            $items = [];
            foreach ($urls as $arg) {
                if ($arg instanceof SimplePie) {
                    $items = array_merge($items, $arg->get_items(0, $limit));
                } else {
                    trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
                }
            }

            usort($items, [get_class($urls[0]), 'sort_items']);

            if ($end === 0) {
                return array_slice($items, $start);
            }

            return array_slice($items, $start, $end);
        }

        trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
        return [];
    }

    /**
     * Store PubSubHubbub links as headers
     *
     * There is no way to find PuSH links in the body of a microformats feed,
     * so they are added to the headers when found, to be used later by get_links.
     * @param \SimplePie\File $file
     * @param string $hub
     * @param string $self
     */
    private function store_links(&$file, $hub, $self)
    {
        if (isset($file->headers['link']['hub']) ||
              (isset($file->headers['link']) &&
               preg_match('/rel=hub/', $file->headers['link']))) {
            return;
        }

        if ($hub) {
            if (isset($file->headers['link'])) {
                if ($file->headers['link'] !== '') {
                    $file->headers['link'] = ', ';
                }
            } else {
                $file->headers['link'] = '';
            }
            $file->headers['link'] .= '<'.$hub.'>; rel=hub';
            if ($self) {
                $file->headers['link'] .= ', <'.$self.'>; rel=self';
            }
        }
    }

    /**
     * Get a DataCache
     *
     * @param string $feed_url Only needed for BC, can be removed in SimplePie 2.0.0
     *
     * @return DataCache
     */
    private function get_cache($feed_url = '')
    {
        if ($this->cache === null) {
            // @trigger_error(sprintf('Not providing as PSR-16 cache implementation is deprecated since SimplePie 1.8.0, please use "SimplePie\SimplePie::set_cache()".'), \E_USER_DEPRECATED);
            $cache = $this->registry->call(Cache::class, 'get_handler', [
                $this->cache_location,
                $this->get_cache_filename($feed_url),
                Base::TYPE_FEED
            ]);

            return new BaseDataCache($cache);
        }

        return $this->cache;
    }
}

class_alias('SimplePie\SimplePie', 'SimplePie');

Youez - 2016 - github.com/yon3zu
LinuXploit