Yields an estimated percentage slice of: 40-50

@param array $book_contents
@param array $metadata
@return \Generator
778248
protected function createPartsAndChaptersGenerator( $book_contents, $metadata ) : \Generator {
		$part_printf = '<div class="part %1$s" id="%2$s">';
		$part_printf .= '<div class="part-title-wrap"><h3 class="part-number">%3$s</h3><h1 class="part-title">%4$s</h1></div>%5$s';
		$part_printf .= '</div>';

		$chapter_printf = '<div class="chapter %1$s" id="%2$s">';
		$chapter_printf .= '<div class="chapter-title-wrap"><h3 class="chapter-number">%3$s</h3><h2 class="chapter-title">%4$s</h2>%5$s</div>';
		$chapter_printf .= '<div class="ugc chapter-ugc">%6$s</div>%7$s';
		$chapter_printf .= '</div>';

		$ticks = 0;
		foreach ( $book_contents['part'] as $key => $part ) {
			$ticks = $ticks + 1 + count( $book_contents['part'][ $key ]['chapters'] );
		}
		$y = new PercentageYield( 40, 50, $ticks );

		$vars = [
			'post_title' => '',
			'stylesheet' => $this->stylesheet,
			'post_content' => '',
			'append_chapter_content' => '',
			'isbn' => ( isset( $metadata['pb_ebook_isbn'] ) ) ? $metadata['pb_ebook_isbn'] : '',
			'lang' => $this->lang,
		];

		// Parts, Chapters
		$i = 1;
		$j = 1;
		$c = 1;
		$p = 1;
		foreach ( $book_contents['part'] as $part ) {
			yield from $y->tick( $this->generatorPrefix . __( 'Exporting parts and chapters', 'pressbooks' ) );

			$invisibility = ( get_post_meta( $part['ID'], 'pb_part_invisible', true ) === 'on' ) ? 'invisible' : '';

			$part_printf_changed = '';
			$array_pos = count( $this->manifest );
			$has_chapters = false;

			// Inject introduction class?
			if ( ! $this->hasIntroduction && count( $book_contents['part'] ) > 1 ) {
				$part_printf_changed = str_replace( '<div class="part %s" id=', '<div class="part introduction %s" id=', $part_printf );
				$this->hasIntroduction = true;
			}

			// Inject part content?
			$part_content = trim( $part['post_content'] );
			if ( $part_content ) {
				$part_content = $this->kneadHtml( $this->preProcessPostContent( $part_content ), 'custom', $p );
				$part_printf_changed = str_replace( '</h1></div>%5$s</div>', '</h1></div><div class="ugc part-ugc">%5$s</div></div>', $part_printf );
			}

			foreach ( $part['chapters'] as $chapter ) {
				yield from $y->tick( $this->generatorPrefix . __( 'Exporting parts and chapters', 'pressbooks' ) );

				if ( ! $chapter['export'] ) {
					continue; // Skip
				}

				$chapter_printf_changed = '';
				$chapter_id = $chapter['ID'];
				$subclass = $this->taxonomy->getChapterType( $chapter_id );
				$slug = $chapter['post_name'];
				$title = ( get_post_meta( $chapter_id, 'pb_show_title', true ) ? $chapter['post_title'] : '' );
				$after_title = '';
				$content = $this->kneadHtml( $chapter['post_content'], 'chapter', $j );
				$append_chapter_content = $this->kneadHtml( apply_filters( 'pb_append_chapter_content', '', $chapter_id ), 'chapter', $j );
				$short_title = false; // Ie. running header title is not used in EPUB
				$subtitle = trim( get_post_meta( $chapter_id, 'pb_subtitle', true ) );
				$author = $this->contributors->get( $chapter_id, 'pb_authors' );

				if ( Export::shouldParseSubsections() === true ) {
					if ( Book::getSubsections( $chapter_id ) !== false ) {
						$content = Book::tagSubsections( $content, $chapter_id );
						$content = $this->html5ToXhtml( $content );
					}
				}

				if ( $author ) {
					if ( $this->wrapHeaderElements ) {
						$after_title = '<h2 class="chapter-author">' . Sanitize\decode( $author ) . '</h2>' . $after_title;
					} else {
						$content = '<h2 class="chapter-author">' . Sanitize\decode( $author ) . '</h2>' . $content;
					}
				}

				if ( $subtitle ) {
					if ( $this->wrapHeaderElements ) {
						$after_title = '<h2 class="chapter-subtitle">' . Sanitize\decode( $subtitle ) . '</h2>' . $after_title;
					} else {
						$content = '<h2 class="chapter-subtitle">' . Sanitize\decode( $subtitle ) . '</h2>' . $content;
					}
				}

				if ( $short_title ) {
					if ( $this->wrapHeaderElements ) {
						$after_title = '<h6 class="short-title">' . Sanitize\decode( $short_title ) . '</h6>' . $after_title;
					} else {
						$content = '<h6 class="short-title">' . Sanitize\decode( $short_title ) . '</h6>' . $content;
					}
				}

				// Inject introduction class?
				if ( ! $this->hasIntroduction ) {
					$subclass .= ' introduction';
					$this->hasIntroduction = true;
				}

				$section_license = $this->doSectionLevelLicense( $metadata, $chapter_id );
				if ( $section_license ) {
					$append_chapter_content .= $this->kneadHtml( $this->tidy( $section_license ), 'chapter', $j );
				}

				$my_chapter_number = ( strpos( $subclass, 'numberless' ) === false ) ? $c : '';
				$vars['post_title'] = $chapter['post_title'];
				$vars['post_content'] = sprintf(
					$chapter_printf,
					$subclass,
					$slug,
					( $this->numbered ? $my_chapter_number : '' ),
					Sanitize\decode( $title ),
					$after_title,
					$content,
					$var['append_chapter_content'] = $append_chapter_content,
					''
				);

				$file_id = 'chapter-' . sprintf( '%03s', $j );
				$filename = "{$file_id}-{$slug}.{$this->filext}";

				\Pressbooks\Utility\put_contents(
					$this->tmpDir . "/OEBPS/$filename",
					$this->loadTemplate( $this->dir . '/templates/epub201/html.php', $vars )
				);

				$this->manifest[ $file_id ] = [
					'ID' => $chapter['ID'],
					'post_title' => $chapter['post_title'],
					'filename' => $filename,
				];

				$has_chapters = true;

				$j++;

				if ( $my_chapter_number !== '' ) {
					++$c;
				}
			}

			if ( count( $book_contents['part'] ) === 1 && $part_content ) { // only part, has content
				$slug = $part['post_name'];
				$m = ( 'invisible' === $invisibility ) ? '' : $p;
				$vars['post_title'] = $part['post_title'];
				$vars['post_content'] = sprintf(
					( $part_printf_changed ? $part_printf_changed : $part_printf ),
					$invisibility,
					$slug,
					( $this->numbered ? \Pressbooks\L10n\romanize( $m ) : '' ),
					Sanitize\decode( $part['post_title'] ),
					$part_content
				);

				$file_id = 'part-' . sprintf( '%03s', $i );
				$filename = "{$file_id}-{$slug}.{$this->filext}";

				\Pressbooks\Utility\put_contents(
					$this->tmpDir . "/OEBPS/$filename",
					$this->loadTemplate( $this->dir . '/templates/epub201/html.php', $vars )
				);

				// Insert into correct pos
				$this->manifest = array_slice( $this->manifest, 0, $array_pos, true ) + [
					$file_id => [
						'ID' => $part['ID'],
						'post_title' => $part['post_title'],
						'filename' => $filename,
					],
				] + array_slice( $this->manifest, $array_pos, count( $this->manifest ) - 1, true );

				++$i;
				if ( 'invisible' !== $invisibility ) {
					++$p;
				}
			} elseif ( count( $book_contents['part'] ) > 1 ) { // multiple parts
				if ( $has_chapters ) { // has chapter
					$slug = $part['post_name'];
					$m = ( 'invisible' === $invisibility ) ? '' : $p;
					$vars['post_title'] = $part['post_title'];
					$vars['post_content'] = sprintf(
						( $part_printf_changed ? $part_printf_changed : $part_printf ),
						$invisibility,
						$slug,
						( $this->numbered ? \Pressbooks\L10n\romanize( $m ) : '' ),
						Sanitize\decode( $part['post_title'] ),
						$part_content
					);

					$file_id = 'part-' . sprintf( '%03s', $i );
					$filename = "{$file_id}-{$slug}.{$this->filext}";

					\Pressbooks\Utility\put_contents(
						$this->tmpDir . "/OEBPS/$filename",
						$this->loadTemplate( $this->dir . '/templates/epub201/html.php', $vars )
					);

					// Insert into correct pos
					$this->manifest = array_slice( $this->manifest, 0, $array_pos, true ) + [
						$file_id => [
							'ID' => $part['ID'],
							'post_title' => $part['post_title'],
							'filename' => $filename,
						],
					] + array_slice( $this->manifest, $array_pos, count( $this->manifest ) - 1, true );

					++$i;
					if ( 'invisible' !== $invisibility ) {
						++$p;
					}
				} else { // no chapter
					if ( $part_content ) { // has content
						$slug = $part['post_name'];
						$m = ( 'invisible' === $invisibility ) ? '' : $p;
						$vars['post_title'] = $part['post_title'];
						$vars['post_content'] = sprintf(
							( $part_printf_changed ? $part_printf_changed : $part_printf ),
							$invisibility,
							$slug,
							( $this->numbered ? \Pressbooks\L10n\romanize( $m ) : '' ),
							Sanitize\decode( $part['post_title'] ),
							$part_content
						);

						$file_id = 'part-' . sprintf( '%03s', $i );
						$filename = "{$file_id}-{$slug}.{$this->filext}";

						\Pressbooks\Utility\put_contents(
							$this->tmpDir . "/OEBPS/$filename",
							$this->loadTemplate( $this->dir . '/templates/epub201/html.php', $vars )
						);

						// Insert into correct pos
						$this->manifest = array_slice( $this->manifest, 0, $array_pos, true ) + [
							$file_id => [
								'ID' => $part['ID'],
								'post_title' => $part['post_title'],
								'filename' => $filename,
							],
						] + array_slice( $this->manifest, $array_pos, count( $this->manifest ) - 1, true );

						++$i;
						if ( 'invisible' !== $invisibility ) {
							++$p;
						}
					}
				}
			}

			// Did we actually inject the introduction class?
			if ( $part_printf_changed && ! $has_chapters ) {
				$this->hasIntroduction = false;
			}
		}
	}
