Completed
Branch TASK-9118-extensions-page (04eaec)
by
unknown
437:52 queued 424:08
created

Invoice::send_invoice()   F

Complexity

Conditions 21
Paths > 20000

Size

Total Lines 173
Code Lines 126

Duplication

Lines 6
Ratio 3.47 %

Importance

Changes 0
Metric Value
cc 21
eloc 126
nc 30720
nop 1
dl 6
loc 173
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
//Creates the invoice pdf
4
class Invoice {
5
6
	/**
7
	 *
8
	 * @var EE_Registration
9
	 */
10
	private $registration;
11
	/**
12
	 *
13
	 * @var EE_Transaction
14
	 */
15
	private $transaction;
16
	/**
17
	 *
18
	 * @var EE_Payment_Method
19
	 */
20
	private $invoice_payment_method;
21
	private $EE;
0 ignored issues
show
Unused Code introduced by
The property $EE is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
22
	public function __construct($url_link = 0) {
23
24
		if ( $this->registration = EE_Registry::instance()->load_model( 'Registration' )->get_registration_for_reg_url_link( $url_link)) {
0 ignored issues
show
Bug introduced by
The method get_registration_for_reg_url_link cannot be called on \EE_Registry::instance()...d_model('Registration') (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
25
			$this->transaction = $this->registration->transaction();
26
27
			$payment_settings = EE_Config::instance()->gateway->payment_settings;//get_user_meta(EE_Registry::instance()->CFG->wp_user, 'payment_settings', TRUE);
0 ignored issues
show
Unused Code introduced by
$payment_settings is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
Deprecated Code introduced by
The property EE_Config::$gateway has been deprecated.

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
28
			$this->invoice_payment_method = EEM_Payment_Method::instance()->get_one_of_type( 'Invoice' );
29
		} else {
30
			EE_Error::add_error( __( 'Your request appears to be missing some required data, and no information for your transaction could be retrieved.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
31
		}
32
33
	}
34
35
	public function send_invoice( $download = FALSE ) {
36
		$template_args = array();
37
		$EE = EE_Registry::instance();
38
39
		//allow the request to override the default theme defined in the invoice settings
40
		$theme_requested = ( isset( $_REQUEST['theme'] ) && $_REQUEST['theme'] > 0 && $_REQUEST['theme'] < 8 ) ? absint( $_REQUEST['theme'] ) : null;
41
		$themes = array(
42
										1 => "simple.css",
43
										2 => "bauhaus.css",
44
										3 => "ejs.css",
45
										4 => "horizon.css",
46
										5 => "lola.css",
47
										6 => "tranquility.css",
48
										7 => "union.css"
49
									);
50
		//Get the CSS file
51
		if( isset( $themes[ $theme_requested ] ) ) {
52
			$template_args['invoice_css'] = $themes[ $theme_requested ];
53
		}else{
54
			$template_args['invoice_css'] = $this->invoice_payment_method->get_extra_meta( 'legacy_invoice_css', TRUE, 'simple.css' );
55
		}
56
57
		if (is_dir(EVENT_ESPRESSO_GATEWAY_DIR . '/invoice')) {
58
			$template_args['base_url'] = EVENT_ESPRESSO_GATEWAY_URL . 'Invoice/lib/templates/';
59
		} else {
60
			$template_args['base_url'] = EE_GATEWAYS . '/Invoice/lib/templates/';
61
		}
62
		$primary_attendee = $this->transaction->primary_registration()->attendee();
63
64
		$template_args['organization'] = $EE->CFG->organization->get_pretty( 'name' );
65
		$template_args['street'] = empty( $EE->CFG->organization->address_2 ) ? $EE->CFG->organization->get_pretty( 'address_1' ) : $EE->CFG->organization->get_pretty( 'address_1' ) . '<br>' . $EE->CFG->organization->get_pretty( 'address_2' );
66
		$template_args['city'] = $EE->CFG->organization->get_pretty( 'city' );
67
		$template_args['state'] = EE_Registry::instance()->load_model( 'State' )->get_one_by_ID( $EE->CFG->organization->STA_ID );
0 ignored issues
show
Bug introduced by
The method get_one_by_ID cannot be called on \EE_Registry::instance()->load_model('State') (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
68
		$template_args['country'] = EE_Registry::instance()->load_model( 'Country' )->get_one_by_ID( $EE->CFG->organization->CNT_ISO );
0 ignored issues
show
Bug introduced by
The method get_one_by_ID cannot be called on \EE_Registry::instance()->load_model('Country') (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
69
		$template_args['zip'] = $EE->CFG->organization->get_pretty( 'zip' );
70
		$template_args['email'] = $EE->CFG->organization->get_pretty( 'email' );
71
72
		$template_args['registration_code'] = $this->registration->reg_code();
73
		$template_args['registration_date'] = $this->registration->date();
74
		$template_args['name'] = $primary_attendee->full_name();
75
		$template_args['attendee_address'] = $primary_attendee->address();
76
		$template_args['attendee_address2'] = $primary_attendee->address2();
77
		$template_args['attendee_city'] = $primary_attendee->city();
78
		$attendee_state = $primary_attendee->state_obj();
79
		if($attendee_state){
80
			$attendee_state_name = $attendee_state->name();
81
		}else{
82
			$attendee_state_name = '';
83
		}
84
		$template_args['attendee_state'] = $attendee_state_name;
85
		$template_args['attendee_zip'] = $primary_attendee->zip();
86
87
		$template_args['ship_name'] = $template_args['name'];
88
		$template_args['ship_address'] = $template_args['attendee_address'];
89
		$template_args['ship_city'] = $template_args['attendee_city'];
90
		$template_args['ship_state'] = $template_args['attendee_state'];
91
		$template_args['ship_zip'] = $template_args['attendee_zip'];
92
93
		$template_args['total_cost'] = number_format($this->transaction->total(), 2, '.', '');
94
		$template_args['transaction'] = $this->transaction;
95
		$template_args['amount_pd'] = $this->transaction->paid();
96
		$template_args['amount_owed'] = $this->transaction->total() - $this->transaction->paid();
97
		$template_args['payments'] = $this->transaction->approved_payments();
98
		$template_args['net_total'] = '';
99
		$template_args['edit_reg_info_url'] = $this->registration->edit_attendee_information_url();
100
		$template_args['retry_payment_url'] = $this->registration->payment_overview_url();
101
		$template_args['show_line_item_description'] = $this->check_if_any_line_items_have_a_description($this->transaction->total_line_item());
102
		if ($template_args['amount_pd'] != $template_args['total_cost']) {
103
			//$template_args['net_total'] = $this->espressoInvoiceTotals( __('SubTotal', 'event_espresso'), $this->transaction->total());//$this->session_data['cart']['REG']['sub_total']);
104
			$tax_items = $this->transaction->tax_items();
105
			if(!empty($tax_items) ){
106
				foreach ($tax_items as $tax) {
107
					$template_args['net_total'] .= $this->espressoInvoiceTotals( $tax->name(), $tax->total());
0 ignored issues
show
Documentation Bug introduced by
The method total does not exist on object<EE_Base_Class>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
108
				}
109
			}
110
111
			$difference = $template_args['amount_pd'] - $template_args['total_cost'];
112
			if ($difference < 0) {
113
				$text = __('Discount', 'event_espresso');
114
			} else {
115
				$text = __('Extra', 'event_espresso');
116
			}
117
			$template_args['discount'] = $this->espressoInvoiceTotals( $text, $difference );
118
		}
119
120
		$template_args['currency_symbol'] = $EE->CFG->currency->sign;
121
		$template_args['template_payment_instructions'] = wpautop(stripslashes_deep(html_entity_decode($this->invoice_payment_method->get_extra_meta( 'pdf_instructions', TRUE ), ENT_QUOTES)));
122
		$template_args['shameless_plug'] = apply_filters( 'FHEE_Invoice__send_invoice__shameless_plug',true );
123
		if(isset($_GET['receipt'])){
124
			//receipt-specific stuff
125
			$events_for_txn = EEM_Event::instance()->get_all(array(array('Registration.TXN_ID'=>$this->transaction->ID())));
126
			$ticket_line_items_per_event = array();
127
			$registrations_per_line_item = array();
128
			$venues_for_events = array();
129
			foreach($events_for_txn as $event_id => $event){
130
				$line_items_for_this_event = EEM_Line_Item::instance()->get_all(array(array('Ticket.Datetime.EVT_ID'=>$event_id,'TXN_ID'=>$this->transaction->ID())));
131
				$ticket_line_items_per_event[$event_id] = $line_items_for_this_event;
132
				foreach($line_items_for_this_event as $line_item_id => $line_item){
133
					$ticket = $line_item->ticket();
0 ignored issues
show
Documentation Bug introduced by
The method ticket does not exist on object<EE_Base_Class>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
134
					$registrations_for_this_ticket = EEM_Registration::instance()->get_all(array(array('TKT_ID'=>$ticket->ID(),'TXN_ID'=>$this->transaction->ID())));
135
					$registrations_per_line_item[$line_item_id] = $registrations_for_this_ticket;
136
				}
137
				$venues_for_events = array_merge($venues_for_events, $event->venues());
0 ignored issues
show
Documentation Bug introduced by
The method venues does not exist on object<EE_Base_Class>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
138
			}
139
			$tax_total_line_item = EEM_Line_Item::instance()->get_one(array(array('TXN_ID'=>$this->transaction->ID(),'LIN_type'=>  EEM_Line_Item::type_tax_sub_total)));
140
			$questions_to_skip = array(EEM_Attendee::system_question_fname,EEM_Attendee::system_question_lname,  EEM_Attendee::system_question_email);
141
142
143
			$template_args['events_for_txn'] = $events_for_txn;
144
			$template_args['ticket_line_items_per_event'] = $ticket_line_items_per_event;
145
			$template_args['registrations_per_line_item'] = $registrations_per_line_item;
146
			$template_args['venues_for_events'] = $venues_for_events;
147
			$template_args['tax_total_line_item'] = $tax_total_line_item;
148
			$template_args['questions_to_skip'] = $questions_to_skip;
149
			$EE->load_helper( 'Venue_View' );
150
//			d($template_args);
151
			$template_args['download_link'] = $this->registration->receipt_url('download');
152
		}else{
153
			//it's just an invoice we're accessing
154
			$template_args['download_link'] = $this->registration->invoice_url('download');
155
		}
156
157
158
159
		//require helpers
160
		$EE->load_helper( 'Formatter' );
161
162
		//Get the HTML as an object
163
		EE_Registry::instance()->load_helper('Template');
164
		$templates_relative_path = 'modules/gateways/Invoice/lib/templates/';
165
		$template_header = EEH_Template::locate_template( $templates_relative_path . 'invoice_header.template.php', $template_args, TRUE, TRUE );
166
		if(isset($_GET['receipt'])){
167
			$template_body = EEH_Template::locate_template( $templates_relative_path . 'receipt_body.template.php', $template_args, TRUE, TRUE );
168
		}else{
169
			$template_body = EEH_Template::locate_template( $templates_relative_path . 'invoice_body.template.php', $template_args, TRUE, TRUE );
170
		}
171
172
173
		$template_footer = EEH_Template::locate_template( $templates_relative_path . 'invoice_footer.template.php', $template_args, TRUE, TRUE );
174
175
		$copies =  ! empty( $_REQUEST['copies'] ) ? $_REQUEST['copies'] : 1;
176
177
		$content = $this->espresso_replace_invoice_shortcodes($template_header);
178
		for( $x = 1; $x <= $copies; $x++ ) {
179
			$content .= $this->espresso_replace_invoice_shortcodes($template_body);
180
		}
181
		$content .= $this->espresso_replace_invoice_shortcodes($template_footer);
182
183
		//Check if debugging or mobile is set
184
		if (!empty($_REQUEST['html'])) {
185
			echo $content;
186
			exit(0);
187
		}
188
		$invoice_name = $template_args['organization'] . ' ' . __('Invoice #', 'event_espresso') . $template_args['registration_code'] . __(' for ', 'event_espresso') . $template_args['name'];
189
		$invoice_name = str_replace( ' ', '_', $invoice_name );
190
		//Create the PDF
191
		if(array_key_exists('html',$_GET)){
192
			echo $content;
193
		}else{
194
			//only load dompdf if nobody else has yet...
195 View Code Duplication
			if( ! defined('DOMPDF_DIR')){
196
				define('DOMPDF_ENABLE_REMOTE', TRUE);
197
				define('DOMPDF_ENABLE_JAVASCRIPT', FALSE);
198
				define('DOMPDF_ENABLE_CSS_FLOAT', TRUE);
199
				require_once(EE_THIRD_PARTY . 'dompdf/dompdf_config.inc.php');
200
			}
201
			$dompdf = new DOMPDF();
202
			$dompdf->load_html($content);
203
			$dompdf->render();
204
			$dompdf->stream($invoice_name . ".pdf", array( 'Attachment' => $download ));
205
		}
206
		exit(0);
207
	}
208
	/**
209
	 * Checks if this line item, or any of its children, actually has a description.
210
	 * If none do, then the template can decide to not show any description column
211
	 * @param EE_Line_Item $line_item
212
	 * @return boolean
213
	 */
214
	function check_if_any_line_items_have_a_description(EE_Line_Item $line_item){
215
		if($line_item->desc()){
216
			return true;
217
		}else{
218
			foreach($line_item->children() as $child_line_item){
219
				if($this->check_if_any_line_items_have_a_description($child_line_item)){
220
					return true;
221
				}
222
			}
223
			//well, if I and my children don't have descriptions, I guess not
224
			return false;
225
		}
226
	}
227
228
//Perform the shortcode replacement
229
	function espresso_replace_invoice_shortcodes( $content ) {
230
231
		$EE = EE_Registry::instance();
232
		//Create the logo
233
		$invoice_logo_url = $this->invoice_payment_method->get_extra_meta('pdf_logo_image', TRUE,  $EE->CFG->organization->logo_url );
234
		if (!empty($invoice_logo_url)) {
235
			$image_size = getimagesize($invoice_logo_url);
236
			$invoice_logo_image = '<img class="logo screen" src="' . $invoice_logo_url . '" ' . $image_size[3] . ' alt="logo" /> ';
237
		} else {
238
			$invoice_logo_image = '';
239
		}
240
		$SearchValues = array(
241
				"[organization]",
242
				"[registration_code]",
243
				"[transaction_id]",
244
				"[name]",
245
				"[base_url]",
246
				"[download_link]",
247
				"[invoice_logo_image]",
248
				"[street]",
249
				"[city]",
250
				"[state]",
251
				"[zip]",
252
				"[email]",
253
				"[vat]",
254
				"[registration_date]",
255
				"[instructions]",
256
		);
257
		$primary_attendee = $this->transaction->primary_registration()->attendee();
258
		$org_state = EE_Registry::instance()->load_model( 'State' )->get_one_by_ID( $EE->CFG->organization->STA_ID );
0 ignored issues
show
Bug introduced by
The method get_one_by_ID cannot be called on \EE_Registry::instance()->load_model('State') (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
259
		if($org_state){
260
			$org_state_name = $org_state->name();
261
		}else{
262
			$org_state_name = '';
263
		}
264
		$ReplaceValues = array(
265
				$EE->CFG->organization->get_pretty( 'name' ),
266
				$this->registration->reg_code(),
267
				$this->transaction->ID(),
268
				$primary_attendee->full_name(),
269
				(is_dir(EVENT_ESPRESSO_GATEWAY_DIR . '/invoice')) ? EVENT_ESPRESSO_GATEWAY_URL . 'Invoice/lib/templates/' : EE_GATEWAYS_URL . 'Invoice/lib/templates/',
270
				$this->registration->invoice_url(),//home_url() . '/?download_invoice=true&amp;id=' . $this->registration->reg_url_link(),
271
				$invoice_logo_image,
272
				empty( $EE->CFG->organization->address_2 ) ? $EE->CFG->organization->get_pretty( 'address_1' ) : $EE->CFG->organization->get_pretty( 'address_1' ) . '<br>' . $EE->CFG->organization->get_pretty( 'address_2' ),
273
				$EE->CFG->organization->get_pretty( 'city' ),
274
				$org_state_name,
275
				$EE->CFG->organization->get_pretty( 'zip' ),
276
				$EE->CFG->organization->get_pretty( 'email' ),
277
				$EE->CFG->organization->vat,
278
				$this->registration->get_i18n_datetime( 'REG_date', get_option( 'date_format' ) ),
279
				$this->invoice_payment_method->get_extra_meta( 'pdf_instructions', TRUE ),
280
		);
281
282
		return str_replace($SearchValues, $ReplaceValues, $content);
283
	}
284
285
	public function espressoLoadData($items) {
286
		$lines = $items;
287
		$data = array();
288
		foreach ($lines as $line)
289
			$data[] = explode(';', chop($line));
290
291
		return $data;
292
	}
293
294
295
296
	public function espressoInvoiceTotals($text, $total_cost) {
297
298
		$html = '';
299
		if ($total_cost < 0) {
300
			$total_cost = (-1) * $total_cost;
301
		}
302
		$find = array( ' ' );
303
		$replace = array( '-' );
304
		$row_id = strtolower( str_replace( $find, $replace, $text ));
305
		$html .= '<tr id="'.$row_id.'-tr"><td colspan="4">&nbsp;</td>';
306
		$html .= '<td class="item_r">' . $text . '</td>';
307
		$html .= '<td class="item_r">' . $total_cost . '</td>';
308
		$html .= '</tr>';
309
		return $html;
310
	}
311
312
}
313