++ $first_day_offset ); } if ( $first_day_offset ) { $ical_string = $this->update_ical_string_count_by( $ical_string, - $first_day_offset ); } $new_dstart_string = $this->build_dstart_string( $next_occurrrence->start() ); $new_dtend_string = $this->build_dtend_string( $next_occurrrence->end() ); $ical_string = $this->set_ical_string_dt_attribute( $ical_string, 'DTSTART', $new_dstart_string ); $ical_string = $this->set_ical_string_dt_attribute( $ical_string, 'DTEND', $new_dtend_string ); $rset = $this->get_rset_for_ical_string_dtstart( $ical_string, $next_occurrrence ); $post = null; $tuple_dstart = $next_occurrrence->start(); $tuple_duration = $rset->get_duration() ?? $next_occurrrence->get_duration(); } $rset->rewind(); $rset_tuples[] = [ 'ical_string' => $ical_string, 'dtstart' => Dates::immutable( $tuple_dstart ), 'rset' => $rset, 'post' => $post, 'start_time' => $tuple_dstart->format( 'His' ), 'duration' => $tuple_duration, 'collision_exdates' => [], ]; } return $rset_tuples; } /** * Calls the Iterator rewind method on each tuple RSET object. * * @since 6.0.0 * * @param array $rset_tuples A set of tuples to rewind the iterators for. * * @return void The method does not return any value and will have the side * effect of rewinding each tuple RSET iterator. */ private function rewind_tuples_rset( array $rset_tuples ) { foreach ( array_column( $rset_tuples, 'rset' ) as $rset ) { $rset->rewind(); } } /** * Sort the RRULEs to have the one that contain the DTSTART on top. * * @param array $ical_strings A list of converted iCalendar format strings. * * @return array A sorted map from iCalendar format strings to a boolean value * indicating whether they contain the DTSTART or not. * * @throws Migration_Exception If there's any issue converting the iCalendar format strings. */ private function sort_ical_strings( array $ical_strings ) { $map = array_combine( $ical_strings, array_map( function ( $ical_string ) { $includes_dtstart = (int) $this->rrule_includes_dtstart( $ical_string, $this->dtstart ); return 10 ** 5 * $includes_dtstart; }, $ical_strings ) ); arsort( $map, SORT_NUMERIC ); //After sorting, we can drop the integer and use a boolean to indicate whether the DTSTART is contained. array_walk( $map, static function ( &$includes_dtstart ) { $includes_dtstart = $includes_dtstart >= 10 ** 5; } ); return $map; } /** * Refreshes the tuples by moving the DTSTART if an EXDATE has been added that "covers" it. * * * @since 6.0.0 * * @param array $tuples The list of tuples representing the recurrence rules converted to * iCalendar format strings. * * @return array The tuples, refreshed to have their DTSTART moved to the next available if an * EXDATE is "covering" it. * * @throws Migration_Exception If there's an issue building the RSETs from the iCalendar strings. */ private function refresh_tuples_dtstart( array $tuples ) { foreach ( $tuples as $k => &$tuple ) { if ( 0 === $k ) { // The first RSET will not need the update. continue; } /** @var RSet_Wrapper $rset */ $rset = $tuple['rset']; $ical_string_wo_exdates = $tuple['ical_string']; $exdates = $rset->getExDates(); $collision_exdates = $tuple['collision_exdates']; $rule_count = $this->get_ical_string_count( $ical_string_wo_exdates ); if ( null !== $rule_count && count( $collision_exdates ) >= $rule_count ) { // If the rule COUNT matches the number of EXDATEs, it will not generate any Occurrence. $tuple = null; continue; } // The RSET will return the first Occurrence available given the current DTSTART and EXDATEs. $new_dtstart = $rset->offsetGet( 0 ); $is_after_new_dtstart = static function ( DateTime $exdate ) use ( $new_dtstart ) { return $exdate > $new_dtstart; }; if ( null === $new_dtstart ) { // The RRULE is completely covered by EXDATEs, hence the first RRULE contains it: no need to port. $tuple = null; continue; } // Collision EXDATEs have been added on Occurrences: any one we drop as not applicable is -1 to the COUNT. $applicable_collision_exdates = array_filter( $collision_exdates, $is_after_new_dtstart ); $count_adjust = count( $collision_exdates ) - count( $applicable_collision_exdates ); $new_ical_string = $this->update_ical_string_count_by( $ical_string_wo_exdates, - $count_adjust ); // Prune any EXDATE before the new new DTSTART. $applicable_exdates = array_filter( $exdates, $is_after_new_dtstart ); // Build a new RSET and add the EXDATEs to it. $transition_rset = $this->get_rset_for_ical_string_dtstart( $new_ical_string, $new_dtstart ); foreach ( $applicable_exdates as $exdate ) { $transition_rset->addExDate( $exdate ); } // Build a new RSET using the RFC string that will include the EXDATEs. $new_rset = $this->get_rset_for_ical_string_dtstart( $transition_rset->get_rfc_string( true ), $new_dtstart ); // Update the tuple values. $tuple = array_merge( $tuple, [ 'ical_string' => $new_rset->get_rfc_string( true ), 'dtstart' => Dates::immutable( $new_dtstart ), 'rset' => $new_rset, ] ); } return array_values( array_filter( $tuples ) ); } /** * Reduces the set of tuples by finding the ones that would produce only 1 Occurrence and * transforming them into RDATEs of the first RSET. * * @since 6.0.0 * * @param array $tuples The list of tuples representing the recurrence rules converted to * iCalendar format strings. * * @return array The tuples, refreshed to have their DTSTART moved to the next available if an * EXDATE is "covering" it. * * @throws Migration_Exception If there's an issue building the required RSETs from the iCalendar * format strings. */ private function reduce_tuples( array $tuples ) { // We have no tuples, just return empty array. if ( empty( $tuples ) ) { return []; } $first_tuple = array_shift( $tuples ); if ( empty( $tuples ) ) { array_unshift( $tuples, $first_tuple ); return $tuples; } /** @var RSet_Wrapper $first_rset */ $first_rset = $first_tuple['rset']; $to_rdate = array_filter( array_column( $tuples, 'rset' ), static function ( RSet_Wrapper $rset ) { return $rset->isFinite() && 1 === $rset->count(); } ); if ( ! count( $to_rdate ) ) { // No tuple to remove, move on. array_unshift( $tuples, $first_tuple ); return $tuples; } if ( count( $to_rdate ) ) { foreach ( array_keys( $to_rdate ) as $key ) { $first_rset->addDate( $tuples[ $key ]['rset']->offsetGet( 0 ) ); unset( $tuples[ $key ] ); } } $first_ical_string = $first_rset->get_rfc_string(); $first_rset = $this->get_rset_for_ical_string_dtstart( $first_ical_string, $first_tuple['dtstart'] ); $first_tuple = array_merge( $first_tuple, [ 'ical_string' => $first_ical_string, 'rset' => $first_rset, ] ); array_unshift( $tuples, $first_tuple ); return $tuples; } /** * Updates a tuple iCalendar string and RSET object to include the specified set of RDATEs. * * @since 6.0.0 * * @param array $rdates A set of RDATE objects to add to the * rule tuple. * @param array $tuple The tuple to update. * * @return array The tuple, its iCalendar string and RSET object modified to include the * RDATEs. * * @throws Migration_Exception If there's any issue building of modifying the RSET object. */ private function add_rdates_to_tuple( array $rdates, array $tuple ) { try { if ( ! count( $rdates ) ) { return $tuple; } $rdates_strings = $this->from_event_recurrence_converter->convert_recurrence_rules( $rdates, $this->duration, false ); if ( ! count( $rdates_strings ) ) { return $tuple; } $rdates_strings = reset( $rdates_strings ); /** @var RSet_Wrapper $head_rset */ $head_rset = $tuple['rset']; $current_string = $head_rset->get_rfc_string(); $new_head_rset = $this->get_rset_for_ical_string_dtstart( $current_string . "\n" . implode( "\n", $rdates_strings ), $this->dtstart ); $tuple['ical_string'] = $new_head_rset->get_rfc_string(); $tuple['rset'] = $new_head_rset; return $tuple; } catch ( Requirement_Error $e ) { throw new Migration_Exception( $e->getMessage(), $e->getCode(), $e ); } } /** * Applies exclusion rules and dates to each tuple element. * * @since 6.0.0 * * @param array> $exclusions A set of exclusion rules in the format used by the * `_EventRecurrence` meta; these can include both rules * and dates. * @param array> $tuples A set of tuples to update. * * @return array> The updated tuples. * * @throws Migration_Exception If there's any issue building the RSET object required for the * updates or there are issues with the exclusions' conversion. */ private function apply_exclusions_to_tuples( array $exclusions, array $tuples ) { try { $converted = $this->from_event_recurrence_converter ->convert_exclusion_rules( $exclusions ); if ( empty( $converted ) ) { return $tuples; } $exrules = array_filter( $converted, static function ( $exrule ) { return strpos( $exrule, 'EXRULE' ) === 0; } ); $exdates = array_diff_key( $converted, $exrules ); if ( count( $exrules ) > 1 ) { throw new Migration_Exception( 'Only 1 EXRULE should be present: ' . count( $exrules ) . ' found.' ); } $exrule = reset( $exrules ); foreach ( $tuples as &$tuple ) { $ical_string_raw = $tuple['ical_string']; if ( count( $exdates ) ) { $ical_string_raw .= "\n" . implode( "\n", $exdates ); } if ( count( $exrules ) ) { $aligned_exrule = $this->realign_exrule_for_rrule( $exrule, $ical_string_raw, $this->dtstart, $tuple['dtstart'] ); if ( $aligned_exrule ) { $ical_string_raw .= "\n" . $aligned_exrule; } } $new_rset = $this->get_rset_for_ical_string_dtstart( $ical_string_raw, $tuple['dtstart'] ); $new_ical_string = $new_rset->get_rfc_string( true ); $tuple['rset'] = $new_rset; $tuple['ical_string'] = $new_ical_string; } } catch ( Requirement_Error $e ) { throw new Migration_Exception( $e->getMessage(), $e->getCode(), $e ); } return $tuples; } /** * Checks and updates the iCalendar format string to remove any "technical" never-ending * limit value that might have been added for the purpose of working on it. * * @since 6.0.0 * * @param string $ical_string The iCalendar format string to check and remove the technical * limit value from. * * @return string The updated iCalendar format string. */ private function remove_ical_string_technical_never_ending_limit( string $ical_string ): string { $until_value = $this->get_ical_string_attribute_value( $ical_string, 'UNTIL', null ); if ( $until_value === null ) { return $ical_string; } $seconds = (int) Dates::immutable( $until_value )->format( 's' ); if ( $seconds !== 23 ) { return $ical_string; } return $this->set_ical_string_until_limit( $ical_string, null ); } /** * Updates a set of iCalendar format strings imposing an UNTIL limit on each never-ending * RRULE to make it computable. * * @since 6.0.0 * * @param array $ical_strings The set of iCalendar format strings to update. * * * @return array The udpated iCalendar format strings. * * @throws Exception If there's any issue building the date objects required * for the computation. */ private function apply_technical_never_ending_limit( array $ical_strings ): array { // Apply an odd seconds limit that will be carried across the computation. $never_limit_date = $this->get_never_limit_date(); $never_limit_date = $never_limit_date->setTime( $never_limit_date->format( 'H' ), $never_limit_date->format( 'i' ), 23 ); $ical_strings = $this->limit_never_ending_strings( $ical_strings, $never_limit_date ); return $ical_strings; } } 3-Year Fernie Pride Society Membership - Fernie Pride Society
Skip to content Skip to footer

3-Year Fernie Pride Society Membership

$20.00

SKU: 100003 Category: Product ID: 9014

Description

When you purchase a membership, you are supporting a great organization. Your membership helps us to show community partners that our organization is needed in the Elk Valley, which helps us secure support and funding for some great programming and initiatives.

In return we will:
*Keep our excellent programming and initiatives going,
*Keep you up to date on Pride in the Elk Valley through social media posts,
*Invite you to attend our annual AGM meeting so you can ask questions and give input to your community association.

Vancouver Foundation Logo in Colour

About Us

The Fernie Pride Society supports and connects the 2SLGBTQ+ community in the Elk Valley.  Incorporated in December 2016, the Society is a hub for 2SLGBTQ+ people and their allies, programming special events as well as providing resource referrals.

 

Get In Touch

102 Commerce Road
Fernie, BC
V0B 1M5

Fernie Pride acknowledges that we reside on land located within Qukin ʔamakʔis, the unceded traditional territory of Yaq̓it ʔa·knuqⱡi’it.

We recognize that we live and work within their vast lands. ʔakanuxunik̓ are from Yaq̓it ʔa·knuqⱡi‘it and are members of the Ktunaxa speaking peoples of British Columbia, Idaho, and Montana.

Fernie Pride Society © 2024 | Website Design by Claris Media