493983
private function replaceMagicDirFileConstants(StreamMetaData $metadata): void
    {
        $magicConstFinder = new NodeFinderVisitor([Dir::class, File::class]);
        $traverser        = new NodeTraverser();
        $traverser->addVisitor($magicConstFinder);
        $traverser->traverse($metadata->syntaxTree);

        /** @var MagicConst[] $magicConstants */
        $magicConstants = $magicConstFinder->getFoundNodes();
        $magicFileValue = $metadata->uri;
        $magicDirValue  = dirname($magicFileValue);
        foreach ($magicConstants as $magicConstantNode) {
            $tokenPosition = $magicConstantNode->getAttribute('startTokenPos');
            $replacement   = $magicConstantNode instanceof Dir ? $magicDirValue : $magicFileValue;

            $metadata->tokenStream[$tokenPosition][1] = "'{$replacement}'";
        }
    }
714974
public function putContents( $contents, $ex_lock = false ) : int
    {
        $flags = $ex_lock ? LOCK_EX : 0;
        $res = file_put_contents( $this->path, $contents, $flags );
        if ($res === FALSE){
            throw new FileOutputException($this);
        }
        return $res;
    }
557205
public static function getAll(Bookboon $bookboon) : BookboonResponse
    {
        $bResponse = $bookboon->rawRequest("/exams");

        $bResponse->setEntityStore(
            new EntityStore(static::getEntitiesFromArray($bResponse->getReturnArray()))
        );

        return $bResponse;
    }
378563
public function get10()
    {
        // Is it valid?
        if ($this->isValid()) {
            // Is it already an ISBN-10?  If so, return as-is.
            if (strlen($this->raw) == 10) {
                return $this->raw;
            } elseif (strlen($this->raw) == 13
                && substr($this->raw, 0, 3) == '978'
            ) {
                // Is it a Bookland EAN?  If so, we can convert to ISBN-10.
                $start = substr($this->raw, 3, 9);
                return $start . self::getISBN10CheckDigit($start);
            }
        }

        // If we made it this far, conversion was not possible:
        return false;
    }
1351963
function convert() {

		// Create ICML

		$vars = [
			'meta' => \Pressbooks\Book::getBookInformation(),
			'book_contents' => $this->preProcessBookContents( \Pressbooks\Book::getBookContents() ),
		];

		$cc_copyright = strip_tags( $this->doCopyrightLicense( $vars['meta'] ) );
		$vars['do_copyright_license'] = $cc_copyright;

		$book_html = $this->loadTemplate( __DIR__ . '/templates/xhtml.php', $vars );
		$content = $this->transformXML( $book_html, PB_PLUGIN_DIR . 'symbionts/icml/tkbr2icml-v044.xsl' );

		// Save ICML as file in exports folder

		$filename = $this->timestampedFileName( '.icml' );
		\Pressbooks\Utility\put_contents( $filename, $content );
		$this->outputPath = $filename;

		if ( ! filesize( $this->outputPath ) ) {
			$this->logError( $this->bookHtmlError( $book_html ) );
			unlink( $this->outputPath );

			return false;
		}

		return true;

	}
907029
protected function cloneMetadata() {
		$metadata_post_id = ( new \Pressbooks\Metadata )->getMetaPostId();

		if ( ! $metadata_post_id ) {
			return false;
		}

		$book_information = schema_to_book_information( $this->sourceBookMetadata );

		// Cover image
		if ( ! \Pressbooks\Image\is_default_cover( $book_information['pb_cover_image'] ) ) {
			$new_cover_id = $this->downloads->fetchAndSaveUniqueImage( $book_information['pb_cover_image'] );
			if ( $new_cover_id > 0 ) {
				$this->clonedItems['media'][] = $new_cover_id; // Counter
				$book_information['pb_cover_image'] = wp_get_attachment_url( $new_cover_id );
			} else {
				$book_information['pb_cover_image'] = default_cover_url();
			}
		} else {
			$book_information['pb_cover_image'] = default_cover_url();
		}

		// Everything else
		$book_information['pb_is_based_on'] = $this->sourceBookUrl;
		$metadata_array_values = [ 'pb_keywords_tags', 'pb_bisac_subject', 'pb_additional_subjects' ];
		foreach ( $book_information as $key => $value ) {
			if ( $this->contributors->isValid( $key ) ) {
				$values = oxford_comma_explode( $value );
				foreach ( $values as $v ) {
					$this->contributors->insert( $v, $metadata_post_id, $key );
				}
			} elseif ( in_array( $key, $metadata_array_values, true ) ) {
				$values = explode( ', ', $value );
				foreach ( $values as $v ) {
					add_post_meta( $metadata_post_id, $key, $v );
				}
			} elseif ( $key === 'pb_title' ) {
				update_post_meta( $metadata_post_id, $key, $this->targetBookTitle );
			} else {
				update_post_meta( $metadata_post_id, $key, $value );
				if ( $key === 'pb_book_license' ) {
					wp_set_object_terms( $metadata_post_id, $value, \Pressbooks\Licensing::TAXONOMY ); // Link
				}
			}
		}

		// Remove the current user from the author field in Book Info
		$user_data = get_userdata( get_current_user_id() );
		$this->contributors->unlink( $user_data->user_nicename, $metadata_post_id );

		return $metadata_post_id;
	}
1104972
public function upgradeBookInformation() {

		// Metadata

		$meta_post = $this->getMetaPost();
		if ( ! $meta_post ) {
			return; // Do nothing
		}

		$metadata = $this->getMetaPostMetadata();
		$compare = $this->getDeprecatedComparisonTable( 'metadata' );

		foreach ( $metadata as $meta_key => $meta_value ) {
			$new_meta_key = ( isset( $compare[ $meta_key ] ) ) ? $compare[ $meta_key ] : false;
			if ( $new_meta_key ) {
				$meta_id = $this->getMidByKey( $meta_post->ID, $meta_key );
				if ( $meta_id ) {
					if ( isset( $this->upgradeCheckboxes[ $meta_key ] ) ) {
						$meta_value = 'on';
					} elseif ( is_array( $meta_value ) ) {
						$meta_value = array_values( $meta_value );
						$meta_value = array_pop( $meta_value );
					}

					// Overrides
					if ( 'pb_language' === $new_meta_key ) {
						$meta_value = substr( strtolower( $meta_value ), 0, 2 );
					}
					if ( 'pb_publication_date' === $new_meta_key ) {
						$meta_value = strtotime( $meta_value );
					}

					// Update the original $meta_key to the $new_meta_key
					update_metadata_by_mid( 'post', $meta_id, $meta_value, $new_meta_key );
				}
			}
		}
		// Force title change
		update_metadata( 'post', $meta_post->ID, 'pb_title', get_bloginfo( 'name' ) );
	}
1063355
protected function fixPartChapterStructure( array $book_structure, $has_permission, array $replacement_keys ) {

		$part_base = 'parts';
		$part_rest_url = rest_url( sprintf( '%s/%s', $this->namespace, $part_base ) );
		$chapter_base = 'chapters';
		$chapter_rest_url = rest_url( sprintf( '%s/%s', $this->namespace, $chapter_base ) );

		$part = [];
		foreach ( $book_structure['part'] as $old_p ) {
			$new_p = [];
			foreach ( $old_p as $old_key => $val ) {
				$new_key = strtr( $old_key, $replacement_keys );
				$new_p[ $new_key ] = $val;
			}
			$chapters = [];
			foreach ( $new_p['chapters'] as $old_ch ) {
				if ( $has_permission || in_array( $old_ch['post_status'], [ 'web-only', 'publish' ], true ) ) {
					$new_ch = [];
					foreach ( $old_ch as $old_key => $val ) {
						$new_key = strtr( $old_key, $replacement_keys );
						$new_ch[ $new_key ] = $val;
					}
					$new_ch['link'] = get_permalink( $new_ch['id'] );
					$new_ch['chapter-type'] = wp_get_object_terms(
						$new_ch['id'], 'chapter-type', [
							'fields' => 'ids',
						]
					);
					$this->linkCollector['chapter'][] = [
						'href' => trailingslashit( $chapter_rest_url ) . $new_ch['id'],
						'embeddable' => true,
					];

					// Metadata
					$request_metadata = new \WP_REST_Request( 'GET', "/pressbooks/v2/{$chapter_base}/{$new_ch['id']}/metadata" );
					$response_metadata = rest_do_request( $request_metadata );
					$new_ch['metadata'] = $this->prepare_response_for_collection( $response_metadata );
					$this->linkCollector['metadata'][] = [
						'href' => trailingslashit( $chapter_rest_url ) . "{$new_ch['id']}/metadata",
					];
					unset( $new_ch['metadata']['_links'] );

					$chapters[] = $new_ch;
				}
			}
			$new_p['chapters'] = $chapters;
			$new_p['link'] = get_permalink( $new_p['id'] );
			$this->linkCollector['part'][] = [
				'href' => trailingslashit( $part_rest_url ) . $new_p['id'],
				'embeddable' => true,
			];
			$part[] = $new_p;
		}

		return $part;
	}
776369
public function render_print_book_toc($chapters, $book, $cm) {

        $first = true;

        $context = context_module::instance($cm->id);

        $toc = ''; // Representation of toc (HTML).

        switch ($book->numbering) {
            case BOOK_NUM_NONE:
                $toc .= html_writer::start_tag('div', array('class' => 'book_toc_none'));
                break;
            case BOOK_NUM_NUMBERS:
                $toc .= html_writer::start_tag('div', array('class' => 'book_toc_numbered'));
                break;
            case BOOK_NUM_BULLETS:
                $toc .= html_writer::start_tag('div', array('class' => 'book_toc_bullets'));
                break;
            case BOOK_NUM_INDENTED:
                $toc .= html_writer::start_tag('div', array('class' => 'book_toc_indented'));
                break;
        }

        $toc .= html_writer::tag('a', '', array('name' => 'toc')); // Representation of toc (HTML).

        $toc .= html_writer::tag('h2', get_string('toc', 'mod_book'), ['class' => 'text-center p-b-2']);
        $toc .= html_writer::start_tag('ul');
        foreach ($chapters as $ch) {
            if (!$ch->hidden) {
                $title = book_get_chapter_title($ch->id, $chapters, $book, $context);
                if (!$ch->subchapter) {

                    if ($first) {
                        $toc .= html_writer::start_tag('li');
                    } else {
                        $toc .= html_writer::end_tag('ul');
                        $toc .= html_writer::end_tag('li');
                        $toc .= html_writer::start_tag('li');
                    }

                } else {

                    if ($first) {
                        $toc .= html_writer::start_tag('li');
                        $toc .= html_writer::start_tag('ul');
                        $toc .= html_writer::start_tag('li');
                    } else {
                        $toc .= html_writer::start_tag('li');
                    }

                }

                if (!$ch->subchapter) {
                    $toc .= html_writer::link(new moodle_url('#ch' . $ch->id), $title,
                            array('title' => s($title), 'class' => 'font-weight-bold text-decoration-none'));
                    $toc .= html_writer::start_tag('ul');
                } else {
                    $toc .= html_writer::link(new moodle_url('#ch' . $ch->id), $title,
                            array('title' => s($title), 'class' => 'text-decoration-none'));
                    $toc .= html_writer::end_tag('li');
                }
                $first = false;
            }
        }

        $toc .= html_writer::end_tag('ul');
        $toc .= html_writer::end_tag('li');
        $toc .= html_writer::end_tag('ul');
        $toc .= html_writer::end_tag('div');

        $toc = str_replace('<ul></ul>', '', $toc); // Cleanup of invalid structures.

        return $toc;
    }
863709
protected function convertWordToRecord(array $word, array $fieldNames, array $metadata, array $filenames): array
    {
        $numberValidator = new NumberValidator();
        $output = [];
        foreach ($fieldNames as $fieldName) {
            $field = isset($word[$fieldName][0])
                ? array_shift($word[$fieldName])
                : (isset($metadata[$fieldName]) ? $metadata[$fieldName] : '');
            if (is_array($field)) {
                $includedFilename = false;
                if (is_string($this->csvOnly)) {
                    $html = (new \esperecyan\html_filter\Filter(
                        null,
                        ['before' => function (\DOMElement $body) use ($filenames, &$includedFilename) {
                            foreach (['img', 'audio', 'video'] as $elementName) {
                                foreach ($body->getElementsByTagName($elementName) as $element) {
                                    $src = $element->getAttribute('src');
                                    if (in_array($src, $filenames)) {
                                        $includedFilename = true;
                                        $element->setAttribute('src', sprintf($this->csvOnly, $src));
                                    }
                                }
                            }
                        }]
                    ))->filter($field['html']);
                }
                $field
                    = $includedFilename ? (new \League\HTMLToMarkdown\HtmlConverter())->convert($html) : $field['lml'];
            } elseif (is_float($field)) {
                $field = $numberValidator->serializeFloat($field);
            } elseif (is_string($this->csvOnly)
                && in_array($fieldName, ['image', 'audio', 'video']) && in_array($field, $filenames)) {
                $field = sprintf($this->csvOnly, $field);
            }
            $output[] = $field;
        }
        return $output;
    }
1241414
private function generateDocumentBody(array $metadata)
    {
        $lines = [];

        if ($properties = $this->generateDocumentProperties($metadata)) {
            $lines[] = $properties;
        }

        if ($this->hasMultipleEmbedded($metadata)) {
            $lines[] = $this->generateDocumentConstructor($metadata);
        }

        if ($methods = $this->generateDocumentMethods($metadata)) {
            $lines[] = $methods;
        }

        return rtrim(implode("\n", $lines));
    }
641565
def binarycontent_sections(chunk):
    ''''''
    # using string split because it is significantly faster than regex.

    # use common text of start and end tags to split the text
    # (i.e. without < or </ tag beginning)
    binary_content_tag = BINARY_CONTENT_START[1:]
    if binary_content_tag not in chunk:
        # if no tags are present, don't do any extra work
        yield chunk

    else:
        # split on common portion of foxml:binaryContent
        sections = chunk.split(binary_content_tag)
        for sec in sections:
            extra = b''
            # check the end of the section to determine start/end tag
            if sec.endswith(b'</'):
                extra = sec[-2:]
                yield sec[:-2]

            elif sec.endswith(b'<'):
                extra = sec[-1:]
                yield sec[:-1]

            else:
                yield sec

            if extra:
                # yield the actual binary content tag
                # (delimiter removed by split, but needed for processing)
                yield b''.join([extra, binary_content_tag])
609288
public static function getAll(
        Bookboon $bookboon,
        bool $extendedMetadata = false,
        array $bookTypes = [self::_OWN_TYPE]
    ) : BookboonResponse {
        $variables = [
            'bookType' => join(',', $bookTypes),
            'extendedMetadata' => $extendedMetadata ? 'true' : 'false'
        ];

        $bResponse = $bookboon->rawRequest("/books", $variables);

        $bResponse->setEntityStore(
            new EntityStore(static::getEntitiesFromArray($bResponse->getReturnArray()))
        );

        return $bResponse;
    }
446116
function initMetadataConversions() {
  var mdc = this.metadataConversions

  mdc['publish'] = {
    deserialize: function (dateString) {
      if (dateString)
        return new Date(Date.parse(dateString))
      else
        return dateString
    },
    serialize: function (date) {
      if (date instanceof Date) {
        return date.getFullYear() + '-' 
          + ('0' + (date.getMonth()+1)).slice(-2) + '-'
          + ('0' + date.getDate())
      } else {
        return date.toString()
      }
    }
  }

  mdc['tags'] = {
    deserialize: function (tagString) { //prob not very readable
      if (S(tagString).contains(',')) return tagString.split(',').map(function(tag){ return tag.trim() })
      //else if (S(tagString).contains(' ')) return tagString.split(' ').map(function(tag){ return tag.trim() })
      else return [tagString]
    },
    serialize: function (tagArray) {
      return tagArray.join(', ')
    }
  }
}
346686
function parseReadme(book) {
    var logger = book.getLogger();

    return parseStructureFile(book, 'readme')
    .spread(function(file, result) {
        if (!file) {
            throw new error.FileNotFoundError({ filename: 'README' });
        }

        logger.debug.ln('readme found at', file.getPath());

        var readme = Readme.create(file, result);
        return book.set('readme', readme);
    });
}
1092831
public function convertGenerator() : \Generator {
		yield 1 => $this->generatorPrefix . __( 'Initializing', 'pressbooks' );

		yield from $this->transformGenerator();

		if ( ! $this->transformOutput ) {
			throw new \Exception();
		}

		yield 75 => $this->generatorPrefix . __( 'Saving file to exports folder', 'pressbooks' );
		$filename = $this->timestampedFileName( '.html' );
		\Pressbooks\Utility\put_contents( $filename, $this->transformOutput );
		$this->outputPath = $filename;
		yield 80 => $this->generatorPrefix . __( 'Export successful', 'pressbooks' );
	}